doc/sql/20260609_knowledge_base_vector.sql
ÎļþÒÑɾ³ý doc/sql/20260613_customer_level.sql
ÎļþÒÑɾ³ý doc/sql/20260613_quality_attachment_optimize.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ -- ============================================================ -- ä¸åæ ¼ç®¡çæ¨¡åä¼å -- 1. åºå¼ quality_inspect_file 表ï¼éä»¶æ¹ç¨ storage_attachment ä½ç³» -- 2. æ£éªè®°å½éä»¶éè¿ storage_attachment (record_type='quality_inspect') å ³è -- 3. ä¸åæ ¼åéä»¶éè¿ storage_attachment (record_type='quality_unqualified') å ³è -- çææ¥æï¼2026-06-13 -- ============================================================ -- å¯éï¼å¦æ quality_inspect_file 表åå¨ä¸ææ°æ®ï¼éè¦å è¿ç§»æ°æ®åå é¤ -- æ°æ®è¿ç§»ï¼å°æ§éä»¶æ°æ®è¿ç§»å° storage_attachment è¡¨ï¼ -- INSERT INTO storage_attachment (name, url, file_size, application, record_type, record_id, create_time, create_user, tenant_id, dept_id, is_deleted) -- SELECT name, url, file_size, 'FILE', 'quality_inspect', inspect_id, create_time, create_user, tenant_id, dept_id, 0 -- FROM quality_inspect_file; -- å 餿§çæ£éªé件表ï¼ç¡®è®¤æ°æ®å·²è¿ç§»åæ§è¡ï¼ -- DROP TABLE IF EXISTS quality_inspect_file; doc/sql/20260613_quality_module_completion.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,58 @@ -- ============================================================ -- ä¸åæ ¼ç®¡çæ¨¡åè¡¥å ¨ -- 1. å·²æè¡¨è¡¥å ç¼ºå¤±åæ®µ -- 2. æ°å»º quality_unqualified_order ä¸åæ ¼åå¤çå表 -- çææ¥æï¼2026-06-13 -- ============================================================ -- Phase 1A: quality_inspect è¡¥å process_type åæ®µ ALTER TABLE quality_inspect ADD COLUMN process_type INT DEFAULT NULL COMMENT 'å·¥åºç±»åï¼å¹é æ°æ®åå ¸ product_process_type'; -- Phase 1B: quality_unqualified è¡¥å 4 ä¸ªåæ®µ ALTER TABLE quality_unqualified ADD COLUMN reason_analysis VARCHAR(500) DEFAULT NULL COMMENT 'åå åæ'; ALTER TABLE quality_unqualified ADD COLUMN preventive_corrective VARCHAR(500) DEFAULT NULL COMMENT 'é¢é²ä¸çº æ£æªæ½'; ALTER TABLE quality_unqualified ADD COLUMN loss_working VARCHAR(200) DEFAULT NULL COMMENT 'å·¥æ¶æå¤±'; ALTER TABLE quality_unqualified ADD COLUMN loss_material VARCHAR(200) DEFAULT NULL COMMENT 'ææè´¹æå¤±'; -- Phase 1C: quality_test_standard è¡¥å process_type åæ®µ ALTER TABLE quality_test_standard ADD COLUMN process_type INT DEFAULT NULL COMMENT 'å·¥åºç±»å'; -- Phase 2: æ°å»º quality_unqualified_order ä¸åæ ¼åå¤çå表 CREATE TABLE IF NOT EXISTS quality_unqualified_order ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主é®', order_no VARCHAR(32) NOT NULL COMMENT 'å¤çåç¼å·ï¼åç¼BHG+æ¥æ+èªå¢åºå·', unqualified_id BIGINT COMMENT 'å ³èquality_unqualified.id', project_name VARCHAR(100) COMMENT '项ç®åç§°', project_no VARCHAR(50) COMMENT '项ç®ç¼å·', equipment_id BIGINT COMMENT 'å ³è设å¤ID', equipment_name VARCHAR(100) COMMENT '设å¤åç§°', equipment_drawing_no VARCHAR(50) COMMENT '设å¤å¾å·', material_name VARCHAR(100) COMMENT 'ç©æ/é¨ä»¶åç§°', product_model_id BIGINT COMMENT 'å ³è产ååå·ID', material_drawing_no VARCHAR(50) COMMENT 'ç©æå¾å·', specification_model VARCHAR(100) COMMENT 'åå·è§æ ¼', material_quality VARCHAR(50) COMMENT 'æè´¨', quantity DECIMAL(10,2) COMMENT 'æ»æ°é', unqualified_quantity DECIMAL(10,2) COMMENT 'ä¸åæ ¼æ°é', unqualified_process TINYINT COMMENT 'ä¸åæ ¼å·¥åºï¼1=æ¥æï¼2=å¶ç¨ï¼3=æå', supplier_name VARCHAR(100) COMMENT 'ä¾åºååç§°', inspector_name VARCHAR(50) COMMENT 'æ£éªå', inspect_date DATE COMMENT 'æ£éªæ¥æ', responsible_person VARCHAR(50) COMMENT '责任人', responsible_dept VARCHAR(50) COMMENT '责任é¨é¨', problem_description VARCHAR(500) COMMENT 'é®é¢æè¿°', reason_analysis VARCHAR(500) COMMENT 'åå åæå建议', correction_action VARCHAR(500) COMMENT 'çº æ£æªæ½', disposal_method TINYINT COMMENT 'å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶ï¼2=åå ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åº', repair_evaluation VARCHAR(500) COMMENT 'åå /è¿åç»´ä¿®è¯ä¼°', preventive_action VARCHAR(500) COMMENT 'é¢é²æªæ½', status TINYINT DEFAULT 0 COMMENT 'ç¶æï¼0=è稿ï¼1=å¾ å®¡æ¹ï¼2=审æ¹ä¸ï¼3=已宿ï¼4=已驳å', remark VARCHAR(500) COMMENT '夿³¨', create_by INT COMMENT 'åå»ºç¨æ·', update_by INT COMMENT 'ä¿®æ¹ç¨æ·', create_time DATETIME COMMENT 'å建æ¶é´', update_time DATETIME COMMENT 'ä¿®æ¹æ¶é´', tenant_id BIGINT COMMENT 'ç§æ·ID', dept_id BIGINT COMMENT 'é¨é¨ID', deleted TINYINT DEFAULT 0 COMMENT 'é»è¾å é¤ï¼0=å¦ï¼1=æ¯' ); doc/sql/20260613_sales_ledger_approval.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,9 @@ -- éå®å°è´¦å¢å 审æ¹ç¶æå段 -- 0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å ALTER TABLE sales_ledger ADD COLUMN IF NOT EXISTS approval_status INT DEFAULT 0 COMMENT '审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å'; -- ç产主计åå¢å 审æ¹ç¶æå段ï¼ä¸éå®å°è´¦å®¡æ¹ç¶æåæ¥ï¼ ALTER TABLE production_plan ADD COLUMN IF NOT EXISTS approval_status INT DEFAULT NULL COMMENT '审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å'; docs/customer_follow_up_export.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,93 @@ # æ´½è°è¿åº¦å¯¼åº ## æ¶åé¡µé¢ - **ç§æµ·å®¢æ·å表** â æä½åæå·¥å ·æ å¢å "å¯¼åºæ´½è°è¿åº¦"æé® ## API | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/basic/customer-follow/export` | å¯¼åºæ´½è°è¿åº¦ | **请æ±åæ°ï¼Query String æ Form Dataï¼ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | customerName | String | å¦ | 客æ·åç§°ï¼æ¨¡ç³æç´¢ï¼ | | customerType | String | å¦ | 客æ·åç±» | **ååºï¼** æä»¶æµï¼Excel ä¸è½½ï¼ï¼ååºå¤´ `Content-Disposition: attachment; filename=æ´½è°è¿åº¦.xlsx` ## 导åºè¡¨æ ¼å | åå | åæ®µ | 说æ | |------|------|------| | 客æ·åç§° | customerName | | | 客æ·åç±» | customerType | | | 客æ·ç级 | customerLevel | | | è系人 | contactPerson | | | èç³»çµè¯ | contactPhone | | | ç»´æ¤äºº | maintainer | | | è·è¿æ¹å¼ | followUpMethod | | | è·è¿ç¨åº¦ | followUpLevel | | | è·è¿æ¶é´ | followUpTime | æ ¼å¼ yyyy-MM-dd HH:mm:ss | | è·è¿äºº | followerUserName | | | è·è¿å 容 | content | | æ¯è¡ä¸æ¡è·è¿è®°å½ï¼å®¢æ·æå¤æ¡è·è¿æ¶å±å¼å¤è¡ï¼ã ## å端修æ¹ç¹ ### 1. å·¥å ·æ ææä½åå¢å æé® ```html <el-button type="warning" icon="el-icon-download" @click="exportFollowUp">å¯¼åºæ´½è°è¿åº¦</el-button> ``` ### 2. å¯¼åºæ¹æ³ ```js // å¯¼åºæ´½è°è¿åº¦ exportFollowUp() { this.$confirm('ç¡®è®¤å¯¼åºææå®¢æ·çæ´½è°è¿åº¦æ°æ®åï¼', 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'info' }).then(() => { this.downloadFollowUpExcel(); }).catch(() => {}); }, // æ§è¡å¯¼åº downloadFollowUpExcel() { const params = new URLSearchParams(); if (this.queryParams.customerName) { params.append('customerName', this.queryParams.customerName); } if (this.queryParams.customerType) { params.append('customerType', this.queryParams.customerType); } // POST æ¹å¼ä¸è½½æä»¶ fetch('/basic/customer-follow/export', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString(), responseType: 'blob' }).then(response => { if (!response.ok) throw new Error('导åºå¤±è´¥'); return response.blob(); }).then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'æ´½è°è¿åº¦.xlsx'; a.click(); window.URL.revokeObjectURL(url); }).catch(err => { this.$message.error('导åºå¤±è´¥ï¼' + err.message); }); } ``` > 注ï¼å¦æé¡¹ç®ä¸æå°è£ 好çæä»¶ä¸è½½å·¥å ·å½æ°ï¼å¦ `downloadBlob`ï¼ï¼å»ºè®®ç´æ¥å¤ç¨ã docs/customer_handover.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,117 @@ # å®¢æ·æ¡£æ¡ â 客æ·äº¤æ¥åè½ ## æ¶åé¡µé¢ - **ç§æµ·å®¢æ·å表** â æä½åå¢å "客æ·äº¤æ¥"æé® - å ¬æµ·å®¢æ·ä¸æ¾ç¤ºæ¤æé® ## API | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/basic/customer/handover` | 客æ·äº¤æ¥ | **请æ±ä½ï¼** ```json { "id": 123, "maintainer": "å¼ ä¸" } ``` **ååºï¼** ```json { "code": 200, "msg": "æä½æå" } ``` ## å端修æ¹ç¹ ### 1. ç§æµ·å®¢æ·å表 â æä½åå¢å æé® ```html <el-button type="text" @click="handleHandover(row)">客æ·äº¤æ¥</el-button> ``` ä» å¨ `row.type === 0`ï¼ç§æµ·å®¢æ·ï¼æ¶æ¾ç¤ºã ### 2. 交æ¥å¼¹çª ```html <el-dialog title="客æ·äº¤æ¥" :visible.sync="handoverDialogVisible" width="400px"> <el-form :model="handoverForm" label-width="100px"> <el-form-item label="å½åç»´æ¤äºº"> <span>{{ handoverForm.oldMaintainer }}</span> </el-form-item> <el-form-item label="æ°ç»´æ¤äºº" prop="maintainer"> <el-select v-model="handoverForm.maintainer" placeholder="è¯·éæ©æ°ç»´æ¤äºº" filterable> <el-option v-for="user in userList" :key="user.userId" :label="user.userName" :value="user.userName" /> </el-select> </el-form-item> </el-form> <div slot="footer"> <el-button @click="handoverDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitHandover">ç¡®å®</el-button> </div> </el-dialog> ``` ### 3. data æ°æ® ```js data() { return { handoverDialogVisible: false, handoverForm: { id: null, oldMaintainer: '', maintainer: '' }, userList: [], // è´è´£äººå表ï¼å¤ç¨ç°æç¨æ·ä¸ææ°æ®æº } } ``` ### 4. æ¹æ³ ```js // æå¼äº¤æ¥å¼¹çª handleHandover(row) { this.handoverForm.id = row.id; this.handoverForm.oldMaintainer = row.maintainer; this.handoverForm.maintainer = ''; this.handoverDialogVisible = true; }, // æäº¤äº¤æ¥ submitHandover() { if (!this.handoverForm.maintainer) { this.$message.warning('è¯·éæ©æ°ç»´æ¤äºº'); return; } postRequest('/basic/customer/handover', { id: this.handoverForm.id, maintainer: this.handoverForm.maintainer }).then(res => { if (res.code === 200) { this.$message.success('äº¤æ¥æå'); this.handoverDialogVisible = false; this.getList(); // å·æ°å表 } }); } ``` ## 注æäºé¡¹ - äº¤æ¥æé®ä» å¨ç§æµ·å®¢æ·å表æ¾ç¤ºï¼`row.type === 0`ï¼ - æ°ç»´æ¤äººä¸ææ°æ®æºå¯å¤ç¨ç³»ç»ä¸å·²æçç¨æ·éæ©å¨æ¥å£ï¼å¦ `/system/user/list`ï¼ - äº¤æ¥æååå表èªå¨å·æ°ï¼ç»´æ¤äººåæ´æ°ä¸ºæ°å¼ - å端ä¼åæ¥æ´æ° `maintenanceTime`ï¼ç»´æ¤æ¶é´ï¼ä¸ºå½åæ¶é´ docs/quality_attachment_optimize.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,131 @@ # ä¸åæ ¼ç®¡çæ¨¡å â å端èè°ææ¡£ ## æ¶åé¡µé¢ - **æ£éªè®°å½å表/详æ ** â éä»¶ä¸ä¼ /æ¥ç - **ä¸åæ ¼å管çå表/详æ ** â éä»¶ä¸ä¼ /æ¥ç ## åæ´è¯´æ éä»¶ä½ç³»ä»ç¬ç«ç `quality_inspect_file` 表æ¹ä¸ºä½¿ç¨ç³»ç»ç»ä¸ç `storage_attachment` 表ï¼éè¿ `recordType` + `recordId` å ³èãå端éä»¶ä¸ä¼ /åæ¾æ¹å¼åç³»ç»å ¶ä»æ¨¡åï¼å¦éè´å°è´¦ã设å¤ç»´ä¿®çï¼ä¿æä¸è´ã ## API åæ´ ### æ£éªè®°å½ | æ¥å£ | åæ´è¯´æ | |------|---------| | `POST /quality/qualityInspect/add` | 请æ±ä½æ°å¢ `storageBlobDTOs` åæ®µ | | `POST /quality/qualityInspect/update` | 请æ±ä½æ°å¢ `storageBlobDTOs` åæ®µ | | `GET /quality/qualityInspect/{id}` | ååºæ°å¢ `storageBlobVOs` åæ®µ | ### ä¸åæ ¼å | æ¥å£ | åæ´è¯´æ | |------|---------| | `POST /quality/qualityUnqualified/add` | 请æ±ä½æ°å¢ `storageBlobDTOs` åæ®µ | | `POST /quality/qualityUnqualified/update` | 请æ±ä½æ°å¢ `storageBlobDTOs` åæ®µ | | `GET /quality/qualityUnqualified/{id}` | ååºæ°å¢ `storageBlobVOs` åæ®µ | ## æ°æ®ç»æ ### StorageBlobDTOï¼ä¸ä¼ æ¶ä¼ å ¥ï¼ ```json { "id": "ä¸´æ¶æä»¶IDï¼å符串ï¼", "name": "æä»¶å", "url": "æä»¶è·¯å¾", "fileSize": 1024 } ``` ### StorageBlobVOï¼æ¥è¯¢æ¶è¿åï¼ ```json { "id": 1, "name": "æ£éªæ¥å.pdf", "url": "/upload/20260613/xxx.pdf", "fileSize": 102400, "application": "FILE" } ``` ## å端修æ¹ç¹ ### 1. æ£éªè®°å½ â æ°å¢/ç¼è¾è¡¨åå¢å éä»¶ä¸ä¼ ```html <!-- éä»¶ä¸ä¼ ç»ä»¶ï¼ä½¿ç¨ç³»ç»å·²æçæä»¶ä¸ä¼ ç»ä»¶ï¼ --> <file-upload v-model="form.storageBlobDTOs" :file-list="form.storageBlobVOs" @change="handleFileChange" /> ``` ### 2. æ£éªè®°å½ â 详æ 页å±ç¤ºéä»¶ ```html <el-form-item label="éä»¶"> <template v-if="form.storageBlobVOs && form.storageBlobVOs.length > 0"> <div v-for="file in form.storageBlobVOs" :key="file.id"> <a :href="file.url" target="_blank">{{ file.name }}</a> <span style="margin-left: 10px; color: #999">{{ (file.fileSize / 1024).toFixed(1) }}KB</span> </div> </template> <span v-else>æ éä»¶</span> </el-form-item> ``` ### 3. ä¸åæ ¼å â æ°å¢/ç¼è¾è¡¨åå¢å éä»¶ä¸ä¼ ```html <file-upload v-model="form.storageBlobDTOs" :file-list="form.storageBlobVOs" /> ``` ### 4. ä¸åæ ¼å â 详æ å±ç¤ºéä»¶ ```html <el-form-item label="éä»¶"> <template v-if="form.storageBlobVOs && form.storageBlobVOs.length > 0"> <div v-for="file in form.storageBlobVOs" :key="file.id"> <a :href="file.url" target="_blank">{{ file.name }}</a> </div> </template> <span v-else>æ éä»¶</span> </el-form-item> ``` ### 5. 表å data è¡¥å åæ®µ ```js data() { return { form: { storageBlobDTOs: [], // ä¸ä¼ æ¶ä¼ å ¥ storageBlobVOs: [], // æ¥è¯¢æ¶è¿å // ... å ¶ä»å段 } } } ``` ## åºå¼å 容 - `quality_inspect_file` 表åºå¼ï¼æ°æ®å·²è¿ç§»å° `storage_attachment` 表 - åç«¯å¦æä¹åæå¯¹æ¥ `POST /quality/qualityInspectFile/add` çæ¥å£ï¼éç§»é¤ç¸å ³ä»£ç ## æ°æ®åºåæ´ æ§è¡æä»¶ï¼`doc/sql/20260613_quality_attachment_optimize.sql` ## 注æäºé¡¹ - éä»¶ä¸ä¼ 使ç¨ç³»ç»å·²æçæä»¶ä¸ä¼ æ¥å£ï¼å¦ `/file/upload`ï¼ï¼å°è¿åçä¸´æ¶æä»¶IDéè¿ `storageBlobDTOs` ä¼ å ¥ - 妿ä¸ä¼ `storageBlobDTOs` æä¼ 空æ°ç»ï¼ä¸ä¼å é¤å·²æéä»¶ï¼éè¦å é¤éä»¶æ¶ä¼ 空æ°ç»å³å¯ - å端项ç®å¦å·²æéç¨çæä»¶ä¸ä¼ /éä»¶å±ç¤ºç»ä»¶ï¼ç´æ¥å¤ç¨å³å¯ docs/quality_unqualified_order.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,282 @@ # ä¸åæ ¼åå¤çå â å端èè°ææ¡£ ## æ¶åé¡µé¢ - **ä¸åæ ¼åå¤çåå表/详æ ** â æ°å¢é¡µé¢ ## åæ´è¯´æ æ°å¢ `quality_unqualified_order` ä¸åæ ¼åå¤ç忍¡åï¼æ¯æå¯¹ä¸åæ ¼åè¿è¡æ£å¼çå¤ç½®è®°å½ï¼å å«å®¡æ¹ç¶ææºï¼è稿âå¾ å®¡æ¹â审æ¹ä¸â已宿/已驳åï¼ãé件使ç¨ç³»ç»ç»ä¸ç `storage_attachment` 表ã ## API ### ä¸åæ ¼åå¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/qualityUnqualifiedOrder/save` | æ°å¢å¤çåï¼ç¼å·èªå¨çæï¼ | | PUT | `/qualityUnqualifiedOrder/update` | ä¿®æ¹å¤çå | | DELETE | `/qualityUnqualifiedOrder/delete` | æ¹éå é¤ï¼é»è¾å é¤ï¼ | | GET | `/qualityUnqualifiedOrder/listPage` | å页æ¥è¯¢ | | GET | `/qualityUnqualifiedOrder/{id}` | æ¥ç详æ | ### 请æ±/ååºåæ° **QualityUnqualifiedOrder 对象ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | id | Long | å¦ | 主é®ï¼ä¿®æ¹æ¶å¿ å¡«ï¼ | | orderNo | String | å¦ | å¤çåç¼å·ï¼èªå¨çæï¼åç¼ BHG+æ¥æ+åºå· | | unqualifiedId | Long | å¦ | å ³èä¸åæ ¼åID | | projectName | String | å¦ | 项ç®åç§° | | projectNo | String | å¦ | 项ç®ç¼å· | | equipmentId | Long | å¦ | å ³è设å¤ID | | equipmentName | String | å¦ | 设å¤åç§° | | equipmentDrawingNo | String | å¦ | 设å¤å¾å· | | materialName | String | å¦ | ç©æ/é¨ä»¶åç§° | | productModelId | Long | å¦ | å ³è产ååå·ID | | materialDrawingNo | String | å¦ | ç©æå¾å· | | specificationModel | String | å¦ | åå·è§æ ¼ | | materialQuality | String | å¦ | æè´¨ | | quantity | BigDecimal | å¦ | æ»æ°é | | unqualifiedQuantity | BigDecimal | å¦ | ä¸åæ ¼æ°é | | unqualifiedProcess | Integer | å¦ | ä¸åæ ¼å·¥åºï¼1=æ¥æï¼2=å¶ç¨ï¼3=æå | | supplierName | String | å¦ | ä¾åºååç§° | | inspectorName | String | å¦ | æ£éªå | | inspectDate | Date | å¦ | æ£éªæ¥æ (yyyy-MM-dd) | | responsiblePerson | String | å¦ | 责任人 | | responsibleDept | String | å¦ | 责任é¨é¨ | | problemDescription | String | å¦ | é®é¢æè¿° | | reasonAnalysis | String | å¦ | åå åæå建议 | | correctionAction | String | å¦ | çº æ£æªæ½ | | disposalMethod | Integer | å¦ | å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶ï¼2=åå ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åº | | repairEvaluation | String | å¦ | åå /è¿åç»´ä¿®è¯ä¼° | | preventiveAction | String | å¦ | é¢é²æªæ½ | | status | Integer | å¦ | ç¶æï¼0=è稿ï¼1=å¾ å®¡æ¹ï¼2=审æ¹ä¸ï¼3=已宿ï¼4=已驳å | | remark | String | å¦ | 夿³¨ | | storageBlobDTOs | List\<StorageBlobDTO\> | å¦ | éä»¶ä¸ä¼ å表 | | storageBlobVOs | List\<StorageBlobVO\> | å¦ | éä»¶åæ¾åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼ | ### å页æ¥è¯¢åæ° | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | pageNum | Integer | å¦ | 页ç ï¼é»è®¤1 | | pageSize | Integer | å¦ | æ¯é¡µæ¡æ°ï¼é»è®¤10 | | status | Integer | å¦ | ç¶æçé | | projectName | String | å¦ | 项ç®åç§°æ¨¡ç³æç´¢ | | orderNo | String | å¦ | ç¼å·æ¨¡ç³æç´¢ | | entryDateStart | String | å¦ | å建æ¶é´èµ·å§ | | entryDateEnd | String | å¦ | å建æ¶é´ç»æ | ### å é¤è¯·æ±ä½ ```json [1, 2, 3] ``` ## æ°æ®ç»æ ### StorageBlobDTOï¼ä¸ä¼ æ¶ä¼ å ¥ï¼ ```json { "id": "ä¸´æ¶æä»¶IDï¼å符串ï¼", "name": "æä»¶å", "url": "æä»¶è·¯å¾", "fileSize": 1024 } ``` ### StorageBlobVOï¼æ¥è¯¢æ¶è¿åï¼ ```json { "id": 1, "name": "æ£éªæ¥å.pdf", "url": "/upload/20260613/xxx.pdf", "fileSize": 102400, "application": "FILE" } ``` ## å端修æ¹ç¹ ### 1. ä¸åæ ¼åå¤çå â æ°å¢/ç¼è¾è¡¨å ```html <el-form :model="form" :rules="rules" ref="formRef"> <el-form-item label="项ç®åç§°" prop="projectName"> <el-input v-model="form.projectName" /> </el-form-item> <el-form-item label="项ç®ç¼å·" prop="projectNo"> <el-input v-model="form.projectNo" /> </el-form-item> <el-form-item label="设å¤åç§°" prop="equipmentName"> <el-input v-model="form.equipmentName" /> </el-form-item> <el-form-item label="ç©æ/é¨ä»¶åç§°" prop="materialName"> <el-input v-model="form.materialName" /> </el-form-item> <el-form-item label="åå·è§æ ¼" prop="specificationModel"> <el-input v-model="form.specificationModel" /> </el-form-item> <el-form-item label="æè´¨" prop="materialQuality"> <el-input v-model="form.materialQuality" /> </el-form-item> <el-form-item label="æ»æ°é" prop="quantity"> <el-input-number v-model="form.quantity" /> </el-form-item> <el-form-item label="ä¸åæ ¼æ°é" prop="unqualifiedQuantity"> <el-input-number v-model="form.unqualifiedQuantity" /> </el-form-item> <el-form-item label="ä¸åæ ¼å·¥åº" prop="unqualifiedProcess"> <el-select v-model="form.unqualifiedProcess"> <el-option label="æ¥æ" :value="1" /> <el-option label="å¶ç¨" :value="2" /> <el-option label="æå" :value="3" /> </el-select> </el-form-item> <el-form-item label="ä¾åºååç§°" prop="supplierName"> <el-input v-model="form.supplierName" /> </el-form-item> <el-form-item label="æ£éªå" prop="inspectorName"> <el-input v-model="form.inspectorName" /> </el-form-item> <el-form-item label="æ£éªæ¥æ" prop="inspectDate"> <el-date-picker v-model="form.inspectDate" type="date" value-format="yyyy-MM-dd" /> </el-form-item> <el-form-item label="责任人" prop="responsiblePerson"> <el-input v-model="form.responsiblePerson" /> </el-form-item> <el-form-item label="责任é¨é¨" prop="responsibleDept"> <el-input v-model="form.responsibleDept" /> </el-form-item> <el-form-item label="é®é¢æè¿°" prop="problemDescription"> <el-input type="textarea" v-model="form.problemDescription" /> </el-form-item> <el-form-item label="åå åæ" prop="reasonAnalysis"> <el-input type="textarea" v-model="form.reasonAnalysis" /> </el-form-item> <el-form-item label="çº æ£æªæ½" prop="correctionAction"> <el-input type="textarea" v-model="form.correctionAction" /> </el-form-item> <el-form-item label="å¤ç½®æ¹å¼" prop="disposalMethod"> <el-select v-model="form.disposalMethod"> <el-option label="è®©æ¥æ¥æ¶" :value="1" /> <el-option label="åå ç»´ä¿®" :value="2" /> <el-option label="è¿åç»´ä¿®" :value="3" /> <el-option label="æ¢è´§" :value="4" /> <el-option label="éè´§" :value="5" /> <el-option label="æ¥åº" :value="6" /> </el-select> </el-form-item> <el-form-item label="ç»´ä¿®è¯ä¼°" prop="repairEvaluation"> <el-input type="textarea" v-model="form.repairEvaluation" /> </el-form-item> <el-form-item label="é¢é²æªæ½" prop="preventiveAction"> <el-input type="textarea" v-model="form.preventiveAction" /> </el-form-item> <el-form-item label="夿³¨" prop="remark"> <el-input type="textarea" v-model="form.remark" /> </el-form-item> <el-form-item label="éä»¶"> <file-upload v-model="form.storageBlobDTOs" :file-list="form.storageBlobVOs" /> </el-form-item> </el-form> ``` ### 2. ä¸åæ ¼åå¤çå â å表页 ```html <el-table :data="tableData" border> <el-table-column prop="orderNo" label="å¤çåç¼å·" /> <el-table-column prop="projectName" label="项ç®åç§°" /> <el-table-column prop="materialName" label="ç©æåç§°" /> <el-table-column prop="specificationModel" label="åå·è§æ ¼" /> <el-table-column prop="unqualifiedQuantity" label="ä¸åæ ¼æ°é" /> <el-table-column prop="disposalMethod" label="å¤ç½®æ¹å¼"> <template #default="{ row }"> {{ disposalMethodMap[row.disposalMethod] }} </template> </el-table-column> <el-table-column prop="status" label="ç¶æ"> <template #default="{ row }"> <el-tag :type="statusTagType(row.status)">{{ statusMap[row.status] }}</el-tag> </template> </el-table-column> <el-table-column label="æä½"> <template #default="{ row }"> <el-button type="text" @click="handleDetail(row.id)">详æ </el-button> <el-button type="text" @click="handleEdit(row)">ç¼è¾</el-button> <el-button type="text" @click="handleDelete(row.id)">å é¤</el-button> </template> </el-table-column> </el-table> ``` ### 3. data æ°æ® ```js data() { return { form: { storageBlobDTOs: [], storageBlobVOs: [], }, query: { pageNum: 1, pageSize: 10, status: null, projectName: '', orderNo: '', }, statusMap: { 0: 'è稿', 1: 'å¾ å®¡æ¹', 2: '审æ¹ä¸', 3: '已宿', 4: '已驳å' }, disposalMethodMap: { 1: 'è®©æ¥æ¥æ¶', 2: 'åå ç»´ä¿®', 3: 'è¿åç»´ä¿®', 4: 'æ¢è´§', 5: 'éè´§', 6: 'æ¥åº' }, unqualifiedProcessMap: { 1: 'æ¥æ', 2: 'å¶ç¨', 3: 'æå' }, } } ``` ### 4. API è°ç¨ ```js import request from '@/utils/request' // å页æ¥è¯¢ export function listPage(query) { return request({ url: '/qualityUnqualifiedOrder/listPage', method: 'get', params: query }) } // 详æ export function getDetail(id) { return request({ url: `/qualityUnqualifiedOrder/${id}`, method: 'get' }) } // æ°å¢ export function save(data) { return request({ url: '/qualityUnqualifiedOrder/save', method: 'post', data }) } // ä¿®æ¹ export function update(data) { return request({ url: '/qualityUnqualifiedOrder/update', method: 'put', data }) } // å é¤ export function remove(ids) { return request({ url: '/qualityUnqualifiedOrder/delete', method: 'delete', data: ids }) } ``` ## 注æäºé¡¹ - å¤çåç¼å· `orderNo` ç±å端èªå¨çæï¼åç¼ "BHG" + æ¥æ + 3ä½èªå¢åºå·ï¼ï¼å端æ éä¼ å ¥ - æ°å¢æ¶ `status` é»è®¤ä¸º 0ï¼è稿ï¼ï¼æ éå端设置 - å é¤ä¸ºé»è¾å é¤ï¼éè¿ `deleted` åæ®µæ è®° - éä»¶ä¸ä¼ 使ç¨ç³»ç»å·²æçæä»¶ä¸ä¼ ç»ä»¶ï¼å°è¿åçä¸´æ¶æä»¶IDéè¿ `storageBlobDTOs` ä¼ å ¥ - ä¸åæ ¼åå¤çåå¯å ³è `quality_unqualified` 表çè®°å½ï¼éè¿ `unqualifiedId` åæ®µï¼ docs/sales_ledger_approval.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,101 @@ # éå®å°è´¦ â ååå®¡æ¹ ## æ¶åé¡µé¢ - **éå®å°è´¦æ°å¢/ç¼è¾é¡µé¢** â æ°å¢æ¶èªå¨å起审æ¹ï¼å表å±ç¤ºå®¡æ¹ç¶æ - **åå审æ¹ç®¡ç** â å®¡æ¹æ¨¡æ¿é ç½®ãå®¡æ¹æµç¨å¤ç - **ç产主计åå表** â å±ç¤ºå®¡æ¹ç¶æå ## åç«¯åæ´è¯´æ ### æ°å¢æä¸¾ `TypeEnums` æ°å¢ `SALES_LEDGER_APPROVAL(19L, "éå®å®¡æ¹")` ### 审æ¹ç¶æ `SalesLedger.approvalStatus` å `ProductionPlan.approvalStatus`ï¼ | å¼ | å«ä¹ | |----|------| | 0 | å¾ å®¡æ¹ | | 1 | 审æ¹ä¸ | | 2 | å·²éè¿ | | 3 | 已驳å | ### å®¡æ¹æµç¨ 1. éå®å°è´¦æ°å¢æ¶èªå¨å起审æ¹ï¼`sales_ledger.approval_status = 0` 2. 审æ¹ä¸ç¶æå为 `1`ï¼å®¡æ¹éè¿å为 `2`ï¼å®¡æ¹é©³åå为 `3` 3. 审æ¹éè¿åï¼èªå¨å建ç产主计åï¼`production_plan.approval_status = 2` 4. å®¡æ¹æ¨¡æ¿éè¦å¨**åå审æ¹ç®¡ç**ä¸åç¬é ç½®ï¼ä¸å¨ååå®¡æ¹æ¨¡æ¿å表ä¸å±ç¤ºï¼ ## API æ æ°å¢å端è°ç¨æ¥å£ï¼å®¡æ¹ç±å端èªå¨åèµ·ã ## å端修æ¹ç¹ ### 1. éå®å°è´¦å表 â å¢å 审æ¹ç¶æå ```html <el-table-column label="审æ¹ç¶æ" prop="approvalStatus" width="100"> <template slot-scope="scope"> <el-tag v-if="scope.row.approvalStatus === 0" type="info">å¾ å®¡æ¹</el-tag> <el-tag v-else-if="scope.row.approvalStatus === 1" type="warning">审æ¹ä¸</el-tag> <el-tag v-else-if="scope.row.approvalStatus === 2" type="success">å·²éè¿</el-tag> <el-tag v-else-if="scope.row.approvalStatus === 3" type="danger">已驳å</el-tag> </template> </el-table-column> ``` ### 2. éå®å°è´¦è¯¦æ â å±ç¤ºå®¡æ¹ç¶æ ```html <el-form-item label="审æ¹ç¶æ"> <el-tag v-if="form.approvalStatus === 0" type="info">å¾ å®¡æ¹</el-tag> <el-tag v-else-if="form.approvalStatus === 1" type="warning">审æ¹ä¸</el-tag> <el-tag v-else-if="form.approvalStatus === 2" type="success">å·²éè¿</el-tag> <el-tag v-else-if="form.approvalStatus === 3" type="danger">已驳å</el-tag> </el-form-item> ``` ### 3. ç产主计åå表 â å¢å 审æ¹ç¶æå ```html <el-table-column label="审æ¹ç¶æ" prop="approvalStatus" width="100"> <template slot-scope="scope"> <el-tag v-if="scope.row.approvalStatus === 2" type="success">å·²éè¿</el-tag> <el-tag v-else-if="scope.row.approvalStatus === 3" type="danger">已驳å</el-tag> <el-tag v-else type="info">-</el-tag> </template> </el-table-column> ``` ### 4. å®¡æ¹æ¨¡æ¿é ç½® å¨**åå审æ¹ç®¡ç > å®¡æ¹æ¨¡æ¿**页é¢ï¼æ°å¢æ¨¡æ¿æ¶ï¼ - **ä¸å¡ç±»å**éæ©"éå®å®¡æ¹(19)" - é 置审æ¹èç¹ - 模æ¿é ç½®åï¼éå®å°è´¦æ°å¢æ¶èªå¨å¹é ææ°æ¨¡æ¿åèµ·å®¡æ¹ ### 5. åå审æ¹å表 审æ¹å表已èªå¨æ¯æéå®å®¡æ¹ç±»åçå±ç¤ºï¼ - å®¡æ¹æ 颿 ¼å¼ï¼`{éå®ååå·}éå®å®¡æ¹` - å表ä¸çåå·åå±ç¤ºéå®ååå· ## æ°æ®åºåæ´ æ§è¡æä»¶ï¼`doc/sql/20260613_sales_ledger_approval.sql` ```sql ALTER TABLE sales_ledger ADD COLUMN IF NOT EXISTS approval_status INT DEFAULT 0 COMMENT '审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å'; ALTER TABLE production_plan ADD COLUMN IF NOT EXISTS approval_status INT DEFAULT NULL COMMENT '审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å'; ``` ## 注æäºé¡¹ - éå®å®¡æ¹æ¨¡æ¿ä¸å¨ååå®¡æ¹æ¨¡æ¿ä¸æå表ä¸å±ç¤ºï¼ä¸éè´å®¡æ¹ãæ¥ä»·å®¡æ¹ãå货审æ¹ä¸è´ï¼ï¼éè¦å¨å®¡æ¹æ¨¡æ¿ç®¡ç页é¢åç¬é ç½® - 审æ¹éè¿åèªå¨å建ç产主计åï¼æ¥æºæ 记为"éå®"ï¼ä¸åç¶æä¸º"æªä¸å" - 审æ¹é©³ååï¼éå®å°è´¦å¯ç¼è¾éæ°æäº¤ï¼å½åçæ¬ä» æ¯ææ°å¢æ¶å起审æ¹ï¼ - å¯¼å ¥çéå®å°è´¦ä¸ä¼èªå¨å起审æ¹ï¼å¦é审æ¹éåç¬å¤ç docs/²»ºÏ¸ñ¹ÜÀíÄ£¿éÂß¼·ÖÎö.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,495 @@ # ä¸åæ ¼ç®¡çæ¨¡åé»è¾åæ ## 1. 模åå®ä½ `quality` å ä¸ç"ä¸åæ ¼ç®¡ç"æ¯ä¸ä¸ªç¬ç«çä¸å¡éç¯ï¼**æ£éª(è´¨æ£) â ä¸åæ ¼åç»è®° â ä¸åæ ¼åå¤ç â ä¸åæ ¼åå¤çå(å®¡æ¹æµ)**ãæ¤å¤è¿å 嫿£æµæ åç»´æ¤ãæ£éªæ¥åçæãè´¨éæ¥è¡¨ç»è®¡ä¸ä¸ªé å¥è½åã æ ¸å¿ç®æ ï¼ 1. è¦çåæææ£éªãè¿ç¨æ£éªãåºåæ£éªä¸ç§è´¨æ£åºæ¯ã 2. æ£éªä¸åæ ¼æ¶èªå¨ç»è®°ä¸åæ ¼åï¼æ¯æè¿å·¥/è¿ä¿®/æ¥åº/è®©æ¥æ¾è¡åç§å¤çæ¹å¼ã 3. ä¸åæ ¼åå¤çåèµ°å®¡æ¹æµç¨ï¼è稿âå¾ å®¡æ¹â审æ¹ä¸â已宿/已驳åï¼ã 4. æä¾åæ ¼çãæåº¦è¶å¿ãæ£æµææ æåçç»è®¡æ¥è¡¨ã --- ## 2. æ°æ®åºè¡¨ç»æ ### 2.1 quality_inspectï¼æ£éªè®°å½ä¸»è¡¨ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | inspect_type | INT | **å¿ å¡«**ã0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | | inspect_state | INT | 0=æªæäº¤(è稿)ï¼1=å·²æäº¤ | | check_time | DATE | æ£æµæ¥æ | | supplier | VARCHAR | ä¾åºååç§°ï¼åæææ£éªä½¿ç¨ï¼ | | customer | VARCHAR | 客æ·åç§°ï¼è¿ç¨/åºåæ£éªä½¿ç¨ï¼ | | process | VARCHAR | å·¥åº/é¨ä»¶ç±»åï¼è¿ç¨æ£éªä½¿ç¨ï¼ | | process_type | INT | å·¥åºç±»åï¼éå¹é æ°æ®åå ¸ `product_process_type` | | check_name | VARCHAR | æ£éªå | | product_id | BIGINT | **å¿ å¡«**ãå ³è产åID | | product_name | VARCHAR | 产ååç§° | | model | VARCHAR | è§æ ¼åå· | | unit | VARCHAR | åä½ | | quantity | DECIMAL | æ»æ°é | | qualified_quantity | DECIMAL | åæ ¼æ°é | | unqualified_quantity | DECIMAL | ä¸åæ ¼æ°é | | check_company | VARCHAR | æ£æµåä½ | | check_result | VARCHAR | æ£æµç»æï¼"åæ ¼"/"ä¸åæ ¼"ï¼ | | defective_phenomena | VARCHAR | ä¸åæ ¼ç°è±¡æè¿° | | product_main_id | BIGINT | å ³èæ¥å·¥IDï¼è¿ç¨/åºåæ£éªä½¿ç¨ï¼ | | product_model_id | BIGINT | å ³è产ååå·ID | | purchase_ledger_id | BIGINT | å ³èéè´å°è´¦IDï¼åæææ£éªä½¿ç¨ï¼ | | test_standard_id | BIGINT | å ³èæ£æµæ å主表ID | | create_time | DATETIME | å建æ¶é´ï¼èªå¨å¡«å ï¼ | | create_user | INT | åå»ºç¨æ·ï¼èªå¨å¡«å ï¼ | | update_time | DATETIME | ä¿®æ¹æ¶é´ï¼èªå¨å¡«å ï¼ | | update_user | INT | ä¿®æ¹ç¨æ·ï¼èªå¨å¡«å ï¼ | | tenant_id | BIGINT | ç§æ·IDï¼èªå¨å¡«å ï¼ | | dept_id | BIGINT | é¨é¨IDï¼èªå¨å¡«å ï¼ | ### 2.2 quality_inspect_paramï¼æ£éªåæ°æç»ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | parameter_item | VARCHAR | æ£æµææ åç§° | | unit | VARCHAR | åä½ | | standard_value | VARCHAR | æ åå¼ | | control_value | VARCHAR | å æ§å¼ | | test_value | VARCHAR | æ£éªå¼ | | inspect_id | BIGINT | **å¿ å¡«**ãå ³è quality_inspect.id | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | > 䏿¡æ£éªè®°å½ (quality_inspect) 坹夿¡æ£éªåæ° (quality_inspect_param)ã ### 2.3 quality_inspect_fileï¼æ£éªéä»¶ï¼â ï¸ **å·²åºå¼** > **æ¤è¡¨å·²åºå¼**ï¼éä»¶ä½ç³»æ¹ä¸ºä½¿ç¨ç³»ç»ç»ä¸ç `storage_attachment` 表ï¼éè¿ `record_type='quality_inspect'` + `record_id` å ³èã > æ°æ®è¿ç§» SQLï¼`doc/sql/20260613_quality_attachment_optimize.sql` > å端èè°ææ¡£ï¼`docs/quality_attachment_optimize.md` | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | name | VARCHAR | æä»¶åç§° | | url | VARCHAR | æä»¶è·¯å¾ | | file_size | INT | æä»¶å¤§å° | | inspect_id | BIGINT | **å¿ å¡«**ãå ³è quality_inspect.id | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | ### 2.4 quality_unqualifiedï¼ä¸åæ ¼åè®°å½ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | inspect_type | INT | **å¿ å¡«**ã0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | | inspect_state | INT | **å¿ å¡«**ã0=å¾ å¤çï¼1=å·²å¤ç | | check_time | DATE | æ£æµæ¥æ | | check_name | VARCHAR | æ£éªå | | product_id | BIGINT | å ³è产åID | | product_name | VARCHAR | 产ååç§° | | model | VARCHAR | è§æ ¼åå·ï¼åå¨çå¯è½æ¯ product_model.id æç´æ¥ææ¬ï¼ | | unit | VARCHAR | åä½ | | quantity | DECIMAL | æ°é | | defective_phenomena | VARCHAR | ä¸åæ ¼ç°è±¡ | | deal_result | VARCHAR | å¤çç»æï¼**"è¿ä¿®"/"è¿å·¥"/"æ¥åº"/"è®©æ¥æ¾è¡"** | | deal_name | VARCHAR | å¤ç人 | | deal_time | DATE | å¤çæ¥æ | | reason_analysis | VARCHAR | åå åæ | | preventive_corrective | VARCHAR | é¢é²ä¸çº æ£æªæ½ | | loss_working | VARCHAR | å·¥æ¶æå¤± | | loss_material | VARCHAR | ææè´¹æå¤± | | inspect_id | BIGINT | å ³è quality_inspect.idï¼å¦ææ¯æ£éªä¸åæ ¼èªå¨çæï¼ | | product_model_id | BIGINT | å ³è产ååå·ID | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | | storage_blob_dtos (èæ) | List\<StorageBlobDTO\> | éä»¶ä¸ä¼ åæ°ï¼`@TableField(exist=false)`ï¼ï¼æ¿ä»£æ§ç temp_file_ids | | storage_blob_vos (èæ) | List\<StorageBlobVO\> | éä»¶æ¥è¯¢åæ¾ï¼`@TableField(exist=false)`ï¼ï¼æ¿ä»£æ§ç common_file_list | | method (èæ) | Boolean | æ è¯æ¯å¦ä¸åæ ¼å¤çèªå·±æ°å¢ï¼`@TableField(exist=false)`ï¼ | ### 2.5 quality_unqualified_orderï¼ä¸åæ ¼åå¤çåï¼ > **å·²å®ç°**ãSQLï¼`doc/sql/20260613_quality_module_completion.sql`ï¼åç«¯ææ¡£ï¼`docs/quality_unqualified_order.md` | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | order_no | VARCHAR | å¤çåç¼å·ï¼åç¼ "BHG"+ æ¥æ + åºå·ï¼èªå¨çæ | | unqualified_id | BIGINT | å ³è quality_unqualified.id | | project_name | VARCHAR | 项ç®åç§° | | project_no | VARCHAR | 项ç®ç¼å· | | equipment_id | BIGINT | å ³è设å¤ID | | equipment_name | VARCHAR | 设å¤åç§° | | equipment_drawing_no | VARCHAR | 设å¤å¾å· | | material_name | VARCHAR | ç©æ/é¨ä»¶åç§° | | product_model_id | BIGINT | å ³è产ååå·ID | | material_drawing_no | VARCHAR | ç©æå¾å· | | specification_model | VARCHAR | åå·è§æ ¼ | | material_quality | VARCHAR | æè´¨ | | quantity | DECIMAL | æ»æ°é | | unqualified_quantity | DECIMAL | ä¸åæ ¼æ°é | | unqualified_process | TINYINT | ä¸åæ ¼å·¥åºï¼1=æ¥æï¼2=å¶ç¨ï¼3=æå | | supplier_name | VARCHAR | ä¾åºååç§° | | inspector_name | VARCHAR | æ£éªå | | inspect_date | DATE | æ£éªæ¥æ | | responsible_person | VARCHAR | 责任人 | | responsible_dept | VARCHAR | 责任é¨é¨ | | problem_description | VARCHAR | é®é¢æè¿° | | reason_analysis | VARCHAR | åå åæå建议 | | correction_action | VARCHAR | çº æ£æªæ½ | | disposal_method | TINYINT | å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶ï¼2=åå ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åº | | repair_evaluation | VARCHAR | åå /è¿åç»´ä¿®è¯ä¼° | | preventive_action | VARCHAR | é¢é²æªæ½ | | status | TINYINT | ç¶æï¼0=è稿ï¼1=å¾ å®¡æ¹ï¼2=审æ¹ä¸ï¼3=已宿ï¼4=已驳å | | remark | VARCHAR | 夿³¨ | | create_by / update_by / create_time / update_time / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | | deleted | TINYINT | é»è¾å é¤ï¼0=å¦ï¼1=æ¯ | ### 2.6 quality_test_standardï¼æ£æµæ åä¸»è¡¨ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | standard_no | VARCHAR | æ åç¼å· | | standard_name | VARCHAR | æ ååç§° | | state | VARCHAR | ç¶æ | | remark | VARCHAR | 夿³¨ | | inspect_type | INT | ç±»å«ï¼0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | | process_id | INT | å·¥åºID | | process_type | INT | å·¥åºç±»å | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | ### 2.7 quality_test_standard_paramï¼æ£æµæ ååæ°ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | BIGINT | 主é®ï¼èªå¢ | | parameter_item | VARCHAR | åæ°é¡¹ï¼ææ åç§°ï¼ | | unit | VARCHAR | åä½ | | standard_value | VARCHAR | æ åå¼ | | control_value | VARCHAR | å æ§å¼ | | default_value | VARCHAR | é»è®¤å¼ | | test_standard_id | BIGINT | å ³è quality_test_standard.id | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | ### 2.8 quality_test_standard_bindingï¼æ£æµæ å-产åå ³èï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | id | INT | 主é®ï¼èªå¢ | | product_id | BIGINT | 产åID | | test_standard_id | INT | å ³è quality_test_standard.id | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | > å¤å¯¹å¤å ³ç³»ï¼ä¸ä¸ªäº§åå¯ç»å®å¤ä¸ªæ£æµæ åï¼ä¸ä¸ªæ£æµæ åå¯ç¨äºå¤ä¸ªäº§åã --- ## 3. æ ¸å¿ä¸å¡æµç¨ ### 3.1 è´¨æ£å®æ´é¾è·¯ ``` æ£æµæ åç»´æ¤ â å建æ£éªå â 填忣éªåæ° â æäº¤æ£éª â ââââââââââââââââ´âââââââââââââââ â â ç»æ=ä¸åæ ¼ ç»æ=åæ ¼ â â èªå¨çæä¸åæ ¼åè®°å½ èªå¨åæ ¼å ¥åº (quality_unqualified) (è°ç¨ StockUtils) â ä¸åæ ¼åå¤ç(deal) â âââââââââ¬âââââââââ¼âââââââââ â â â â è¿ä¿® è¿å·¥ æ¥åº è®©æ¥æ¾è¡ (è¿ç¨/åºå) (å ¨é¨ç±»å) â â â â å éç产 å éç产 å ¥ä¸åæ ¼åº å ¥åæ ¼åº 订å+路线 åä¸ (unqualified (qualified +å·¥å stock) stock) â ä¸åæ ¼åå¤çå(approval flow) è稿 â å¾ å®¡æ¹ â 审æ¹ä¸ â 已宿/已驳å ``` ### 3.2 æ£éªæäº¤é»è¾ï¼QualityInspectServiceImpl.submitï¼ 1. æ ¡éª `checkResult` ä¸è½ä¸ºç©ºã 2. 妿 `checkResult = "ä¸åæ ¼"`ï¼ - èªå¨åå»ºä¸æ¡ `quality_unqualified` è®°å½ï¼`inspect_state=0`ï¼å¾ å¤çï¼ã - ä¸åæ ¼ç°è±¡èªå¨çæä¸ºï¼æææ£éªåæ°åç§°æ¼æ¥ + "è¿äºææ ä¸åå¨ä¸åæ ¼"ã 3. 妿 `checkResult = "åæ ¼"`ï¼ - è°ç¨ `StockUtils.addStock()` ç´æ¥å ¥åºï¼å ¥åºç±»å `QUALITYINSPECT_STOCK_IN`ï¼ã 4. å°æ£éªå `inspect_state` æ´æ°ä¸º 1ï¼å·²æäº¤ï¼ã ### 3.3 ä¸åæ ¼åå¤çé»è¾ï¼QualityUnqualifiedServiceImpl.dealï¼ æ ¸å¿åæ°ï¼`dealResult` å³å®å¤çè·¯å¾ï¼åä¸ºä¸¤å¤§åæ¯ã #### 忝Aï¼è¿ç¨æ£éª/åºåæ£éªï¼inspectType != 0 䏿 productMainIdï¼ | dealResult | å¤çé»è¾ | |------------|----------| | **"è¿ä¿®"æ"è¿å·¥"** | 1. æ ¹æ® `productMainId` æ¥å°åå§ç产订å(ProductOrder)ãå·¥èºè·¯çº¿ä¸»è¡¨(ProductProcessRoute)ãå·¥èºè·¯çº¿å表(ProductProcessRouteItem) | | | 2. å éä¸ä»½æ°çç产订åï¼quantity=ä¸åæ ¼æ°éï¼completeQuantity=0ï¼æ¶é´æ¸ ç©ºï¼ | | | 3. å éä¸ä»½æ°çå·¥èºè·¯çº¿ä¸»è¡¨ï¼å ³èæ°è®¢åï¼ | | | 4. éæ¡å éå·¥èºè·¯çº¿åè¡¨ï¼æ¯æ¡å éåèªå¨çæå¯¹åºå·¥å(ProductWorkOrder)ï¼å·¥åå·è§å `"FG" + yyyyMMdd + 3ä½èªå¢åºå·` | | **"æ¥åº"** | è°ç¨ `StockUtils.addUnStock()` å ¥ä¸åæ ¼åºï¼ç±»å `DEFECTIVE_SCRAP`ï¼ | | **"è®©æ¥æ¾è¡"** | è°ç¨ `StockUtils.addStock()` å ¥åæ ¼åºï¼ç±»å `DEFECTIVE_PASS`ï¼ | #### 忝Bï¼åæææ£éªï¼inspectType == 0ï¼ | dealResult | å¤çé»è¾ | |------------|----------| | **"æ¥åº"** | å éè¿ productName + model æ¥ product_model.idï¼åè°ç¨ `StockUtils.addUnStock()` å ¥ä¸åæ ¼åº | | **"è®©æ¥æ¾è¡"** | å䏿¥æ¾ modelIdï¼åè°ç¨ `StockUtils.addStock()` å ¥åæ ¼åº | | **"è¿ä¿®"/"è¿å·¥"** | åæææ£éªä¸æ¯æè¿ä¿®/è¿å·¥ï¼ä»£ç 䏿 æ¤åæ¯ï¼ä¸æ§è¡ä»»ä½æä½ï¼ | > å ³é®å¤æé»è¾ä½äº `QualityUnqualifiedServiceImpl.java:81`ï¼ > ```java > if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) > ``` > åªæå ³èäºæ£éªå䏿£éªç±»å䏿¯åææ(0)æ¶ï¼æèµ°è¿ç¨/åºåçå¤ç忝ï¼å å«è¿ä¿®/è¿å·¥é»è¾ï¼ã å¤ç宿åå° `inspect_state` 置为 1ï¼å·²å¤çï¼ã ### 3.4 ä¸åæ ¼åå¤çåæµç¨ï¼QualityUnqualifiedOrderï¼ å¤ç忝坹ä¸åæ ¼åçæ£å¼å¤ç½®è®°å½ï¼å 嫿´ä¸°å¯çåæ®µå审æ¹ç¶ææºï¼ ``` è稿(0) â å¾ å®¡æ¹(1) â 审æ¹ä¸(2) â 已宿(3) â â å¯ç¼è¾/å é¤ å·²é©³å(4) ``` - **ç¼å·èªå¨çæ**ï¼åç¼ `"BHG"` + 彿¥èªå¢åºå·ï¼éè¿ `OrderUtils.countTodayByCreateTime` å®ç°ï¼ã - **å¤ç½®æ¹å¼æä¸¾**ï¼1=è®©æ¥æ¥æ¶ï¼2=åå ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åºã - **å页æ¥è¯¢**ï¼æ¯ææ statusãprojectNameãorderNo çéã - **CRUD**ï¼æ¯ææ°å¢ãä¿®æ¹ãå é¤ï¼é»è¾å é¤éè¿ deleted åæ®µï¼ã ### 3.5 æ£éªåå é¤é»è¾ï¼QualityInspectController.delï¼ 1. æ ¡éªæ¯å¦å·²æäº¤ï¼`inspectState==1` ä¸å 许å é¤ï¼ã 2. 级èå é¤å ³èçæ£éªåæ° (quality_inspect_param)ã 3. 级èå é¤å ³èçæ£éªéä»¶ (quality_inspect_file)ã 4. å 餿£éªåæ¬èº«ã ### 3.6 ä¸åæ ¼åå é¤é»è¾ï¼QualityUnqualifiedController.delï¼ 1. æ ¡éªæ¯å¦å·²å¤çï¼`inspectState==1` ä¸å 许å é¤ï¼ã 2. 级èå é¤å ³èéä»¶ï¼éè¿ commonFileService æ businessId + type å é¤ï¼ã 3. æ¹éå é¤ä¸åæ ¼åè®°å½ã ### 3.7 æ£æµæ åç»´æ¤ - æ£æµæ å主表 (quality_test_standard) ç»´æ¤æ åç¼å·ãåç§°ãéç¨æ£éªç±»åãå·¥åºç±»åã - æ£æµæ ååæ° (quality_test_standard_param) ç»´æ¤ææ ãåä½ãæ åå¼ãå æ§å¼ãé»è®¤å¼ã - æ£æµæ å-产åç»å® (quality_test_standard_binding) å®ç°å¤å¯¹å¤å ³èã - **å é¤ä¿æ¤**ï¼å 餿£æµæ åå伿£æ¥æ¯å¦è¢«æ£éªåå¼ç¨ï¼å¼ç¨åç¦æ¢å é¤ã - **åæ°å¤å¶**ï¼æ¯æ `copyParam` å°æä¸ªæ åçåæ°å¤å¶å°å¦ä¸ä¸ªæ åã - **å®¡æ ¸**ï¼æä¾ `qualityTestStandardAudit` æ¥å£ã --- ## 4. API æ¥å£æ»è§ ### 4.1 æ£éªè®°å½ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/quality/qualityInspect/add` | æ°å¢æ£éªåï¼å«æ£éªåæ°ï¼ | | DELETE | `/quality/qualityInspect/del` | æ¹éå 餿£éªåï¼çº§èå é¤åæ°åéä»¶ï¼ | | GET | `/quality/qualityInspect/{id}` | æ¥ç详æ ï¼å«æ£éªåæ°ï¼ | | POST | `/quality/qualityInspect/update` | ä¿®æ¹æ£éªåï¼å å æ§åæ°åææ°åæ°ï¼ | | GET | `/quality/qualityInspect/listPage` | å页æ¥è¯¢ï¼æç±»å JOIN ä¸åä¸å¡è¡¨ï¼ | | POST | `/quality/qualityInspect/export` | å¯¼åº Excelï¼ä¸åç±»åéèä¸ååï¼ | | POST | `/quality/qualityInspect/submit` | æäº¤æ£éªï¼åæ ¼å ¥åº/ä¸åæ ¼ç»è®°ï¼ | | POST | `/quality/qualityInspect/down` | ä¸è½½ Word æ£éªæ¥åï¼poi-tl æ¨¡æ¿æ¸²æï¼ | ### 4.2 ä¸åæ ¼å管ç | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/quality/qualityUnqualified/add` | æ°å¢ä¸åæ ¼åï¼æå·¥å½å ¥ï¼ç¶æ=å¾ å¤çï¼ | | DELETE | `/quality/qualityUnqualified/del` | æ¹éå é¤ï¼å·²å¤çä¸å¯å ï¼ | | GET | `/quality/qualityUnqualified/{id}` | 详æ ï¼å«éä»¶åè¡¨ï¼ | | POST | `/quality/qualityUnqualified/update` | ä¿®æ¹ä¸åæ ¼å | | GET | `/quality/qualityUnqualified/listPage` | å页æ¥è¯¢ï¼æç±»åãç¶æã产ååãæ¥æçéï¼ | | POST | `/quality/qualityUnqualified/export` | å¯¼åº Excel | | POST | `/quality/qualityUnqualified/deal` | **å¤çä¸åæ ¼å**ï¼è¿ä¿®/è¿å·¥/æ¥åº/è®©æ¥æ¾è¡ï¼ | ### 4.3 ä¸åæ ¼åå¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/qualityUnqualifiedOrder/listPage` | å页æ¥è¯¢ï¼æ¯æ status/projectName/orderNo çéï¼ | | POST | `/qualityUnqualifiedOrder/save` | æ°å¢ï¼èªå¨çæç¼å·ï¼ | | PUT | `/qualityUnqualifiedOrder/update` | ä¿®æ¹ | | DELETE | `/qualityUnqualifiedOrder/delete` | æ¹éå é¤ | ### 4.4 æ£æµæ å | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/qualityTestStandard/add` | æ°å¢æ£æµæ å | | DELETE | `/qualityTestStandard/del` | å é¤ï¼æå¼ç¨æ¶ç¦æ¢ï¼ | | POST | `/qualityTestStandard/update` | ä¿®æ¹ | | GET | `/qualityTestStandard/listPage` | å页æ¥è¯¢ | | POST | `/qualityTestStandard/copyParam` | å¤å¶åæ°å°å¦ä¸ä¸ªæ å | | POST | `/qualityTestStandard/qualityTestStandardAudit` | å®¡æ ¸æ£æµæ å | | GET | `/qualityTestStandard/getQualityTestStandardByProductId` | æäº§åIDè·åæ åï¼éè¿ç»å®è¡¨ JOINï¼ | | GET | `/qualityTestStandard/getQualityTestStandardParamByTestStandardId` | ææ åIDè·ååæ°å表 | ### 4.5 æ£æµæ åç»å® | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/qualityTestStandardBinding/add` | æ°å¢ç»å® | | DELETE | `/qualityTestStandardBinding/del` | å é¤ç»å® | | GET | `/qualityTestStandardBinding/list` | æ¥è¯¢ç»å®å表 | ### 4.6 æ£æµæ ååæ° | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/qualityTestStandardParam/add` | æ°å¢åæ° | | DELETE | `/qualityTestStandardParam/del` | å é¤åæ° | | POST | `/qualityTestStandardParam/update` | ä¿®æ¹åæ° | | GET | `/qualityTestStandardParam/list` | æ¥è¯¢åæ°å表 | ### 4.7 æ£éªåæ° | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/quality/qualityInspectParam/{inspectId}` | ææ£éªIDæ¥åæ°å表 | | POST | `/quality/qualityInspectParam/update` | ä¿®æ¹åæ° | | DELETE | `/quality/qualityInspectParam/del` | å é¤åæ° | ### 4.8 æ£éªéä»¶ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/quality/qualityInspectFile/add` | æ°å¢éä»¶ | | DELETE | `/quality/qualityInspectFile/del` | å é¤éä»¶ | | GET | `/quality/qualityInspectFile/listPage` | å页æ¥è¯¢ | ### 4.9 è´¨éæ¥è¡¨ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/qualityReport/getInspectStatistics` | æ£éªç»è®¡ï¼æåææ/åæå/æååç»çæ»æ°å宿æ°ï¼ | | GET | `/qualityReport/getPassRateStatistics` | åæ ¼çç»è®¡ï¼æææ±æ»ï¼æ»æ°ã宿æ°ãåæ ¼æ°ãä¸åæ ¼æ°ã宿çãåæ ¼çï¼ | | GET | `/qualityReport/getMonthlyPassRateStatistics` | æåº¦åæ ¼çï¼12个æ à 3ç±»ï¼CTEéå½ï¼ | | GET | `/qualityReport/getYearlyPassRateStatistics` | å¹´åº¦åæ ¼ç | | GET | `/qualityReport/getMonthlyCompletionDetails` | æåº¦å®ææç»ï¼æ¯æåææ/åæå/æå宿æ°ï¼ | | GET | `/qualityReport/getTopParameters` | æ£æµææ æåï¼Top 4 + å ¶ä»æ±æ»ï¼ | --- ## 5. å ³é®æ°æ®å ³è ``` product (产ååç±») âââ product (å ·ä½äº§å) âââ product_model (产ååå·) âââ quality_inspect.product_model_id âââ quality_unqualified (éè¿ model åæ®µå ³è) âââ quality_test_standard_binding.product_id production_product_main (ç产æ¥å·¥) âââ quality_inspect.product_main_id (è¿ç¨/åºåæ£éª) âââ production_product_main.work_order_id â product_work_order âââ product_order â sales_ledger (éå®å°è´¦) purchase_ledger (éè´å°è´¦) âââ quality_inspect.purchase_ledger_id (åæææ£éª) product_process_route (å·¥èºè·¯çº¿ä¸»è¡¨) âââ product_process_route_item (å·¥èºè·¯çº¿å表) âââ product_work_order (å·¥å) ``` ### å页æ¥è¯¢æ¶ JOIN çç¥ - **åæææ£éª (inspectType=0)**ï¼LEFT JOIN `purchase_ledger` è·åéè´ååå·ã - **è¿ç¨/åºåæ£éª (inspectType != 0)**ï¼LEFT JOIN `production_product_main` â `product_work_order` â `product_order` â `sales_ledger` è·åå·¥åå·åéå®ååå·ã - **ä¸åæ ¼åå表**ï¼LEFT JOIN `product_model` è§£æåå·ï¼model åæ®µå¯è½æ¯ ID æææ¬ï¼ã --- ## 6. ä¸å¤é¨æ¨¡åçäº¤äº | 交äºç¹ | è°ç¨æ¹å¼ | 说æ | |--------|----------|------| | åºå管ç (stock) | `StockUtils.addStock()` / `StockUtils.addUnStock()` | åæ ¼å ¥åº / ä¸åæ ¼å ¥åº | | ç产管ç (production) | ç´æ¥æä½ Mapper | è¿å·¥/è¿ä¿®æ¶å éç产订å+å·¥èºè·¯çº¿+å·¥å | | é件管ç (commonFile) | `CommonFileService` / `TempFileService` | ä¸´æ¶æä»¶è½¬æ£å¼æä»¶ãæä¸å¡ID+ç±»åæ¥è¯¢å é¤ | | æ°æ®åå ¸ (dict) | `DictUtils` | processType æ ¡éªï¼å¯¼åºæ¶ translate | | éè´å°è´¦ (procurement) | `ProcurementRecordService` | åæææ£éªå ³èéè´è®°å½ | --- ## 7. æä¸¾å¼æ±æ» ### inspectTypeï¼æ£éªç±»å«ï¼ | å¼ | å«ä¹ | |----|------| | 0 | åæææ£éª | | 1 | è¿ç¨æ£éª | | 2 | åºåæ£éª | ### inspectStateï¼æ£éªåç¶æ / ä¸åæ ¼åç¶æï¼ | å¼ | å«ä¹ï¼æ£éªåï¼ | å«ä¹ï¼ä¸åæ ¼åï¼ | |----|---------------|------------------| | 0 | æªæäº¤(è稿) | å¾ å¤ç | | 1 | å·²æäº¤ | å·²å¤ç | ### dealResultï¼ä¸åæ ¼åå¤çç»æï¼ | å¼ | å«ä¹ | éç¨åºæ¯ | |----|------|----------| | è¿ä¿® | è¿ä¿®å¤ç | ä» è¿ç¨/åºåæ£éª | | è¿å·¥ | è¿å·¥å¤çï¼é建ç产订åï¼ | ä» è¿ç¨/åºåæ£éª | | æ¥åº | å ¥ä¸åæ ¼åº | å ¨é¨ç±»å | | è®©æ¥æ¾è¡ | å ¥åæ ¼åº | å ¨é¨ç±»å | ### disposalMethodï¼å¤çåå¤ç½®æ¹å¼ï¼ | å¼ | å«ä¹ | |----|------| | 1 | è®©æ¥æ¥æ¶ | | 2 | åå ç»´ä¿® | | 3 | è¿åç»´ä¿® | | 4 | æ¢è´§ | | 5 | éè´§ | | 6 | æ¥åº | ### unqualifiedProcessï¼ä¸åæ ¼å·¥åºï¼ | å¼ | å«ä¹ | |----|------| | 1 | æ¥æ | | 2 | å¶ç¨ | | 3 | æå | ### statusï¼å¤çåç¶æï¼ | å¼ | å«ä¹ | |----|------| | 0 | è稿 | | 1 | å¾ å®¡æ¹ | | 2 | 审æ¹ä¸ | | 3 | 已宿 | | 4 | 已驳å | --- ## 8. ææ¯å®ç°è¦ç¹ 1. **MyBatis-Plus èªå¨å¡«å **ï¼create_timeãcreate_userãupdate_timeãupdate_userãtenant_idãdept_id åéè¿ `@TableField(fill = ...)` èªå¨å¡«å ã 2. **äºå¡ç®¡ç**ï¼`QualityInspectServiceImpl` æ æ³¨ `@Transactional(rollbackFor = Exception.class)`ï¼ç¡®ä¿æ°å¢/ä¿®æ¹æ£éªåä¸åæ°æä½çååæ§ã 3. **Word æ¥åçæ**ï¼ä½¿ç¨ poi-tl 模æ¿å¼æï¼æ¨¡æ¿æä»¶ `/static/report-template.docx`ï¼éè¿ `HackLoopTableRenderPolicy` 渲æåæ°åè¡¨è¡¨æ ¼ã 4. **Excel 导åºå¨æå**ï¼æ ¹æ® inspectType 卿éèä¸ç¸å ³åï¼åæææ£éªéè customer/processï¼åºåæ£éªéè supplier/customer/processï¼ã 5. **æåº¦ç»è®¡ CTE**ï¼`getMonthlyPassRateStatistics` ä½¿ç¨ MySQL WITH RECURSIVE çæ 1-12 æåºåï¼CROSS JOIN 3 ç§äº§åç±»åï¼LEFT JOIN å®é æ°æ®ï¼ç¡®ä¿æ¯ææ¯ç±»åé½ææ°æ®è¡ã 6. **ä¸åæ ¼å model åæ®µå ¼å®¹**ï¼model åæ®µå¯è½åå¨ product_model.idï¼æ°åï¼æç´æ¥ææ¬ï¼æ¥è¯¢æ¶ LEFT JOIN product_model å°è¯è§£æï¼å¹¶ç¨ method åæ®µæ è®°ã 7. **è¿å·¥å·¥åå·çæ**ï¼æ¥æåç¼ `yyyyMMdd` + 3 ä½èªå¢åºå·ï¼åç¼ `"FG"`ï¼éè¿æ¥è¯¢å½æ¥æå¤§å·¥åå·å®ç°èªå¢ã 8. **æä»¶ç®¡ç**ï¼åç«¯ä¼ tempFileIdsï¼å端éè¿ `TempFileService.migrateTempFilesToFormal()` å°ä¸´æ¶æä»¶è½¬ä¸ºæ£å¼æä»¶å¹¶ç»å®å°ä¸å¡IDã src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
@@ -126,7 +126,7 @@ private Long tenantId; /** * 审æ¹ç±»å 1-å ¬åºç®¡ç 2-请å管ç 3-åºå·®ç®¡ç 4-æ¥é管ç 5-éè´å®¡æ¹ 6-æ¥ä»·å®¡æ¹ 7-åè´§å®¡æ¹ 8-å±é©ä½ä¸å®¡æ¹ * 审æ¹ç±»å 1-å ¬åºç®¡ç 2-请å管ç 3-åºå·®ç®¡ç 4-æ¥é管ç 5-éè´å®¡æ¹ 6-æ¥ä»·å®¡æ¹ 7-åè´§å®¡æ¹ 8-å±é©ä½ä¸å®¡æ¹ 9-åå ¬ç¨åå®¡æ¹ 19-éå®å®¡æ¹ */ private Integer approveType; src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -39,13 +39,18 @@ import com.ruoyi.project.system.service.ISysNoticeService; import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.production.mapper.ProductionPlanMapper; import com.ruoyi.production.pojo.ProductionPlan; import com.ruoyi.quality.utils.QualityInspectHelper; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.mapper.SalesQuotationMapper; import com.ruoyi.sales.mapper.ShippingInfoMapper; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.pojo.SalesQuotation; import com.ruoyi.sales.pojo.ShippingInfo; import com.ruoyi.sales.service.impl.SalesLedgerProductServiceImpl; import com.ruoyi.staff.mapper.HolidayApplicationMapper; import com.ruoyi.staff.pojo.HolidayApplication; import lombok.RequiredArgsConstructor; @@ -84,6 +89,9 @@ private final SalesLedgerProductMapper salesLedgerProductMapper; private final StockUtils stockUtils; private final SalesQuotationMapper salesQuotationMapper; private final SalesLedgerMapper salesLedgerMapper; private final SalesLedgerProductServiceImpl salesLedgerProductService; private final ProductionPlanMapper productionPlanMapper; private final ShippingInfoMapper shippingInfoMapper; private final QualityInspectHelper qualityInspectHelper; private final EnterpriseNewsScopeUserMapper enterpriseNewsScopeUserMapper; @@ -126,6 +134,12 @@ ShippingInfo shippingInfo = shippingInfoMapper.selectById(vo.getBusinessId()); if (shippingInfo != null) { vo.setShippingNo(shippingInfo.getShippingNo()); } } else if (TypeEnums.SALES_LEDGER_APPROVAL.getCode().equals(vo.getBusinessType())) { // éå®å®¡æ¹ - æ¥è¯¢éå®ååå· SalesLedger salesLedger = salesLedgerMapper.selectById(vo.getBusinessId()); if (salesLedger != null) { vo.setQuotationNo(salesLedger.getSalesContractNo()); } } } @@ -550,6 +564,10 @@ } if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) { handleNewsApprovalFinished(instance, status); return; } if (TypeEnums.SALES_LEDGER_APPROVAL.getCode().equals(businessType)) { handleSalesLedgerApprovalFinished(instance, status); } } @@ -667,6 +685,36 @@ salesQuotationMapper.updateById(salesQuote); } private void handleSalesLedgerApprovalFinished(ApprovalInstance instance, String status) { SalesLedger salesLedger = salesLedgerMapper.selectById(instance.getBusinessId()); if (salesLedger == null) { return; } if ("APPROVED".equals(status)) { salesLedger.setApprovalStatus(2); salesLedgerMapper.updateById(salesLedger); // 审æ¹éè¿åå建ç产主计å createProductionPlansForApproved(salesLedger); } else if ("REJECTED".equals(status)) { salesLedger.setApprovalStatus(3); salesLedgerMapper.updateById(salesLedger); } else if ("PENDING".equals(status)) { salesLedger.setApprovalStatus(1); salesLedgerMapper.updateById(salesLedger); } } private void createProductionPlansForApproved(SalesLedger salesLedger) { List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList( new LambdaQueryWrapper<SalesLedgerProduct>() .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId()) .eq(SalesLedgerProduct::getIsProduction, true) ); for (SalesLedgerProduct product : products) { salesLedgerProductService.addProductionDataForApproved(product, 2); } } private void handleShippingApprovalFinished(ApprovalInstance instance, String status) { ShippingInfo shippingInfo = shippingInfoMapper.selectOne( new LambdaQueryWrapper<ShippingInfo>() src/main/java/com/ruoyi/approve/service/impl/ApprovalTemplateServiceImpl.java
@@ -128,7 +128,7 @@ new LambdaQueryWrapper<ApprovalTemplate>() .eq(ApprovalTemplate::getDeleted, 0) .eq(ApprovalTemplate::getEnabled, 1) .notIn(ApprovalTemplate::getBusinessType, List.of(5L, 6L, 7L)) .notIn(ApprovalTemplate::getBusinessType, List.of(5L, 6L, 7L, 19L)) .orderByDesc(ApprovalTemplate::getTemplateType) .orderByDesc(ApprovalTemplate::getId) ); src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -458,6 +458,8 @@ return "å±é©ä½ä¸å®¡æ¹"; case 9: return "åå ¬ç¨å审æ¹"; case 19: return "éå®å®¡æ¹"; } return null; } src/main/java/com/ruoyi/basic/controller/CustomerController.java
@@ -152,4 +152,14 @@ public R back(@PathVariable("id") Long id) { return R.ok(customerService.back(id)); } /** * 客æ·äº¤æ¥ï¼è½¬ç§»ç§æµ·å®¢æ·ç»´æ¤äºº */ @Log(title = "客æ·äº¤æ¥", businessType = BusinessType.UPDATE) @PostMapping("/handover") public R handover(@RequestBody CustomerDto customer) { customerService.handoverCustomer(customer); return R.ok(); } } src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java
@@ -8,11 +8,14 @@ import com.ruoyi.basic.pojo.CustomerReturnVisit; import com.ruoyi.basic.service.CustomerFollowUpService; import com.ruoyi.basic.service.CustomerReturnVisitService; import com.ruoyi.basic.vo.CustomerFollowUpExportVo; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import io.swagger.v3.oas.annotations.Operation; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -160,4 +163,15 @@ return AjaxResult.success(); } /** * å¯¼åºæ´½è°è¿åº¦ï¼æè·è¿è®°å½å±å¼ï¼ */ @Operation(summary = "å¯¼åºæ´½è°è¿åº¦") @PostMapping("/export") @Log(title = "æ´½è°è¿åº¦-导åº", businessType = BusinessType.EXPORT) public void export(HttpServletResponse response, String customerName, String customerType) { ExcelUtil<CustomerFollowUpExportVo> util = new ExcelUtil<CustomerFollowUpExportVo>(CustomerFollowUpExportVo.class); util.exportExcel(response, customerFollowUpService.selectFollowUpExportList(customerName, customerType), "æ´½è°è¿åº¦"); } } src/main/java/com/ruoyi/basic/dto/CustomerDto.java
@@ -1,6 +1,7 @@ package com.ruoyi.basic.dto; import com.ruoyi.basic.pojo.Customer; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import lombok.Data; import lombok.EqualsAndHashCode; @@ -29,4 +30,9 @@ * å ±äº«ç¨æ·IDå表 */ private List<Long> userIds; /** * ç»´æ¤äººId */ private Integer maintainerId; } src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -76,6 +76,7 @@ SAFE_ACCIDENT("safe_accident"), // Quality QUALITY_UNQUALIFIED("quality_unqualified"), QUALITY_UNQUALIFIED_ORDER("quality_unqualified_order"), QUALITY_TEST_STANDARD_PARAM("quality_test_standard_param"), QUALITY_TEST_STANDARD_BINDING("quality_test_standard_binding"), QUALITY_TEST_STANDARD("quality_test_standard"), src/main/java/com/ruoyi/basic/mapper/CustomerFollowUpMapper.java
@@ -2,6 +2,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.basic.pojo.CustomerFollowUp; import com.ruoyi.basic.vo.CustomerFollowUpExportVo; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <br> @@ -13,4 +17,10 @@ * @since 2026/03/04 14:46 */ public interface CustomerFollowUpMapper extends BaseMapper<CustomerFollowUp> { /** * æ¥è¯¢æ´½è°è¿åº¦å¯¼åºæ°æ®ï¼å®¢æ·å ³èè·è¿è®°å½ï¼ */ List<CustomerFollowUpExportVo> selectFollowUpExportList(@Param("customerName") String customerName, @Param("customerType") String customerType); } src/main/java/com/ruoyi/basic/service/CustomerFollowUpService.java
@@ -5,6 +5,7 @@ import com.ruoyi.basic.pojo.CustomerFollowUp; import com.ruoyi.basic.dto.CustomerFollowUpFileDto; import com.ruoyi.basic.pojo.CustomerFollowUpFile; import com.ruoyi.basic.vo.CustomerFollowUpExportVo; import org.springframework.web.multipart.MultipartFile; import java.util.Collection; @@ -59,4 +60,9 @@ * è·åè·è¿è¯¦æ */ CustomerFollowUpDto getFollowUpWithFiles(Integer id); /** * æ¥è¯¢æ´½è°è¿åº¦å¯¼åºæ°æ® */ List<CustomerFollowUpExportVo> selectFollowUpExportList(String customerName, String customerType); } src/main/java/com/ruoyi/basic/service/ICustomerService.java
@@ -97,6 +97,13 @@ Boolean back(Long id); /** * 客æ·äº¤æ¥ï¼å°ç§æµ·å®¢æ·çç»´æ¤äººè½¬ç§»ç»æ°è´è´£äºº * * @param customerDto 客æ·DTOï¼å å«å®¢æ·IDåæ°ç»´æ¤äººï¼ */ void handoverCustomer(CustomerDto customerDto); /** * æ¥è¯¢å®¢æ·å¾æ¥å表 * @param page * @param customerName src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.dto.CustomerFollowUpDto; import com.ruoyi.basic.dto.CustomerFollowUpFileDto; import com.ruoyi.basic.vo.CustomerFollowUpExportVo; import com.ruoyi.basic.mapper.CustomerFollowUpMapper; import com.ruoyi.basic.pojo.CustomerFollowUp; import com.ruoyi.basic.pojo.CustomerFollowUpFile; @@ -269,4 +270,9 @@ return dto; } @Override public List<CustomerFollowUpExportVo> selectFollowUpExportList(String customerName, String customerType) { return baseMapper.selectFollowUpExportList(customerName, customerType); } } src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -431,6 +431,24 @@ } @Override public void handoverCustomer(CustomerDto customerDto) { Customer customer = customerMapper.selectById(customerDto.getId()); if (customer == null) { throw new ServiceException("客æ·ä¸åå¨"); } if (customer.getType() != 0) { throw new ServiceException("ä» ç§æµ·å®¢æ·æ¯æäº¤æ¥"); } if (customerDto.getMaintainer() == null || customerDto.getMaintainer().trim().isEmpty()) { throw new ServiceException("æ°ç»´æ¤äººä¸è½ä¸ºç©º"); } customer.setMaintainer(customerDto.getMaintainer()); customer.setMaintenanceTime(new Date()); customer.setCreateUser(customerDto.getMaintainerId()); customerMapper.updateById(customer); } @Override public IPage<CustomerTransactionsVo> customewTransactions(Page page, String customerName) { return customerMapper.customewTransactions(page, customerName); } src/main/java/com/ruoyi/basic/vo/CustomerFollowUpExportVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,49 @@ package com.ruoyi.basic.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import lombok.Data; import java.time.LocalDateTime; /** * å®¢æ·æ´½è°è¿åº¦å¯¼åºVO * æ¯è¡ä¸æ¡è·è¿è®°å½ï¼åæ¶å å«å®¢æ·åºæ¬ä¿¡æ¯ * * @author ruoyi * @date 2026-06-13 */ @Data public class CustomerFollowUpExportVo { @Excel(name = "客æ·åç§°") private String customerName; @Excel(name = "客æ·åç±»") private String customerType; @Excel(name = "è系人") private String contactPerson; @Excel(name = "èç³»çµè¯") private String contactPhone; @Excel(name = "ç»´æ¤äºº") private String maintainer; @Excel(name = "è·è¿æ¹å¼") private String followUpMethod; @Excel(name = "è·è¿ç¨åº¦") private String followUpLevel; @Excel(name = "è·è¿æ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime followUpTime; @Excel(name = "è·è¿äºº") private String followerUserName; @Excel(name = "è·è¿å 容") private String content; } src/main/java/com/ruoyi/common/enums/TypeEnums.java
@@ -24,7 +24,8 @@ OVERTIME_APPROVAL(15L, "å ç审æ¹"), TRAVEL_REIMBURSEMENT_APPROVAL(16L, "åºå·®æ¥é审æ¹"), EXPENSE_APPROVAL(17L, "è´¹ç¨å®¡æ¹"), ENTERPRISE_NEWS_APPROVAL(18L, "ä¼ä¸æ°é»å®¡æ¹"); ENTERPRISE_NEWS_APPROVAL(18L, "ä¼ä¸æ°é»å®¡æ¹"), SALES_LEDGER_APPROVAL(19L, "éå®å®¡æ¹"); src/main/java/com/ruoyi/production/pojo/ProductionPlan.java
@@ -82,4 +82,7 @@ @Schema(description = "ç¶æ 0æªä¸å 1é¨åä¸å 2å·²ä¸å") private Integer status; @Schema(description = "审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å") private Integer approvalStatus; } src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -1,6 +1,9 @@ package com.ruoyi.quality.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; @@ -25,6 +28,8 @@ @Resource private IQualityUnqualifiedService qualityUnqualifiedService; @Resource private FileUtil fileUtil; /** @@ -37,7 +42,9 @@ @Log(title = "æ°å¢ä¸åæ ¼ç®¡ç", businessType = BusinessType.INSERT) public R<?> add(@RequestBody QualityUnqualified qualityUnqualified) { qualityUnqualified.setInspectState(0); return R.ok(qualityUnqualifiedService.save(qualityUnqualified)); qualityUnqualifiedService.save(qualityUnqualified); fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED, qualityUnqualified.getId(), qualityUnqualified.getStorageBlobDTOs()); return R.ok(true); } /** @@ -78,7 +85,9 @@ @Operation(summary = "ä¸åæ ¼ç®¡çä¿®æ¹") @Log(title = "ä¸åæ ¼ç®¡çä¿®æ¹", businessType = BusinessType.UPDATE) public R<?> update(@RequestBody QualityUnqualified qualityUnqualified) { return R.ok(qualityUnqualifiedService.updateById(qualityUnqualified)); qualityUnqualifiedService.updateById(qualityUnqualified); fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED, qualityUnqualified.getId(), qualityUnqualified.getStorageBlobDTOs()); return R.ok(true); } /** src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,74 @@ package com.ruoyi.quality.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import com.ruoyi.quality.service.IQualityUnqualifiedOrderService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.List; @RestController @RequestMapping("/qualityUnqualifiedOrder") @Tag(name = "ä¸åæ ¼åå¤çå") public class QualityUnqualifiedOrderController { @Resource private IQualityUnqualifiedOrderService orderService; @Resource private FileUtil fileUtil; @PostMapping("/save") @Operation(summary = "æ°å¢ä¸åæ ¼åå¤çå") @Log(title = "æ°å¢ä¸åæ ¼åå¤çå", businessType = BusinessType.INSERT) public R<?> save(@RequestBody QualityUnqualifiedOrder order) { String orderNo = OrderUtils.countTodayByCreateTime( orderService.getBaseMapper(), "BHG", "order_no", order.getCreateTime() != null ? order.getCreateTime() : LocalDateTime.now()); order.setOrderNo(orderNo); order.setStatus(0); orderService.save(order); fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId(), order.getStorageBlobDTOs()); return R.ok(true); } @PutMapping("/update") @Operation(summary = "ä¿®æ¹ä¸åæ ¼åå¤çå") @Log(title = "ä¿®æ¹ä¸åæ ¼åå¤çå", businessType = BusinessType.UPDATE) public R<?> update(@RequestBody QualityUnqualifiedOrder order) { orderService.updateById(order); fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId(), order.getStorageBlobDTOs()); return R.ok(true); } @DeleteMapping("/delete") @Operation(summary = "å é¤ä¸åæ ¼åå¤çå") @Log(title = "å é¤ä¸åæ ¼åå¤çå", businessType = BusinessType.DELETE) public R<?> delete(@RequestBody List<Long> ids) { return R.ok(orderService.removeBatchByIds(ids)); } @GetMapping("/listPage") @Operation(summary = "ä¸åæ ¼åå¤çåå页æ¥è¯¢") @Log(title = "ä¸åæ ¼åå¤çåå页æ¥è¯¢", businessType = BusinessType.OTHER) public R<?> listPage(Page page, QualityUnqualifiedOrder query) { return R.ok(orderService.listPage(page, query)); } @GetMapping("/{id}") @Operation(summary = "ä¸åæ ¼åå¤çå详æ ") @Log(title = "ä¸åæ ¼åå¤çå详æ ", businessType = BusinessType.OTHER) public R<?> detail(@PathVariable Long id) { return R.ok(orderService.getDetail(id)); } } src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java
@@ -2,6 +2,8 @@ import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.basic.dto.StorageBlobDTO; import com.ruoyi.basic.dto.StorageBlobVO; import com.ruoyi.dto.DateQueryDto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import com.ruoyi.quality.pojo.QualityInspect; @@ -29,4 +31,9 @@ private String workOrderNo; private String purchaseContractNo; /** éä»¶åè¡¨ï¼æ°å¢/ç¼è¾æ¶ä¼ å ¥ï¼ */ private List<StorageBlobDTO> storageBlobDTOs; /** éä»¶åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼ */ private List<StorageBlobVO> storageBlobVOs; } src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,14 @@ package com.ruoyi.quality.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface QualityUnqualifiedOrderMapper extends BaseMapper<QualityUnqualifiedOrder> { IPage<QualityUnqualifiedOrder> listPage(Page page, @Param("query") QualityUnqualifiedOrder query); } src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -2,6 +2,8 @@ import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.basic.dto.StorageBlobDTO; import com.ruoyi.basic.dto.StorageBlobVO; import com.ruoyi.dto.DateQueryDto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,6 +14,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; import java.util.List; /** * è´¨é管ç--åææ/è¿ç¨/åºåæ£éª @@ -62,6 +65,12 @@ */ @Excel(name = "å·¥åº") private String process; /** * å·¥åºç±»å */ @Excel(name = "å·¥åºç±»å") private Integer processType; /** * æ£éªå @@ -162,4 +171,12 @@ @TableField(fill = FieldFill.INSERT) private Long deptId; @Schema(description = "éä»¶åè¡¨ï¼æ°å¢/ç¼è¾æ¶ä¼ å ¥ï¼") @TableField(exist = false) private List<StorageBlobDTO> storageBlobDTOs; @Schema(description = "éä»¶åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼") @TableField(exist = false) private List<StorageBlobVO> storageBlobVOs; } src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java
@@ -69,6 +69,9 @@ @Schema(description = "å·¥åºid") private Integer processId; @Schema(description = "å·¥åºç±»å") private Integer processType; @TableField(fill = FieldFill.INSERT) private Long deptId; } src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
@@ -2,6 +2,8 @@ import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.basic.dto.StorageBlobDTO; import com.ruoyi.basic.dto.StorageBlobVO; import com.ruoyi.dto.DateQueryDto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,6 +14,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; import java.util.List; /** * è´¨é管ç--ä¸åæ ¼å管ç @@ -111,6 +114,29 @@ @Excel(name = "å¤çæ¥æ", width = 30, dateFormat = "yyyy-MM-dd") private Date dealTime; /** * åå åæ */ @Excel(name = "åå åæ") private String reasonAnalysis; /** * é¢é²ä¸çº æ£æªæ½ */ @Excel(name = "é¢é²ä¸çº æ£æªæ½") private String preventiveCorrective; /** * å·¥æ¶æå¤± */ @Excel(name = "å·¥æ¶æå¤±") private String lossWorking; /** * ææè´¹æå¤± */ @Excel(name = "ææè´¹æå¤±") private String lossMaterial; @Schema(description = "å建æ¶é´") @@ -146,4 +172,12 @@ @Schema(description = "å ³è产ååå·id") private Long productModelId; @Schema(description = "éä»¶åè¡¨ï¼æ°å¢/ç¼è¾æ¶ä¼ å ¥ï¼") @TableField(exist = false) private List<StorageBlobDTO> storageBlobDTOs; @Schema(description = "éä»¶åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼") @TableField(exist = false) private List<StorageBlobVO> storageBlobVOs; } src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,150 @@ package com.ruoyi.quality.pojo; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.basic.dto.StorageBlobDTO; import com.ruoyi.basic.dto.StorageBlobVO; import com.ruoyi.dto.DateQueryDto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; import java.util.List; /** * è´¨é管ç--ä¸åæ ¼åå¤çå * quality_unqualified_order */ @TableName(value = "quality_unqualified_order") @Data public class QualityUnqualifiedOrder extends DateQueryDto implements Serializable { private static final long serialVersionUID = 1L; @TableId(type = IdType.AUTO) private Long id; @Schema(description = "å¤çåç¼å·") private String orderNo; @Schema(description = "å ³èä¸åæ ¼åID") private Long unqualifiedId; @Excel(name = "项ç®åç§°") private String projectName; @Excel(name = "项ç®ç¼å·") private String projectNo; @Schema(description = "å ³è设å¤ID") private Long equipmentId; @Excel(name = "设å¤åç§°") private String equipmentName; @Schema(description = "设å¤å¾å·") private String equipmentDrawingNo; @Excel(name = "ç©æ/é¨ä»¶åç§°") private String materialName; @Schema(description = "å ³è产ååå·ID") private Long productModelId; @Schema(description = "ç©æå¾å·") private String materialDrawingNo; @Excel(name = "åå·è§æ ¼") private String specificationModel; @Schema(description = "æè´¨") private String materialQuality; @Excel(name = "æ»æ°é") private BigDecimal quantity; @Excel(name = "ä¸åæ ¼æ°é") private BigDecimal unqualifiedQuantity; @Excel(name = "ä¸åæ ¼å·¥åº", readConverterExp = "1=æ¥æ,2=å¶ç¨,3=æå") private Integer unqualifiedProcess; @Excel(name = "ä¾åºååç§°") private String supplierName; @Excel(name = "æ£éªå") private String inspectorName; @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "æ£éªæ¥æ", width = 30, dateFormat = "yyyy-MM-dd") private Date inspectDate; @Schema(description = "责任人") private String responsiblePerson; @Schema(description = "责任é¨é¨") private String responsibleDept; @Schema(description = "é®é¢æè¿°") private String problemDescription; @Schema(description = "åå åæå建议") private String reasonAnalysis; @Schema(description = "çº æ£æªæ½") private String correctionAction; @Excel(name = "å¤ç½®æ¹å¼", readConverterExp = "1=è®©æ¥æ¥æ¶,2=åå ç»´ä¿®,3=è¿åç»´ä¿®,4=æ¢è´§,5=éè´§,6=æ¥åº") private Integer disposalMethod; @Schema(description = "åå /è¿åç»´ä¿®è¯ä¼°") private String repairEvaluation; @Schema(description = "é¢é²æªæ½") private String preventiveAction; @Excel(name = "ç¶æ", readConverterExp = "0=è稿,1=å¾ å®¡æ¹,2=审æ¹ä¸,3=已宿,4=已驳å") private Integer status; @Schema(description = "夿³¨") private String remark; @Schema(description = "åå»ºç¨æ·") @TableField(value = "create_by", fill = FieldFill.INSERT) private Integer createBy; @Schema(description = "ä¿®æ¹ç¨æ·") @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE) private Integer updateBy; @Schema(description = "å建æ¶é´") @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @Schema(description = "ä¿®æ¹æ¶é´") @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @Schema(description = "ç§æ·ID") @TableField(fill = FieldFill.INSERT) private Long tenantId; @Schema(description = "é¨é¨ID") @TableField(fill = FieldFill.INSERT) private Long deptId; @TableLogic @TableField(fill = FieldFill.INSERT) private Integer deleted; @Schema(description = "éä»¶åè¡¨ï¼æ°å¢/ç¼è¾æ¶ä¼ å ¥ï¼") @TableField(exist = false) private List<StorageBlobDTO> storageBlobDTOs; @Schema(description = "éä»¶åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼") @TableField(exist = false) private List<StorageBlobVO> storageBlobVOs; } src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ package com.ruoyi.quality.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; public interface IQualityUnqualifiedOrderService extends IService<QualityUnqualifiedOrder> { IPage<QualityUnqualifiedOrder> listPage(Page page, QualityUnqualifiedOrder query); QualityUnqualifiedOrder getDetail(Long id); } src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -9,6 +9,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; @@ -56,6 +59,7 @@ private final StockUtils stockUtils; private final StockInventoryService stockInventoryService; private final StockInRecordService stockInRecordService; private final FileUtil fileUtil; private QualityInspectMapper qualityInspectMapper; private IQualityInspectParamService qualityInspectParamService; @@ -78,6 +82,8 @@ qualityInspectParam.setInspectId(qualityInspect.getId()); } qualityInspectParamService.saveBatch(qualityInspectDto.getQualityInspectParams()); // ä¿åéä»¶ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_INSPECT, qualityInspect.getId(), qualityInspectDto.getStorageBlobDTOs()); return 0; } @@ -88,6 +94,8 @@ QualityInspectDto qualityInspectDto = new QualityInspectDto(); BeanUtils.copyProperties(qualityInspect, qualityInspectDto); qualityInspectDto.setQualityInspectParams(qualityInspectParams); // æ¥è¯¢éä»¶ qualityInspectDto.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.QUALITY_INSPECT, qualityInspect.getId())); return qualityInspectDto; } @@ -286,7 +294,10 @@ } QualityInspect qualityInspect = new QualityInspect(); BeanUtils.copyProperties(qualityInspectDto, qualityInspect); return qualityInspectMapper.updateById(qualityInspect); int result = qualityInspectMapper.updateById(qualityInspect); // ä¿åéä»¶ fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_INSPECT, qualityInspectDto.getId(), qualityInspectDto.getStorageBlobDTOs()); return result; } @Override src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,34 @@ package com.ruoyi.quality.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.quality.mapper.QualityUnqualifiedOrderMapper; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import com.ruoyi.quality.service.IQualityUnqualifiedOrderService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; @AllArgsConstructor @Service public class QualityUnqualifiedOrderServiceImpl extends ServiceImpl<QualityUnqualifiedOrderMapper, QualityUnqualifiedOrder> implements IQualityUnqualifiedOrderService { private final QualityUnqualifiedOrderMapper orderMapper; private final FileUtil fileUtil; @Override public IPage<QualityUnqualifiedOrder> listPage(Page page, QualityUnqualifiedOrder query) { return orderMapper.listPage(page, query); } @Override public QualityUnqualifiedOrder getDetail(Long id) { QualityUnqualifiedOrder order = orderMapper.selectById(id); if (order != null) { order.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId())); } return order; } } src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -5,6 +5,9 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanUtils; @@ -54,6 +57,7 @@ private final ProductionOperationTaskMapper productionOperationTaskMapper; private final StockUninventoryService stockUninventoryService; private final StockInRecordService stockInRecordService; private final FileUtil fileUtil; @Override public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) { @@ -117,7 +121,11 @@ @Override public QualityUnqualified getUnqualified(Integer id) { return qualityUnqualifiedMapper.getUnqualified(id); QualityUnqualified unqualified = qualityUnqualifiedMapper.getUnqualified(id); if (unqualified != null) { unqualified.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.QUALITY_UNQUALIFIED, unqualified.getId())); } return unqualified; } private void createReworkProductionByNewModel(ProductionProductMain sourceMain, BigDecimal quantity) { src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -140,5 +140,9 @@ @TableField(exist = false) private Boolean hasProductionRecord; /** * 审æ¹ç¶æï¼0-å¾ å®¡æ¹ï¼1-审æ¹ä¸ï¼2-å·²éè¿ï¼3-已驳å */ private Integer approvalStatus; } src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -171,7 +171,6 @@ if (salesLedgerProduct.getId() == null) { salesLedgerProduct.setRegisterDate(LocalDateTime.now()); result = salesLedgerProductMapper.insert(salesLedgerProduct); addProductionData(salesLedgerProduct); } else { //æ¥è¯¢åæ¬ç产ååå·id result = salesLedgerProductMapper.updateById(salesLedgerProduct); @@ -215,6 +214,17 @@ * æ°å¢çäº§æ°æ® */ public void addProductionData(SalesLedgerProduct salesLedgerProduct) { addProductionDataInternal(salesLedgerProduct, null); } /** * 审æ¹éè¿åå建ç产主计åï¼å¸¦å®¡æ¹ç¶æï¼ */ public void addProductionDataForApproved(SalesLedgerProduct salesLedgerProduct, int approvalStatus) { addProductionDataInternal(salesLedgerProduct, approvalStatus); } private void addProductionDataInternal(SalesLedgerProduct salesLedgerProduct, Integer approvalStatus) { //å å¤æè¯¥äº§åæ¯å¦éè¦ç产 if (!salesLedgerProduct.getIsProduction()) { return; @@ -230,10 +240,12 @@ productionPlan.setQtyRequired(salesLedgerProduct.getQuantity()); productionPlan.setSource("éå®"); productionPlan.setStatus(0); productionPlan.setRequiredDate(salesLedger.getDeliveryDate());//éæ±æ¥æ=äº¤è´§æ¥æ productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate());//æ¿è¯ºæ¥æ=äº¤è´§æ¥æ productionPlan.setRequiredDate(salesLedger.getDeliveryDate()); productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate()); if (approvalStatus != null) { productionPlan.setApprovalStatus(approvalStatus); } productionPlanMapper.insert(productionPlan); } /** src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -12,6 +12,10 @@ import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper; import com.ruoyi.account.pojo.sales.AccountInvoiceApplication; import com.ruoyi.account.pojo.sales.AccountSalesCollection; import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; import com.ruoyi.approve.pojo.ApprovalTemplate; import com.ruoyi.approve.service.ApprovalInstanceService; import com.ruoyi.approve.service.ApprovalTemplateService; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.mapper.CustomerMapper; @@ -21,6 +25,7 @@ import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.enums.FileNameType; import com.ruoyi.common.enums.SaleEnum; import com.ruoyi.common.enums.TypeEnums; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.EnumUtil; @@ -125,6 +130,11 @@ ; @Autowired private SysUserMapper sysUserMapper; @Autowired private ApprovalInstanceService approvalInstanceService; @Autowired private ApprovalTemplateService approvalTemplateService; @Override public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) { @@ -578,7 +588,11 @@ contractNo = generateSalesContractNo(salesLedgerDto.getEntryDate()); } salesLedger.setSalesContractNo(contractNo); salesLedger.setApprovalStatus(0); salesLedgerMapper.insert(salesLedger); // æ°å¢æ¶åèµ·ååå®¡æ¹ submitApproval(salesLedger); } else { salesLedgerMapper.updateById(salesLedger); } @@ -625,8 +639,6 @@ for (SalesLedgerProduct salesLedgerProduct : insertList) { salesLedgerProduct.setType(type.getCode()); salesLedgerProductMapper.insert(salesLedgerProduct); // æ·»å çäº§æ°æ® salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct); } } } @@ -770,4 +782,33 @@ return totalAmount; } } /** * æ°å¢éå®å°è´¦æ¶åèµ·ååå®¡æ¹ */ private void submitApproval(SalesLedger salesLedger) { LoginUser loginUser = SecurityUtils.getLoginUser(); ApprovalTemplate template = approvalTemplateService.getOne( new LambdaQueryWrapper<ApprovalTemplate>() .eq(ApprovalTemplate::getBusinessType, TypeEnums.SALES_LEDGER_APPROVAL.getCode()) .eq(ApprovalTemplate::getDeleted, 0) .orderByDesc(ApprovalTemplate::getId) .last("limit 1") ); if (template == null) { log.warn("éå®å®¡æ¹æ¨¡æ¿ä¸åå¨ï¼è·³è¿å起审æ¹"); return; } ApprovalInstanceDto instanceDto = new ApprovalInstanceDto(); instanceDto.setTemplateId(template.getId()); instanceDto.setTemplateName(template.getTemplateName()); instanceDto.setBusinessId(salesLedger.getId()); instanceDto.setBusinessType(TypeEnums.SALES_LEDGER_APPROVAL.getCode()); instanceDto.setCurrentLevel(1); instanceDto.setTitle(salesLedger.getSalesContractNo() + "éå®å®¡æ¹"); instanceDto.setApplicantId(loginUser.getUserId()); instanceDto.setApplicantName(loginUser.getNickName()); instanceDto.setApplyTime(LocalDateTime.now()); approvalInstanceService.add(instanceDto); } } src/main/resources/mapper/basic/CustomerFollowUpMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,30 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.basic.mapper.CustomerFollowUpMapper"> <select id="selectFollowUpExportList" resultType="com.ruoyi.basic.vo.CustomerFollowUpExportVo"> select c.customer_name as customerName, c.customer_type as customerType, c.contact_person as contactPerson, c.contact_phone as contactPhone, c.maintainer as maintainer, f.follow_up_method as followUpMethod, f.follow_up_level as followUpLevel, f.follow_up_time as followUpTime, f.follower_user_name as followerUserName, f.content as content from customer_follow_up f left join customer c on f.customer_id = c.id <where> <if test="customerName != null and customerName != ''"> and c.customer_name like concat('%', #{customerName}, '%') </if> <if test="customerType != null and customerType != ''"> and c.customer_type = #{customerType} </if> </where> order by c.id desc, f.follow_up_time desc </select> </mapper> src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml
@@ -16,6 +16,10 @@ qu.deal_result, qu.deal_name, qu.deal_time, qu.reason_analysis, qu.preventive_corrective, qu.loss_working, qu.loss_material, CASE WHEN qu.model = pm.id THEN pm.model ELSE qu.model @@ -76,6 +80,10 @@ qu.deal_result, qu.deal_name, qu.deal_time, qu.reason_analysis, qu.preventive_corrective, qu.loss_working, qu.loss_material, CASE WHEN qu.model = pm.id THEN pm.model ELSE qu.model src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,26 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.ruoyi.quality.mapper.QualityUnqualifiedOrderMapper"> <select id="listPage" resultType="com.ruoyi.quality.pojo.QualityUnqualifiedOrder"> SELECT * FROM quality_unqualified_order <where> <if test="query.status != null"> AND status = #{query.status} </if> <if test="query.projectName != null and query.projectName != ''"> AND project_name LIKE CONCAT('%', #{query.projectName}, '%') </if> <if test="query.orderNo != null and query.orderNo != ''"> AND order_no LIKE CONCAT('%', #{query.orderNo}, '%') </if> <if test="query.entryDateStart != null and query.entryDateStart != ''"> AND create_time >= #{query.entryDateStart} </if> <if test="query.entryDateEnd != null and query.entryDateEnd != ''"> AND create_time <= #{query.entryDateEnd} </if> </where> order by create_time desc </select> </mapper>