doc/20260615_add_actual_time_to_production_product_main.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,4 @@ -- ç产æ¥å·¥æåï¼production_product_main æ°å¢å®é å¼å§/ç»ææ¶é´å段 ALTER TABLE production_product_main ADD COLUMN actual_start_time datetime NULL COMMENT 'å®é å¼å§æ¶é´' AFTER work_hour, ADD COLUMN actual_end_time datetime NULL COMMENT 'å®é ç»ææ¶é´' AFTER actual_start_time; doc/20260615_add_disposal_method_to_production_order.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,3 @@ -- ç产订åå¢å å¤ç½®æ¹å¼å段ï¼ä¸åæ ¼åå¤çååä¼ æ è®°ï¼ ALTER TABLE production_order ADD COLUMN disposal_method int NULL COMMENT 'å¤ç½®æ¹å¼ï¼2=åå ç»´ä¿®,3=è¿åç»´ä¿®ï¼' AFTER is_end_order; doc/20260615_add_opinion_fields_to_quality_unqualified_order.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,5 @@ -- ä¸åæ ¼åå¤çåå¢å æè§/å³å®å段 ALTER TABLE quality_unqualified_order ADD COLUMN dept_opinion varchar(500) NULL COMMENT '责任é¨é¨ä¸»ç®¡æè§' AFTER remark, ADD COLUMN company_decision varchar(500) NULL COMMENT 'å ¬å¸å¤çå³å®' AFTER dept_opinion, ADD COLUMN general_manager_opinion varchar(500) NULL COMMENT 'æ»ç»çæè§' AFTER company_decision; doc/20260615_change_operation_task_time_to_datetime.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,6 @@ -- çäº§å·¥åæ¶é´å段ï¼date æ¹ä¸º datetimeï¼æ¯ææ¶åç§ ALTER TABLE production_operation_task MODIFY COLUMN plan_start_time datetime NULL COMMENT '计åå¼å§æ¶é´', MODIFY COLUMN plan_end_time datetime NULL COMMENT '计åç»ææ¶é´', MODIFY COLUMN actual_start_time datetime NULL COMMENT 'å®é å¼å§æ¶é´', MODIFY COLUMN actual_end_time datetime NULL COMMENT 'å®é ç»ææ¶é´'; docs/production_remove_bom_pick.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,79 @@ # ç产模åç§»é¤ BOM å颿/è¡¥æ ## æ¶åé¡µé¢ - ç产订å详æ 页ï¼é¢æå Tabï¼ - ç产订åå表页 - çäº§é¢æç®¡ç页 - ç产补æ/éæè®°å½é¡µ - åºåå ¥åºç®¡ç页ï¼éæå®¡æ ¸ï¼ ## API ### å é¤çæ¥å£ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /productionOrder/pick/{productionOrderId} | æ ¹æ®è®¢åIDæ¥è¯¢BOM颿å | | POST | /productionOrderPick/savePick | ä¿å颿å°çº¿è¾¹ä» | | POST | /productionOrderPick/updatePick | 忴颿ï¼å«è¡¥æ/éæï¼ | | GET | /productionOrderPick/detail/{productionOrderId} | æ¥è¯¢å·²é¢æè¯¦æ | | GET | /productionOrderPickRecord/feeding | æ¥è¯¢è¡¥æè®°å½ | | GET | /productionBomStructure/listByBomId/{bomId} | æ¥è¯¢BOMç»ææ | | POST | /productionBomStructure/addOrUpdateBomStructs | æ°å¢/ä¿®æ¹BOMç»æ | ### ååºåæ®µåæ´ **`GET /productionOrder/page`ã`/productionOrder/list`ã`/productionOrder/{id}`**ï¼ ç§»é¤ååºåæ®µï¼ | åæ° | ç±»å | 说æ | |------|------|------| | bomNo | String | BOMç¼å·ï¼å·²ç§»é¤ï¼ | | returned | Boolean | æ¯å¦å·²éæï¼å·²ç§»é¤ï¼ | ## å端修æ¹ç¹ ### 1. ç产订å详æ 页 å é¤é¢æå Tab åç¸å ³æ¥å£è°ç¨ï¼ ```html <!-- å é¤ä»¥ä¸ Tab --> <el-tab-pane label="颿å" name="pick"> <pick-list :order-id="orderId" /> </el-tab-pane> ``` ### 2. ç产订åå表页 ç§»é¤è¡¨æ ¼ä¸ç BOM ç¼å·åéæç¶æåï¼ ```html <!-- å é¤ä»¥ä¸å --> <el-table-column label="BOMç¼å·" prop="bomNo" /> <el-table-column label="éæç¶æ" prop="returned" /> ``` ### 3. çäº§é¢æ/è¡¥æ/éæé¡µé¢ æ´ä¸ªé¡µé¢æ¨¡åå¯ç§»é¤ï¼å æ¬ï¼ - 颿页é¢ï¼`productionOrderPick` ç¸å ³è·¯ç±ãç»ä»¶ï¼ - è¡¥æè®°å½é¡µé¢ï¼`productionOrderPickRecord` ç¸å ³è·¯ç±ãç»ä»¶ï¼ - BOM ç»æç®¡ç页é¢ï¼`productionBomStructure` ç¸å ³è·¯ç±ãç»ä»¶ï¼ ### 4. åºåå ¥åºç®¡ç页 ç§»é¤éæå®¡æ ¸ç¸å ³ç `ProductionOrderPick` æ°æ®å¤çé»è¾ãå ¥åºè®°å½ä¸åå ³èé¢æè®°å½è¡¨ç `returnQty` 计ç®ã ### 5. æ¥å·¥æå ¥å æ¥å·¥æ¶æå ¥åä¸åä» BOM ç»æè§£æï¼æ¹ä¸ºç´æ¥ä½¿ç¨å½åå·¥åºç产åè§æ ¼ä½ä¸ºæå ¥åãå端æ éæ¹å¨ï¼å端èªå¨å¤çã ## 注æäºé¡¹ - æ¬æ¬¡åæ´åï¼é¢ææä½ç±ç¨æ·ç´æ¥å¨åºåç®¡çæ¨¡åè¿è¡ï¼ä¸åä¸ç产工åå ³è - ç产订åå表åå岿°æ®ä¸ `bomNo` å `returned` åæ®µä¸åè¿åï¼å端å¦ç¼åäºè¿äºå段éåå ¼å®¹å¤ç - ææ `/productionOrderPick`ã`/productionOrderPickRecord`ã`/productionBomStructure`ã`/productionOrderBom` æ¥å£å·²ç§»é¤ï¼è°ç¨è¿äºæ¥å£çå端代ç éå ¨é¨æ¸ ç - æ°æ®åºè¡¨ `production_order_pick`ã`production_order_pick_record`ã`production_order_bom`ã`production_bom_structure` å¦éä¿çå岿°æ®å¯æä¸å é¤ docs/production_report_split.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,146 @@ # ç产æ¥å·¥æåï¼å¼å§æ¥å·¥/ç»ææ¥å·¥ï¼å工人æéè¿æ»¤ ## æ¶åé¡µé¢ - ç产工åå表页ï¼å¯æ¥å·¥å·¥åçéï¼ - ç产æ¥å·¥é¡µï¼å¼å§æ¥å·¥ / ç»ææ¥å·¥ï¼ - æ¥å·¥å°è´¦é¡µï¼å®é å·¥æ¶å±ç¤ºï¼ ## API ### æ°å¢æ¥å£ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | /productionProductMain/startWork | å¼å§æ¥å·¥ | **请æ±åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | productionOperationTaskId | Long | æ¯ | ç产工åID | | userId | Long | æ¯ | æ¥å·¥äººåID | **ååºï¼** `{ "code": 200, "msg": "æä½æå", "data": true }` ### åæ´æ¥å£ **`POST /productionProductMain/addProductMain`ï¼ç»ææ¥å·¥ï¼**ï¼ å ¥åå¢å ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | id | Long | æ¯ | å¼å§æ¥å·¥è¿åç ProductionProductMain ID | **`GET /productionOperationTask/page`ã`/productionOperationTask/list`**ï¼ æ°å¢æ¥è¯¢åæ°ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | filterMine | Boolean | å¦ | 为 true æ¶ä» è¿åå½åç¨æ·è¢«ææ´¾çå·¥å | ### ååºåæ®µåæ´ **`GET /productionProductMain/listPage`ã`/page`ã`/{id}`**ï¼ æ°å¢ååºåæ®µï¼ | åæ° | ç±»å | 说æ | |------|------|------| | actualStartTime | String | å®é å¼å§æ¶é´ (yyyy-MM-dd HH:mm:ss) | | actualEndTime | String | å®é ç»ææ¶é´ (yyyy-MM-dd HH:mm:ss) | ## å端修æ¹ç¹ ### 1. ç产æ¥å·¥é¡µ â æåä¸ºä¸¤æ¥æä½ **å¼å§æ¥å·¥æé®ï¼** ```html <el-button type="primary" @click="handleStartWork">å¼å§æ¥å·¥</el-button> ``` ```js handleStartWork() { this.$confirm('确认å¼å§æ¥å·¥ï¼', 'æç¤º', { type: 'info' }).then(() => { startWork({ productionOperationTaskId: this.taskId, userId: this.selectedUserId }).then(res => { this.startRecordId = res.data; // ä¿åè¿åçæ¥å·¥è®°å½IDï¼ä¾ç»ææ¥å·¥ä½¿ç¨ this.$message.success('å¼å§æ¥å·¥æå'); this.refreshTaskStatus(); }); }); } ``` **ç»ææ¥å·¥æé®ï¼åæ¥å·¥æäº¤æé®æ¹é ï¼ï¼** ```html <el-button type="success" @click="handleFinishWork" :disabled="!startRecordId">ç»ææ¥å·¥</el-button> ``` ```js handleFinishWork() { this.$refs.form.validate(valid => { if (valid) { addProductMain({ id: this.startRecordId, // å¿ é¡»ä¼ å ¥å¼å§æ¥å·¥è®°å½ID quantity: this.form.quantity, scrapQty: this.form.scrapQty, userId: this.selectedUserId, productionOperationParamList: this.paramList }).then(() => { this.$message.success('ç»ææ¥å·¥æå'); this.resetForm(); }); } }); } ``` ### 2. å·¥åå表页 â æéè¿æ»¤ å¢å "ä» çæç"çéå¼å ³ï¼ ```html <el-switch v-model="filterMine" active-text="ä» çæç" @change="handleFilterChange" /> ``` ```js data() { return { filterMine: false, } }, methods: { handleFilterChange(val) { this.loadTaskList(); }, loadTaskList() { const params = { ...this.queryParams }; if (this.filterMine) { params.filterMine = true; } listTask(params).then(res => { this.taskList = res.rows; }); } } ``` ### 3. æ¥å·¥å°è´¦é¡µ â å±ç¤ºå®é å·¥æ¶ å°è´¦ä¸ç `workHour` åæ®µç°å¨åºäºå®é å¼å§/ç»ææ¶é´èªå¨è®¡ç®ï¼ä»¥å°æ¶ä¸ºåä½ï¼ï¼åç«¯ç´æ¥å±ç¤ºå³å¯ï¼æ éé¢å¤å¤çã ## 注æäºé¡¹ - æ¥å·¥æµç¨å为两æ¥ï¼å è°ç¨ `/startWork` å¼å§ï¼åè°ç¨ `/addProductMain`ï¼ä¼ å ¥å¼å§æ¥å·¥è¿åç `id`ï¼ç»æ - å¼å§æ¥å·¥åå·¥åç¶æå为"ç产ä¸"ï¼ç»ææ¥å·¥åæå建产åºåãæå ¥ååæ ¸ç®è®°å½ - å®é å·¥æ¶ = actualEndTime - actualStartTimeï¼èªå¨è®¡ç®ï¼ä¹å¯æå¨ä¼ å ¥ workHour è¦çï¼ - å·¥åæªææ´¾ï¼userIds 为空æ `[]`ï¼æ¶ææå·¥äººå¯æä½ï¼å·²ææ´¾æ¶ä» è¢«ææ´¾äººå¯æä½ - å端éç¼å `startRecordId`ï¼å¼å§æ¥å·¥è¿åç IDï¼ï¼ç»ææ¥å·¥æ¶ä¼ å ¥ - å¦æç¨æ·å ³é页é¢åéæ°æå¼ï¼éè¦æ¥è¯¢ `status=0` çè¿è¡ä¸æ¥å·¥è®°å½æ¥æ¢å¤ `startRecordId` docs/quality_unqualified_order.md
@@ -1,34 +1,49 @@ # ä¸åæ ¼åå¤çå â å端èè°ææ¡£ # ä¸åæ ¼åå¤ç忍¡åï¼QualityUnqualifiedOrderï¼ ## æ¦è¿° ä¸åæ ¼åå¤ç忝æ£å¼çä¸åæ ¼åå¤ç½®æµç¨æ¨¡åï¼æ¿ä»£æ§çä¸åæ ¼ç®¡çï¼`/quality/qualityUnqualified`ï¼ä¸çå¤ç½®åè½ãæ§æ¨¡åçä¸åæ ¼ååç°ï¼æ°å¢/å表/详æ ï¼ç»§ç»ä½¿ç¨ï¼ä½**å¤ç½®æä½ç»ä¸ä½¿ç¨æ¬æ¨¡å**ã ### èªå¨å建æºå¶ 彿£éªåï¼åææ/è¿ç¨/åºåæ£éªï¼æäº¤æ¶ï¼å¦æ**ä¸åæ ¼æ°é > 0**ï¼ç³»ç»å¨å建 `QualityUnqualified` è®°å½çåæ¶ï¼**èªå¨åå»ºä¸æ¡ä¸åæ ¼åå¤çå**ï¼`unqualifiedProcess`ï¼ä¸åæ ¼å·¥åºï¼æ ¹æ®æ£éªç±»å«èªå¨æ å°ï¼ | æ£éªç±»å« | inspectType | unqualifiedProcess | |----------|-------------|-------------------| | åæææ£éª | 0 | 1ï¼æ¥æï¼ | | è¿ç¨æ£éª | 0 | 2ï¼å¶ç¨ï¼ | | åºåæ£éª | 0 | 3ï¼æåï¼ | å¤çååå§ç¶æä¸º `0`ï¼è稿ï¼ï¼åç»å¯ç¼è¾å¤ç½®æ¹å¼å¹¶æäº¤å®¡æ¹ã ### 䏿§æ¨¡åçå ³ç³» | | æ§ï¼ä¸åæ ¼ç®¡ç | æ°ï¼ä¸åæ ¼åå¤çå | |---|---|---| | è·¯å¾ | `/quality/qualityUnqualified` | `/qualityUnqualifiedOrder` | | ç¨é | ä¸åæ ¼å馿¬¡è®°å½ãæ¥ç | æ£å¼å¤ç½®æµç¨ï¼å«å®¡æ¹ï¼ | | å¤ç½®æ¹å¼ | `dealResult` èªç±ææ¬ | `disposalMethod` ç»æåæä¸¾ | | å建æ¹å¼ | æ£éªåæäº¤èªå¨å建 / æå¨æ°å¢ | æ£éªåæäº¤èªå¨å建 / æå¨æ°å¢ | ## æ¶åé¡µé¢ - **ä¸åæ ¼åå¤çåå表/详æ ** â æ°å¢é¡µé¢ ## åæ´è¯´æ æ°å¢ `quality_unqualified_order` ä¸åæ ¼åå¤ç忍¡åï¼æ¯æå¯¹ä¸åæ ¼åè¿è¡æ£å¼çå¤ç½®è®°å½ï¼å å«å®¡æ¹ç¶ææºï¼è稿âå¾ å®¡æ¹â审æ¹ä¸â已宿/已驳åï¼ãé件使ç¨ç³»ç»ç»ä¸ç `storage_attachment` 表ã - ä¸åæ ¼åå¤çåå表页 - ä¸åæ ¼åå¤çåæ°å¢/ç¼è¾é¡µ - ä¸åæ ¼åå¤çå详æ 页 ## API ### ä¸åæ ¼åå¤çå ### 1. æ°å¢å¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/qualityUnqualifiedOrder/save` | æ°å¢å¤çåï¼ç¼å·èªå¨çæï¼ | | PUT | `/qualityUnqualifiedOrder/update` | ä¿®æ¹å¤çå | | DELETE | `/qualityUnqualifiedOrder/delete` | æ¹éå é¤ï¼é»è¾å é¤ï¼ | | GET | `/qualityUnqualifiedOrder/listPage` | å页æ¥è¯¢ | | GET | `/qualityUnqualifiedOrder/{id}` | æ¥ç详æ | | POST | /qualityUnqualifiedOrder/save | æ°å¢ä¸åæ ¼åå¤çå | ### 请æ±/ååºåæ° **QualityUnqualifiedOrder 对象ï¼** **请æ±åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | id | Long | å¦ | 主é®ï¼ä¿®æ¹æ¶å¿ å¡«ï¼ | | orderNo | String | å¦ | å¤çåç¼å·ï¼èªå¨çæï¼åç¼ BHG+æ¥æ+åºå· | | unqualifiedId | Long | å¦ | å ³èä¸åæ ¼åID | | unqualifiedId | Long | æ¯ | å ³èä¸åæ ¼åID | | projectName | String | å¦ | 项ç®åç§° | | projectNo | String | å¦ | 项ç®ç¼å· | | equipmentId | Long | å¦ | å ³è设å¤ID | @@ -41,7 +56,7 @@ | materialQuality | String | å¦ | æè´¨ | | quantity | BigDecimal | å¦ | æ»æ°é | | unqualifiedQuantity | BigDecimal | å¦ | ä¸åæ ¼æ°é | | unqualifiedProcess | Integer | å¦ | ä¸åæ ¼å·¥åºï¼1=æ¥æï¼2=å¶ç¨ï¼3=æå | | unqualifiedProcess | Integer | å¦ | ä¸åæ ¼å·¥åºï¼1=æ¥æ, 2=å¶ç¨, 3=æå | | supplierName | String | å¦ | ä¾åºååç§° | | inspectorName | String | å¦ | æ£éªå | | inspectDate | Date | å¦ | æ£éªæ¥æ (yyyy-MM-dd) | @@ -50,233 +65,501 @@ | problemDescription | String | å¦ | é®é¢æè¿° | | reasonAnalysis | String | å¦ | åå åæå建议 | | correctionAction | String | å¦ | çº æ£æªæ½ | | disposalMethod | Integer | å¦ | å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶ï¼2=åå ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åº | | **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\> | å¦ | éä»¶åæ¾åè¡¨ï¼æ¥è¯¢æ¶è¿åï¼ | | deptOpinion | String | å¦ | 责任é¨é¨ä¸»ç®¡æè§ | | companyDecision | String | å¦ | å ¬å¸å¤çå³å® | | generalManagerOpinion | String | å¦ | æ»ç»çæè§ | | storageBlobDTOs | List | å¦ | éä»¶å表 | ### å页æ¥è¯¢åæ° **èªå¨è¡ä¸ºï¼** - èªå¨çæå¤çåç¼å·ï¼`BHGyyMMdd+æµæ°´å·`ï¼ - **æå¨æ°å¢æ¶**ï¼éäºå¤ç½®æ¹å¼ â ç¶æèªå¨ä¸º `3`ï¼å·²å®æï¼ï¼æ²¡é â ç¶æä¸º `0`ï¼èç¨¿ï¼ - **è´¨æ£èªå¨å建æ¶**ï¼ç¶æåå§ä¸º `0`ï¼è稿ï¼ï¼ééè¿å¤çæ¥å£è¡¥å å¤ç½®æ¹å¼ - **å½ `disposalMethod` éæ© 2ï¼åå ç»´ä¿®ï¼æ 3ï¼è¿åç»´ä¿®ï¼æ¶ï¼èªå¨å建è¿ä¿®ç产订å** **ååºï¼** `{ "code": 200, "msg": "æä½æå", "data": true }` ### 2. ä¿®æ¹å¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | PUT | /qualityUnqualifiedOrder/update | ä¿®æ¹ä¸åæ ¼åå¤çå | **请æ±åæ°ï¼** 䏿°å¢ç¸åï¼é¢å¤éè¦ `id` åæ®µã ### 3. å é¤å¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | DELETE | /qualityUnqualifiedOrder/delete | å é¤ä¸åæ ¼åå¤çå | **请æ±åæ°ï¼** `[id1, id2, ...]` â ID æ°ç» ### 4. å页æ¥è¯¢ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /qualityUnqualifiedOrder/listPage | å页æ¥è¯¢ | **æ¥è¯¢åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | pageNum | Integer | å¦ | 页ç ï¼é»è®¤1 | | pageSize | Integer | å¦ | æ¯é¡µæ¡æ°ï¼é»è®¤10 | | status | Integer | å¦ | ç¶æçé | | projectName | String | å¦ | 项ç®åç§°æ¨¡ç³æç´¢ | | orderNo | String | å¦ | ç¼å·æ¨¡ç³æç´¢ | | entryDateStart | String | å¦ | å建æ¶é´èµ·å§ | | entryDateEnd | String | å¦ | å建æ¶é´ç»æ | | page | int | å¦ | 页ç ï¼é»è®¤1ï¼ | | size | int | å¦ | æ¯é¡µæ¡æ°ï¼é»è®¤10ï¼ | | status | Integer | å¦ | ç¶æï¼0=è稿, 1=å¾ å®¡æ¹, 2=审æ¹ä¸, 3=已宿, 4=已驳å | | projectName | String | å¦ | 项ç®åç§°ï¼æ¨¡ç³å¹é ï¼ | | orderNo | String | å¦ | å¤çåç¼å·ï¼æ¨¡ç³å¹é ï¼ | | entryDateStart | String | å¦ | å建æ¶é´èµ· (yyyy-MM-dd) | | entryDateEnd | String | å¦ | å建æ¶é´æ¢ (yyyy-MM-dd) | ### å é¤è¯·æ±ä½ **ååºå段ï¼** è¿å `QualityUnqualifiedOrder` å ¨é¨å段ï¼å« `storageBlobVOs`ï¼éä»¶å表ï¼ã ```json [1, 2, 3] ``` ### 5. è¯¦æ æ¥è¯¢ ## æ°æ®ç»æ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /qualityUnqualifiedOrder/{id} | å¤çå详æ | ### StorageBlobDTOï¼ä¸ä¼ æ¶ä¼ å ¥ï¼ **ååºï¼** è¿ååæ¡ `QualityUnqualifiedOrder` å ¨é¨å段ï¼å«éä»¶ã ```json { "id": "ä¸´æ¶æä»¶IDï¼å符串ï¼", "name": "æä»¶å", "url": "æä»¶è·¯å¾", "fileSize": 1024 } ``` ### 6. å¤çï¼å¤ç½®ï¼ ### StorageBlobVOï¼æ¥è¯¢æ¶è¿åï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | /qualityUnqualifiedOrder/deal | 对èç¨¿ç¶æçå¤çåè¡¥å å¤ç½®æ¹å¼å¹¶å®æ | ```json { "id": 1, "name": "æ£éªæ¥å.pdf", "url": "/upload/20260613/xxx.pdf", "fileSize": 102400, "application": "FILE" **请æ±åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | **id** | **Long** | **æ¯** | å¤çåID | | **disposalMethod** | **Integer** | **æ¯** | **å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶, 2=åå ç»´ä¿®, 3=è¿åç»´ä¿®, 4=æ¢è´§, 5=éè´§, 6=æ¥åº** | | repairEvaluation | String | å¦ | åå /è¿åç»´ä¿®è¯ä¼° | | reasonAnalysis | String | å¦ | åå åæå建议 | | correctionAction | String | å¦ | çº æ£æªæ½ | | preventiveAction | String | å¦ | é¢é²æªæ½ | | remark | String | å¦ | 夿³¨ | | deptOpinion | String | å¦ | 责任é¨é¨ä¸»ç®¡æè§ | | companyDecision | String | å¦ | å ¬å¸å¤çå³å® | | generalManagerOpinion | String | å¦ | æ»ç»çæè§ | **èªå¨è¡ä¸ºï¼** - ç¶ææ´æ°ä¸º `3`ï¼å·²å®æï¼ - å¤ç½®æ¹å¼ä¸º 2ï¼åå ç»´ä¿®ï¼æ 3ï¼è¿åç»´ä¿®ï¼æ¶ï¼èªå¨å建è¿ä¿®ç产订å **ååºï¼** `{ "code": 200, "msg": "æä½æå", "data": true }` ### 7. 导åºå¤çå | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /qualityUnqualifiedOrder/export/{id} | 导åºä¸åæ ¼åå¤çå为 Excel | **请æ±åæ°ï¼** `id` â å¤çåIDï¼è·¯å¾åæ°ï¼ **ååºï¼** æä»¶æµï¼`Content-Type: application/vnd.ms-excel`ï¼æä»¶å `ä¸åæ ¼åå¤çå_{ç¼å·}.xls` **模æ¿å段æ å°ï¼** | 模æ¿ä½ç½® | åæ®µ | |----------|------| | 项ç®åç§° | projectName | | 项ç®ç¼å· | projectNo | | 设å¤åç§° | equipmentName | | 设å¤å¾å· | equipmentDrawingNo | | ç©æåç§° | materialName | | ç©æå¾å· | materialDrawingNo | | åå·è§æ ¼ | specificationModel | | æè´¨ | materialQuality | | æ»æ°é | quantity | | ä¸åæ ¼æ° | unqualifiedQuantity | | ä¸åæ ¼å·¥åº | unqualifiedProcessï¼å¾éæ¥æ/å¶ç¨/æåï¼ | | ä¾è´§ååç§° | supplierName | | æ£éªå | inspectorName | | æ£éªæ¥æ | inspectDate | | 责任人 | responsiblePerson | | 责任é¨é¨ | responsibleDept | | é®é¢æè¿° | problemDescription | | åå åæå建议 | reasonAnalysis | | çº æ£æªæ½ | correctionAction | | å¤ç½®æ¹å¼ | disposalMethodï¼å¾é对åºéé¡¹ï¼ | | åå /è¿åç»´ä¿®è¯ä¼° | repairEvaluation | | é¢é²æªæ½ | preventiveAction | | 责任é¨é¨ä¸»ç®¡æè§ | deptOpinion | | å ¬å¸å¤çå³å® | companyDecision | | æ»ç»çæè§ | generalManagerOpinion | **å端è°ç¨ç¤ºä¾ï¼** ```js // å表页æä½åå¢å å¯¼åºæé® <el-button text type="primary" @click="handleExport(row.id)">导åº</el-button> // 详æ 页å¢å å¯¼åºæé® <el-button type="primary" @click="handleExport">导åº</el-button> methods: { handleExport(id) { window.open(`/api/qualityUnqualifiedOrder/export/${id}`); }, } ``` ## å端修æ¹ç¹ ### 1. ä¸åæ ¼åå¤çå â æ°å¢/ç¼è¾è¡¨å ### 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> <template> <div class="app-container"> <!-- æç´¢æ --> <el-form :model="queryParams" :inline="true"> <el-form-item label="å¤çåç¼å·"> <el-input v-model="queryParams.orderNo" placeholder="è¾å ¥ç¼å·" /> </el-form-item> <el-form-item label="项ç®åç§°"> <el-input v-model="queryParams.projectName" placeholder="è¾å ¥é¡¹ç®" /> </el-form-item> <el-form-item label="ç¶æ"> <el-select v-model="queryParams.status" placeholder="å ¨é¨" clearable> <el-option label="è稿" :value="0" /> <el-option label="å¾ å®¡æ¹" :value="1" /> <el-option label="审æ¹ä¸" :value="2" /> <el-option label="已宿" :value="3" /> <el-option label="已驳å" :value="4" /> </el-select> </el-form-item> <el-form-item label="å建æ¶é´"> <el-date-picker v-model="dateRange" type="daterange" value-format="yyyy-MM-dd" start-placeholder="å¼å§" end-placeholder="ç»æ" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">æ¥è¯¢</el-button> <el-button @click="resetQuery">éç½®</el-button> </el-form-item> </el-form> <!-- æä½æé® --> <el-row :gutter="10" class="mb8"> <el-button type="primary" @click="handleAdd">æ°å¢å¤çå</el-button> <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete">å é¤</el-button> </el-row> <!-- è¡¨æ ¼ --> <el-table :data="list" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" /> <el-table-column label="å¤çåç¼å·" prop="orderNo" width="160" /> <el-table-column label="项ç®åç§°" prop="projectName" /> <el-table-column label="åå·è§æ ¼" prop="specificationModel" width="120" /> <el-table-column label="ä¸åæ ¼æ°é" prop="unqualifiedQuantity" width="100" /> <el-table-column label="å¤ç½®æ¹å¼" width="110"> <template #default="{ row }"> {{ disposalMethodMap[row.disposalMethod] }} </template> </el-table-column> <el-table-column label="ç¶æ" width="80"> <template #default="{ row }"> <el-tag :type="statusTagType(row.status)">{{ statusMap[row.status] }}</el-tag> </template> </el-table-column> <el-table-column label="æ£éªå" prop="inspectorName" width="100" /> <el-table-column label="æ£éªæ¥æ" prop="inspectDate" width="110" /> <el-table-column label="å建æ¶é´" prop="createTime" width="160" /> <el-table-column label="æä½" width="120" fixed="right"> <template #default="{ row }"> <el-button text type="primary" @click="handleDetail(row.id)">详æ </el-button> <el-button text type="primary" @click="handleEdit(row)">ç¼è¾</el-button> </template> </el-table-column> </el-table> <pagination :total="total" v-model:page="page" v-model:limit="size" @pagination="loadList" /> </div> </template> ``` ### 2. ä¸åæ ¼åå¤çå â å表页 ```js data() { return { list: [], total: 0, page: 1, size: 10, selectedIds: [], dateRange: [], queryParams: { orderNo: '', projectName: '', status: null, }, disposalMethodMap: { 1: 'è®©æ¥æ¥æ¶', 2: 'åå ç»´ä¿®', 3: 'è¿åç»´ä¿®', 4: 'æ¢è´§', 5: 'éè´§', 6: 'æ¥åº' }, statusMap: { 0: 'è稿', 1: 'å¾ å®¡æ¹', 2: '审æ¹ä¸', 3: '已宿', 4: '已驳å' }, } }, methods: { statusTagType(status) { const map = { 0: 'info', 1: 'warning', 2: '', 3: 'success', 4: 'danger' }; return map[status] || 'info'; }, loadList() { const params = { ...this.queryParams, page: this.page, size: this.size }; if (this.dateRange && this.dateRange.length === 2) { params.entryDateStart = this.dateRange[0]; params.entryDateEnd = this.dateRange[1]; } listPage(params).then(res => { this.list = res.rows; this.total = res.total; }); }, handleQuery() { this.page = 1; this.loadList(); }, resetQuery() { this.queryParams = { orderNo: '', projectName: '', status: null }; this.dateRange = []; this.handleQuery(); }, handleSelectionChange(selection) { this.selectedIds = selection.map(i => i.id); }, handleAdd() { this.$router.push('/quality/unqualified-order/add'); }, handleEdit(row) { this.$router.push({ path: '/quality/unqualified-order/edit', query: { id: row.id } }); }, handleDetail(id) { this.$router.push({ path: '/quality/unqualified-order/detail', query: { id } }); }, handleDelete() { this.$confirm('确认å é¤éä¸çå¤çåï¼').then(() => { deleteOrders(this.selectedIds).then(() => { this.$message.success('å 餿å'); this.loadList(); }); }); }, } ``` ### 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> ``` <template> <div class="app-container"> <el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="å ³èä¸åæ ¼å" prop="unqualifiedId"> <el-select v-model="form.unqualifiedId" placeholder="éæ©ä¸åæ ¼å" filterable> <el-option v-for="item in unqualifiedList" :key="item.id" :label="item.productName + ' ' + item.model + ' (' + item.quantity + ')'" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <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-col> </el-row> ### 3. data æ°æ® <el-divider>åºæ¬ä¿¡æ¯</el-divider> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="项ç®åç§°" prop="projectName"> <el-input v-model="form.projectName" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="项ç®ç¼å·" prop="projectNo"> <el-input v-model="form.projectNo" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="ç©æ/é¨ä»¶åç§°" prop="materialName"> <el-input v-model="form.materialName" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç©æå¾å·" prop="materialDrawingNo"> <el-input v-model="form.materialDrawingNo" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="åå·è§æ ¼" prop="specificationModel"> <el-input v-model="form.specificationModel" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="æè´¨" prop="materialQuality"> <el-input v-model="form.materialQuality" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="ä¾åºå" prop="supplierName"> <el-input v-model="form.supplierName" /> </el-form-item> </el-col> </el-row> <el-divider>ä¸åæ ¼ä¿¡æ¯</el-divider> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="æ»æ°é" prop="quantity"> <el-input-number v-model="form.quantity" :min="0" :precision="2" style="width:100%" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="ä¸åæ ¼æ°é" prop="unqualifiedQuantity"> <el-input-number v-model="form.unqualifiedQuantity" :min="0" :precision="2" style="width:100%" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="æ£éªæ¥æ" prop="inspectDate"> <el-date-picker v-model="form.inspectDate" type="date" value-format="yyyy-MM-dd" style="width:100%" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="æ£éªå" prop="inspectorName"> <el-input v-model="form.inspectorName" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="责任人" prop="responsiblePerson"> <el-input v-model="form.responsiblePerson" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="责任é¨é¨" prop="responsibleDept"> <el-input v-model="form.responsibleDept" /> </el-form-item> </el-col> </el-row> <el-form-item label="é®é¢æè¿°" prop="problemDescription"> <el-input v-model="form.problemDescription" type="textarea" :rows="2" /> </el-form-item> <el-divider>å¤ç½®å³ç</el-divider> <el-form-item label="å¤ç½®æ¹å¼" prop="disposalMethod"> <el-radio-group v-model="form.disposalMethod"> <el-radio :value="1">è®©æ¥æ¥æ¶</el-radio> <el-radio :value="2">åå ç»´ä¿®</el-radio> <el-radio :value="3">è¿åç»´ä¿®</el-radio> <el-radio :value="4">æ¢è´§</el-radio> <el-radio :value="5">éè´§</el-radio> <el-radio :value="6">æ¥åº</el-radio> </el-radio-group> </el-form-item> <el-form-item v-if="form.disposalMethod === 2 || form.disposalMethod === 3" label="ç»´ä¿®è¯ä¼°" prop="repairEvaluation"> <el-input v-model="form.repairEvaluation" type="textarea" :rows="3" placeholder="è¯ä¼°ç»´ä¿®å¯è¡æ§ãæéå·¥æ¶ãç©æç" /> </el-form-item> <el-form-item label="åå åæå建议" prop="reasonAnalysis"> <el-input v-model="form.reasonAnalysis" type="textarea" :rows="3" /> </el-form-item> <el-form-item label="çº æ£æªæ½" prop="correctionAction"> <el-input v-model="form.correctionAction" type="textarea" :rows="3" /> </el-form-item> <el-form-item label="é¢é²æªæ½" prop="preventiveAction"> <el-input v-model="form.preventiveAction" type="textarea" :rows="3" /> </el-form-item> <el-divider>å®¡æ¹æè§</el-divider> <el-form-item label="责任é¨é¨ä¸»ç®¡æè§" prop="deptOpinion"> <el-input v-model="form.deptOpinion" type="textarea" :rows="2" /> </el-form-item> <el-form-item label="å ¬å¸å¤çå³å®" prop="companyDecision"> <el-input v-model="form.companyDecision" type="textarea" :rows="2" /> </el-form-item> <el-form-item label="æ»ç»çæè§" prop="generalManagerOpinion"> <el-input v-model="form.generalManagerOpinion" type="textarea" :rows="2" /> </el-form-item> <el-divider>éä»¶</el-divider> <el-form-item label="éä»¶"> <file-upload v-model="form.storageBlobDTOs" /> </el-form-item> </el-form> <div class="text-center"> <el-button type="primary" @click="handleSubmit">æäº¤</el-button> <el-button @click="handleCancel">åæ¶</el-button> </div> </div> </template> ``` ```js data() { return { form: { storageBlobDTOs: [], storageBlobVOs: [], unqualifiedId: null, disposalMethod: null, }, query: { pageNum: 1, pageSize: 10, status: null, projectName: '', orderNo: '', rules: { unqualifiedId: [{ required: true, message: 'è¯·éæ©å ³èä¸åæ ¼å', trigger: 'change' }], disposalMethod: [{ required: true, message: 'è¯·éæ©å¤ç½®æ¹å¼', trigger: 'change' }], }, statusMap: { 0: 'è稿', 1: 'å¾ å®¡æ¹', 2: '审æ¹ä¸', 3: '已宿', 4: '已驳å' }, disposalMethodMap: { 1: 'è®©æ¥æ¥æ¶', 2: 'åå ç»´ä¿®', 3: 'è¿åç»´ä¿®', 4: 'æ¢è´§', 5: 'éè´§', 6: 'æ¥åº' }, unqualifiedProcessMap: { 1: 'æ¥æ', 2: 'å¶ç¨', 3: 'æå' }, unqualifiedList: [], } }, mounted() { // å è½½å¾ å¤ççä¸åæ ¼åå表 loadUnqualifiedList({ inspectState: 0 }).then(res => this.unqualifiedList = res.rows); if (this.$route.query.id) { getDetail(this.$route.query.id).then(res => this.form = res.data); } }, methods: { handleSubmit() { this.$refs.form.validate(valid => { if (!valid) return; const api = this.form.id ? updateOrder : saveOrder; api(this.form).then(() => { this.$message.success(this.form.id ? 'ä¿®æ¹æå' : 'æ°å¢æå'); this.$router.back(); }); }); }, handleCancel() { this.$router.back(); }, } ``` ### 4. API è°ç¨ ## å¤ç½®æ¹å¼è¯´æ ```js import request from '@/utils/request' | å¼ | å«ä¹ | ç³»ç»èªå¨è¡ä¸º | |----|------|------------| | 1 | è®©æ¥æ¥æ¶ | æ èªå¨æä½ï¼é人工åç»å¤ç | | 2 | åå ç»´ä¿® | **èªå¨å建è¿ä¿®ç产订å**ï¼FG å¼å¤´ NPS ç¼å·ï¼ï¼å éåå·¥åºè·¯çº¿ | | 3 | è¿åç»´ä¿® | **èªå¨å建è¿ä¿®ç产订å**ï¼FG å¼å¤´ NPS ç¼å·ï¼ï¼å éåå·¥åºè·¯çº¿ | | 4 | æ¢è´§ | æ èªå¨æä½ | | 5 | éè´§ | æ èªå¨æä½ | | 6 | æ¥åº | æ èªå¨æä½ï¼åºåæ£åç±æ§æ¨¡å `/quality/qualityUnqualified/deal` å¤çï¼ | // å页æ¥è¯¢ 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 }) } ``` è´¨æ£èªå¨å建 ââ> 0(è稿) ââ> è°ç¨ /deal éæ©å¤ç½®æ¹å¼ ââ> 3(已宿) æå¨æ°å¢(没éå¤ç½®æ¹å¼) ââ> 0(è稿) ââ> è°ç¨ /deal ââ> 3(已宿) æå¨æ°å¢(éäºå¤ç½®æ¹å¼) ââ> 3(已宿) ``` ## 注æäºé¡¹ - å¤çåç¼å· `orderNo` ç±å端èªå¨çæï¼åç¼ "BHG" + æ¥æ + 3ä½èªå¢åºå·ï¼ï¼å端æ éä¼ å ¥ - æ°å¢æ¶ `status` é»è®¤ä¸º 0ï¼è稿ï¼ï¼æ éå端设置 - å é¤ä¸ºé»è¾å é¤ï¼éè¿ `deleted` åæ®µæ è®° - éä»¶ä¸ä¼ 使ç¨ç³»ç»å·²æçæä»¶ä¸ä¼ ç»ä»¶ï¼å°è¿åçä¸´æ¶æä»¶IDéè¿ `storageBlobDTOs` ä¼ å ¥ - ä¸åæ ¼åå¤çåå¯å ³è `quality_unqualified` 表çè®°å½ï¼éè¿ `unqualifiedId` åæ®µï¼ - æ£éªåæäº¤æ¶ï¼ä¸åæ ¼æ°é > 0 ä¼èªå¨å建å¤çåï¼ç¶æä¸ºè稿ï¼ï¼**æ éæå¨æ°å¢** - æå¨æ°å¢å¤çåæ¶ï¼éäºå¤ç½®æ¹å¼ç´æ¥å®æï¼æ²¡éåä¿æè稿 - èç¨¿ç¶æçå¤çåéè¿ `/qualityUnqualifiedOrder/deal` æ¥å£è¡¥å å¤ç½®æ¹å¼ - æ§çä¸åæ ¼ç®¡çï¼`/quality/qualityUnqualified`ï¼ç»§ç»ç¨äºä¸åæ ¼å馿¬¡è®°å½åå表æ¥ç - å¤ç½®æä½ç»ä¸ä½¿ç¨æ¬æ¨¡åï¼`/qualityUnqualifiedOrder`ï¼ - éæ©"åå ç»´ä¿®"æ"è¿åç»´ä¿®"æ¶ï¼ç³»ç»èªå¨å建è¿ä¿®ç产订åï¼æ éæå¨æä½ - è¿ä¿®ç产订åç `disposalMethod` åæ®µæ è®°äºå¤ç½®æ¹å¼ï¼å¯å¨ç产订åå表åºåæ®é订ååè¿ä¿®è®¢å - å¤çåç¼å·èªå¨çæï¼åç¼ä¸º `BHG` - éä»¶éè¿ `storageBlobDTOs` åæ®µä¸ä¼ ï¼æ¥è¯¢æ¶è¿å `storageBlobVOs` src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -421,6 +421,9 @@ Map<String, BigDecimal> monthPayableMap = new HashMap<>(); // æåº¦åºæ¶ï¼éå®åºåº-éè´§ï¼ salesOutboundVos.forEach(item -> { if (item.getShippingDate() == null) { return; } String month = item.getShippingDate().format(monthFormatter); monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getOutboundAmount()).orElse(BigDecimal.ZERO))); src/main/java/com/ruoyi/ai/tools/ManufacturingAgentTools.java
@@ -615,10 +615,10 @@ map.put("id", item.getId()); map.put("workOrderNo", safe(item.getWorkOrderNo())); map.put("productionOrderId", item.getProductionOrderId()); map.put("planStartTime", formatDate(item.getPlanStartTime())); map.put("planEndTime", formatDate(item.getPlanEndTime())); map.put("actualStartTime", formatDate(item.getActualStartTime())); map.put("actualEndTime", formatDate(item.getActualEndTime())); map.put("planStartTime", formatDateTime(item.getPlanStartTime())); map.put("planEndTime", formatDateTime(item.getPlanEndTime())); map.put("actualStartTime", formatDateTime(item.getActualStartTime())); map.put("actualEndTime", formatDateTime(item.getActualEndTime())); map.put("planQuantity", item.getPlanQuantity()); map.put("completeQuantity", item.getCompleteQuantity()); map.put("status", item.getStatus()); src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
@@ -1,14 +1,10 @@ package com.ruoyi.basic.dto; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.production.bean.dto.ProductStructureDto; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.List; @EqualsAndHashCode(callSuper = true) @Data public class ProductModelDto extends ProductModel { private List<ProductStructureDto> productStructureList; } src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java
@@ -4,7 +4,7 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; @Data public class ProductionTaskStatisticsDto { @@ -16,16 +16,16 @@ private String workOrderNo; @Schema(description = "计åå¼å§æ¶é´") private LocalDate planStartTime; private LocalDateTime planStartTime; @Schema(description = "计åç»ææ¶é´") private LocalDate planEndTime; private LocalDateTime planEndTime; @Schema(description = "å®é å¼å§æ¶é´") private LocalDate actualStartTime; private LocalDateTime actualStartTime; @Schema(description = "å®é ç»ææ¶é´") private LocalDate actualEndTime; private LocalDateTime actualEndTime; @Schema(description = "è®¡åæ°é") private BigDecimal planQuantity; src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -47,4 +47,10 @@ @Schema(description = "æ¯å¦ç产") private Integer isProduction; @Schema(description = "æ¯å¦æå½åç»å½ç¨æ·è¿æ»¤æé") private Boolean filterByCurrentUser; @Schema(description = "å½åç¨æ·IDï¼ç¨äºSQLæéè¿æ»¤") private Long currentUserId; } src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
@@ -1,5 +1,6 @@ package com.ruoyi.production.bean.dto; import com.fasterxml.jackson.annotation.JsonProperty; import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam; import com.ruoyi.production.pojo.ProductionProductMain; import io.swagger.v3.oas.annotations.media.Schema; @@ -71,4 +72,32 @@ @Schema(description = "å·¥åºåæ°å表") private List<ProductionOrderRoutingOperationParam> productionOperationParamList; @Schema(description = "å½åç¨æ·IDï¼ç¨äºæéè¿æ»¤") private Long currentUserId; @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public void setId(Long id) { super.setId(id); } @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public Long getId() { return super.getId(); } @Schema(description = "å¼å§æ¥å·¥è®°å½IDï¼ç»ææ¥å·¥æ¶ä¼ å ¥ï¼") private Long startRecordId; /** * è·åç»ææ¥å·¥æéçå¼å§è®°å½IDï¼ä¼å å startRecordIdï¼å ¶æ¬¡åç»§æ¿ç id */ public Long resolveStartRecordId() { if (startRecordId != null) { return startRecordId; } return super.getId(); } } src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
@@ -35,9 +35,6 @@ @Schema(description = "产åå¾ç") private List<StorageBlobVO> productImages; @Schema(description = "bomç¼å·") private String bomNo; @Schema(description = "宿è¿åº¦") @Excel(name = "宿è¿åº¦",sort = 7) private BigDecimal completionStatus; src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -1,6 +1,7 @@ package com.ruoyi.production.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; @@ -24,14 +25,24 @@ @GetMapping("/page") @Operation(summary = "å页æ¥è¯¢") public R page(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { return R.ok(productionOperationTaskService.pageProductionOperationTask(page, dto)); public R page(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto, @RequestParam(required = false) Boolean filterMine) { Long currentUserId = null; if (Boolean.TRUE.equals(filterMine)) { currentUserId = SecurityUtils.getUserId(); } return R.ok(productionOperationTaskService.pageProductionOperationTask(page, dto, currentUserId)); } @GetMapping("/list") @Operation(summary = "å·¥åå表") public R<List<ProductionOperationTaskVo>> list(ProductionOperationTaskDto dto) { return R.ok(productionOperationTaskService.listProductionOperationTask(dto)); public R<List<ProductionOperationTaskVo>> list(ProductionOperationTaskDto dto, @RequestParam(required = false) Boolean filterMine) { Long currentUserId = null; if (Boolean.TRUE.equals(filterMine)) { currentUserId = SecurityUtils.getUserId(); } return R.ok(productionOperationTaskService.listProductionOperationTask(dto, currentUserId)); } @GetMapping("/{id}") src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
@@ -8,7 +8,6 @@ import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionOrderPickVo; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; @@ -84,12 +83,6 @@ @Operation(summary = "çäº§è®¢åæ¥è¯¢æ¥æº") public R<List<ProductionPlanVo>> getSource(@PathVariable Long id) { return R.ok(productionOrderService.getSource(id)); } @GetMapping("/pick/{productionOrderId}") @Operation(summary = "æ ¹æ®è®¢åidæ¥è¯¢bom颿å") public R<List<ProductionOrderPickVo>> pick(@PathVariable Long productionOrderId) { return R.ok(productionOrderService.pick(productionOrderId)); } @GetMapping("/ordeDetail") src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
@@ -56,6 +56,17 @@ return R.ok(productionProductMainService.addProductMain(productionProductMainDto)); } /** * å¼å§æ¥å·¥ * @param productionProductMainDto * @return */ @PostMapping("/startWork") @PreAuthorize("@ss.hasPermi('productionProductMain:add')") public R startWork(@RequestBody ProductionProductMainDto productionProductMainDto) { return R.ok(productionProductMainService.startWork(productionProductMainDto)); } @PostMapping @Operation(summary = "æ°å¢ç产æ¥å·¥") public R add(@RequestBody ProductionProductMainDto productionProductMainDto) { src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
@@ -1,12 +1,13 @@ package com.ruoyi.production.pojo; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; /** @@ -43,16 +44,24 @@ private String workOrderNo; @Schema(description = "计åå¼å§æ¶é´") private LocalDate planStartTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime planStartTime; @Schema(description = "计åç»ææ¶é´") private LocalDate planEndTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime planEndTime; @Schema(description = "å®é å¼å§æ¶é´") private LocalDate actualStartTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime actualStartTime; @Schema(description = "å®é ç»ææ¶é´") private LocalDate actualEndTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime actualEndTime; @Schema(description = "ç¶æ 1 å¾ ç¡®è®¤ 2 å¾ ç产 3çäº§ä¸ 4å·²ç产") private Integer status; src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
@@ -87,4 +87,7 @@ @Schema(description = "æ¯å¦ç»æï¼") @TableField("is_end_order") private Boolean endOrder; @Schema(description = "å¤ç½®æ¹å¼ï¼ä¸åæ ¼åå¤çååä¼ ï¼2=åå ç»´ä¿®,3=è¿åç»´ä¿®ï¼") private Integer disposalMethod; } src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
@@ -48,12 +48,6 @@ @Schema(description = "å·¥èºè·¯çº¿ç¼ç ") private String processRouteCode; @Schema(description = "åºç¡bomçid") private Long bomId; @Schema(description = "订åbomçid") private Long orderBomId; @Schema(description = "å建人ID") @TableField(fill = FieldFill.INSERT) private Long createUser; src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
@@ -60,4 +60,14 @@ @Schema(description = "å·¥æ¶") private BigDecimal workHour; @Schema(description = "å®é å¼å§æ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime actualStartTime; @Schema(description = "å®é ç»ææ¶é´") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime actualEndTime; } src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -13,9 +13,11 @@ public interface ProductionOperationTaskService extends IService<ProductionOperationTask> { IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto productionOperationTaskDto); ProductionOperationTaskDto productionOperationTaskDto, Long currentUserId); List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto productionOperationTaskDto); List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto productionOperationTaskDto, Long currentUserId); ProductionOperationTaskVo getProductionOperationTaskInfo(Long id); src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/ProductionOrderService.java
@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionOrderPickVo; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; @@ -29,8 +28,6 @@ Object bindingRoute(ProductionOrderDto productionOrderDto); List<ProductionPlanVo> getSource(Long id); List<ProductionOrderPickVo> pick(Long productionOrderId); ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto productionOrderDto); src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
@@ -18,6 +18,8 @@ Boolean addProductMain(ProductionProductMainDto productionProductMainDto); Boolean startWork(ProductionProductMainDto productionProductMainDto); Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto); Boolean removeProductMain(Long id); src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -60,9 +60,12 @@ private String tempDir; @Override public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto, Long currentUserId) { // å页æ¥è¯¢ç产工åºä»»å¡ Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); if (dto != null && currentUserId != null) { dto.setCurrentUserId(currentUserId); } IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto); fillOperationTypes(result.getRecords()); fillUserNames(result.getRecords()); @@ -70,8 +73,11 @@ } @Override public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) { public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto, Long currentUserId) { // æ¥è¯¢å·¥åºä»»å¡å表 if (dto != null && currentUserId != null) { dto.setCurrentUserId(currentUserId); } List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class); fillOperationTypes(result); fillUserNames(result); src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
ÎļþÒÑɾ³ý src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
@@ -7,7 +7,6 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.mapper.*; import com.ruoyi.production.util.TaskPlanQuantityUtil; import com.ruoyi.technology.mapper.*; import com.ruoyi.production.pojo.*; import com.ruoyi.production.service.ProductionOrderRoutingOperationService; @@ -37,8 +36,6 @@ private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; private final ProductionOrderMapper productionOrderMapper; private final ProductionOrderRoutingMapper productionOrderRoutingMapper; private final ProductionOrderBomMapper productionOrderBomMapper; private final ProductionBomStructureMapper productionBomStructureMapper; private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; @Override @@ -137,37 +134,9 @@ throw new ServiceException("ç产订åä¸åå¨"); } // è·å订åBOM ProductionOrderBom orderBom = productionOrderBomMapper.selectOne( Wrappers.<ProductionOrderBom>lambdaQuery() .eq(ProductionOrderBom::getProductionOrderId, productionOrder.getId())); // ç¡®å®æ ¹äº§åè§æ ¼ID Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null ? orderBom.getProductModelId() : productionOrder.getProductModelId(); // è·åBOMç»æå表 List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null ? Collections.emptyList() : productionBomStructureMapper.selectList( Wrappers.<ProductionBomStructure>lambdaQuery() .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) .orderByAsc(ProductionBomStructure::getId)); // æå»ºå·¥åºéæ±éæ å° Map<String, BigDecimal> operationDemandedQuantityMap = TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId); // è·åå·¥èºè·¯çº¿å·¥åºï¼ç¨äºè®¡ç®è®¡åæ°éï¼ TechnologyRoutingOperation sourceOperation = technologyRoutingOperationMapper.selectById( updatedOperation.getTechnologyRoutingOperationId()); // å°åæ¥çç§ææ¹æ³æ¿æ¢ä¸ºè°ç¨å·¥å ·ç±» BigDecimal planQuantity = TaskPlanQuantityUtil.resolveTaskPlanQuantity( sourceOperation, operationDemandedQuantityMap, productionOrder, rootProductModelId); BigDecimal planQuantity = productionOrder.getQuantity() != null ? productionOrder.getQuantity() : BigDecimal.ZERO; task.setPlanQuantity(planQuantity); task.setCompleteQuantity(BigDecimal.ZERO); task.setWorkOrderNo(generateNextTaskNo()); src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -16,9 +16,7 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionBomStructureVo; import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; import com.ruoyi.production.bean.vo.ProductionOrderPickVo; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; @@ -34,8 +32,6 @@ import com.ruoyi.production.service.ProductionOrderService; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.stock.mapper.StockInventoryMapper; import com.ruoyi.stock.pojo.StockInventory; import com.ruoyi.technology.mapper.*; import com.ruoyi.technology.pojo.*; import lombok.RequiredArgsConstructor; @@ -58,18 +54,13 @@ private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; private final ProductionOperationTaskMapper productionOperationTaskMapper; private final ProductionOrderBomMapper productionOrderBomMapper; private final ProductionBomStructureMapper productionBomStructureMapper; private final ProductionOrderMapper productionOrderMapper; private final ProductionProductMainMapper productionProductMainMapper; private final ProductionProductOutputMapper productionProductOutputMapper; private final ProductionOrderPickMapper productionOrderPickMapper; private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper; private final QualityInspectMapper qualityInspectMapper; private final QualityInspectParamMapper qualityInspectParamMapper; private final QualityInspectFileMapper qualityInspectFileMapper; private final ProductionPlanMapper productionPlanMapper; private final StockInventoryMapper stockInventoryMapper; private final StorageAttachmentMapper storageAttachmentMapper; private final StorageBlobMapper storageBlobMapper; private final SalesLedgerMapper salesLedgerMapper; @@ -78,8 +69,6 @@ private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper; private final TechnologyOperationMapper technologyOperationMapper; private final TechnologyBomMapper technologyBomMapper; private final TechnologyBomStructureMapper technologyBomStructureMapper; private final FileUtil fileUtil; @Override @@ -212,9 +201,7 @@ @Override public int syncProductionOrderSnapshot(Long productionOrderId) { // åæ¥è®¢åå·¥èºãå·¥åºãåæ°åBOMå¿«ç § ProductionOrder productionOrder = this.getById(productionOrderId); // åæ°ä¸åç½®æ¡ä»¶æ ¡éª if (productionOrder == null) { throw new ServiceException("ç产订åä¸åå¨"); } @@ -225,42 +212,24 @@ if (technologyRouting == null) { throw new ServiceException("å·¥èºè·¯çº¿ä¸åå¨"); } // 订åå¿«ç §æâå æ¸ å建âå¤çï¼ä¿è¯å·¥èºè·¯çº¿ãå·¥åºãåæ°ãBOM å ¨é¨æ¥èªåä¸çæ¬ã clearProductionSnapshot(productionOrderId); ProductionOrderBom orderBom = syncProductionOrderBomSnapshot(productionOrder, technologyRouting); //ç产订åå·¥èºè·¯çº¿è¡¨ ProductionOrderRouting orderRouting = new ProductionOrderRouting(); orderRouting.setProductionOrderId(productionOrder.getId()); orderRouting.setTechnologyRoutingId(technologyRouting.getId()); orderRouting.setProductModelId(technologyRouting.getProductModelId()); orderRouting.setProcessRouteCode(technologyRouting.getProcessRouteCode()); orderRouting.setDescription(technologyRouting.getDescription()); orderRouting.setBomId(technologyRouting.getBomId()); orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId()); productionOrderRoutingMapper.insert(orderRouting); int syncedParamCount = 0; // æ¥è¯¢å¹¶åå¤ä¸å¡æ°æ® List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList( Wrappers.<TechnologyRoutingOperation>lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId()) .orderByDesc(TechnologyRoutingOperation::getDragSort) .orderByDesc(TechnologyRoutingOperation::getId)); // Build task plan quantities from order BOM snapshot demand instead of recomputing from technology BOM units. Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null ? orderBom.getProductModelId() : productionOrder.getProductModelId(); List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null ? Collections.emptyList() : productionBomStructureMapper.selectList( Wrappers.<ProductionBomStructure>lambdaQuery() .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) .orderByAsc(ProductionBomStructure::getId)); Map<String, BigDecimal> operationDemandedQuantityMap = buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId); BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity()); Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds( // éåå¤çæ°æ®å¹¶ç»è£ ç»æ routingOperations.stream() .map(TechnologyRoutingOperation::getTechnologyOperationId) .filter(Objects::nonNull) @@ -273,7 +242,6 @@ .max(Integer::compareTo) .orElse(null); for (TechnologyRoutingOperation sourceOperation : routingOperations) { // 订åå·¥åºä¿åçæ¯å·¥èºå·¥åºå¿«ç §ï¼åç»æ¥å·¥åªä¾èµå¿«ç §ï¼ä¸åç´æ¥å¼ç¨å·¥èºä¸»æ°æ®ã ProductionOrderRoutingOperation targetOperation = new ProductionOrderRoutingOperation(); targetOperation.setProductionOrderId(productionOrder.getId()); targetOperation.setTechnologyRoutingOperationId(sourceOperation.getId()); @@ -292,11 +260,7 @@ ProductionOperationTask task = new ProductionOperationTask(); task.setProductionOrderRoutingOperationId(targetOperation.getId()); task.setProductionOrderId(productionOrder.getId()); task.setPlanQuantity(resolveTaskPlanQuantity( sourceOperation, operationDemandedQuantityMap, productionOrder, rootProductModelId)); task.setPlanQuantity(orderQuantity); task.setCompleteQuantity(BigDecimal.ZERO); task.setWorkOrderNo(generateNextTaskNo()); task.setStatus(2); @@ -308,7 +272,6 @@ .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, sourceOperation.getId()) .orderByAsc(TechnologyRoutingOperationParam::getId)); for (TechnologyRoutingOperationParam sourceParam : sourceParams) { // å·¥åºæ§è¡åæ°åæ ·åå¿«ç §ï¼é¿å å·¥èºåæ°è°æ´å½±åå·²ä¸è¾¾è®¢åã ProductionOrderRoutingOperationParam targetParam = new ProductionOrderRoutingOperationParam(); targetParam.setProductionOrderId(productionOrder.getId()); targetParam.setProductionOrderRoutingOperationId(targetOperation.getId()); @@ -331,150 +294,12 @@ return syncedParamCount; } private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> bomStructures, Long rootProductModelId) { if (bomStructures == null || bomStructures.isEmpty()) { return Collections.emptyMap(); } Map<Long, ProductionBomStructure> structureById = bomStructures.stream() .filter(item -> item != null && item.getId() != null) .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); Map<String, BigDecimal> demandedQuantityMap = new HashMap<>(); Set<String> mergedOutputNodeKeySet = new HashSet<>(); for (ProductionBomStructure bomStructure : bomStructures) { if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) { continue; } // The BOM row points to the producing operation; task quantity should come from that operation's output node. ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById); Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId); if (outputProductModelId == null) { continue; } String mergedOutputNodeKey = buildOperationOutputNodeKey( bomStructure.getTechnologyOperationId(), outputNode == null ? null : outputNode.getId(), outputProductModelId); if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) { continue; } // demandedQuantity is already the order-level required output quantity for the current output node. BigDecimal demandedQuantity = defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()); String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId); demandedQuantityMap.merge(key, demandedQuantity, BigDecimal::add); } return demandedQuantityMap; } private BigDecimal resolveTaskPlanQuantity(TechnologyRoutingOperation sourceOperation, Map<String, BigDecimal> operationDemandedQuantityMap, ProductionOrder productionOrder, Long rootProductModelId) { if (sourceOperation == null || operationDemandedQuantityMap == null || operationDemandedQuantityMap.isEmpty()) { return defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); } Long outputProductModelId = sourceOperation.getProductModelId() != null ? sourceOperation.getProductModelId() : rootProductModelId; String key = buildOperationDemandedQuantityKey(sourceOperation.getTechnologyOperationId(), outputProductModelId); BigDecimal planQuantity = operationDemandedQuantityMap.get(key); return planQuantity != null ? planQuantity : defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); } private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) { return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId); } private String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) { return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId); } private ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure, Map<Long, ProductionBomStructure> structureById) { if (bomStructure == null) { return null; } // The root node is the first output node; child rows use their direct parent as the current operation output. if (bomStructure.getParentId() == null) { return bomStructure; } ProductionBomStructure parent = structureById.get(bomStructure.getParentId()); return parent != null ? parent : bomStructure; } private Long resolveOutputProductModelId(ProductionBomStructure outputNode, Long rootProductModelId) { if (outputNode == null) { return rootProductModelId; } return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId; } private ProductionOrderBom syncProductionOrderBomSnapshot(ProductionOrder productionOrder, TechnologyRouting technologyRouting) { // åæ¥è®¢åBOMå¿«ç §ç»æ if (technologyRouting.getBomId() == null) { return null; } TechnologyBom technologyBom = technologyBomMapper.selectById(technologyRouting.getBomId()); if (technologyBom == null) { throw new ServiceException("å·¥èºBOMä¸åå¨"); } // æ¥è¯¢å¹¶åå¤ä¸å¡æ°æ® List<TechnologyBomStructure> structureList = technologyBomStructureMapper.selectList( Wrappers.<TechnologyBomStructure>lambdaQuery() .eq(TechnologyBomStructure::getBomId, technologyBom.getId()) .orderByAsc(TechnologyBomStructure::getId)); // éåå¤çæ°æ®å¹¶ç»è£ ç»æ TechnologyBomStructure root = structureList.stream().filter(item -> item.getParentId() == null).findFirst().orElse(null); BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity()); ProductionOrderBom orderBom = new ProductionOrderBom(); orderBom.setProductionOrderId(productionOrder.getId()); orderBom.setBomId(Long.valueOf(technologyBom.getId())); orderBom.setProductModelId(root != null ? root.getProductModelId() : productionOrder.getProductModelId()); orderBom.setRemark(technologyBom.getRemark()); orderBom.setBomNo(technologyBom.getBomNo()); orderBom.setVersion(technologyBom.getVersion()); // æä¹ åæè¾åºå¤çç»æ productionOrderBomMapper.insert(orderBom); Map<Long, Long> idMap = new HashMap<>(); BigDecimal lastProcessDemandedQuantity = orderQuantity; for (TechnologyBomStructure source : structureList) { // åèç¹ parentId éè¦æ å°ææ°å¿«ç §èç¹ idï¼æè½ä¿çåå§ BOM å±çº§ã ProductionBomStructure target = new ProductionBomStructure(); target.setProductionOrderId(productionOrder.getId()); target.setProductionOrderBomId(orderBom.getId()); target.setParentId(source.getParentId() == null ? null : idMap.get(source.getParentId())); target.setProductModelId(source.getProductModelId()); target.setTechnologyOperationId(source.getOperationId()); target.setUnitQuantity(source.getUnitQuantity()); target.setDemandedQuantity(lastProcessDemandedQuantity.multiply(source.getUnitQuantity())); target.setUnit(source.getUnit()); productionBomStructureMapper.insert(target); idMap.put(source.getId(), target.getId()); lastProcessDemandedQuantity = target.getDemandedQuantity(); } return orderBom; } private void clearProductionSnapshot(Long productionOrderId) { // æ¸ ç订åå·²çæçå·¥èºä¸BOMå¿«ç §æ°æ® boolean hasPickRecord = productionOrderPickRecordMapper.selectCount( // æ¥è¯¢å¹¶åå¤ä¸å¡æ°æ® Wrappers.<ProductionOrderPickRecord>lambdaQuery() .eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)) > 0; // åæ°ä¸åç½®æ¡ä»¶æ ¡éª if (hasPickRecord) { throw new ServiceException("ç产订åå·²åå¨é¢æè®°å½ï¼ä¸è½éæ°çæå¿«ç §"); } List<Long> taskIds = productionOperationTaskMapper.selectList( Wrappers.<ProductionOperationTask>lambdaQuery() .eq(ProductionOperationTask::getProductionOrderId, productionOrderId)) // éåå¤çæ°æ®å¹¶ç»è£ ç»æ .stream().map(ProductionOperationTask::getId).collect(Collectors.toList()); if (!taskIds.isEmpty()) { // å·²ææ¥å·¥è®°å½è¯´æè®¢åå·²å¼å·¥ï¼æ¤æ¶ä¸å 许åéå»ºå¿«ç §ã boolean started = productionProductMainMapper.selectCount( Wrappers.<ProductionProductMain>lambdaQuery() .in(ProductionProductMain::getProductionOperationTaskId, taskIds)) > 0; @@ -490,12 +315,6 @@ .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId)); productionOrderRoutingMapper.delete(Wrappers.<ProductionOrderRouting>lambdaQuery() .eq(ProductionOrderRouting::getProductionOrderId, productionOrderId)); productionBomStructureMapper.delete(Wrappers.<ProductionBomStructure>lambdaQuery() .eq(ProductionBomStructure::getProductionOrderId, productionOrderId)); productionOrderBomMapper.delete(Wrappers.<ProductionOrderBom>lambdaQuery() .eq(ProductionOrderBom::getProductionOrderId, productionOrderId)); productionOrderPickMapper.delete(Wrappers.<ProductionOrderPick>lambdaQuery() .eq(ProductionOrderPick::getProductionOrderId, productionOrderId)); } private LambdaQueryWrapper<ProductionOrder> buildQueryWrapper(ProductionOrderDto dto) { @@ -1013,122 +832,6 @@ throw new ServiceException("ç产订åä¸åå¨"); } return productionOrder.getId(); } @Override public List<ProductionOrderPickVo> pick(Long productionOrderId) { // æ¥è¯¢è®¢åé¢æãææä¸éææç» if (productionOrderId == null) { return Collections.emptyList(); } // æ¥è¯¢å¹¶åå¤ä¸å¡æ°æ® ProductionOrderBom orderBom = productionOrderBomMapper.selectOne( Wrappers.<ProductionOrderBom>lambdaQuery() .eq(ProductionOrderBom::getProductionOrderId, productionOrderId) .orderByDesc(ProductionOrderBom::getId) .last("limit 1")); if (orderBom == null || orderBom.getId() == null) { return Collections.emptyList(); } // æ¥è¯¢å®æ´çBOMç»æï¼å æ¬æ ¹èç¹ï¼ï¼ç¨äºè®¡ç®å±çº§éæ±æ°é List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.listByBomId(orderBom.getId()); if (bomStructureList == null || bomStructureList.isEmpty()) { return Collections.emptyList(); } // æ¥è¯¢ç产订åè·åè®¢åæ°é ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId); BigDecimal orderQuantity = productionOrder != null ? defaultDecimal(productionOrder.getQuantity()) : BigDecimal.ZERO; // æå»ºæ å½¢ç»æå¹¶è®¡ç®å±çº§éæ±æ°é Map<Long, ProductionBomStructureVo> structureByIdMap = bomStructureList.stream() .filter(s -> s != null && s.getId() != null) .collect(Collectors.toMap(ProductionBomStructureVo::getId, s -> s)); // æå±çº§è®¡ç®éæ±æ°éï¼åçº§éæ±æ°é = ç¶çº§éæ±æ°é à å级åä½äº§åºæéæ°é for (ProductionBomStructureVo structure : bomStructureList) { if (structure == null) continue; if (structure.getParentId() == null || structure.getParentId() == 0) { // æ ¹èç¹ï¼éæ±æ°é = è®¢åæ°é structure.setDemandedQuantity(orderQuantity); } else { // åèç¹ï¼éæ±æ°é = ç¶çº§éæ±æ°é à å级åä½äº§åºæéæ°é ProductionBomStructureVo parent = structureByIdMap.get(structure.getParentId()); if (parent != null) { BigDecimal parentDemandedQty = defaultDecimal(parent.getDemandedQuantity()); BigDecimal unitQuantity = defaultDecimal(structure.getUnitQuantity()); structure.setDemandedQuantity(parentDemandedQty.multiply(unitQuantity)); } } } // è¿æ»¤åºéæ ¹èç¹ï¼å®é é¢æé¡¹ï¼ // æé¤æå ¥åä¸äº§åºåç¸å䏿¯ä¾ä¸º1çæ åµï¼èªèº«å å·¥ï¼ä¸éè¦é¢æï¼ List<ProductionBomStructureVo> childStructureList = bomStructureList.stream() .filter(s -> s != null && s.getParentId() != null && s.getParentId() != 0) .filter(s -> { ProductionBomStructureVo parent = structureByIdMap.get(s.getParentId()); if (parent == null) { return true; } // æå ¥åä¸äº§åºåç¸å䏿¯ä¾ä¸º1æ¶ï¼ä¸éè¦é¢æ boolean sameProduct = Objects.equals(s.getProductModelId(), parent.getProductModelId()); boolean unitRatio = BigDecimal.ONE.compareTo(defaultDecimal(s.getUnitQuantity())) == 0; return !(sameProduct && unitRatio); }) .collect(Collectors.toList()); // éåå¤çæ°æ®å¹¶ç»è£ ç»æ List<Long> productModelIds = childStructureList.stream() .map(ProductionBomStructureVo::getProductModelId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); Map<Long, BigDecimal> stockQuantityMap = new HashMap<>(); Map<Long, LinkedHashSet<String>> stockBatchNoMap = new HashMap<>(); if (!productModelIds.isEmpty()) { List<StockInventory> stockList = stockInventoryMapper.selectList( Wrappers.<StockInventory>lambdaQuery() .in(StockInventory::getProductModelId, productModelIds)); for (StockInventory stockItem : stockList) { if (stockItem == null || stockItem.getProductModelId() == null) { continue; } Long productModelId = stockItem.getProductModelId(); stockQuantityMap.merge(productModelId, defaultDecimal(stockItem.getQualitity()), BigDecimal::add); String batchNo = stockItem.getBatchNo(); if (batchNo != null && !batchNo.trim().isEmpty()) { stockBatchNoMap.computeIfAbsent(productModelId, key -> new LinkedHashSet<>()).add(batchNo); } } } List<ProductionOrderPickVo> pickList = new ArrayList<>(); for (ProductionBomStructureVo structure : childStructureList) { if (structure == null || structure.getProductModelId() == null) { continue; } Long productModelId = structure.getProductModelId(); ProductionOrderPickVo vo = new ProductionOrderPickVo(); vo.setProductModelId(productModelId); vo.setOperationName(structure.getOperationName()); vo.setTechnologyOperationId(structure.getTechnologyOperationId()); vo.setProductName(structure.getProductName()); vo.setModel(structure.getModel()); vo.setDemandedQuantity(defaultDecimal(structure.getDemandedQuantity())); vo.setUnit(structure.getUnit()); List<String> batchNoList = stockBatchNoMap.get(productModelId) == null ? Collections.emptyList() : new ArrayList<>(stockBatchNoMap.get(productModelId)); vo.setBatchNoList(batchNoList); vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO)); vo.setBom(true); pickList.add(vo); } return pickList; } @Override src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
@@ -63,7 +63,7 @@ * 1. ä» å 许åä¸äº§ååå·ç计ååå¹¶ï¼ * 2. å·²ä¸åæé¨åä¸åç计åä¸å è®¸åæ¬¡åå¹¶ï¼ * 3. ä¸åæ°éä¸è½å¤§äºæé计åå©ä½éæ±æ»éï¼ * 4. ä¸åæ¶ç»ä¸è°ç¨ ProductionOrderService.saveProductionOrderï¼ç¡®ä¿åç»å·¥èº/BOM/颿é»è¾ä¸è´ã * 4. ä¸åæ¶ç»ä¸è°ç¨ ProductionOrderService.saveProductionOrderï¼ç¡®ä¿åç»å·¥èºé»è¾ä¸è´ã */ @Override @Transactional(rollbackFor = Exception.class) src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -1,5 +1,6 @@ package com.ruoyi.production.service.impl; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -14,9 +15,9 @@ import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.production.bean.dto.ProductStructureDto; import com.ruoyi.production.bean.dto.ProductionProductMainDto; import com.ruoyi.production.enums.ProductOrderStatusEnum; import com.ruoyi.production.mapper.*; @@ -39,13 +40,14 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -72,8 +74,6 @@ private final ProductionAccountMapper productionAccountMapper; private final ProductionOperationTaskMapper productionOperationTaskMapper; private final ProductionOrderMapper productionOrderMapper; private final ProductionOrderBomMapper productionOrderBomMapper; private final ProductionBomStructureMapper productionBomStructureMapper; private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; @@ -219,106 +219,179 @@ @Override public Boolean addProductMain(ProductionProductMainDto dto) { // æ°å¢ç产æ¥å·¥ä¸»è®°å½ // å ¼å®¹æ§æµç¨ï¼å¦ææ²¡æå¼å§æ¥å·¥è®°å½IDï¼èµ°ä¸æ¥æ¥å·¥ï¼èªå¨å建+ç»æï¼ Long startRecordId = dto.resolveStartRecordId(); if (startRecordId == null) { return oneStepWork(dto); } dto.setId(startRecordId); return finishWork(dto); } @Override public Boolean startWork(ProductionProductMainDto dto) { // å¼å§æ¥å·¥ï¼å建æ¥å·¥è®°å½ï¼æ è®°å®é å¼å§æ¶é´ Long taskId = resolveTaskId(dto); if (taskId == null) { throw new ServiceException("è¯·ä¼ å ¥ç产工åID"); } return addProductMainByProductionTask(dto); } @Override public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) { // ä¿åç产æ¥å·¥ä¸»è®°å½ return addProductMain(productionProductMainDto); } @Override public Boolean removeProductMain(Long id) { // å é¤ç产æ¥å·¥ä¸»è®°å½ ProductionProductMain currentMain = productionProductMainMapper.selectById(id); if (currentMain == null) { return true; } return removeProductMainByProductionTask(currentMain); } private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) { // æçäº§ä»»å¡æ°å¢æ¥å·¥ä¸»è®°å½ Long taskId = resolveTaskId(dto); if (taskId == null) { throw new ServiceException("ç产工åIDä¸è½ä¸ºç©º"); } SysUser user = userMapper.selectUserById(dto.getUserId()); ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId); if (productionOperationTask == null) { ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); if (task == null) { throw new ServiceException("ç产工åä¸åå¨"); } ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId()); if (routingOperation == null) { throw new ServiceException("订åå·¥èºè·¯çº¿å·¥åºä¸åå¨"); // æéæ ¡éªï¼å·²ææ´¾æ¶ä» è¢«ææ´¾äººå¯æä½ validateWorkerPermission(task); if (task.getStatus() != null && task.getStatus() != 2 && task.getStatus() != 3) { throw new ServiceException("å½åå·¥åç¶æä¸å 许å¼å§æ¥å·¥ï¼ä» å¾ ç产æç产ä¸ç¶æçå·¥å坿ä½"); } ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId()); if (productionOrder == null) { throw new ServiceException("ç产订åä¸åå¨"); SysUser user = userMapper.selectUserById(dto.getUserId()); ProductionProductMain main = new ProductionProductMain(); main.setProductNo(generateProductNo()); main.setUserId(user == null ? dto.getUserId() : user.getUserId()); main.setUserName(user == null ? dto.getUserName() : user.getNickName()); main.setProductionOperationTaskId(taskId); main.setStatus(0); main.setActualStartTime(LocalDateTime.now()); productionProductMainMapper.insert(main); // å·¥åç¶æ -> çäº§ä¸ task.setStatus(3); if (task.getActualStartTime() == null) { task.setActualStartTime(LocalDateTime.now()); } TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()); TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); ProductModel productModel = productModelMapper.selectById( routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : productionOrder.getProductModelId()); productionOperationTaskMapper.updateById(task); // ç产订å -> ç产è¿è¡ä¸ ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); if (productionOrder != null && productionOrder.getStartTime() == null) { productionOrder.setStartTime(LocalDateTime.now()); productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); productionOrderMapper.updateById(productionOrder); } return true; } private Boolean oneStepWork(ProductionProductMainDto dto) { // å ¼å®¹æ§ä¸æ¥æ¥å·¥æµç¨ï¼èªå¨å建å¼å§è®°å½å¹¶ç«å³ç»æ Long taskId = resolveTaskId(dto); if (taskId == null) { throw new ServiceException("è¯·ä¼ å ¥ç产工åID"); } ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); if (task == null) { throw new ServiceException("ç产工åä¸åå¨"); } validateWorkerPermission(task); if (task.getStatus() != null && task.getStatus() != 2 && task.getStatus() != 3) { throw new ServiceException("å½åå·¥åç¶æä¸å 许æ¥å·¥"); } SysUser user = userMapper.selectUserById(dto.getUserId()); ProductionProductMain main = new ProductionProductMain(); main.setProductNo(generateProductNo()); main.setUserId(user == null ? dto.getUserId() : user.getUserId()); main.setUserName(user == null ? dto.getUserName() : user.getNickName()); main.setProductionOperationTaskId(taskId); main.setStatus(0); main.setActualStartTime(LocalDateTime.now()); productionProductMainMapper.insert(main); if (task.getActualStartTime() == null) { task.setActualStartTime(LocalDateTime.now()); } task.setStatus(3); productionOperationTaskMapper.updateById(task); ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); if (productionOrder != null && productionOrder.getStartTime() == null) { productionOrder.setStartTime(LocalDateTime.now()); productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); productionOrderMapper.updateById(productionOrder); } dto.setId(main.getId()); return finishWork(dto); } private Boolean finishWork(ProductionProductMainDto dto) { // ç»ææ¥å·¥ï¼æ´æ°å¼å§æ¥å·¥è®°å½ï¼å建产åºãæå ¥åãæ ¸ç®è®°å½ ProductionProductMain currentMain = productionProductMainMapper.selectById(dto.getId()); if (currentMain == null) { throw new ServiceException("å¼å§æ¥å·¥è®°å½ä¸åå¨"); } if (currentMain.getStatus() == null || currentMain.getStatus() != 0) { throw new ServiceException("该æ¥å·¥è®°å½å·²ç»ææç¶æå¼å¸¸"); } Long taskId = currentMain.getProductionOperationTaskId(); ProductionOperationTask task = productionOperationTaskMapper.selectById(taskId); if (task == null) { throw new ServiceException("ç产工åä¸åå¨"); } validateWorkerPermission(task); // æ´æ°æ¥å·¥è®°å½ä¸ºå·²ç»æï¼è®°å½ç»ææ¶é´ currentMain.setActualEndTime(LocalDateTime.now()); currentMain.setStatus(1); if (dto.getWorkHour() != null) { currentMain.setWorkHour(dto.getWorkHour()); } else if (currentMain.getActualStartTime() != null) { // æ ¹æ®å¼å§/ç»ææ¶é´è®¡ç®å®é å·¥æ¶ï¼å°æ¶ï¼ long seconds = Duration.between(currentMain.getActualStartTime(), currentMain.getActualEndTime()).getSeconds(); currentMain.setWorkHour(BigDecimal.valueOf(seconds).divide(BigDecimal.valueOf(3600), 4, RoundingMode.HALF_UP)); } productionProductMainMapper.updateById(currentMain); // 忥工åºåæ° ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(task.getProductionOrderRoutingOperationId()); if (routingOperation != null) { syncOperationParamInputValue(dto, routingOperation.getId(), currentMain.getId()); } // è·å产åè§æ ¼ ProductModel productModel = null; if (routingOperation != null) { productModel = productModelMapper.selectById( routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : getProductionOrderProductModelId(task)); } if (productModel == null) { throw new ServiceException("产åè§æ ¼ä¸åå¨"); } ProductionProductMain productionProductMain = new ProductionProductMain(); productionProductMain.setProductNo(generateProductNo()); productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId()); productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName()); productionProductMain.setProductionOperationTaskId(taskId); productionProductMain.setStatus(0); productionProductMain.setWorkHour(dto.getWorkHour()); productionProductMainMapper.insert(productionProductMain); syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); // æå ¥å ProductionProductInput productionProductInput = new ProductionProductInput(); productionProductInput.setProductionProductMainId(currentMain.getId()); productionProductInput.setProductModelId(productModel.getId()); productionProductInput.setInputQuantity(defaultDecimal(dto.getQuantity())); productionProductInput.setQuantity(productionProductInput.getInputQuantity()); productionProductInputMapper.insert(productionProductInput); List<ProductStructureDto> productStructureDtos = resolveInputStructures( productionOrder.getId(), routingOperation, productModel.getId()); // å¦ææ²¡æbomåèç¹äºï¼é£ä¹æå ¥å°±æ¯ä»æ¬èº« if (productStructureDtos.isEmpty()) { ProductStructureDto fallbackInput = new ProductStructureDto(); fallbackInput.setProductModelId(productModel.getId()); fallbackInput.setUnitQuantity(BigDecimal.ONE); productStructureDtos.add(fallbackInput); } for (ProductStructureDto item : productStructureDtos) { // å½åå®ç°æå·¥åºæåç´æ¥ä½ä¸ºæå ¥ï¼åç»è¥æ¥å ¥é¢æè®°å½å¯å¨è¿éæ¿æ¢æ¥æºã ProductionProductInput productionProductInput = new ProductionProductInput(); productionProductInput.setProductionProductMainId(productionProductMain.getId()); productionProductInput.setProductModelId(item.getProductModelId()); productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity()))); productionProductInput.setQuantity(productionProductInput.getInputQuantity()); productionProductInputMapper.insert(productionProductInput); } // 产åºå ProductionProductOutput productionProductOutput = new ProductionProductOutput(); productionProductOutput.setProductionProductMainId(productionProductMain.getId()); productionProductOutput.setProductionProductMainId(currentMain.getId()); productionProductOutput.setProductModelId(productModel.getId()); productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity())); productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty())); productionProductOutputMapper.insert(productionProductOutput); BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity()); BigDecimal scrapQty = defaultDecimal(productionProductOutput.getScrapQty()); BigDecimal productQty = reportQty; String qualifiedBatchNo = null; List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( TechnologyRoutingOperation technologyRoutingOperation = routingOperation != null ? technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()) : null; TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); List<ProductionOrderRoutingOperation> routingOperationList = routingOperation != null ? productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())) : new ArrayList<>(); boolean isLastOperation = routingOperation != null && routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); if (productQty.compareTo(BigDecimal.ZERO) > 0) { if (Boolean.TRUE.equals(routingOperation.getIsQuality())) { // è´¨æ£å·¥åºå çææ£éªåï¼éè´¨æ£å·¥åºç´æ¥å ¥åæ ¼ååºåã if (routingOperation != null && Boolean.TRUE.equals(routingOperation.getIsQuality())) { int inspectType = isLastOperation ? 2 : 1; String process = isLastOperation ? null : technologyOperation == null ? null : technologyOperation.getName(); Product product = productMapper.selectById(productModel.getProductId()); @@ -331,7 +404,7 @@ qualityInspect.setProcess(process); qualityInspect.setInspectState(0); qualityInspect.setInspectType(inspectType); qualityInspect.setProductMainId(productionProductMain.getId()); qualityInspect.setProductMainId(currentMain.getId()); qualityInspect.setProductModelId(productModel.getId()); qualityInspectMapper.insert(qualityInspect); List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); @@ -350,45 +423,46 @@ } } else { StockInventoryDto stockInventoryDto = new StockInventoryDto(); stockInventoryDto.setRecordId(productionProductMain.getId()); stockInventoryDto.setRecordId(currentMain.getId()); stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode())); stockInventoryDto.setQualitity(productQty); stockInventoryDto.setProductModelId(productModel.getId()); stockInventoryService.addStockInRecordOnly(stockInventoryDto); qualifiedBatchNo = resolveLatestStockInBatchNo( productionProductMain.getId(), currentMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productModel.getId(), "0"); } productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty)); if (ObjectUtils.isNull(productionOperationTask.getActualStartTime())) { productionOperationTask.setActualStartTime(LocalDate.now()); task.setCompleteQuantity(defaultDecimal(task.getCompleteQuantity()).add(productQty)); if (task.getActualStartTime() == null) { task.setActualStartTime(LocalDateTime.now()); } // æ¥å·¥é©±å¨å·¥åç¶ææµè½¬ï¼æäº§åºå³è¿è¡ä¸ï¼è¾¾å°è®¡åéå³å®å·¥ã productionOperationTask.setStatus(3); if (productionOperationTask.getPlanQuantity() != null && productionOperationTask.getCompleteQuantity().compareTo(productionOperationTask.getPlanQuantity()) >= 0) { productionOperationTask.setActualEndTime(LocalDate.now()); productionOperationTask.setStatus(4); task.setStatus(3); if (task.getPlanQuantity() != null && task.getCompleteQuantity().compareTo(task.getPlanQuantity()) >= 0) { task.setActualEndTime(LocalDateTime.now()); task.setStatus(4); } productionOperationTaskMapper.updateById(productionOperationTask); productionOperationTaskMapper.updateById(task); if (ObjectUtils.isNull(productionOrder.getStartTime())) { productionOrder.setStartTime(LocalDateTime.now()); } // 订åç¶æç±æåä¸éå·¥åºçåæ ¼äº§åºæ¨å¨ï¼é¿å ä¸é´å·¥åºæåå®å·¥ã productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); if (isLastOperation) { productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty)); if (productionOrder.getQuantity() != null && productionOrder.getCompleteQuantity().compareTo(productionOrder.getQuantity()) >= 0) { productionOrder.setEndTime(LocalDateTime.now()); productionOrder.setStatus(ProductOrderStatusEnum.FINISHED.getCode()); ProductionOrder productionOrder = productionOrderMapper.selectById(task.getProductionOrderId()); if (productionOrder != null) { if (productionOrder.getStartTime() == null) { productionOrder.setStartTime(LocalDateTime.now()); } productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); if (isLastOperation) { productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty)); if (productionOrder.getQuantity() != null && productionOrder.getCompleteQuantity().compareTo(productionOrder.getQuantity()) >= 0) { productionOrder.setEndTime(LocalDateTime.now()); productionOrder.setStatus(ProductOrderStatusEnum.FINISHED.getCode()); } } productionOrderMapper.updateById(productionOrder); } productionOrderMapper.updateById(productionOrder); BigDecimal workHours = BigDecimal.ZERO; if (technologyOperation != null && technologyOperation.getSalaryQuota() != null) { @@ -397,13 +471,14 @@ : technologyOperation.getSalaryQuota(); } ProductionAccount productionAccount = new ProductionAccount(); productionAccount.setProductionProductMainId(productionProductMain.getId()); productionAccount.setSchedulingUserId(user == null ? null : user.getUserId()); productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName()); productionAccount.setProductionProductMainId(currentMain.getId()); SysUser user = userMapper.selectUserById(dto.getUserId()); productionAccount.setSchedulingUserId(user == null ? currentMain.getUserId() : user.getUserId()); productionAccount.setSchedulingUserName(user == null ? currentMain.getUserName() : user.getNickName()); productionAccount.setFinishedNum(productQty); productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null); productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName()); productionAccount.setSchedulingDate(LocalDateTime.now()); productionAccount.setSchedulingDate(currentMain.getActualEndTime() != null ? currentMain.getActualEndTime() : LocalDateTime.now()); productionAccountMapper.insert(productionAccount); } if (scrapQty.compareTo(BigDecimal.ZERO) > 0) { @@ -411,10 +486,54 @@ productModel.getId(), scrapQty, StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId(), currentMain.getId(), qualifiedBatchNo); } return true; } private Long getProductionOrderProductModelId(ProductionOperationTask task) { // ä»ç产订åè·å产åè§æ ¼ID if (task == null || task.getProductionOrderId() == null) { return null; } ProductionOrder order = productionOrderMapper.selectById(task.getProductionOrderId()); return order == null ? null : order.getProductModelId(); } private void validateWorkerPermission(ProductionOperationTask task) { // æ ¡éªå½åç¨æ·æ¯å¦æææä½æ¤å·¥åï¼æªææ´¾æ¶äººäººå¯æä½ï¼å·²ææ´¾æ¶ä» è¢«ææ´¾äººå¯æä½ if (task == null) { return; } String userIds = task.getUserIds(); if (userIds == null || userIds.isEmpty() || "[]".equals(userIds.trim())) { return; } Long currentUserId = SecurityUtils.getUserId(); if (currentUserId == null) { return; } List<Long> assignedIds = JSON.parseArray(userIds, Long.class); if (assignedIds == null || !assignedIds.contains(currentUserId)) { throw new ServiceException("æ¨æªè¢«ææ´¾å°æ¤å·¥åï¼æ æ³æä½"); } } @Override public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) { // ä¿åç产æ¥å·¥ä¸»è®°å½ return addProductMain(productionProductMainDto); } @Override public Boolean removeProductMain(Long id) { // å é¤ç产æ¥å·¥ä¸»è®°å½ ProductionProductMain currentMain = productionProductMainMapper.selectById(id); if (currentMain == null) { return true; } return removeProductMainByProductionTask(currentMain); } private String resolveLatestStockInBatchNo(Long recordId, @@ -502,64 +621,6 @@ target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId()); target.setProductionProductMainId(productionProductMainId); return target; } private List<ProductStructureDto> resolveInputStructures(Long productionOrderId, ProductionOrderRoutingOperation routingOperation, Long outputProductModelId) { if (productionOrderId == null || routingOperation == null || routingOperation.getTechnologyOperationId() == null) { return new ArrayList<>(); } ProductionOrderBom orderBom = productionOrderBomMapper.selectOne( Wrappers.<ProductionOrderBom>lambdaQuery() .eq(ProductionOrderBom::getProductionOrderId, productionOrderId) .orderByDesc(ProductionOrderBom::getId) .last("limit 1")); if (orderBom == null || orderBom.getId() == null) { return new ArrayList<>(); } List<ProductionBomStructure> bomNodeList = productionBomStructureMapper.selectList( Wrappers.<ProductionBomStructure>lambdaQuery() .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) .orderByAsc(ProductionBomStructure::getId)); if (bomNodeList.isEmpty()) { return new ArrayList<>(); } Map<Long, ProductionBomStructure> nodeMap = bomNodeList.stream() .filter(item -> item != null && item.getId() != null) .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); Long currentOutputModelId = routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : outputProductModelId; Map<Long, BigDecimal> unitQtyByProductModel = new LinkedHashMap<>(); for (ProductionBomStructure node : bomNodeList) { if (node == null || node.getParentId() == null || node.getProductModelId() == null) { continue; } if (!Objects.equals(node.getTechnologyOperationId(), routingOperation.getTechnologyOperationId())) { continue; } ProductionBomStructure parent = nodeMap.get(node.getParentId()); if (parent == null || !Objects.equals(parent.getProductModelId(), currentOutputModelId)) { continue; } unitQtyByProductModel.merge(node.getProductModelId(), defaultDecimal(node.getUnitQuantity()), BigDecimal::add); } List<ProductStructureDto> result = new ArrayList<>(); for (Map.Entry<Long, BigDecimal> entry : unitQtyByProductModel.entrySet()) { if (entry.getValue().compareTo(BigDecimal.ZERO) <= 0) { continue; } ProductStructureDto item = new ProductStructureDto(); item.setProductModelId(entry.getKey()); item.setUnitQuantity(entry.getValue()); result.add(item); } return result; } private Boolean removeProductMainByProductionTask(ProductionProductMain productionProductMain) { src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java
@@ -1,131 +1,14 @@ package com.ruoyi.production.util; import com.ruoyi.production.pojo.ProductionBomStructure; import com.ruoyi.production.pojo.ProductionOrder; import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import lombok.experimental.UtilityClass; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * å·¥åè®¡åæ°é计ç®å·¥å ·ç±» */ @UtilityClass public class TaskPlanQuantityUtil { /** * 计ç®å·¥åè®¡åæ°éï¼ä½¿ç¨ TechnologyRoutingOperationï¼ */ public BigDecimal resolveTaskPlanQuantity(TechnologyRoutingOperation sourceOperation, Map<String, BigDecimal> operationDemandedQuantityMap, ProductionOrder productionOrder, Long rootProductModelId) { if (sourceOperation == null || operationDemandedQuantityMap == null || operationDemandedQuantityMap.isEmpty()) { return defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); } Long outputProductModelId = sourceOperation.getProductModelId() != null ? sourceOperation.getProductModelId() : rootProductModelId; String key = buildOperationDemandedQuantityKey(sourceOperation.getTechnologyOperationId(), outputProductModelId); BigDecimal planQuantity = operationDemandedQuantityMap.get(key); return planQuantity != null ? planQuantity : defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); } /** * 计ç®å·¥åè®¡åæ°éï¼ä½¿ç¨ ProductionOrderRoutingOperationï¼ */ public BigDecimal resolveTaskPlanQuantity(ProductionOrderRoutingOperation routingOperation, Map<String, BigDecimal> demandedQuantityMap, BigDecimal orderQuantity, Long rootProductModelId) { if (routingOperation == null || demandedQuantityMap == null || demandedQuantityMap.isEmpty()) { return orderQuantity; } Long outputProductModelId = routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : rootProductModelId; String key = buildOperationDemandedQuantityKey(routingOperation.getTechnologyOperationId(), outputProductModelId); BigDecimal planQuantity = demandedQuantityMap.get(key); return planQuantity != null ? planQuantity : orderQuantity; } /** * æå»ºå·¥åºéæ±éæ å°è¡¨ */ public Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> bomStructures, Long rootProductModelId) { if (bomStructures == null || bomStructures.isEmpty()) { return Collections.emptyMap(); } Map<Long, ProductionBomStructure> structureById = new HashMap<>(); for (ProductionBomStructure item : bomStructures) { if (item != null && item.getId() != null) { structureById.put(item.getId(), item); } } Map<String, BigDecimal> demandedQuantityMap = new HashMap<>(); Set<String> mergedOutputNodeKeySet = new HashSet<>(); for (ProductionBomStructure bomStructure : bomStructures) { if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) { continue; } ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById); Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId); if (outputProductModelId == null) { continue; } String mergedOutputNodeKey = buildOperationOutputNodeKey(bomStructure.getTechnologyOperationId(), outputNode == null ? null : outputNode.getId(), outputProductModelId); if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) { continue; } BigDecimal demandedQuantity = defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()); String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId); demandedQuantityMap.merge(key, demandedQuantity, BigDecimal::add); } return demandedQuantityMap; } /** * æå»ºå·¥åºéæ±ékey */ public String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) { return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId); } /** * æå»ºè¾åºèç¹key */ public String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) { return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId); } /** * è§£æå·¥åºè¾åºèç¹ */ public ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure, Map<Long, ProductionBomStructure> structureById) { if (bomStructure == null) { return null; } if (bomStructure.getParentId() == null) { return bomStructure; } ProductionBomStructure parent = structureById.get(bomStructure.getParentId()); return parent != null ? parent : bomStructure; } /** * è§£æè¾åºäº§åè§æ ¼ID */ public Long resolveOutputProductModelId(ProductionBomStructure outputNode, Long rootProductModelId) { if (outputNode == null) { return rootProductModelId; } return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId; } /** * é»è®¤BigDecimalå¼ src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java
@@ -8,10 +8,12 @@ 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.mapper.QualityUnqualifiedOrderMapper; 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 jakarta.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; @@ -26,6 +28,8 @@ @Resource private IQualityUnqualifiedOrderService orderService; @Resource private QualityUnqualifiedOrderMapper orderMapper; @Resource private FileUtil fileUtil; @PostMapping("/save") @@ -33,29 +37,35 @@ @Log(title = "æ°å¢ä¸åæ ¼åå¤çå", businessType = BusinessType.INSERT) public R<?> save(@RequestBody QualityUnqualifiedOrder order) { String orderNo = OrderUtils.countTodayByCreateTime( orderService.getBaseMapper(), "BHG", "order_no", orderMapper, "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); if (order.getStatus() == null) { order.setStatus(order.getDisposalMethod() != null ? 3 : 0); } boolean result = orderService.save(order); if (result) { fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId(), order.getStorageBlobDTOs()); } return R.ok(result); } @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); boolean result = orderService.updateWithRework(order); if (result) { fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId(), order.getStorageBlobDTOs()); } return R.ok(result); } @DeleteMapping("/delete") @Operation(summary = "å é¤ä¸åæ ¼åå¤çå") @Log(title = "å é¤ä¸åæ ¼åå¤çå", businessType = BusinessType.DELETE) public R<?> delete(@RequestBody List<Long> ids) { return R.ok(orderService.removeBatchByIds(ids)); return R.ok(orderMapper.deleteByIds(ids) > 0); } @GetMapping("/listPage") @@ -71,4 +81,18 @@ public R<?> detail(@PathVariable Long id) { return R.ok(orderService.getDetail(id)); } @PostMapping("/deal") @Operation(summary = "ä¸åæ ¼åå¤ç") @Log(title = "ä¸åæ ¼åå¤ç", businessType = BusinessType.OTHER) public R<?> deal(@RequestBody QualityUnqualifiedOrder order) { return R.ok(orderService.deal(order)); } @GetMapping("/export/{id}") @Operation(summary = "导åºä¸åæ ¼åå¤çå") @Log(title = "导åºä¸åæ ¼åå¤çå", businessType = BusinessType.EXPORT) public void export(@PathVariable Long id, HttpServletResponse response) { orderService.export(id, response); } } src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java
@@ -7,8 +7,12 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper public interface QualityUnqualifiedOrderMapper extends BaseMapper<QualityUnqualifiedOrder> { IPage<QualityUnqualifiedOrder> listPage(Page page, @Param("query") QualityUnqualifiedOrder query); int deleteByIds(@Param("ids") List<Long> ids); } src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java
@@ -112,6 +112,15 @@ @Schema(description = "夿³¨") private String remark; @Schema(description = "责任é¨é¨ä¸»ç®¡æè§") private String deptOpinion; @Schema(description = "å ¬å¸å¤çå³å®") private String companyDecision; @Schema(description = "æ»ç»çæè§") private String generalManagerOpinion; @Schema(description = "åå»ºç¨æ·") @TableField(value = "create_by", fill = FieldFill.INSERT) private Integer createBy; @@ -136,7 +145,6 @@ @TableField(fill = FieldFill.INSERT) private Long deptId; @TableLogic @TableField(fill = FieldFill.INSERT) private Integer deleted; src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java
@@ -4,10 +4,19 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import jakarta.servlet.http.HttpServletResponse; public interface IQualityUnqualifiedOrderService extends IService<QualityUnqualifiedOrder> { IPage<QualityUnqualifiedOrder> listPage(Page page, QualityUnqualifiedOrder query); QualityUnqualifiedOrder getDetail(Long id); boolean save(QualityUnqualifiedOrder order); boolean deal(QualityUnqualifiedOrder order); boolean updateWithRework(QualityUnqualifiedOrder order); void export(Long id, HttpServletResponse response); } src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -16,6 +16,7 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.HackLoopTableRenderPolicy; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.web.domain.R; import com.ruoyi.procurementrecord.service.ProcurementRecordService; @@ -24,9 +25,11 @@ import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.mapper.QualityTestStandardMapper; import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; import com.ruoyi.quality.mapper.QualityUnqualifiedOrderMapper; import com.ruoyi.quality.pojo.QualityInspect; import com.ruoyi.quality.pojo.QualityInspectParam; import com.ruoyi.quality.pojo.QualityUnqualified; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import com.ruoyi.stock.pojo.StockInRecord; import com.ruoyi.stock.service.StockInRecordService; import com.ruoyi.quality.service.IQualityInspectParamService; @@ -67,6 +70,8 @@ private QualityTestStandardMapper qualityTestStandardMapper; private QualityUnqualifiedMapper qualityUnqualifiedMapper; private QualityUnqualifiedOrderMapper qualityUnqualifiedOrderMapper; private SalesLedgerProductMapper salesLedgerProductMapper; @@ -161,6 +166,26 @@ qualityUnqualified.setDefectivePhenomena(text + "è¿äºææ ä¸åå¨ä¸åæ ¼");//ä¸åæ ¼ç°è±¡ qualityUnqualified.setInspectId(qualityInspect.getId()); qualityUnqualifiedMapper.insert(qualityUnqualified); // èªå¨å建ä¸åæ ¼åå¤çåï¼æµå ¥æ°æ¨¡å QualityUnqualifiedOrder order = new QualityUnqualifiedOrder(); order.setUnqualifiedId(qualityUnqualified.getId()); order.setUnqualifiedProcess(qualityInspect.getInspectType() + 1); order.setUnqualifiedQuantity(qualityInspect.getUnqualifiedQuantity()); order.setQuantity(qualityInspect.getQuantity()); order.setProductModelId(qualityInspect.getProductModelId()); order.setInspectorName(qualityInspect.getCheckName()); if (qualityInspect.getCheckTime() != null) { order.setInspectDate(new java.util.Date(qualityInspect.getCheckTime().getTime())); } order.setSupplierName(qualityInspect.getSupplier()); order.setSpecificationModel(qualityInspect.getModel()); order.setProblemDescription(qualityInspect.getDefectivePhenomena()); order.setStatus(0); String orderNo = OrderUtils.countTodayByCreateTime( qualityUnqualifiedOrderMapper, "BHG", "order_no", LocalDateTime.now()); order.setOrderNo(orderNo); qualityUnqualifiedOrderMapper.insert(order); } qualityInspect.setInspectState(1);//å·²æäº¤ src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java
@@ -1,15 +1,48 @@ package com.ruoyi.quality.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; 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.RecordTypeEnum; import com.ruoyi.basic.utils.FileUtil; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.production.mapper.ProductionOperationTaskMapper; import com.ruoyi.production.mapper.ProductionOrderMapper; import com.ruoyi.production.mapper.ProductionOrderRoutingMapper; import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper; import com.ruoyi.production.mapper.ProductionProductMainMapper; import com.ruoyi.production.pojo.ProductionOperationTask; import com.ruoyi.production.pojo.ProductionOrder; import com.ruoyi.production.pojo.ProductionOrderRouting; import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; import com.ruoyi.production.pojo.ProductionProductMain; import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; import com.ruoyi.quality.mapper.QualityUnqualifiedOrderMapper; import com.ruoyi.quality.pojo.QualityInspect; import com.ruoyi.quality.pojo.QualityUnqualified; import com.ruoyi.quality.pojo.QualityUnqualifiedOrder; import com.ruoyi.quality.service.IQualityInspectService; import com.ruoyi.quality.service.IQualityUnqualifiedOrderService; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @AllArgsConstructor @Service @@ -17,6 +50,13 @@ private final QualityUnqualifiedOrderMapper orderMapper; private final FileUtil fileUtil; private final QualityUnqualifiedMapper qualityUnqualifiedMapper; private final IQualityInspectService qualityInspectService; private final ProductionProductMainMapper productionProductMainMapper; private final ProductionOrderMapper productionOrderMapper; private final ProductionOrderRoutingMapper productionOrderRoutingMapper; private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; private final ProductionOperationTaskMapper productionOperationTaskMapper; @Override public IPage<QualityUnqualifiedOrder> listPage(Page page, QualityUnqualifiedOrder query) { @@ -31,4 +71,277 @@ } return order; } @Override @Transactional(rollbackFor = Exception.class) public boolean save(QualityUnqualifiedOrder order) { boolean result = super.save(order); // å¤ç½®æ¹å¼å å«"ç»´ä¿®"ï¼2=åå ç»´ä¿®, 3=è¿åç»´ä¿®ï¼æ¶ï¼èªå¨å建è¿ä¿®ç产订å if (order.getDisposalMethod() != null && (order.getDisposalMethod() == 2 || order.getDisposalMethod() == 3)) { createReworkProductionOrder(order); } return result; } @Override @Transactional(rollbackFor = Exception.class) public boolean deal(QualityUnqualifiedOrder order) { QualityUnqualifiedOrder existing = orderMapper.selectById(order.getId()); if (existing == null) { return false; } existing.setDisposalMethod(order.getDisposalMethod()); existing.setRepairEvaluation(order.getRepairEvaluation()); existing.setReasonAnalysis(order.getReasonAnalysis()); existing.setCorrectionAction(order.getCorrectionAction()); existing.setPreventiveAction(order.getPreventiveAction()); existing.setRemark(order.getRemark()); existing.setDeptOpinion(order.getDeptOpinion()); existing.setCompanyDecision(order.getCompanyDecision()); existing.setGeneralManagerOpinion(order.getGeneralManagerOpinion()); existing.setStatus(3); boolean result = updateById(existing); if (result && existing.getDisposalMethod() != null && (existing.getDisposalMethod() == 2 || existing.getDisposalMethod() == 3)) { createReworkProductionOrder(existing); } return result; } @Override @Transactional(rollbackFor = Exception.class) public boolean updateWithRework(QualityUnqualifiedOrder order) { boolean result = updateById(order); if (result && order.getDisposalMethod() != null && (order.getDisposalMethod() == 2 || order.getDisposalMethod() == 3)) { createReworkProductionOrder(order); } return result; } @Override public void export(Long id, HttpServletResponse response) { QualityUnqualifiedOrder order = getDetail(id); if (order == null) { throw new ServiceException("å¤çåä¸åå¨"); } try (InputStream is = this.getClass().getResourceAsStream("/static/ä¸åæ ¼åå¤çå.xls"); POIFSFileSystem fs = new POIFSFileSystem(is); HSSFWorkbook wb = new HSSFWorkbook(fs)) { Sheet sheet = wb.getSheetAt(0); setCellValue(sheet, 2, 1, order.getProjectName()); setCellValue(sheet, 2, 5, order.getProjectNo()); setCellValue(sheet, 3, 1, order.getEquipmentName()); setCellValue(sheet, 3, 5, order.getEquipmentDrawingNo()); setCellValue(sheet, 4, 1, order.getMaterialName()); setCellValue(sheet, 4, 5, order.getMaterialDrawingNo()); setCellValue(sheet, 5, 1, order.getSpecificationModel()); setCellValue(sheet, 5, 3, order.getMaterialQuality()); setCellValue(sheet, 5, 5, order.getQuantity()); setCellValue(sheet, 5, 7, order.getUnqualifiedQuantity()); // ä¸åæ ¼å·¥åº - åªæ¿æ¢å¯¹åºçâ¡ä¸ºâ if (order.getUnqualifiedProcess() != null) { String origin = "â¡æ¥æ â¡å¶ç¨ â¡æå"; int idx = order.getUnqualifiedProcess() - 1; if (idx >= 0 && idx < 3) { origin = origin.replaceFirst("â¡", "â"); if (idx >= 1) origin = origin.replaceFirst("â¡", idx == 1 ? "â" : "â¡"); if (idx >= 2) origin = origin.replaceFirst("â¡", "â"); } // æç´¢å¼ä¾æ¬¡æ¿æ¢ StringBuilder sb = new StringBuilder(); int found = 0; for (char c : "â¡æ¥æ â¡å¶ç¨ â¡æå".toCharArray()) { if (c == 'â¡') { sb.append(found == idx ? 'â' : 'â¡'); found++; } else { sb.append(c); } } setCellValue(sheet, 6, 1, sb.toString()); } setCellValue(sheet, 6, 5, order.getSupplierName()); setCellValue(sheet, 7, 1, order.getInspectorName()); setCellValue(sheet, 7, 3, order.getInspectDate()); setCellValue(sheet, 7, 5, order.getResponsiblePerson()); setCellValue(sheet, 7, 7, order.getResponsibleDept()); setCellValue(sheet, 8, 1, order.getProblemDescription()); setCellValue(sheet, 9, 1, order.getReasonAnalysis()); setCellValue(sheet, 10, 1, order.getCorrectionAction()); // å¤ç½®æ¹å¼ - åªæ¿æ¢å¯¹åºçâ¡ä¸ºâ if (order.getDisposalMethod() != null) { String template = "â¡è®©æ¥æ¥æ¶ â¡åå ç»´ä¿® â¡è¿åç»´ä¿® â¡æ¢è´§ â¡éè´§ â¡æ¥åº"; int idx = order.getDisposalMethod() - 1; StringBuilder sb = new StringBuilder(); int found = 0; for (char c : template.toCharArray()) { if (c == 'â¡') { sb.append(found == idx ? 'â' : 'â¡'); found++; } else { sb.append(c); } } setCellValue(sheet, 11, 1, sb.toString()); } setCellValue(sheet, 12, 1, order.getRepairEvaluation()); setCellValue(sheet, 13, 1, order.getPreventiveAction()); setCellValue(sheet, 14, 1, order.getDeptOpinion()); setCellValue(sheet, 15, 1, order.getCompanyDecision()); setCellValue(sheet, 16, 1, order.getGeneralManagerOpinion()); response.setContentType("application/vnd.ms-excel"); String fileName = URLEncoder.encode("ä¸åæ ¼åå¤çå_" + order.getOrderNo(), "UTF-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls"); OutputStream os = response.getOutputStream(); wb.write(os); os.flush(); os.close(); } catch (Exception e) { throw new RuntimeException("导åºå¤±è´¥", e); } } private void setCellValue(Sheet sheet, int rowIdx, int colIdx, Object value) { if (value == null) return; Row row = sheet.getRow(rowIdx); if (row == null) row = sheet.createRow(rowIdx); Cell cell = row.getCell(colIdx); if (cell == null) cell = row.createCell(colIdx); if (value instanceof Date) { cell.setCellValue((Date) value); } else if (value instanceof Number) { cell.setCellValue(((Number) value).doubleValue()); } else { cell.setCellValue(value.toString()); } } private void createReworkProductionOrder(QualityUnqualifiedOrder order) { if (order.getUnqualifiedId() == null) { return; } QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(order.getUnqualifiedId()); if (unqualified == null || unqualified.getInspectId() == null) { return; } QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId()); if (qualityInspect == null || qualityInspect.getProductMainId() == null) { return; } ProductionProductMain sourceMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId()); if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) { return; } ProductionOperationTask sourceTask = productionOperationTaskMapper.selectById(sourceMain.getProductionOperationTaskId()); if (sourceTask == null) { return; } ProductionOrder sourceOrder = productionOrderMapper.selectById(sourceTask.getProductionOrderId()); if (sourceOrder == null) { return; } BigDecimal reworkQty = order.getUnqualifiedQuantity() != null ? order.getUnqualifiedQuantity() : unqualified.getQuantity() != null ? unqualified.getQuantity() : BigDecimal.ONE; ProductionOrder newOrder = new ProductionOrder(); BeanUtils.copyProperties(sourceOrder, newOrder); newOrder.setId(null); newOrder.setNpsNo(generateNextProductionOrderNo("FG")); newOrder.setQuantity(reworkQty); newOrder.setCompleteQuantity(BigDecimal.ZERO); newOrder.setStartTime(null); newOrder.setEndTime(null); newOrder.setCreateTime(null); newOrder.setUpdateTime(null); newOrder.setDisposalMethod(order.getDisposalMethod()); productionOrderMapper.insert(newOrder); Map<Long, Long> routingIdMap = new HashMap<>(); List<ProductionOrderRouting> sourceRoutings = productionOrderRoutingMapper.selectList( Wrappers.<ProductionOrderRouting>lambdaQuery() .eq(ProductionOrderRouting::getProductionOrderId, sourceOrder.getId()) .orderByAsc(ProductionOrderRouting::getId)); for (ProductionOrderRouting sourceRouting : sourceRoutings) { ProductionOrderRouting newRouting = new ProductionOrderRouting(); BeanUtils.copyProperties(sourceRouting, newRouting); newRouting.setId(null); newRouting.setProductionOrderId(newOrder.getId()); newRouting.setCreateTime(null); newRouting.setUpdateTime(null); productionOrderRoutingMapper.insert(newRouting); routingIdMap.put(sourceRouting.getId(), newRouting.getId()); } List<ProductionOrderRoutingOperation> sourceOperations = productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getProductionOrderId, sourceOrder.getId()) .orderByAsc(ProductionOrderRoutingOperation::getDragSort) .orderByAsc(ProductionOrderRoutingOperation::getId)); for (ProductionOrderRoutingOperation sourceOperation : sourceOperations) { ProductionOrderRoutingOperation newOperation = new ProductionOrderRoutingOperation(); BeanUtils.copyProperties(sourceOperation, newOperation); newOperation.setId(null); newOperation.setProductionOrderId(newOrder.getId()); newOperation.setOrderRoutingId(routingIdMap.get(sourceOperation.getOrderRoutingId())); newOperation.setCreateTime(null); newOperation.setUpdateTime(null); productionOrderRoutingOperationMapper.insert(newOperation); ProductionOperationTask newTask = new ProductionOperationTask(); newTask.setProductionOrderRoutingOperationId(newOperation.getId()); newTask.setProductionOrderId(newOrder.getId()); newTask.setPlanQuantity(newOrder.getQuantity()); newTask.setCompleteQuantity(BigDecimal.ZERO); newTask.setWorkOrderNo(generateNextTaskNo("FG")); newTask.setStatus(1); productionOperationTaskMapper.insert(newTask); } } private String generateNextProductionOrderNo(String prefix) { String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String orderPrefix = prefix + datePrefix; ProductionOrder latestOrder = productionOrderMapper.selectOne( Wrappers.<ProductionOrder>lambdaQuery() .likeRight(ProductionOrder::getNpsNo, orderPrefix) .orderByDesc(ProductionOrder::getNpsNo) .last("limit 1")); int sequence = 1; if (latestOrder != null && latestOrder.getNpsNo() != null && latestOrder.getNpsNo().startsWith(orderPrefix)) { try { sequence = Integer.parseInt(latestOrder.getNpsNo().substring(orderPrefix.length())) + 1; } catch (NumberFormatException ignored) { sequence = 1; } } return orderPrefix + String.format("%04d", sequence); } private String generateNextTaskNo(String prefix) { String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String taskPrefix = prefix + datePrefix; ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne( Wrappers.<ProductionOperationTask>lambdaQuery() .likeRight(ProductionOperationTask::getWorkOrderNo, taskPrefix) .orderByDesc(ProductionOperationTask::getWorkOrderNo) .last("limit 1")); int sequence = 1; if (latestTask != null && latestTask.getWorkOrderNo() != null && latestTask.getWorkOrderNo().startsWith(taskPrefix)) { try { sequence = Integer.parseInt(latestTask.getWorkOrderNo().substring(taskPrefix.length())) + 1; } catch (NumberFormatException ignored) { sequence = 1; } } return taskPrefix + String.format("%03d", sequence); } } src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -19,8 +19,6 @@ import com.ruoyi.stock.dto.StockInventoryDto; import com.ruoyi.stock.dto.StockUninventoryDto; import com.ruoyi.stock.execl.StockInRecordExportData; import com.ruoyi.production.mapper.ProductionOrderPickMapper; import com.ruoyi.production.pojo.ProductionOrderPick; import com.ruoyi.stock.mapper.StockInRecordMapper; import com.ruoyi.stock.mapper.StockInventoryMapper; import com.ruoyi.stock.mapper.StockUninventoryMapper; @@ -44,7 +42,6 @@ private StockInRecordMapper stockInRecordMapper; private StockInventoryMapper stockInventoryMapper; private StockUninventoryMapper stockUninventoryMapper; private ProductionOrderPickMapper productionOrderPickMapper; @Override public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) { @@ -158,32 +155,6 @@ return stockUninventoryMapper.selectOne(eq); } /** * åæ»ç产éæå ¥åºçé¢æè®°å½éææ°é * @param stockInRecord å ¥åºè®°å½ */ private void rollbackFeedReturnQty(StockInRecord stockInRecord) { ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId()); if (productionOrderPick != null) { BigDecimal returnQty = productionOrderPick.getReturnQty(); if (returnQty == null) { returnQty = BigDecimal.ZERO; } BigDecimal newReturnQty = returnQty.subtract(stockInRecord.getStockInNum()); if (newReturnQty.compareTo(BigDecimal.ZERO) < 0) { newReturnQty = BigDecimal.ZERO; } productionOrderPick.setReturnQty(newReturnQty); // éæ°è®¡ç®å®é ç¨é BigDecimal actualQty = productionOrderPick.getQuantity().add( productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO) .subtract(newReturnQty); productionOrderPick.setActualQty(actualQty); productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0); productionOrderPickMapper.updateById(productionOrderPick); } } @Override @Transactional(rollbackFor = Exception.class) public int batchDeletePending(List<Long> ids) { @@ -194,11 +165,6 @@ } if (stockInRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockInRecord.getApprovalStatus())) { throw new BaseException("åªæå¾ å®¡æ¹ç¶æçè®°å½æè½å é¤,å ¥åºæ¹æ¬¡:" + stockInRecord.getInboundBatches()); } // 妿æ¯ç产éæå ¥åºï¼å 餿¶éè¦åæ»é¢æè®°å½çéææ°é if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { rollbackFeedReturnQty(stockInRecord); } } return stockInRecordMapper.deleteBatchIds(ids); @@ -223,12 +189,6 @@ } stockInRecord.setApprovalStatus(approvalStatus); stockInRecordMapper.updateById(stockInRecord); // 审æ¹é©³åæ¶ï¼å¦ææ¯ç产éæå ¥åºï¼éè¦åæ»é¢æè®°å½çéææ°é if (ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus) && StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { rollbackFeedReturnQty(stockInRecord); } // 审æ¹éè¿æ¶ï¼åºåå¢å if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) { @@ -292,27 +252,6 @@ // åªæé©³åç¶ææè½éæ°å®¡æ ¸ if (!ReviewStatusEnum.REJECTED.getCode().equals(stockInRecord.getApprovalStatus())) { throw new BaseException("åªæé©³åç¶æçè®°å½æè½éæ°å®¡æ ¸,å ¥åºæ¹æ¬¡:" + stockInRecord.getInboundBatches()); } // 妿æ¯ç产éæå ¥åºï¼æ¢å¤éææ°éï¼å ä¸ºé©³åæ¶å·²æ£åï¼ if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId()); if (productionOrderPick != null) { BigDecimal returnQty = productionOrderPick.getReturnQty(); if (returnQty == null) { returnQty = BigDecimal.ZERO; } // éæ°å®¡æ ¸æ¶æ¢å¤éææ°é BigDecimal newReturnQty = returnQty.add(stockInRecord.getStockInNum()); productionOrderPick.setReturnQty(newReturnQty); // éæ°è®¡ç®å®é ç¨é BigDecimal actualQty = productionOrderPick.getQuantity().add( productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO) .subtract(newReturnQty); productionOrderPick.setActualQty(actualQty); productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0); productionOrderPickMapper.updateById(productionOrderPick); } } // å°ç¶ææ¹ä¸ºå¾ å®¡æ ¸ src/main/resources/mapper/production/ProductionBomStructureMapper.xml
ÎļþÒÑɾ³ý src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -70,6 +70,9 @@ <if test="c != null and c.workOrderNo != null and c.workOrderNo != ''"> and pot.work_order_no like concat('%', #{c.workOrderNo}, '%') </if> <if test="c != null and c.currentUserId != null"> and (pot.user_ids is null or pot.user_ids = '' or pot.user_ids = '[]' or json_contains(pot.user_ids, json_quote(cast(#{c.currentUserId} as char)))) </if> </where> order by pot.production_order_id desc, poro.drag_sort </select> src/main/resources/mapper/production/ProductionOrderBomMapper.xml
ÎļþÒÑɾ³ý src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -52,9 +52,7 @@ pm.model as model, po.is_end_order as endOrder, tr.process_route_code as processRouteCode, ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus, tb.bom_no as bomNo, pop_return.returned as returned ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus </sql> <sql id="ProductionOrderVoFrom"> @@ -74,13 +72,6 @@ left join product_model pm on po.product_model_id = pm.id left join product p on pm.product_id = p.id left join technology_routing tr on po.technology_routing_id = tr.id left join technology_bom tb on tb.id = tr.bom_id left join ( select production_order_id as productionOrderId, if(max(case when ifnull(is_returned, 0) = 1 then 1 else 0 end) = 1, true, false) as returned from production_order_pick group by production_order_id ) pop_return on pop_return.productionOrderId = po.id </sql> <sql id="ProductionOrderWhere"> @@ -164,7 +155,6 @@ po.quantity, ifnull(po.complete_quantity, 0) as completeQuantity, round(ifnull(po.complete_quantity, 0) / nullif(po.quantity, 0) * 100, 2) as completionStatus, tb.bom_no, datediff(po_sales.deliveryDate, curdate()) as deliveryDaysDiff, po_sales.deliveryDate as deliveryDate, false as isFh @@ -184,7 +174,6 @@ left join product_model pm on po.product_model_id = pm.id left join product p on pm.product_id = p.id left join technology_routing tr on po.technology_routing_id = tr.id left join technology_bom tb on tr.bom_id = tb.id where po.create_time between #{startTime} and #{endTime} order by po.create_time desc </select> src/main/resources/mapper/production/ProductionOrderPickMapper.xml
ÎļþÒÑɾ³ý src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
ÎļþÒÑɾ³ý src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml
@@ -12,7 +12,6 @@ <result column="update_time" property="updateTime" /> <result column="technology_routing_id" property="technologyRoutingId" /> <result column="process_route_code" property="processRouteCode" /> <result column="bom_id" property="bomId" /> <result column="create_user" property="createUser" /> <result column="dept_id" property="deptId" /> </resultMap> src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -12,6 +12,8 @@ <result column="create_user" property="createUser" /> <result column="create_time" property="createTime" /> <result column="update_user" property="updateUser" /> <result column="actual_start_time" property="actualStartTime" /> <result column="actual_end_time" property="actualEndTime" /> </resultMap> <select id="listPageProductionProductMainDto" resultType="com.ruoyi.production.bean.dto.ProductionProductMainDto"> @@ -81,6 +83,9 @@ <if test="c.productMainId != null"> and ppm.id = #{c.productMainId} </if> <if test="c.currentUserId != null"> and (pot.user_ids is null or pot.user_ids = '' or pot.user_ids = '[]' or json_contains(pot.user_ids, json_quote(cast(#{c.currentUserId} as char)))) </if> </where> order by ppm.create_time desc </select> src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml
@@ -23,4 +23,11 @@ </where> order by create_time desc </select> <delete id="deleteByIds"> DELETE FROM quality_unqualified_order WHERE id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> </delete> </mapper> src/main/resources/static/²»ºÏ¸ñÆ·´¦Àíµ¥.xlsBinary files differ