From 741918a903e17b2ec7522556d2c043b8d35dd8a1 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 15 六月 2026 17:42:58 +0800
Subject: [PATCH] 生产取消bom,不合格管理定制化

---
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java                     |   25 
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java            |  313 +++++++
 src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java                       |    4 
 src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java            |   19 
 src/main/resources/static/不合格品处理单.xls                                                           |    0 
 doc/20260615_add_actual_time_to_production_product_main.sql                                     |    4 
 src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java                       |   29 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java                               |    3 
 src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java                        |   61 -
 src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java              |   11 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java         |   10 
 src/main/java/com/ruoyi/production/service/ProductionProductMainService.java                    |    2 
 docs/production_report_split.md                                                                 |  146 +++
 src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java                            |   19 
 doc/20260615_add_disposal_method_to_production_order.sql                                        |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java                  |    2 
 src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml                           |    1 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java |   37 
 src/main/java/com/ruoyi/basic/dto/ProductModelDto.java                                          |    4 
 doc/20260615_add_opinion_fields_to_quality_unqualified_order.sql                                |    5 
 doc/20260615_change_operation_task_time_to_datetime.sql                                         |    6 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java                 |  301 -------
 src/main/java/com/ruoyi/production/service/ProductionOrderService.java                          |    3 
 src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java                               |   10 
 src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java               |   42 
 docs/quality_unqualified_order.md                                                               |  693 +++++++++++----
 src/main/java/com/ruoyi/production/controller/ProductionOrderController.java                    |    7 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java           |  393 +++++---
 src/main/java/com/ruoyi/ai/tools/ManufacturingAgentTools.java                                   |    8 
 src/main/resources/mapper/production/ProductionOrderMapper.xml                                  |   13 
 src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java                               |   10 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java                             |    6 
 src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java                    |    9 
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                          |    3 
 /dev/null                                                                                       |   60 -
 src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java                              |   10 
 src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java                         |    3 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java                     |    6 
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                            |    5 
 src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java                  |    6 
 src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml                             |    7 
 src/main/java/com/ruoyi/production/pojo/ProductionOrder.java                                    |    3 
 src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java                               |  117 --
 docs/production_remove_bom_pick.md                                                              |   79 +
 44 files changed, 1,487 insertions(+), 1,011 deletions(-)

diff --git a/doc/20260615_add_actual_time_to_production_product_main.sql b/doc/20260615_add_actual_time_to_production_product_main.sql
new file mode 100644
index 0000000..9841044
--- /dev/null
+++ b/doc/20260615_add_actual_time_to_production_product_main.sql
@@ -0,0 +1,4 @@
+-- 鐢熶骇鎶ュ伐鎷嗗垎锛歱roduction_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;
diff --git a/doc/20260615_add_disposal_method_to_production_order.sql b/doc/20260615_add_disposal_method_to_production_order.sql
new file mode 100644
index 0000000..d85cbbb
--- /dev/null
+++ b/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;
diff --git a/doc/20260615_add_opinion_fields_to_quality_unqualified_order.sql b/doc/20260615_add_opinion_fields_to_quality_unqualified_order.sql
new file mode 100644
index 0000000..793b372
--- /dev/null
+++ b/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 '璐d换閮ㄩ棬涓荤鎰忚' 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;
diff --git a/doc/20260615_change_operation_task_time_to_datetime.sql b/doc/20260615_change_operation_task_time_to_datetime.sql
new file mode 100644
index 0000000..b074453
--- /dev/null
+++ b/doc/20260615_change_operation_task_time_to_datetime.sql
@@ -0,0 +1,6 @@
+-- 鐢熶骇宸ュ崟鏃堕棿瀛楁锛歞ate 鏀逛负 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 '瀹為檯缁撴潫鏃堕棿';
diff --git a/docs/production_remove_bom_pick.md b/docs/production_remove_bom_pick.md
new file mode 100644
index 0000000..b54f1c4
--- /dev/null
+++ b/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 鍙婄浉鍏虫帴鍙h皟鐢細
+
+```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 缁撴瀯瑙f瀽锛屾敼涓虹洿鎺ヤ娇鐢ㄥ綋鍓嶅伐搴忕殑浜у搧瑙勬牸浣滀负鎶曞叆鍝併�傚墠绔棤闇�鏀瑰姩锛屽悗绔嚜鍔ㄥ鐞嗐��
+
+## 娉ㄦ剰浜嬮」
+
+- 鏈鍙樻洿鍚庯紝棰嗘枡鎿嶄綔鐢辩敤鎴风洿鎺ュ湪搴撳瓨绠$悊妯″潡杩涜锛屼笉鍐嶄笌鐢熶骇宸ュ崟鍏宠仈
+- 鐢熶骇璁㈠崟鍒楄〃鍜屽巻鍙叉暟鎹腑 `bomNo` 鍜� `returned` 瀛楁涓嶅啀杩斿洖锛屽墠绔缂撳瓨浜嗚繖浜涘瓧娈甸渶鍋氬吋瀹瑰鐞�
+- 鎵�鏈� `/productionOrderPick`銆乣/productionOrderPickRecord`銆乣/productionBomStructure`銆乣/productionOrderBom` 鎺ュ彛宸茬Щ闄わ紝璋冪敤杩欎簺鎺ュ彛鐨勫墠绔唬鐮侀渶鍏ㄩ儴娓呯悊
+- 鏁版嵁搴撹〃 `production_order_pick`銆乣production_order_pick_record`銆乣production_order_bom`銆乣production_bom_structure` 濡傞渶淇濈暀鍘嗗彶鏁版嵁鍙殏涓嶅垹闄�
diff --git a/docs/production_report_split.md b/docs/production_report_split.md
new file mode 100644
index 0000000..ef0a636
--- /dev/null
+++ b/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; // 淇濆瓨杩斿洖鐨勬姤宸ヨ褰旾D锛屼緵缁撴潫鎶ュ伐浣跨敤
+      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, // 蹇呴』浼犲叆寮�濮嬫姤宸ヨ褰旾D
+        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`
diff --git a/docs/quality_unqualified_order.md b/docs/quality_unqualified_order.md
index 92ec796..95cc83c 100644
--- a/docs/quality_unqualified_order.md
+++ b/docs/quality_unqualified_order.md
@@ -1,34 +1,49 @@
-# 涓嶅悎鏍煎搧澶勭悊鍗� 鈥� 鍓嶇鑱旇皟鏂囨。
+# 涓嶅悎鏍煎搧澶勭悊鍗曟ā鍧楋紙QualityUnqualifiedOrder锛�
+
+## 姒傝堪
+
+涓嶅悎鏍煎搧澶勭悊鍗曟槸姝e紡鐨勪笉鍚堟牸鍝佸缃祦绋嬫ā鍧楋紝鏇夸唬鏃х殑涓嶅悎鏍肩鐞嗭紙`/quality/qualityUnqualified`锛変腑鐨勫缃姛鑳姐�傛棫妯″潡鐨勪笉鍚堟牸鍝佸彂鐜帮紙鏂板/鍒楄〃/璇︽儏锛夌户缁娇鐢紝浣�**澶勭疆鎿嶄綔缁熶竴浣跨敤鏈ā鍧�**銆�
+
+### 鑷姩鍒涘缓鏈哄埗
+
+褰撴楠屽崟锛堝師鏉愭枡/杩囩▼/鍑哄巶妫�楠岋級鎻愪氦鏃讹紝濡傛灉**涓嶅悎鏍兼暟閲� > 0**锛岀郴缁熷湪鍒涘缓 `QualityUnqualified` 璁板綍鐨勫悓鏃讹紝**鑷姩鍒涘缓涓�鏉′笉鍚堟牸鍝佸鐞嗗崟**锛宍unqualifiedProcess`锛堜笉鍚堟牸宸ュ簭锛夋牴鎹楠岀被鍒嚜鍔ㄦ槧灏勶細
+
+| 妫�楠岀被鍒� | inspectType | unqualifiedProcess |
+|----------|-------------|-------------------|
+| 鍘熸潗鏂欐楠� | 0 | 1锛堟潵鏂欙級 |
+| 杩囩▼妫�楠� | 0 | 2锛堝埗绋嬶級 |
+| 鍑哄巶妫�楠� | 0 | 3锛堟垚鍝侊級 |
+
+澶勭悊鍗曞垵濮嬬姸鎬佷负 `0`锛堣崏绋匡級锛屽悗缁彲缂栬緫澶勭疆鏂瑰紡骞舵彁浜ゅ鎵广��
+
+### 涓庢棫妯″潡鐨勫叧绯�
+
+| | 鏃э細涓嶅悎鏍肩鐞� | 鏂帮細涓嶅悎鏍煎搧澶勭悊鍗� |
+|---|---|---|
+| 璺緞 | `/quality/qualityUnqualified` | `/qualityUnqualifiedOrder` |
+| 鐢ㄩ�� | 涓嶅悎鏍煎搧棣栨璁板綍銆佹煡鐪� | 姝e紡澶勭疆娴佺▼锛堝惈瀹℃壒锛� |
+| 澶勭疆鏂瑰紡 | `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 | 鍚� | 璐d换閮ㄩ棬涓荤鎰忚 |
+| 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** | **鏄�** | 澶勭悊鍗旾D |
+| **disposalMethod** | **Integer** | **鏄�** | **澶勭疆鏂瑰紡锛�1=璁╂鎺ユ敹, 2=鍘傚唴缁翠慨, 3=杩斿巶缁翠慨, 4=鎹㈣揣, 5=閫�璐�, 6=鎶ュ簾** |
+| repairEvaluation | String | 鍚� | 鍘傚唴/杩斿巶缁翠慨璇勪及 |
+| reasonAnalysis | String | 鍚� | 鍘熷洜鍒嗘瀽鍙婂缓璁� |
+| correctionAction | String | 鍚� | 绾犳鎺柦 |
+| preventiveAction | String | 鍚� | 棰勯槻鎺柦 |
+| remark | String | 鍚� | 澶囨敞 |
+| deptOpinion | String | 鍚� | 璐d换閮ㄩ棬涓荤鎰忚 |
+| companyDecision | String | 鍚� | 鍏徃澶勭悊鍐冲畾 |
+| generalManagerOpinion | String | 鍚� | 鎬荤粡鐞嗘剰瑙� |
+
+**鑷姩琛屼负锛�**
+- 鐘舵�佹洿鏂颁负 `3`锛堝凡瀹屾垚锛�
+- 澶勭疆鏂瑰紡涓� 2锛堝巶鍐呯淮淇級鎴� 3锛堣繑鍘傜淮淇級鏃讹紝鑷姩鍒涘缓杩斾慨鐢熶骇璁㈠崟
+
+**鍝嶅簲锛�** `{ "code": 200, "msg": "鎿嶄綔鎴愬姛", "data": true }`
+
+### 7. 瀵煎嚭澶勭悊鍗�
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /qualityUnqualifiedOrder/export/{id} | 瀵煎嚭涓嶅悎鏍煎搧澶勭悊鍗曚负 Excel |
+
+**璇锋眰鍙傛暟锛�** `id` 鈥� 澶勭悊鍗旾D锛堣矾寰勫弬鏁帮級
+
+**鍝嶅簲锛�** 鏂囦欢娴侊紝`Content-Type: application/vnd.ms-excel`锛屾枃浠跺悕 `涓嶅悎鏍煎搧澶勭悊鍗昣{缂栧彿}.xls`
+
+**妯℃澘瀛楁鏄犲皠锛�**
+
+| 妯℃澘浣嶇疆 | 瀛楁 |
+|----------|------|
+| 椤圭洰鍚嶇О | projectName |
+| 椤圭洰缂栧彿 | projectNo |
+| 璁惧鍚嶇О | equipmentName |
+| 璁惧鍥惧彿 | equipmentDrawingNo |
+| 鐗╂枡鍚嶇О | materialName |
+| 鐗╂枡鍥惧彿 | materialDrawingNo |
+| 鍨嬪彿瑙勬牸 | specificationModel |
+| 鏉愯川 | materialQuality |
+| 鎬绘暟閲� | quantity |
+| 涓嶅悎鏍兼暟 | unqualifiedQuantity |
+| 涓嶅悎鏍煎伐搴� | unqualifiedProcess锛堝嬀閫夋潵鏂�/鍒剁▼/鎴愬搧锛� |
+| 渚涜揣鍟嗗悕绉� | supplierName |
+| 妫�楠屽憳 | inspectorName |
+| 妫�楠屾棩鏈� | inspectDate |
+| 璐d换浜� | responsiblePerson |
+| 璐d换閮ㄩ棬 | responsibleDept |
+| 闂鎻忚堪 | problemDescription |
+| 鍘熷洜鍒嗘瀽鍙婂缓璁� | reasonAnalysis |
+| 绾犳鎺柦 | correctionAction |
+| 澶勭疆鏂瑰紡 | disposalMethod锛堝嬀閫夊搴旈�夐」锛� |
+| 鍘傚唴/杩斿巶缁翠慨璇勪及 | repairEvaluation |
+| 棰勯槻鎺柦 | preventiveAction |
+| 璐d换閮ㄩ棬涓荤鎰忚 | 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="璐d换浜�" prop="responsiblePerson">
-    <el-input v-model="form.responsiblePerson" />
-  </el-form-item>
-  <el-form-item label="璐d换閮ㄩ棬" 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="璐d换浜�" prop="responsiblePerson">
+            <el-input v-model="form.responsiblePerson" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="璐d换閮ㄩ棬" 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="璐d换閮ㄩ棬涓荤鎰忚" 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 | 鍘傚唴缁翠慨 | **鑷姩鍒涘缓杩斾慨鐢熶骇璁㈠崟**锛團G 寮�澶� NPS 缂栧彿锛夛紝鍏嬮殕鍘熷伐搴忚矾绾� |
+| 3 | 杩斿巶缁翠慨 | **鑷姩鍒涘缓杩斾慨鐢熶骇璁㈠崟**锛團G 寮�澶� NPS 缂栧彿锛夛紝鍏嬮殕鍘熷伐搴忚矾绾� |
+| 4 | 鎹㈣揣 | 鏃犺嚜鍔ㄦ搷浣� |
+| 5 | 閫�璐� | 鏃犺嚜鍔ㄦ搷浣� |
+| 6 | 鎶ュ簾 | 鏃犺嚜鍔ㄦ搷浣滐紙搴撳瓨鎵e噺鐢辨棫妯″潡 `/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`
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
index f42599a..66dfe99 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
+++ b/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)));
diff --git a/src/main/java/com/ruoyi/ai/tools/ManufacturingAgentTools.java b/src/main/java/com/ruoyi/ai/tools/ManufacturingAgentTools.java
index 1ff96c1..4106e4f 100644
--- a/src/main/java/com/ruoyi/ai/tools/ManufacturingAgentTools.java
+++ b/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());
diff --git a/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java b/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
index 15e428d..0df057f 100644
--- a/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
+++ b/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;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java b/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java
index 28949d7..fd8d8f8 100644
--- a/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java
+++ b/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;
diff --git a/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java b/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java
deleted file mode 100644
index 11393f3..0000000
--- a/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ruoyi.production.bean.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-public class BomImportDto {
-    @Schema(description = "鐖朵骇鍝佸悕绉�")
-    @Excel(name = "鐖朵骇鍝佸悕绉�")
-    private String parentName;
-
-    @Schema(description = "鐖朵骇鍝佽鏍�")
-    @Excel(name = "鐖朵骇鍝佽鏍�")
-    private String parentSpec;
-
-    @Schema(description = "瀛愪骇鍝佸悕绉�")
-    @Excel(name = "瀛愪骇鍝佸悕绉�")
-    private String childName;
-
-    @Schema(description = "瀛愪骇鍝佽鏍�")
-    @Excel(name = "瀛愪骇鍝佽鏍�")
-    private String childSpec;
-
-    @Schema(description = "鍗曚綅鐢ㄩ噺")
-    @Excel(name = "鍗曚綅鐢ㄩ噺")
-    private BigDecimal unitQty;
-
-    @Schema(description = "宸ュ簭")
-    @Excel(name = "宸ュ簭")
-    private String process;
-
-    @Schema(description = "澶囨敞")
-    @Excel(name = "澶囨敞")
-    private String remark;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java
deleted file mode 100644
index 85f28d1..0000000
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.ruoyi.production.bean.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@Data
-public class ProductStructureDto {
-    @Schema(description = "涓婚敭ID")
-    private Long id;
-    @Schema(description = "BOM涓婚敭ID")
-    private Long bomId;
-    @Schema(description = "鐖剁骇ID")
-    private Long parentId;
-    @Schema(description = "浜у搧鍨嬪彿ID")
-    private Long productModelId;
-    @Schema(description = "鍗曚綅鐢ㄩ噺")
-    private BigDecimal unitQuantity;
-    @Schema(description = "鍗曚綅")
-    private String unit;
-    @Schema(description = "宸ュ簭ID")
-    private Long processId;
-    @Schema(description = "宸ュ簭鍚嶇О")
-    private String processName;
-    @Schema(description = "浜у搧鍚嶇О")
-    private String productName;
-    @Schema(description = "瑙勬牸鍨嬪彿")
-    private String model;
-    @Schema(description = "瀛愯妭鐐�")
-    private List<ProductStructureDto> children;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java
deleted file mode 100644
index c898c56..0000000
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.ruoyi.production.bean.dto;
-
-import com.ruoyi.production.pojo.ProductionBomStructure;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class ProductionBomStructureDto extends ProductionBomStructure {
-
-    @Schema(description = "宸ュ簭鍚嶇О")
-    private String operationName;
-
-    @Schema(description = "浜у搧鍚嶇О")
-    private String productName;
-
-    @Schema(description = "浜у搧ID")
-    private Long productId;
-
-    @Schema(description = "瑙勬牸鍨嬪彿")
-    private String model;
-
-    private String tempId;
-
-    private String parentTempId;
-
-    private List<ProductionBomStructureDto> children;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
index 8a75dcd..8f5650a 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
+++ b/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锛岀敤浜嶴QL鏉冮檺杩囨护")
+    private Long currentUserId;
 }
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java
deleted file mode 100644
index 1b226ad..0000000
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.ruoyi.production.bean.dto;
-
-import com.fasterxml.jackson.annotation.JsonAlias;
-import com.ruoyi.production.pojo.ProductionOrderPick;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@Data
-@Schema(name = "ProductionOrderPickDto", description = "鐢熶骇璁㈠崟棰嗘枡淇濆瓨鍙傛暟")
-public class ProductionOrderPickDto extends ProductionOrderPick {
-
-    @Schema(description = "鐢熶骇璁㈠崟ID")
-    private Long productionOrderId;
-
-    @Schema(description = "鐢熶骇宸ュ崟ID")
-    private Long productionOperationTaskId;
-
-    @Schema(description = "鎵瑰彿")
-    private String batchNo;
-
-    @Schema(description = "鎵瑰彿鍒楄〃")
-    private List<String> batchNoList;
-
-    @Schema(description = "棰嗘枡鏁伴噺")
-    private BigDecimal pickQuantity;
-
-    @Schema(description = "棰嗘枡绫诲瀷锛�1姝e父棰嗘枡锛�2琛ユ枡")
-    private Byte pickType;
-
-    @Schema(description = "澶囨敞")
-    private String remark;
-
-    @Schema(description = "琛ユ枡鍘熷洜")
-    private String feedingReason;
-
-    @Schema(description = "鏈琛ユ枡鏁伴噺")
-    private BigDecimal feedingQuantity;
-
-    @Schema(description = "棰嗘枡鏄庣粏鍒楄〃")
-    @JsonAlias({"dto", "productionOrderPickDto"})
-    private List<ProductionOrderPickDto> pickList;
-
-    @Schema(description = "闇�瑕佸垹闄ょ殑棰嗘枡ID鍒楄〃")
-    private List<Long> deletePickIds;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java
deleted file mode 100644
index 6954c4a..0000000
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.ruoyi.production.bean.dto;
-
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Schema(name = "ProductionOrderPickRecordDto", description = "棰嗘枡璁板綍鏌ヨ鍙傛暟")
-public class ProductionOrderPickRecordDto extends ProductionOrderPickRecord {
-}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
index cbac4b5..a758f7e 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
+++ b/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 = "寮�濮嬫姤宸ヨ褰旾D锛堢粨鏉熸姤宸ユ椂浼犲叆锛�")
+    private Long startRecordId;
+
+    /**
+     * 鑾峰彇缁撴潫鎶ュ伐鎵�闇�鐨勫紑濮嬭褰旾D锛屼紭鍏堝彇 startRecordId锛屽叾娆″彇缁ф壙鐨� id
+     */
+    public Long resolveStartRecordId() {
+        if (startRecordId != null) {
+            return startRecordId;
+        }
+        return super.getId();
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java
deleted file mode 100644
index 36f9221..0000000
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.production.bean.vo;
-
-import com.ruoyi.production.pojo.ProductionBomStructure;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class ProductionBomStructureVo extends ProductionBomStructure {
-
-    @Schema(description = "宸ュ簭鍚嶇О")
-    private String operationName;
-
-    @Schema(description = "浜у搧鍚嶇О")
-    private String productName;
-
-    @Schema(description = "浜у搧ID")
-    private Long productId;
-
-    @Schema(description = "瑙勬牸鍨嬪彿")
-    private String model;
-
-    private List<ProductionBomStructureVo> children;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java
deleted file mode 100644
index aea1c85..0000000
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.ruoyi.production.bean.vo;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.time.LocalDateTime;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Schema(name = "ProductionOrderPickRecordVo", description = "宸查鏂欒鎯�")
-public class ProductionOrderPickRecordVo extends ProductionOrderPickRecord {
-
-    @Schema(description = "宸ュ簭鍚嶇О")
-    private String operationName;
-
-    @Schema(description = "浜у搧鍚嶇О")
-    private String productName;
-
-    @Schema(description = "鍨嬪彿")
-    private String model;
-
-    @Schema(description = "鍗曚綅")
-    private String unit;
-
-    @Schema(description = "琛ユ枡浜�")
-    private String supplementUserName;
-
-    @Schema(description = "琛ユ枡鏃ユ湡")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime supplementTime;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java
deleted file mode 100644
index d072634..0000000
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.production.bean.vo;
-
-import com.ruoyi.production.pojo.ProductionOrderPick;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class ProductionOrderPickVo extends ProductionOrderPick {
-
-    @Schema(description = "鍗曚綅")
-    private String unit;
-
-    @Schema(description = "搴撳瓨鏁伴噺")
-    private BigDecimal stockQuantity;
-
-    @Schema(description = "棰嗙敤鏁伴噺")
-    private BigDecimal pickQuantity;
-
-    @Schema(description = "浜у搧鍚嶇О")
-    private String productName;
-
-    @Schema(description = "瑙勬牸鍨嬪彿")
-    private String model;
-
-    @Schema(description = "鎵瑰彿")
-    private List<String> batchNoList;
-}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
index 01ef33a..c98156b 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
+++ b/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;
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java b/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java
deleted file mode 100644
index dd1d50e..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
-import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
-import com.ruoyi.production.service.ProductionBomStructureService;
-import io.swagger.v3.oas.annotations.Operation;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@RestController
-@RequestMapping("/productionBomStructure")
-@AllArgsConstructor
-public class ProductionBomStructureController {
-
-    private ProductionBomStructureService productionBomStructureService;
-
-    @GetMapping("/listByBomId/{bomId}")
-    @Operation(summary = "鏍规嵁BOM鏌ヨ鐢熶骇璁㈠崟BOM缁撴瀯鏍�")
-    public R<List<ProductionBomStructureVo>> listByBomId(@PathVariable Long bomId) {
-        return R.ok(productionBomStructureService.listByBomId(bomId));
-    }
-
-    @PostMapping("/addOrUpdateBomStructs")
-    @Operation(summary = "鏂板鎴栦慨鏀笲OM缁撴瀯")
-    public R addProductionBomStructure(@RequestBody ProductionBomStructureDto productionBomStructureDto) {
-        return R.ok(productionBomStructureService.addProductionBomStructure(productionBomStructureDto));
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
index 56ed8c2..6d88dba 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
+++ b/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}")
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java
deleted file mode 100644
index ee0ecdc..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@RestController
-@RequestMapping("/productionOrderBom")
-public class ProductionOrderBomController {
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
index 0a68875..0606c31 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
+++ b/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")
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java
deleted file mode 100644
index a8e2d2e..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
-import com.ruoyi.production.service.ProductionOrderPickService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * <p>
- * 璁㈠崟棰嗘枡绾胯竟浠� 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@RestController
-@RequestMapping("/productionOrderPick")
-@Tag(name = "鐢熶骇璁㈠崟棰嗘枡")
-@RequiredArgsConstructor
-public class ProductionOrderPickController {
-
-    private final ProductionOrderPickService productionOrderPickService;
-
-    @PostMapping("/savePick")
-    @Operation(summary = "棰嗘枡淇濆瓨鍒扮嚎杈逛粨")
-    public R<Boolean> savePick(@RequestBody ProductionOrderPickDto dto) {
-        return R.ok(productionOrderPickService.savePick(dto));
-    }
-
-    @PostMapping("/updatePick")
-    @Operation(summary = "鍙樻洿棰嗘枡")
-    public R<Boolean> updatePick(@RequestBody ProductionOrderPickDto dto) {
-        return R.ok(productionOrderPickService.updatePick(dto));
-    }
-
-    @GetMapping("/detail/{productionOrderId}")
-    @Operation(summary = "鏌ヨ宸查鏂欒鎯�")
-    public R<List<ProductionOrderPickVo>> listPickedDetail(@PathVariable Long productionOrderId) {
-        return R.ok(productionOrderPickService.listPickedDetail(productionOrderId));
-    }
-}
-
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java
deleted file mode 100644
index 05e1a50..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
-import com.ruoyi.production.service.ProductionOrderPickRecordService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.List;
-
-/**
- * <p>
- * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@RestController
-@RequestMapping("/productionOrderPickRecord")
-@Tag(name = "鐢熶骇璁㈠崟棰嗘枡璁板綍")
-@RequiredArgsConstructor
-public class ProductionOrderPickRecordController {
-
-    private final ProductionOrderPickRecordService productionOrderPickRecordService;
-
-    @GetMapping("/feeding")
-    @Operation(summary = "鏌ヨ琛ユ枡璁板綍")
-    public R<List<ProductionOrderPickRecordVo>> listFeedingRecord(ProductionOrderPickRecordDto dto) {
-        return R.ok(productionOrderPickRecordService.listFeedingRecord(dto));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
index 926a59f..307c1b1 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
+++ b/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) {
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java
deleted file mode 100644
index bb9ad78..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
-import com.ruoyi.production.pojo.ProductionBomStructure;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Mapper
-public interface ProductionBomStructureMapper extends BaseMapper<ProductionBomStructure> {
-
-    List<ProductionBomStructureVo> listByBomId(@Param("bomId") Long bomId);
-
-    /**
-     * 棰嗘枡bom
-     * @param bomId
-     * @return
-     */
-    List<ProductionBomStructureVo> pickByBomId(@Param("bomId") Long bomId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java
deleted file mode 100644
index 65c02ff..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.pojo.ProductionOrderBom;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Mapper
-public interface ProductionOrderBomMapper extends BaseMapper<ProductionOrderBom> {
-
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java
deleted file mode 100644
index 3f2b9cc..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
-import com.ruoyi.production.pojo.ProductionOrderPick;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * <p>
- * 璁㈠崟棰嗘枡绾胯竟浠� Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Mapper
-public interface ProductionOrderPickMapper extends BaseMapper<ProductionOrderPick> {
-
-    List<ProductionOrderPickVo> listPickedDetailByOrderId(@Param("productionOrderId") Long productionOrderId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java
deleted file mode 100644
index 6b18e1c..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
-import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * <p>
- * 绾胯竟浠撳嚭鍏ュ簱璁板綍 Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Mapper
-public interface ProductionOrderPickRecordMapper extends BaseMapper<ProductionOrderPickRecord> {
-
-    List<ProductionOrderPickVo> listPickedDetailByOrderId(@Param("productionOrderId") Long productionOrderId);
-
-    List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto);
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java b/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java
deleted file mode 100644
index 5ba8d22..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Data
-@TableName("production_bom_structure")
-@Schema(name = "ProductionBomStructure瀵硅薄", description = "鐢熶骇璁㈠崟BOM浜у搧缁撴瀯")
-public class ProductionBomStructure implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @Schema(description = "涓婚敭ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @Schema(description = "鐖惰妭鐐笽D")
-    private Long parentId;
-
-    @Schema(description = "鐢熶骇璁㈠崟id")
-    private Long productionOrderId;
-
-    @Schema(description = "浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    @Schema(description = "宸ュ簭id")
-    private Long technologyOperationId;
-
-    @Schema(description = "鐢熶骇璁㈠崟BOMid")
-    private Long productionOrderBomId;
-
-    @Schema(description = "鍗曚綅浜у嚭闇�瑕佹暟閲�")
-    private BigDecimal unitQuantity;
-
-    @Schema(description = "闇�姹傛暟閲�")
-    private BigDecimal demandedQuantity;
-
-    @Schema(description = "鍗曚綅")
-    private String unit;
-
-    @Schema(description = "鍒涘缓浜篒D")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @Schema(description = "閮ㄩ棬ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java b/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
index 08399e9..8fd92d2 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
+++ b/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;
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
index 6208146..1842319 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
+++ b/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;
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
deleted file mode 100644
index 3915d97..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Data
-@TableName("production_order_bom")
-@Schema(name = "ProductionOrderBom瀵硅薄", description = "鐢熶骇璁㈠崟BOM")
-public class ProductionOrderBom implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @Schema(description = "涓婚敭ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @Schema(description = "鐢熶骇璁㈠崟id")
-    private Long productionOrderId;
-
-    @Schema(description = "浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    @Schema(description = "BOM缂栧彿")
-    private String bomNo;
-
-    @Schema(description = "澶囨敞")
-    private String remark;
-
-    @Schema(description = "鐗堟湰鍙�")
-    private String version;
-
-    @Schema(description = "bom鐨刬d")
-    private Long bomId;
-
-    @Schema(description = "鍒涘缓浜篒D")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @Schema(description = "閮ㄩ棬ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
deleted file mode 100644
index 61c5d19..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * <p>
- * 璁㈠崟棰嗘枡绾胯竟浠�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Data
-@TableName("production_order_pick")
-@Schema(name = "ProductionOrderPick瀵硅薄", description = "璁㈠崟棰嗘枡绾胯竟浠�")
-public class ProductionOrderPick implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @Schema(description = "涓婚敭id")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @Schema(description = "浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    @Schema(description = "鏁伴噺")
-    private BigDecimal quantity;
-
-    @Schema(description = "鎵瑰彿")
-    private String batchNo;
-
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @Schema(description = "鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @Schema(description = "鐢熶骇璁㈠崟id")
-    private Long productionOrderId;
-
-    @Schema(description = "澶囨敞")
-    private String remark;
-
-    @Schema(description = "鍒涘缓浜篒D")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @Schema(description = "閮ㄩ棬ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long deptId;
-
-    @Schema(description = "宸ュ簭鍚嶇О")
-    private String operationName;
-
-    @Schema(description = "宸ュ簭id")
-    private Long technologyOperationId;
-
-    @Schema(description = "闇�姹傛暟閲�")
-    private BigDecimal demandedQuantity;
-
-    @Schema(description = "琛ユ枡鎬婚噺")
-    private BigDecimal  feedingQty;
-
-    @Schema(description = "閫�鏂欐暟閲�")
-    private BigDecimal  returnQty;
-
-    @Schema(description = "瀹為檯鏁伴噺")
-    private BigDecimal  actualQty;
-
-    @Schema(description = "鏄惁宸查��鏂�")
-    @TableField("is_returned")
-    private Boolean returned;
-
-    @Schema(description = "鏄惁bom棰嗘枡")
-    @TableField("is_bom")
-    private Boolean bom;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java
deleted file mode 100644
index 4f0dc49..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * <p>
- * 绾胯竟浠撳嚭鍏ュ簱璁板綍
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Data
-@TableName("production_order_pick_record")
-@Schema(name = "ProductionOrderPickRecord瀵硅薄", description = "绾胯竟浠撳嚭鍏ュ簱璁板綍")
-public class ProductionOrderPickRecord implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @Schema(description = "涓婚敭id")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @Schema(description = "鍏宠仈棰嗘枡鍗昳d锛坧roduction_order_pick.id锛�")
-    private Long pickId;
-
-    @Schema(description = "鐢熶骇璁㈠崟id")
-    private Long productionOrderId;
-
-    @Schema(description = "鐢熶骇宸ュ崟id")
-    private Long productionOperationTaskId;
-
-    @Schema(description = "浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    @Schema(description = "鎵瑰彿")
-    private String batchNo;
-
-    @Schema(description = "棰嗘枡鏁伴噺")
-    private BigDecimal pickQuantity;
-
-    @Schema(description = "棰嗘枡鍓嶆暟閲�")
-    private BigDecimal beforeQuantity;
-
-    @Schema(description = "棰嗘枡鍚庡墿浣欐暟閲�")
-    private BigDecimal afterQuantity;
-
-    @Schema(description = "棰嗘枡绫诲瀷锛�1姝e父棰嗘枡  2琛ユ枡")
-    private Byte pickType;
-
-    @Schema(description = "澶囨敞")
-    private String remark;
-
-    @Schema(description = "琛ユ枡鍘熷洜")
-    private String feedingReason;
-
-    @Schema(description = "鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @Schema(description = "鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @Schema(description = "鍒涘缓浜篒D")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @Schema(description = "閮ㄩ棬ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long deptId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
index 941fb49..6b581a0 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
@@ -48,12 +48,6 @@
     @Schema(description = "宸ヨ壓璺嚎缂栫爜")
     private String processRouteCode;
 
-    @Schema(description = "鍩虹bom鐨刬d")
-    private Long bomId;
-
-    @Schema(description = "璁㈠崟bom鐨刬d")
-    private Long orderBomId;
-
     @Schema(description = "鍒涘缓浜篒D")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
index 9de89fb..cfae50c 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
+++ b/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;
+
 }
diff --git a/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java b/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java
deleted file mode 100644
index 6e63dfe..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
-import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
-import com.ruoyi.production.pojo.ProductionBomStructure;
-
-import java.util.List;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-public interface ProductionBomStructureService extends IService<ProductionBomStructure> {
-
-    List<ProductionBomStructureVo> listByBomId(Long bomId);
-
-    Boolean addProductionBomStructure(ProductionBomStructureDto productionBomStructureDto);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
index 0945c6a..cd40613 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
+++ b/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);
 
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java
deleted file mode 100644
index da4f9fc..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.pojo.ProductionOrderBom;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-public interface ProductionOrderBomService extends IService<ProductionOrderBom> {
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java
deleted file mode 100644
index ebd6e27..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-
-import java.util.List;
-
-/**
- * <p>
- * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-public interface ProductionOrderPickRecordService extends IService<ProductionOrderPickRecord> {
-
-    List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java
deleted file mode 100644
index 82ee298..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
-import com.ruoyi.production.pojo.ProductionOrderPick;
-
-import java.util.List;
-
-/**
- * <p>
- * 璁㈠崟棰嗘枡绾胯竟浠� 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-public interface ProductionOrderPickService extends IService<ProductionOrderPick> {
-
-    Boolean savePick(ProductionOrderPickDto dto);
-
-    Boolean updatePick(ProductionOrderPickDto dto);
-
-    List<ProductionOrderPickVo> listPickedDetail(Long productionOrderId);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
index deeb0dd..54a65ea 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
+++ b/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);
 
diff --git a/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java b/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
index 6a07d2b..dad858f 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
+++ b/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);
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
deleted file mode 100644
index 0513bdc..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
+++ /dev/null
@@ -1,889 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
-import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
-import com.ruoyi.production.mapper.ProductionBomStructureMapper;
-import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
-import com.ruoyi.production.mapper.ProductionOrderBomMapper;
-import com.ruoyi.production.mapper.ProductionOrderMapper;
-import com.ruoyi.production.mapper.ProductionOrderRoutingMapper;
-import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
-import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
-import com.ruoyi.production.pojo.ProductionBomStructure;
-import com.ruoyi.production.pojo.ProductionOperationTask;
-import com.ruoyi.production.pojo.ProductionOrder;
-import com.ruoyi.production.pojo.ProductionOrderBom;
-import com.ruoyi.production.pojo.ProductionOrderRouting;
-import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
-import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
-import com.ruoyi.production.pojo.ProductionProductMain;
-import com.ruoyi.production.service.ProductionBomStructureService;
-import com.ruoyi.production.util.TaskPlanQuantityUtil;
-import com.ruoyi.technology.mapper.TechnologyOperationMapper;
-import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
-import com.ruoyi.technology.mapper.TechnologyParamMapper;
-import com.ruoyi.technology.pojo.TechnologyOperation;
-import com.ruoyi.technology.pojo.TechnologyOperationParam;
-import com.ruoyi.technology.pojo.TechnologyParam;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Service
-@RequiredArgsConstructor()
-public class ProductionBomStructureServiceImpl extends ServiceImpl<ProductionBomStructureMapper, ProductionBomStructure> implements ProductionBomStructureService {
-
-    private final ProductionBomStructureMapper productionBomStructureMapper;
-    private final ProductionOrderBomMapper productionOrderBomMapper;
-    private final ProductionOrderMapper productionOrderMapper;
-    private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
-    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
-    private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
-    private final ProductionOperationTaskMapper productionOperationTaskMapper;
-    private final ProductionProductMainMapper productionProductMainMapper;
-    private final TechnologyOperationMapper technologyOperationMapper;
-    private final TechnologyOperationParamMapper technologyOperationParamMapper;
-    private final TechnologyParamMapper technologyParamMapper;
-
-    /**
-     * 鏍规嵁BOM鏌ヨ骞剁粍瑁呯粨鏋勬爲銆�
-     */
-    @Override
-    public List<ProductionBomStructureVo> listByBomId(Long bomId) {
-        // 鎸塀OMID鏌ヨ鐢熶骇缁撴瀯鏁版嵁
-        List<ProductionBomStructureVo> list = productionBomStructureMapper.listByBomId(bomId);
-        Map<Long, ProductionBomStructureVo> map = new HashMap<>();
-        for (ProductionBomStructureVo node : list) {
-            node.setChildren(new ArrayList<>());
-            map.put(node.getId(), node);
-        }
-
-        List<ProductionBomStructureVo> tree = new ArrayList<>();
-        for (ProductionBomStructureVo node : list) {
-            Long parentId = node.getParentId();
-            if (parentId == null || parentId == 0L) {
-                tree.add(node);
-                continue;
-            }
-            ProductionBomStructureVo parent = map.get(parentId);
-            if (parent != null) {
-                parent.getChildren().add(node);
-            }
-        }
-        return tree;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean addProductionBomStructure(ProductionBomStructureDto dto) {
-        // 鏂板鐢熶骇BOM缁撴瀯
-        // 璇诲彇褰撳墠璁㈠崟BOM涓婚敭锛屽苟鎶婂墠绔爲缁撴瀯鎷嶅钩鎴愬垪琛�
-        Long orderBomId = dto.getProductionOrderBomId();
-        List<ProductionBomStructureDto> flatDtoList = new ArrayList<>();
-        flattenTree(dto.getChildren(), flatDtoList);
-
-        // 鏌ヨ鏁版嵁搴撳凡鏈夌粨鏋勶紝鐢ㄤ簬鍚庣画鍋氬鍒犳敼瀵规瘮
-        List<ProductionBomStructure> dbList = this.list(new LambdaQueryWrapper<ProductionBomStructure>()
-                .eq(ProductionBomStructure::getProductionOrderBomId, orderBomId));
-
-        // 鏀堕泦鍓嶇浠嶇劧瀛樺湪鐨勮妭鐐笽D
-        Set<Long> frontendIds = new HashSet<>();
-        for (ProductionBomStructureDto item : flatDtoList) {
-            if (item.getId() != null) {
-                frontendIds.add(item.getId());
-            }
-        }
-
-        // 璁$畻闇�瑕佸垹闄ょ殑鑺傜偣锛堟暟鎹簱鏈夈�佸墠绔凡鍒犻櫎锛�
-        Set<Long> deleteIds = new HashSet<>();
-        for (ProductionBomStructure dbItem : dbList) {
-            if (!frontendIds.contains(dbItem.getId())) {
-                deleteIds.add(dbItem.getId());
-            }
-        }
-        // 鍏堝垹鎺夊墠绔凡缁忕Щ闄ょ殑鑺傜偣
-        if (!deleteIds.isEmpty()) {
-            this.removeByIds(deleteIds);
-        }
-
-        // 鎸夋槸鍚︽湁ID鎷嗗垎涓烘柊澧炲拰鏇存柊锛屽悓鏃剁紦瀛樻柊澧炶妭鐐圭殑涓存椂ID鏄犲皠
-        List<ProductionBomStructure> insertList = new ArrayList<>();
-        List<ProductionBomStructure> updateList = new ArrayList<>();
-        Map<String, ProductionBomStructure> tempEntityMap = new HashMap<>();
-
-        for (ProductionBomStructureDto item : flatDtoList) {
-            ProductionBomStructure entity = new ProductionBomStructure();
-            BeanUtils.copyProperties(item, entity);
-            entity.setProductionOrderBomId(orderBomId);
-            if (item.getId() == null) {
-                entity.setParentId(null);
-                insertList.add(entity);
-                tempEntityMap.put(item.getTempId(), entity);
-            } else {
-                updateList.add(entity);
-            }
-        }
-
-        // 鎵归噺鏂板锛屾嬁鍒版暟鎹簱鐢熸垚鐨勭湡瀹濱D
-        if (!insertList.isEmpty()) {
-            this.saveBatch(insertList);
-        }
-
-        // 鏂板鑺傜偣浜屾鍥炲啓鐖禝D锛堝墠绔紶鐨勬槸涓存椂鐖禝D锛�
-        List<ProductionBomStructure> parentFixList = new ArrayList<>();
-        for (ProductionBomStructureDto item : flatDtoList) {
-            if (item.getId() == null && item.getParentTempId() != null) {
-                ProductionBomStructure child = tempEntityMap.get(item.getTempId());
-                if (child == null) {
-                    continue;
-                }
-                ProductionBomStructure parent = tempEntityMap.get(item.getParentTempId());
-                // 鐖惰妭鐐规槸鏈鏂板鏃讹紝鐩存帴鐢ㄦ柊澧炲悗鐨勭湡瀹濱D锛涘惁鍒欏洖閫�涓哄墠绔紶鍏ョ埗ID
-                Long realParentId = parent != null ? parent.getId() : Long.valueOf(item.getParentTempId());
-                child.setParentId(realParentId);
-                parentFixList.add(child);
-            }
-        }
-
-        // 鍥炲啓鏂板鑺傜偣鐨勭埗瀛愬叧绯�
-        if (!parentFixList.isEmpty()) {
-            this.updateBatchById(parentFixList);
-        }
-        // 鎵归噺鏇存柊宸叉湁鑺傜偣
-        if (!updateList.isEmpty()) {
-            this.updateBatchById(updateList);
-        }
-        syncDemandedQuantityAndTaskPlanQuantity(orderBomId, dto.getProductionOrderId());
-        return true;
-    }
-
-    private void syncDemandedQuantityAndTaskPlanQuantity(Long orderBomId, Long productionOrderId) {
-        if (orderBomId == null) {
-            return;
-        }
-        ProductionOrderBom orderBom = productionOrderBomMapper.selectById(orderBomId);
-        if (orderBom == null) {
-            return;
-        }
-        Long currentProductionOrderId = productionOrderId != null ? productionOrderId : orderBom.getProductionOrderId();
-        if (currentProductionOrderId == null) {
-            return;
-        }
-        ProductionOrder productionOrder = productionOrderMapper.selectById(currentProductionOrderId);
-        if (productionOrder == null) {
-            return;
-        }
-
-        BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity());
-        List<ProductionBomStructure> structureList = this.list(
-                Wrappers.<ProductionBomStructure>lambdaQuery()
-                        .eq(ProductionBomStructure::getProductionOrderBomId, orderBomId)
-                        .orderByAsc(ProductionBomStructure::getId));
-        //鍚屾闇�姹傛暟閲�
-        syncStructureDemandedQuantity(structureList, orderQuantity);
-        Long rootProductModelId = orderBom.getProductModelId() != null ? orderBom.getProductModelId() : productionOrder.getProductModelId();
-        //鍚屾鐢熶骇宸ヨ壓璺嚎
-        syncRoutingOperationsByBom(currentProductionOrderId, productionOrder, orderBom, structureList, rootProductModelId);
-        //鍚屾宸ュ崟
-        syncTaskPlanQuantity(
-                currentProductionOrderId,
-                structureList,
-                orderQuantity,
-                rootProductModelId);
-    }
-
-    private void syncStructureDemandedQuantity(List<ProductionBomStructure> structureList, BigDecimal orderQuantity) {
-        if (structureList == null || structureList.isEmpty()) {
-            return;
-        }
-        List<ProductionBomStructure> updateList = new ArrayList<>();
-        BigDecimal lastProcessDemandedQuantity = orderQuantity;
-        for (ProductionBomStructure structure : structureList) {
-            if (structure == null || structure.getId() == null) {
-                continue;
-            }
-
-            BigDecimal demandedQuantity = lastProcessDemandedQuantity.multiply(defaultDecimal(structure.getUnitQuantity()));
-//            if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) {
-//                continue;
-//            }
-            ProductionBomStructure update = new ProductionBomStructure();
-            update.setId(structure.getId());
-            update.setDemandedQuantity(demandedQuantity);
-            updateList.add(update);
-            structure.setDemandedQuantity(demandedQuantity);
-            lastProcessDemandedQuantity = demandedQuantity;
-        }
-        if (!updateList.isEmpty()) {
-            this.updateBatchById(updateList);
-        }
-    }
-
-    private void syncTaskPlanQuantity(Long productionOrderId,
-                                      List<ProductionBomStructure> structureList,
-                                      BigDecimal orderQuantity,
-                                      Long rootProductModelId) {
-        List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList(
-                Wrappers.<ProductionOperationTask>lambdaQuery()
-                        .eq(ProductionOperationTask::getProductionOrderId, productionOrderId)
-                        .orderByAsc(ProductionOperationTask::getId));
-        if (taskList == null || taskList.isEmpty()) {
-            return;
-        }
-        Set<Long> routingOperationIds = taskList.stream()
-                .map(ProductionOperationTask::getProductionOrderRoutingOperationId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        if (routingOperationIds.isEmpty()) {
-            return;
-        }
-        Map<Long, ProductionOrderRoutingOperation> routingOperationMap = productionOrderRoutingOperationMapper
-                .selectBatchIds(routingOperationIds)
-                .stream()
-                .filter(item -> item != null && item.getId() != null)
-                .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left));
-        // Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation.
-        Map<String, BigDecimal> demandedQuantityMap = TaskPlanQuantityUtil.buildOperationDemandedQuantityMap(structureList, rootProductModelId);
-        for (ProductionOperationTask task : taskList) {
-            if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) {
-                continue;
-            }
-            ProductionOrderRoutingOperation routingOperation = routingOperationMap.get(task.getProductionOrderRoutingOperationId());
-            if (routingOperation == null) {
-                continue;
-            }
-            BigDecimal planQuantity = resolveTaskPlanQuantity(
-                    routingOperation,
-                    demandedQuantityMap,
-                    orderQuantity,
-                    rootProductModelId);
-            if (compareDecimal(task.getPlanQuantity(), planQuantity) == 0) {
-                continue;
-            }
-            ProductionOperationTask update = new ProductionOperationTask();
-            update.setId(task.getId());
-            update.setPlanQuantity(planQuantity);
-            productionOperationTaskMapper.updateById(update);
-        }
-    }
-
-    private void syncRoutingOperationsByBom(Long productionOrderId,
-                                            ProductionOrder productionOrder,
-                                            ProductionOrderBom orderBom,
-                                            List<ProductionBomStructure> structureList,
-                                            Long rootProductModelId) {
-        ProductionOrderRouting orderRouting = getOrCreateOrderRoutingSnapshot(productionOrderId, productionOrder, orderBom, rootProductModelId);
-        List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(structureList, rootProductModelId);
-        List<ProductionOrderRoutingOperation> existingOperationList = productionOrderRoutingOperationMapper.selectList(
-                Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
-                        .eq(ProductionOrderRoutingOperation::getOrderRoutingId, orderRouting.getId())
-                        .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId)
-                        .orderByAsc(ProductionOrderRoutingOperation::getDragSort)
-                        .orderByAsc(ProductionOrderRoutingOperation::getId));
-        Map<String, Deque<ProductionOrderRoutingOperation>> existingBucketMap = buildExistingRoutingOperationBucketMap(existingOperationList);
-        List<ProductionOrderRoutingOperation> finalOperationList = new ArrayList<>();
-        for (ProductionOrderRoutingOperation desiredOperation : desiredOperationList) {
-            String bucketKey = buildRoutingOperationBucketKey(
-                    desiredOperation.getTechnologyOperationId(),
-                    desiredOperation.getProductModelId());
-            Deque<ProductionOrderRoutingOperation> matchedQueue = existingBucketMap.get(bucketKey);
-            ProductionOrderRoutingOperation matchedOperation = matchedQueue == null ? null : matchedQueue.pollFirst();
-            if (matchedOperation == null) {
-                matchedOperation = insertRoutingOperationSnapshot(orderRouting.getId(), productionOrderId, desiredOperation);
-            } else {
-                updateRoutingOperationSnapshotIfNecessary(matchedOperation, orderRouting.getId(), productionOrderId, desiredOperation);
-            }
-            finalOperationList.add(matchedOperation);
-        }
-        for (Deque<ProductionOrderRoutingOperation> queue : existingBucketMap.values()) {
-            while (queue != null && !queue.isEmpty()) {
-                removeRoutingOperationSnapshot(queue.pollFirst());
-            }
-        }
-        syncRoutingOperationTasks(productionOrderId, finalOperationList);
-    }
-
-    private ProductionOrderRouting getOrCreateOrderRoutingSnapshot(Long productionOrderId,
-                                                                   ProductionOrder productionOrder,
-                                                                   ProductionOrderBom orderBom,
-                                                                   Long rootProductModelId) {
-        ProductionOrderRouting orderRouting = productionOrderRoutingMapper.selectOne(
-                Wrappers.<ProductionOrderRouting>lambdaQuery()
-                        .eq(ProductionOrderRouting::getProductionOrderId, productionOrderId)
-                        .orderByDesc(ProductionOrderRouting::getId)
-                        .last("limit 1"));
-        if (orderRouting == null) {
-            orderRouting = new ProductionOrderRouting();
-            orderRouting.setProductionOrderId(productionOrderId);
-            orderRouting.setProductModelId(rootProductModelId);
-            orderRouting.setTechnologyRoutingId(productionOrder == null ? null : productionOrder.getTechnologyRoutingId());
-            orderRouting.setBomId(orderBom == null ? null : orderBom.getBomId());
-            orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId());
-            productionOrderRoutingMapper.insert(orderRouting);
-            return orderRouting;
-        }
-        ProductionOrderRouting update = new ProductionOrderRouting();
-        update.setId(orderRouting.getId());
-        boolean changed = false;
-        if (!Objects.equals(orderRouting.getProductModelId(), rootProductModelId)) {
-            update.setProductModelId(rootProductModelId);
-            orderRouting.setProductModelId(rootProductModelId);
-            changed = true;
-        }
-        Long technologyRoutingId = productionOrder == null ? null : productionOrder.getTechnologyRoutingId();
-        if (!Objects.equals(orderRouting.getTechnologyRoutingId(), technologyRoutingId)) {
-            update.setTechnologyRoutingId(technologyRoutingId);
-            orderRouting.setTechnologyRoutingId(technologyRoutingId);
-            changed = true;
-        }
-        Long bomId = orderBom == null ? null : orderBom.getBomId();
-        if (!Objects.equals(orderRouting.getBomId(), bomId)) {
-            update.setBomId(bomId);
-            orderRouting.setBomId(bomId);
-            changed = true;
-        }
-        Long orderBomId = orderBom == null ? null : orderBom.getId();
-        if (!Objects.equals(orderRouting.getOrderBomId(), orderBomId)) {
-            update.setOrderBomId(orderBomId);
-            orderRouting.setOrderBomId(orderBomId);
-            changed = true;
-        }
-        if (changed) {
-            productionOrderRoutingMapper.updateById(update);
-        }
-        return orderRouting;
-    }
-
-    private List<ProductionOrderRoutingOperation> buildDesiredRoutingOperationList(List<ProductionBomStructure> structureList,
-                                                                                   Long rootProductModelId) {
-        if (structureList == null || structureList.isEmpty()) {
-            return Collections.emptyList();
-        }
-        Map<Long, ProductionBomStructure> structureById = structureList.stream()
-                .filter(item -> item != null && item.getId() != null)
-                .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
-
-        // 鏋勫缓鐖�-瀛愭槧灏勫叧绯�
-        Map<Long, List<ProductionBomStructure>> treeMap = buildParentChildMap(structureList);
-
-        // 浣跨敤鍚庡簭閬嶅巻鏋勫缓鎿嶄綔鍒楄〃锛堝厛瀛愬悗鐖讹紝纭繚宸ヨ壓璺嚎椤哄簭姝g‘锛�
-        // 浣跨敤娣卞害浣滀负鎺掑簭渚濇嵁鐨勮緟鍔╃粨鏋�
-        Map<String, ProductionBomStructure> operationMap = new LinkedHashMap<>();
-        Map<String, Integer> depthMap = new HashMap<>();
-        buildOperationListPostOrderWithDepth(null, treeMap, operationMap, depthMap, structureById, rootProductModelId, 1);
-
-        // 鎸夋繁搴︽帓搴忥紝娣卞害澶х殑鎺掑墠闈�
-        List<Map.Entry<String, ProductionBomStructure>> sortedEntries = new ArrayList<>(operationMap.entrySet());
-        sortedEntries.sort((a, b) -> {
-            int depthCompare = Integer.compare(
-                    depthMap.getOrDefault(b.getKey(), 0),
-                    depthMap.getOrDefault(a.getKey(), 0));
-            if (depthCompare != 0) {
-                return depthCompare;
-            }
-            return 0;
-        });
-
-        List<ProductionOrderRoutingOperation> desiredOperationList = new ArrayList<>();
-        int dragSort = 1;
-        for (Map.Entry<String, ProductionBomStructure> entry : sortedEntries) {
-            ProductionBomStructure bomStructure = entry.getValue();
-            Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId);
-            TechnologyOperation technologyOperation = getTechnologyOperation(bomStructure.getTechnologyOperationId());
-            ProductionOrderRoutingOperation routingOperation = new ProductionOrderRoutingOperation();
-            routingOperation.setProductModelId(outputProductModelId);
-            routingOperation.setTechnologyOperationId(bomStructure.getTechnologyOperationId());
-            routingOperation.setOperationName(technologyOperation == null ? null : technologyOperation.getName());
-            routingOperation.setIsQuality(technologyOperation == null ? null : technologyOperation.getIsQuality());
-            routingOperation.setIsProduction(technologyOperation == null ? null : technologyOperation.getIsProduction());
-            routingOperation.setType(technologyOperation == null ? null : technologyOperation.getType());
-            routingOperation.setDragSort(dragSort++);
-            desiredOperationList.add(routingOperation);
-        }
-        return desiredOperationList;
-    }
-
-    private void buildOperationListPostOrderWithDepth(Long parentId,
-                                                      Map<Long, List<ProductionBomStructure>> treeMap,
-                                                      Map<String, ProductionBomStructure> operationMap,
-                                                      Map<String, Integer> depthMap,
-                                                      Map<Long, ProductionBomStructure> structureById,
-                                                      Long rootProductModelId,
-                                                      int currentDepth) {
-        List<ProductionBomStructure> children = treeMap.get(parentId);
-        if (children == null || children.isEmpty()) {
-            return;
-        }
-        for (ProductionBomStructure child : children) {
-            // 鍏堥�掑綊澶勭悊瀛愯妭鐐�
-            buildOperationListPostOrderWithDepth(child.getId(), treeMap, operationMap, depthMap, structureById, rootProductModelId, currentDepth + 1);
-
-            // 鍐嶅鐞嗗綋鍓嶈妭鐐�
-            if (child.getTechnologyOperationId() != null) {
-                Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
-                String key = buildBomOperationDedupKey(child, outputProductModelId);
-                // 淇濈暀娣卞害鏈�澶х殑鎿嶄綔
-                Integer existingDepth = depthMap.get(key);
-                if (existingDepth == null || currentDepth > existingDepth) {
-                    operationMap.put(key, child);
-                    depthMap.put(key, currentDepth);
-                }
-            }
-        }
-    }
-
-    private Map<Long, List<ProductionBomStructure>> buildParentChildMap(List<ProductionBomStructure> structureList) {
-        Map<Long, List<ProductionBomStructure>> treeMap = new LinkedHashMap<>();
-        Map<Long, ProductionBomStructure> structureById = new HashMap<>();
-
-        // 鏋勫缓鐖�-瀛愭槧灏勫拰ID鏄犲皠
-        for (ProductionBomStructure structure : structureList) {
-            if (structure == null) continue;
-            Long parentId = structure.getParentId();
-            treeMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure);
-            if (structure.getId() != null) {
-                structureById.put(structure.getId(), structure);
-            }
-        }
-
-        // 璁$畻姣忎釜鑺傜偣鐨勬繁搴︼紙浠庢牴鑺傜偣鍒板綋鍓嶈妭鐐圭殑璺濈锛屾牴鑺傜偣娣卞害涓�1锛�
-        Map<Long, Integer> depthMap = new HashMap<>();
-        for (ProductionBomStructure structure : structureList) {
-            if (structure == null || structure.getId() == null) continue;
-            computeDepthFromRoot(structure.getId(), structureById, depthMap);
-        }
-
-        // 瀵规瘡涓埗鑺傜偣涓嬬殑瀛愯妭鐐规寜娣卞害鍊掑簭鎺掑簭锛堟渶娣卞眰鐨勪紭鍏堬級
-        for (Map.Entry<Long, List<ProductionBomStructure>> entry : treeMap.entrySet()) {
-            List<ProductionBomStructure> children = entry.getValue();
-            children.sort((a, b) -> {
-                // 浼樺厛鎸夋繁搴︽帓搴忥紝娣卞害澶х殑鎺掑墠闈紙鏈�娣卞眰浼樺厛锛�
-                int depthCompare = Integer.compare(
-                        depthMap.getOrDefault(b.getId(), 0),
-                        depthMap.getOrDefault(a.getId(), 0));
-                if (depthCompare != 0) {
-                    return depthCompare;
-                }
-                // 娣卞害鐩稿悓鏃舵寜ID鎺掑簭淇濊瘉绋冲畾鎬�
-                return Long.compare(a.getId(), b.getId());
-            });
-        }
-
-        return treeMap;
-    }
-
-    /**
-     * 璁$畻鑺傜偣娣卞害锛堜粠鏍硅妭鐐瑰埌褰撳墠鑺傜偣鐨勮窛绂伙級
-     * 鏍硅妭鐐规繁搴︿负1锛屾瘡鍚戜笅涓�灞傛繁搴﹀姞1
-     */
-    private int computeDepthFromRoot(Long nodeId, Map<Long, ProductionBomStructure> structureById, Map<Long, Integer> depthMap) {
-        if (depthMap.containsKey(nodeId)) {
-            return depthMap.get(nodeId);
-        }
-
-        ProductionBomStructure structure = structureById.get(nodeId);
-        if (structure == null) {
-            depthMap.put(nodeId, 1);
-            return 1;
-        }
-
-        Long parentId = structure.getParentId();
-        if (parentId == null || parentId == 0L) {
-            // 鏍硅妭鐐规繁搴︿负1
-            depthMap.put(nodeId, 1);
-            return 1;
-        }
-
-        // 瀛愯妭鐐规繁搴� = 鐖惰妭鐐规繁搴� + 1
-        int parentDepth = computeDepthFromRoot(parentId, structureById, depthMap);
-        int depth = parentDepth + 1;
-        depthMap.put(nodeId, depth);
-        return depth;
-    }
-
-    private void buildOperationListPostOrder(Long parentId,
-                                             Map<Long, List<ProductionBomStructure>> treeMap,
-                                             Map<String, ProductionBomStructure> uniqueOperationMap,
-                                             Map<Long, ProductionBomStructure> structureById,
-                                             Long rootProductModelId) {
-        List<ProductionBomStructure> children = treeMap.get(parentId);
-        if (children == null || children.isEmpty()) {
-            return;
-        }
-        for (ProductionBomStructure child : children) {
-            // 鍏堥�掑綊澶勭悊瀛愯妭鐐�
-            buildOperationListPostOrder(child.getId(), treeMap, uniqueOperationMap, structureById, rootProductModelId);
-
-            // 鍐嶅鐞嗗綋鍓嶈妭鐐�
-            if (child.getTechnologyOperationId() != null) {
-                Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
-                String key = buildBomOperationDedupKey(child, outputProductModelId);
-                // 鍘婚噸鏃朵繚鐣欐繁搴︽渶澶х殑鎿嶄綔锛堝悗搴忛亶鍘嗗厛閬囧埌娣卞眰鑺傜偣锛屾墍浠ョ洿鎺ヨ鐩栧嵆鍙級
-                uniqueOperationMap.put(key, child);
-            }
-        }
-    }
-
-    private Map<String, Deque<ProductionOrderRoutingOperation>> buildExistingRoutingOperationBucketMap(List<ProductionOrderRoutingOperation> existingOperationList) {
-        Map<String, Deque<ProductionOrderRoutingOperation>> existingBucketMap = new LinkedHashMap<>();
-        if (existingOperationList == null || existingOperationList.isEmpty()) {
-            return existingBucketMap;
-        }
-        for (ProductionOrderRoutingOperation routingOperation : existingOperationList) {
-            String bucketKey = buildRoutingOperationBucketKey(
-                    routingOperation.getTechnologyOperationId(),
-                    routingOperation.getProductModelId());
-            existingBucketMap.computeIfAbsent(bucketKey, key -> new ArrayDeque<>()).addLast(routingOperation);
-        }
-        return existingBucketMap;
-    }
-
-    private ProductionOrderRoutingOperation insertRoutingOperationSnapshot(Long orderRoutingId,
-                                                                           Long productionOrderId,
-                                                                           ProductionOrderRoutingOperation desiredOperation) {
-        ProductionOrderRoutingOperation insert = new ProductionOrderRoutingOperation();
-        insert.setOrderRoutingId(orderRoutingId);
-        insert.setProductionOrderId(productionOrderId);
-        insert.setProductModelId(desiredOperation.getProductModelId());
-        insert.setTechnologyOperationId(desiredOperation.getTechnologyOperationId());
-        insert.setOperationName(desiredOperation.getOperationName());
-        insert.setIsQuality(desiredOperation.getIsQuality());
-        insert.setIsProduction(desiredOperation.getIsProduction());
-        insert.setType(desiredOperation.getType());
-        insert.setDragSort(desiredOperation.getDragSort());
-        productionOrderRoutingOperationMapper.insert(insert);
-        syncRoutingOperationParams(insert.getId(), productionOrderId, insert.getTechnologyOperationId());
-        return insert;
-    }
-
-    private void updateRoutingOperationSnapshotIfNecessary(ProductionOrderRoutingOperation currentOperation,
-                                                           Long orderRoutingId,
-                                                           Long productionOrderId,
-                                                           ProductionOrderRoutingOperation desiredOperation) {
-        if (currentOperation == null || currentOperation.getId() == null) {
-            return;
-        }
-        ProductionOrderRoutingOperation update = new ProductionOrderRoutingOperation();
-        update.setId(currentOperation.getId());
-        boolean changed = false;
-        if (!Objects.equals(currentOperation.getOrderRoutingId(), orderRoutingId)) {
-            update.setOrderRoutingId(orderRoutingId);
-            currentOperation.setOrderRoutingId(orderRoutingId);
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getProductionOrderId(), productionOrderId)) {
-            update.setProductionOrderId(productionOrderId);
-            currentOperation.setProductionOrderId(productionOrderId);
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getProductModelId(), desiredOperation.getProductModelId())) {
-            update.setProductModelId(desiredOperation.getProductModelId());
-            currentOperation.setProductModelId(desiredOperation.getProductModelId());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getTechnologyOperationId(), desiredOperation.getTechnologyOperationId())) {
-            update.setTechnologyOperationId(desiredOperation.getTechnologyOperationId());
-            currentOperation.setTechnologyOperationId(desiredOperation.getTechnologyOperationId());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getOperationName(), desiredOperation.getOperationName())) {
-            update.setOperationName(desiredOperation.getOperationName());
-            currentOperation.setOperationName(desiredOperation.getOperationName());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getIsQuality(), desiredOperation.getIsQuality())) {
-            update.setIsQuality(desiredOperation.getIsQuality());
-            currentOperation.setIsQuality(desiredOperation.getIsQuality());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getIsProduction(), desiredOperation.getIsProduction())) {
-            update.setIsProduction(desiredOperation.getIsProduction());
-            currentOperation.setIsProduction(desiredOperation.getIsProduction());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getType(), desiredOperation.getType())) {
-            update.setType(desiredOperation.getType());
-            currentOperation.setType(desiredOperation.getType());
-            changed = true;
-        }
-        if (!Objects.equals(currentOperation.getDragSort(), desiredOperation.getDragSort())) {
-            update.setDragSort(desiredOperation.getDragSort());
-            currentOperation.setDragSort(desiredOperation.getDragSort());
-            changed = true;
-        }
-        if (changed) {
-            productionOrderRoutingOperationMapper.updateById(update);
-        }
-    }
-
-    private void removeRoutingOperationSnapshot(ProductionOrderRoutingOperation routingOperation) {
-        if (routingOperation == null || routingOperation.getId() == null) {
-            return;
-        }
-        ProductionOperationTask task = productionOperationTaskMapper.selectOne(
-                Wrappers.<ProductionOperationTask>lambdaQuery()
-                        .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, routingOperation.getId())
-                        .last("limit 1"));
-        if (task != null) {
-            validateTaskCanRemove(task);
-            productionOperationTaskMapper.deleteById(task.getId());
-        }
-        productionOrderRoutingOperationParamMapper.delete(
-                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
-                        .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperation.getId()));
-        productionOrderRoutingOperationMapper.deleteById(routingOperation.getId());
-    }
-
-    private void syncRoutingOperationTasks(Long productionOrderId, List<ProductionOrderRoutingOperation> routingOperationList) {
-        if (routingOperationList == null || routingOperationList.isEmpty()) {
-            return;
-        }
-        List<Long> routingOperationIdList = routingOperationList.stream()
-                .map(ProductionOrderRoutingOperation::getId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-        if (routingOperationIdList.isEmpty()) {
-            return;
-        }
-        Map<Long, ProductionOperationTask> taskByRoutingOperationId = productionOperationTaskMapper.selectList(
-                        Wrappers.<ProductionOperationTask>lambdaQuery()
-                                .in(ProductionOperationTask::getProductionOrderRoutingOperationId, routingOperationIdList)
-                                .orderByAsc(ProductionOperationTask::getId))
-                .stream()
-                .filter(item -> item != null && item.getProductionOrderRoutingOperationId() != null)
-                .collect(Collectors.toMap(
-                        ProductionOperationTask::getProductionOrderRoutingOperationId,
-                        item -> item,
-                        (left, right) -> left,
-                        LinkedHashMap::new));
-        for (int i = 0; i < routingOperationList.size(); i++) {
-            ProductionOrderRoutingOperation routingOperation = routingOperationList.get(i);
-            if (routingOperation == null || routingOperation.getId() == null) {
-                continue;
-            }
-            boolean shouldHaveTask = i == routingOperationList.size() - 1 || Boolean.TRUE.equals(routingOperation.getIsProduction());
-            ProductionOperationTask existingTask = taskByRoutingOperationId.get(routingOperation.getId());
-            if (shouldHaveTask) {
-                if (existingTask == null) {
-                    ProductionOperationTask task = new ProductionOperationTask();
-                    task.setProductionOrderId(productionOrderId);
-                    task.setProductionOrderRoutingOperationId(routingOperation.getId());
-                    task.setPlanQuantity(BigDecimal.ZERO);
-                    task.setCompleteQuantity(BigDecimal.ZERO);
-                    task.setWorkOrderNo(generateNextTaskNo());
-                    task.setStatus(2);
-                    productionOperationTaskMapper.insert(task);
-                }
-                continue;
-            }
-            if (existingTask != null) {
-                validateTaskCanRemove(existingTask);
-                productionOperationTaskMapper.deleteById(existingTask.getId());
-            }
-        }
-    }
-
-    private void validateTaskCanRemove(ProductionOperationTask task) {
-        if (task == null || task.getId() == null) {
-            return;
-        }
-        if (defaultDecimal(task.getCompleteQuantity()).compareTo(BigDecimal.ZERO) > 0) {
-            throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ簭蹇収" + task.getWorkOrderNo());
-        }
-        long reportCount = productionProductMainMapper.selectCount(
-                Wrappers.<ProductionProductMain>lambdaQuery()
-                        .eq(ProductionProductMain::getProductionOperationTaskId, task.getId()));
-        if (reportCount > 0) {
-            throw new ServiceException("宸ュ簭宸蹭骇鐢熸姤宸ヨ褰曪紝鏃犳硶鏍规嵁 BOM 鍙樻洿鍒犻櫎瀵瑰簲宸ュ崟");
-        }
-    }
-
-    private void syncRoutingOperationParams(Long routingOperationId, Long productionOrderId, Long technologyOperationId) {
-        if (routingOperationId == null || technologyOperationId == null) {
-            return;
-        }
-        List<TechnologyOperationParam> operationParamList = technologyOperationParamMapper.selectList(
-                Wrappers.<TechnologyOperationParam>lambdaQuery()
-                        .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationId)
-                        .orderByAsc(TechnologyOperationParam::getId));
-        for (TechnologyOperationParam operationParam : operationParamList) {
-            TechnologyParam technologyParam = technologyParamMapper.selectById(operationParam.getTechnologyParamId());
-            if (technologyParam == null) {
-                continue;
-            }
-            ProductionOrderRoutingOperationParam snapshot = new ProductionOrderRoutingOperationParam();
-            snapshot.setProductionOrderId(productionOrderId);
-            snapshot.setProductionOrderRoutingOperationId(routingOperationId);
-            snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId());
-            snapshot.setTechnologyOperationParamId(operationParam.getId());
-            snapshot.setParamId(technologyParam.getId());
-            snapshot.setParamCode(technologyParam.getParamCode());
-            snapshot.setParamName(technologyParam.getParamName());
-            snapshot.setParamType(technologyParam.getParamType());
-            snapshot.setParamFormat(technologyParam.getParamFormat());
-            snapshot.setUnit(technologyParam.getUnit());
-            snapshot.setIsRequired(technologyParam.getIsRequired());
-            snapshot.setRemark(technologyParam.getRemark());
-            snapshot.setStandardValue(operationParam.getStandardValue());
-            productionOrderRoutingOperationParamMapper.insert(snapshot);
-        }
-    }
-
-    private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> structureList,
-                                                                      Long rootProductModelId) {
-        if (structureList == null || structureList.isEmpty()) {
-            return Collections.emptyMap();
-        }
-        Map<Long, ProductionBomStructure> structureById = structureList.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 : structureList) {
-            if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
-                continue;
-            }
-            // Resolve the output node first, then read the output node demand for the task plan quantity.
-            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;
-            }
-            // Multiple input rows can point to the same output node, so only count that output demand once.
-            String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId);
-            demandedQuantityMap.merge(key, defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()), BigDecimal::add);
-        }
-        return demandedQuantityMap;
-    }
-
-    private 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;
-    }
-
-    private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) {
-        return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
-    }
-
-    private String buildRoutingOperationBucketKey(Long operationId, Long outputProductModelId) {
-        return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId);
-    }
-
-    private String buildBomOperationDedupKey(ProductionBomStructure bomStructure, Long outputProductModelId) {
-        Long operationId = bomStructure == null ? null : bomStructure.getTechnologyOperationId();
-        Long parentId = bomStructure == null ? null : bomStructure.getParentId();
-        return operationId + "#" + outputProductModelId + "#" + parentId;
-    }
-
-    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; other 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 TechnologyOperation getTechnologyOperation(Long technologyOperationId) {
-        if (technologyOperationId == null) {
-            return null;
-        }
-        return technologyOperationMapper.selectById(technologyOperationId);
-    }
-
-    private String generateNextTaskNo() {
-        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-        ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne(
-                Wrappers.<ProductionOperationTask>lambdaQuery()
-                        .likeRight(ProductionOperationTask::getWorkOrderNo, "GD" + datePrefix)
-                        .orderByDesc(ProductionOperationTask::getWorkOrderNo)
-                        .last("limit 1"));
-        int sequenceNumber = 1;
-        if (latestTask != null && latestTask.getWorkOrderNo() != null && latestTask.getWorkOrderNo().startsWith("GD" + datePrefix)) {
-            try {
-                sequenceNumber = Integer.parseInt(latestTask.getWorkOrderNo().substring(("GD" + datePrefix).length())) + 1;
-            } catch (NumberFormatException ignored) {
-                sequenceNumber = 1;
-            }
-        }
-        return "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
-    }
-
-    private BigDecimal defaultDecimal(BigDecimal value) {
-        return value == null ? BigDecimal.ZERO : value;
-    }
-
-    private int compareDecimal(BigDecimal left, BigDecimal right) {
-        return defaultDecimal(left).compareTo(defaultDecimal(right));
-    }
-
-    /**
-     * 灏嗘爲褰㈢粨鏋勬媿骞虫垚鍒楄〃锛屼究浜庣粺涓�淇濆瓨銆�
-     */
-    private void flattenTree(List<ProductionBomStructureDto> source, List<ProductionBomStructureDto> result) {
-        // 鎵佸钩鍖栧鐞嗘爲
-        if (source == null) {
-            return;
-        }
-        for (ProductionBomStructureDto node : source) {
-            result.add(node);
-            flattenTree(node.getChildren(), result);
-        }
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
index bd6f2df..6770a0d 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
+++ b/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);
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java
deleted file mode 100644
index 800e987..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.mapper.ProductionOrderBomMapper;
-import com.ruoyi.production.pojo.ProductionOrderBom;
-import com.ruoyi.production.service.ProductionOrderBomService;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 鐢熶骇璁㈠崟BOM 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Service
-public class ProductionOrderBomServiceImpl extends ServiceImpl<ProductionOrderBomMapper, ProductionOrderBom> implements ProductionOrderBomService {
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java
deleted file mode 100644
index 4b71eb3..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
-import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-import com.ruoyi.production.service.ProductionOrderPickRecordService;
-import org.springframework.stereotype.Service;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * <p>
- * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-04-21 03:55:52
- */
-@Service
-public class ProductionOrderPickRecordServiceImpl extends ServiceImpl<ProductionOrderPickRecordMapper, ProductionOrderPickRecord> implements ProductionOrderPickRecordService {
-
-    @Override
-    public List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto) {
-        // 鏌ヨ鎶曟枡璁板綍
-        if (dto == null || dto.getProductionOrderId() == null || dto.getPickId() == null) {
-            return Collections.emptyList();
-        }
-        return baseMapper.listFeedingRecord(dto);
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
deleted file mode 100644
index 554b95e..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
+++ /dev/null
@@ -1,1181 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.ReviewStatusEnum;
-import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
-import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
-import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
-import com.ruoyi.production.mapper.ProductionOrderMapper;
-import com.ruoyi.production.mapper.ProductionOrderPickMapper;
-import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
-import com.ruoyi.production.pojo.ProductionOrder;
-import com.ruoyi.production.pojo.ProductionOrderPick;
-import com.ruoyi.production.pojo.ProductionOrderPickRecord;
-import com.ruoyi.production.service.ProductionOrderPickService;
-import com.ruoyi.stock.dto.StockInventoryDto;
-import com.ruoyi.stock.mapper.StockInventoryMapper;
-import com.ruoyi.stock.pojo.StockInRecord;
-import com.ruoyi.stock.pojo.StockInventory;
-import com.ruoyi.stock.pojo.StockOutRecord;
-import com.ruoyi.stock.service.StockInventoryService;
-import com.ruoyi.stock.service.StockInRecordService;
-import com.ruoyi.stock.service.StockOutRecordService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 鐢熶骇璁㈠崟棰嗘枡鏈嶅姟瀹炵幇銆�
- * 璐熻矗棰嗘枡鏂板銆佹洿鏂般�佽ˉ鏂欍�侀��鏂欏強搴撳瓨鑱斿姩銆�
- */
-@Service
-@RequiredArgsConstructor
-public class ProductionOrderPickServiceImpl extends ServiceImpl<ProductionOrderPickMapper, ProductionOrderPick> implements ProductionOrderPickService {
-
-    private static final byte PICK_TYPE_NORMAL = 1;
-    private static final byte PICK_TYPE_FEEDING = 2;
-    private static final String PICK_STOCK_OUT_RECORD_TYPE = StockOutQualifiedRecordTypeEnum.PICK_STOCK_OUT.getCode();
-    private static final String FEED_STOCK_OUT_RECORD_TYPE = StockOutQualifiedRecordTypeEnum.FEED_STOCK_OUT.getCode();
-    private static final String PICK_RETURN_IN_RECORD_TYPE = StockInQualifiedRecordTypeEnum.PICK_RETURN_IN.getCode();
-    private static final String FEED_RETURN_IN_RECORD_TYPE = StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode();
-
-    private final ProductionOrderMapper productionOrderMapper;
-    private final ProductionOperationTaskMapper productionOperationTaskMapper;
-    private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
-    private final StockInventoryMapper stockInventoryMapper;
-    private final StockInventoryService stockInventoryService;
-    private final StockInRecordService stockInRecordService;
-    private final StockOutRecordService stockOutRecordService;
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean savePick(ProductionOrderPickDto dto) {
-        // 棰嗘枡鏂板鎬绘祦绋嬶細
-        // 1) 瑙f瀽鍓嶇琛屾暟鎹苟閫愯鍚堝苟鍙傛暟锛�
-        // 2) 鏍¢獙鍙傛暟涓庢壒娆★紱
-        // 3) 鍏堜繚瀛橀鏂欎富璁板綍锛�
-        // 4) 鍐嶈蛋鈥滃嚭搴撶敵璇� + 瀹℃壒閫氳繃鈥濆畬鎴愬簱瀛樻墸鍑忥紱
-        // 5) 鍐欏叆棰嗘枡娴佹按锛岃褰曟暟閲忓彉鍖栬建杩广��
-        List<ProductionOrderPickDto> pickItems = resolvePickItems(dto);
-        // 閫愯澶勭悊棰嗘枡鏁版嵁锛岃鍙风敤浜庢嫾瑁呯簿纭殑鎶ラ敊淇℃伅銆�
-        for (int i = 0; i < pickItems.size(); i++) {
-            int rowNo = i + 1;
-            ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
-            // 姣忚閮藉仛瀹屾暣鏍¢獙锛屽紓甯镐俊鎭甫琛屽彿銆�
-            validatePickParam(resolvedDto, rowNo);
-
-            // 缁熶竴澶勭悊鎵规锛堟敮鎸佸崟鎵规/澶氭壒娆★級銆�
-            List<String> batchNoList = resolveBatchNoList(resolvedDto);
-            String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
-            String storedBatchNo = formatBatchNoStorage(batchNoList);
-
-            // 淇濆瓨棰嗘枡涓昏褰曞揩鐓с��
-            ProductionOrderPick orderPick = new ProductionOrderPick();
-            orderPick.setProductionOrderId(resolvedDto.getProductionOrderId());
-            orderPick.setProductModelId(resolvedDto.getProductModelId());
-            orderPick.setBatchNo(storedBatchNo);
-            orderPick.setQuantity(resolvedDto.getPickQuantity());
-            orderPick.setRemark(resolvedDto.getRemark());
-            orderPick.setOperationName(resolvedDto.getOperationName());
-            orderPick.setTechnologyOperationId(resolvedDto.getTechnologyOperationId());
-            orderPick.setDemandedQuantity(resolvedDto.getDemandedQuantity());
-            orderPick.setBom(resolvedDto.getBom());
-            orderPick.setReturned(false);
-            // 鏂板涓昏褰曘��
-            baseMapper.insert(orderPick);
-
-            // 鍏堟柊澧炲嚭搴撶敵璇凤紝鍐嶅鎵归�氳繃锛屽畬鎴愬簱瀛樻墸鍑忋��
-            subtractInventory(orderPick.getId(), resolvedDto.getProductModelId(), storedBatchNo, resolvedDto.getPickQuantity(), rowNo, PICK_STOCK_OUT_RECORD_TYPE);
-
-            // 璁板綍鏈棰嗘枡娴佹按锛坆efore=0锛宎fter=鏈棰嗘枡閲忥級銆�
-            insertPickRecord(orderPick.getId(),
-                    resolvedDto.getProductionOrderId(),
-                    resolvedDto.getProductionOperationTaskId(),
-                    resolvedDto.getProductModelId(),
-                    inventoryBatchNo,
-                    resolvedDto.getPickQuantity(),
-                    BigDecimal.ZERO,
-                    resolvedDto.getPickQuantity(),
-                    resolvedDto.getPickType(),
-                    resolvedDto.getRemark(),
-                    resolvedDto.getFeedingReason());
-        }
-        return true;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean updatePick(ProductionOrderPickDto dto) {
-        // 棰嗘枡鏇存柊鍏ュ彛锛堝悓鎺ュ彛鍏煎涓夌被涓氬姟锛夛細
-        // 1) 鏅�氶鏂欐敼閲�/澧炲垹锛�
-        // 2) 琛ユ枡锛坧ickType=2锛夛紱
-        // 3) 閫�鏂欙紙returned=true锛夈��
-        if (dto == null) {
-            throw new ServiceException("鍙傛暟涓嶈兘涓虹┖");
-        }
-        Long productionOrderId = resolveProductionOrderId(dto);
-        if (productionOrderId == null) {
-            throw new ServiceException("鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
-        }
-        ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId);
-        if (productionOrder == null) {
-            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
-        }
-
-        // 鏌ヨ璁㈠崟涓嬬幇鏈夐鏂欒褰曞苟鏋勫缓ID绱㈠紩銆�
-        List<ProductionOrderPick> existingPickList = baseMapper.selectList(
-                Wrappers.<ProductionOrderPick>lambdaQuery()
-                        .eq(ProductionOrderPick::getProductionOrderId, productionOrderId));
-        // 杞垚Map渚夸簬鍚庣画鎸塈D蹇�熸牎楠屼笌鏇存柊銆�
-        Map<Long, ProductionOrderPick> existingPickMap = existingPickList.stream()
-                .filter(item -> item.getId() != null)
-                .collect(Collectors.toMap(ProductionOrderPick::getId, Function.identity(), (a, b) -> a));
-
-        // 琛ユ枡璇锋眰鍗曠嫭璧拌ˉ鏂欏垎鏀��
-        if (isFeedingRequest(dto)) {
-            processFeedingPickItems(dto, existingPickMap, productionOrderId);
-            return true;
-        }
-        // 閫�鏂欒姹傚崟鐙蛋閫�鏂欏垎鏀��
-        if (isReturnRequest(dto)) {
-            processReturnPickItems(dto, existingPickMap, productionOrderId);
-            return true;
-        }
-
-        // 鏅�氭洿鏂板満鏅厛澶勭悊鏄惧紡鍒犻櫎銆�
-        processDeletePickIds(dto, existingPickMap, productionOrderId);
-
-        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(dto);
-        Set<Long> keepPickIdSet = new HashSet<>();
-        // keepPickIdSet 鐢ㄤ簬鏍囪鏈鍓嶇浠嶇劧淇濈暀鐨勬棫璁板綍锛屽悗缁敤浜庤瘑鍒�滄湭鍥炰紶鍗冲垹闄も�濈殑琛屻��
-        for (int i = 0; i < pickItems.size(); i++) {
-            int rowNo = i + 1;
-            ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
-            if (isEmptyUpdateItem(resolvedDto)) {
-                continue;
-            }
-            if (resolvedDto.getProductionOrderId() == null) {
-                resolvedDto.setProductionOrderId(productionOrderId);
-            }
-            validatePickParam(resolvedDto, rowNo);
-
-            if (resolvedDto.getId() == null) {
-                addNewPickInUpdate(resolvedDto, rowNo);
-                continue;
-            }
-            keepPickIdSet.add(resolvedDto.getId());
-            updateExistingPick(resolvedDto, rowNo, existingPickMap);
-        }
-        // 娓呯悊鍓嶇鏈洖浼犳棫琛屽苟鍥炶ˉ搴撳瓨銆�
-        processMissingPickItems(dto, existingPickMap, productionOrderId, keepPickIdSet);
-        return true;
-    }
-
-    @Override
-    public List<ProductionOrderPickVo> listPickedDetail(Long productionOrderId) {
-        // 鏌ヨ璁㈠崟棰嗘枡鏄庣粏锛屽苟琛ラ綈鎵规灞曠ず瀛楁銆�
-        if (productionOrderId == null) {
-            return Collections.emptyList();
-        }
-        List<ProductionOrderPickVo> detailList = baseMapper.listPickedDetailByOrderId(productionOrderId);
-        fillBatchNoList(detailList);
-        fillSelectableBatchNoList(detailList);
-        return detailList;
-    }
-
-    private void processDeletePickIds(ProductionOrderPickDto rootDto,
-                                      Map<Long, ProductionOrderPick> existingPickMap,
-                                      Long productionOrderId) {
-        // 澶勭悊鍓嶇鏄惧紡鍒犻櫎ID锛�
-        // 1) 鏍¢獙鍒犻櫎鐩爣鏄惁灞炰簬褰撳墠璁㈠崟锛�
-        // 2) 鍥炶ˉ搴撳瓨锛�
-        // 3) 鍒犻櫎涓昏褰曪紱
-        // 4) 璁板綍鍒犻櫎娴佹按銆�
-        if (rootDto.getDeletePickIds() == null || rootDto.getDeletePickIds().isEmpty()) {
-            return;
-        }
-        Set<Long> deleteIdSet = new LinkedHashSet<>(rootDto.getDeletePickIds());
-        for (Long deleteId : deleteIdSet) {
-            if (deleteId == null) {
-                continue;
-            }
-            ProductionOrderPick existingPick = existingPickMap.get(deleteId);
-            if (existingPick == null || !Objects.equals(existingPick.getProductionOrderId(), productionOrderId)) {
-                throw new ServiceException("鍒犻櫎澶辫触锛氶鏂欒褰曚笉瀛樺湪鎴栦笉灞炰簬褰撳墠璁㈠崟锛孖D=" + deleteId);
-            }
-            String oldBatchNo = resolveInventoryBatchNoFromStored(existingPick.getBatchNo());
-            BigDecimal oldQuantity = defaultDecimal(existingPick.getQuantity());
-            addInventory(existingPick.getId(), existingPick.getProductModelId(), oldBatchNo, oldQuantity, PICK_RETURN_IN_RECORD_TYPE);
-            // 鍒犻櫎鍏宠仈棰嗘枡娴佹按锛岄伩鍏嶉仐鐣欐棤涓昏褰曘��
-            productionOrderPickRecordMapper.delete(
-                    Wrappers.<ProductionOrderPickRecord>lambdaQuery()
-                            .eq(ProductionOrderPickRecord::getPickId, existingPick.getId())
-            );
-            int affected = baseMapper.deleteById(deleteId);
-            if (affected <= 0) {
-                throw new ServiceException("鍒犻櫎棰嗘枡璁板綍澶辫触锛孖D=" + deleteId);
-            }
-            insertPickRecord(existingPick.getId(),
-                    existingPick.getProductionOrderId(),
-                    rootDto.getProductionOperationTaskId(),
-                    existingPick.getProductModelId(),
-                    oldBatchNo,
-                    oldQuantity,
-                    oldQuantity,
-                    BigDecimal.ZERO,
-                    rootDto.getPickType(),
-                    rootDto.getRemark(),
-                    rootDto.getFeedingReason());
-            existingPickMap.remove(deleteId);
-        }
-    }
-
-    private void processMissingPickItems(ProductionOrderPickDto rootDto,
-                                         Map<Long, ProductionOrderPick> existingPickMap,
-                                         Long productionOrderId,
-                                         Set<Long> keepPickIdSet) {
-        // 澶勭悊鈥滃墠绔湭鍥炰紶鈥濈殑鏃ц锛�
-        // 瀵瑰簲鍦烘櫙鏄敤鎴峰湪鍓嶇鍒犻櫎琛屼絾鏈斁鍏� deletePickIds銆�
-        // 杩欓噷鍏滃簳璇嗗埆骞舵墽琛屽洖琛ュ簱瀛� + 鍒犻櫎涓昏褰� + 鍐欐祦姘淬��
-        if (rootDto.getPickList() == null) {
-            return;
-        }
-        List<ProductionOrderPick> missingPickList = existingPickMap.values().stream()
-                .filter(Objects::nonNull)
-                .filter(item -> item.getId() != null)
-                .filter(item -> Objects.equals(item.getProductionOrderId(), productionOrderId))
-                .filter(item -> !keepPickIdSet.contains(item.getId()))
-                .toList();
-        for (ProductionOrderPick missingPick : missingPickList) {
-            String oldBatchNo = resolveInventoryBatchNoFromStored(missingPick.getBatchNo());
-            BigDecimal oldQuantity = defaultDecimal(missingPick.getQuantity());
-            addInventory(missingPick.getId(), missingPick.getProductModelId(), oldBatchNo, oldQuantity, PICK_RETURN_IN_RECORD_TYPE);
-            // 鍒犻櫎鍏宠仈棰嗘枡娴佹按锛岄伩鍏嶉仐鐣欐棤涓昏褰曘��
-            productionOrderPickRecordMapper.delete(
-                    Wrappers.<ProductionOrderPickRecord>lambdaQuery()
-                            .eq(ProductionOrderPickRecord::getPickId, missingPick.getId())
-            );
-            int affected = baseMapper.deleteById(missingPick.getId());
-            if (affected <= 0) {
-                throw new ServiceException("鍒犻櫎鏈洖浼犻鏂欒褰曞け璐ワ紝ID=" + missingPick.getId());
-            }
-            insertPickRecord(missingPick.getId(),
-                    missingPick.getProductionOrderId(),
-                    rootDto.getProductionOperationTaskId(),
-                    missingPick.getProductModelId(),
-                    oldBatchNo,
-                    oldQuantity,
-                    oldQuantity,
-                    BigDecimal.ZERO,
-                    rootDto.getPickType(),
-                    rootDto.getRemark(),
-                    rootDto.getFeedingReason());
-            existingPickMap.remove(missingPick.getId());
-        }
-    }
-
-    private void addNewPickInUpdate(ProductionOrderPickDto dto, int rowNo) {
-        // 鏇存柊鍦烘櫙涓嬫柊澧炰竴鏉¢鏂欙細
-        // 鏂板涓昏褰� -> 鍑哄簱鐢宠骞跺鎵� -> 鍐欐祦姘淬��
-        List<String> batchNoList = resolveBatchNoList(dto);
-        String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
-        String storedBatchNo = formatBatchNoStorage(batchNoList);
-
-        ProductionOrderPick orderPick = new ProductionOrderPick();
-        orderPick.setProductionOrderId(dto.getProductionOrderId());
-        orderPick.setProductModelId(dto.getProductModelId());
-        orderPick.setBatchNo(storedBatchNo);
-        orderPick.setQuantity(dto.getPickQuantity());
-        orderPick.setRemark(dto.getRemark());
-        orderPick.setOperationName(dto.getOperationName());
-        orderPick.setTechnologyOperationId(dto.getTechnologyOperationId());
-        orderPick.setDemandedQuantity(dto.getDemandedQuantity());
-        orderPick.setBom(dto.getBom());
-        orderPick.setReturned(false);
-        baseMapper.insert(orderPick);
-
-        // 鍏堟柊澧炲嚭搴撶敵璇凤紝鍐嶅鎵归�氳繃锛屽畬鎴愬簱瀛樻墸鍑忋��
-        subtractInventory(orderPick.getId(), dto.getProductModelId(), storedBatchNo, dto.getPickQuantity(), rowNo, PICK_STOCK_OUT_RECORD_TYPE);
-
-        insertPickRecord(orderPick.getId(),
-                dto.getProductionOrderId(),
-                dto.getProductionOperationTaskId(),
-                dto.getProductModelId(),
-                inventoryBatchNo,
-                dto.getPickQuantity(),
-                BigDecimal.ZERO,
-                dto.getPickQuantity(),
-                dto.getPickType(),
-                dto.getRemark(),
-                dto.getFeedingReason());
-    }
-
-    private void processFeedingPickItems(ProductionOrderPickDto rootDto,
-                                         Map<Long, ProductionOrderPick> existingPickMap,
-                                         Long productionOrderId) {
-        // 琛ユ枡娴佺▼鍏ュ彛锛�
-        // 閫愯鏍¢獙琛ユ枡鍙傛暟锛屾牎楠屽師棰嗘枡褰掑睘锛屽啀鎵ц琛ユ枡搴撳瓨鎵e噺鍜屼富璁板綍鍥炲啓銆�
-        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(rootDto);
-        for (int i = 0; i < pickItems.size(); i++) {
-            int rowNo = i + 1;
-            ProductionOrderPickDto resolvedDto = mergeDto(rootDto, pickItems.get(i));
-            if (isEmptyUpdateItem(resolvedDto)) {
-                continue;
-            }
-            if (!isFeedingPick(resolvedDto)) {
-                throw new ServiceException("琛ユ枡璇锋眰涓瓨鍦ㄩ潪琛ユ枡绫诲瀷鏁版嵁");
-            }
-            if (resolvedDto.getProductionOrderId() == null) {
-                resolvedDto.setProductionOrderId(productionOrderId);
-            }
-            validateFeedingParam(resolvedDto, rowNo);
-
-            ProductionOrderPick oldPick = existingPickMap.get(resolvedDto.getId());
-            if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), productionOrderId)) {
-                throw new ServiceException("绗�" + rowNo + "琛岃ˉ鏂欏け璐ワ細鏈壘鍒板搴旂殑棰嗘枡璁板綍");
-            }
-            addFeedingPick(resolvedDto, oldPick, rowNo);
-        }
-    }
-
-    private void addFeedingPick(ProductionOrderPickDto dto, ProductionOrderPick oldPick, int rowNo) {
-        // 琛ユ枡鏍稿績锛�
-        // 1) 鏍¢獙瑙勬牸涓�鑷达紱
-        // 2) 鎵e噺琛ユ枡搴撳瓨锛�
-        // 3) 鍐欒ˉ鏂欐祦姘达紱
-        // 4) 鍥炲啓涓诲崟绱琛ユ枡閲忓拰瀹為檯閲忋��
-        if (dto.getProductModelId() != null && !Objects.equals(dto.getProductModelId(), oldPick.getProductModelId())) {
-            throw new ServiceException("绗�" + rowNo + "琛岃ˉ鏂欏け璐ワ細浜у搧瑙勬牸涓庡師棰嗘枡璁板綍涓嶄竴鑷�");
-        }
-        Long productModelId = oldPick.getProductModelId();
-        List<String> batchNoList = resolveBatchNoList(dto);
-        String inventoryBatchNo = batchNoList.isEmpty()
-                ? resolveInventoryBatchNoFromStored(oldPick.getBatchNo())
-                : formatBatchNoStorage(batchNoList);
-        BigDecimal feedingQuantity = dto.getFeedingQuantity();
-
-        subtractInventory(oldPick.getId(), productModelId, inventoryBatchNo, feedingQuantity, rowNo, FEED_STOCK_OUT_RECORD_TYPE);
-
-        // 璁$畻琛ユ枡鍓嶅悗鏁伴噺骞跺啓琛ユ枡娴佹按銆�
-        BigDecimal beforeFeedingQty = sumFeedingQuantity(dto.getProductionOrderId(), oldPick.getId());
-        BigDecimal afterFeedingQty = beforeFeedingQty.add(feedingQuantity);
-        insertPickRecord(oldPick.getId(),
-                dto.getProductionOrderId(),
-                dto.getProductionOperationTaskId(),
-                productModelId,
-                inventoryBatchNo,
-                feedingQuantity,
-                beforeFeedingQty,
-                afterFeedingQty,
-                PICK_TYPE_FEEDING,
-                dto.getRemark(),
-                dto.getFeedingReason());
-
-        ProductionOrderPick updatePick = new ProductionOrderPick();
-        updatePick.setId(oldPick.getId());
-        updatePick.setFeedingQty(afterFeedingQty);
-        updatePick.setActualQty(calculateActualQty(oldPick, afterFeedingQty));
-        // 鍥炲啓涓昏褰曠殑琛ユ枡绱鍊间笌瀹為檯鐢ㄩ噺銆�
-        int affected = baseMapper.updateById(updatePick);
-        if (affected <= 0) {
-            throw new ServiceException("绗�" + rowNo + "琛岃ˉ鏂欏け璐ワ細鏇存柊棰嗘枡涓昏褰曞け璐�");
-        }
-        oldPick.setFeedingQty(afterFeedingQty);
-        oldPick.setActualQty(updatePick.getActualQty());
-    }
-
-    private void processReturnPickItems(ProductionOrderPickDto rootDto,
-                                        Map<Long, ProductionOrderPick> existingPickMap,
-                                        Long productionOrderId) {
-        // 閫�鏂欐祦绋嬪叆鍙o細
-        // 閫愯鏍¢獙閫�鏂欏弬鏁颁笌棰嗘枡褰掑睘锛屽啀鏇存柊閫�鏂欓噺涓庡疄闄呴噺瀛楁銆�
-        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(rootDto);
-        for (int i = 0; i < pickItems.size(); i++) {
-            int rowNo = i + 1;
-            ProductionOrderPickDto resolvedDto = mergeDto(rootDto, pickItems.get(i));
-            if (isEmptyUpdateItem(resolvedDto)) {
-                continue;
-            }
-            if (resolvedDto.getProductionOrderId() == null) {
-                resolvedDto.setProductionOrderId(productionOrderId);
-            }
-            validateReturnParam(resolvedDto, rowNo);
-
-            ProductionOrderPick oldPick = existingPickMap.get(resolvedDto.getId());
-            if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), productionOrderId)) {
-                throw new ServiceException("绗�" + rowNo + "琛岄��鏂欏け璐ワ細鏈壘鍒板搴旂殑棰嗘枡璁板綍");
-            }
-            updateReturnPick(resolvedDto, oldPick, rowNo);
-        }
-    }
-
-    private void updateReturnPick(ProductionOrderPickDto dto, ProductionOrderPick oldPick, int rowNo) {
-        // 閫�鏂欐洿鏂帮細
-        // 1) returnQty 鎸夆�滄湰娆¢��鏂欓噺鈥濆鐞嗭紱
-        // 2) 鏈閫�鏂欓噺鍥炶ˉ鍒扳�滅敓浜ч��鏂欏叆搴撯�濓紱
-        // 3) 绱姞涓昏褰曢��鏂欐�婚噺骞堕噸绠楀疄闄呴噺銆�
-        BigDecimal oldReturnQty = defaultDecimal(oldPick.getReturnQty());
-        BigDecimal currentReturnQty = defaultDecimal(dto.getReturnQty());
-        BigDecimal totalReturnQty = oldReturnQty.add(currentReturnQty);
-        if (currentReturnQty.compareTo(BigDecimal.ZERO) > 0) {
-            String returnBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo());
-            addInventoryRecordOnly(oldPick.getId(), oldPick.getProductModelId(), returnBatchNo, currentReturnQty, FEED_RETURN_IN_RECORD_TYPE);
-        }
-
-        BigDecimal actualQty = defaultDecimal(oldPick.getQuantity())
-                .add(defaultDecimal(oldPick.getFeedingQty()))
-                .subtract(totalReturnQty);
-        if (actualQty.compareTo(BigDecimal.ZERO) < 0) {
-            throw new ServiceException("绗�" + rowNo + "琛岄��鏂欏け璐ワ細绱閫�鏂欐暟閲忎笉鑳藉ぇ浜庡彲鐢ㄦ暟閲�");
-        }
-        ProductionOrderPick updatePick = new ProductionOrderPick();
-        updatePick.setId(oldPick.getId());
-        updatePick.setReturnQty(totalReturnQty);
-        updatePick.setActualQty(actualQty);
-        updatePick.setReturned(totalReturnQty.compareTo(BigDecimal.ZERO) > 0);
-        int affected = baseMapper.updateById(updatePick);
-        if (affected <= 0) {
-            throw new ServiceException("绗�" + rowNo + "琛岄��鏂欏け璐ワ細鏇存柊棰嗘枡涓昏褰曞け璐�");
-        }
-        oldPick.setReturnQty(updatePick.getReturnQty());
-        oldPick.setActualQty(updatePick.getActualQty());
-        oldPick.setReturned(updatePick.getReturned());
-    }
-
-    private void updateExistingPick(ProductionOrderPickDto dto,
-                                    int rowNo,
-                                    Map<Long, ProductionOrderPick> existingPickMap) {
-        // 鏅�氭洿鏂板崟琛屾牳蹇冩祦绋嬶細
-        // 1) 鏍¢獙鏃ц褰曞瓨鍦ㄤ笖灞炰簬褰撳墠璁㈠崟锛�
-        // 2) 姣旇緝鏂版棫鈥滆鏍�+鎵规鈥濓紝鍐冲畾搴撳瓨澶勭悊绛栫暐锛�
-        // 3) 鏇存柊涓昏褰曪紱
-        // 4) 鍐欏彉鏇存祦姘达紙璁板綍鍓嶅悗鏁伴噺鍙樺寲锛夈��
-        ProductionOrderPick oldPick = existingPickMap.get(dto.getId());
-        if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), dto.getProductionOrderId())) {
-            throw new ServiceException("绗�" + rowNo + "琛屾洿鏂板け璐ワ細鏈壘鍒板搴旂殑棰嗘枡璁板綍");
-        }
-
-        Long oldProductModelId = oldPick.getProductModelId();
-        String oldBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo());
-        BigDecimal oldQuantity = defaultDecimal(oldPick.getQuantity());
-
-        Long newProductModelId = dto.getProductModelId();
-        List<String> newBatchNoList = resolveBatchNoList(dto);
-        String newBatchNo = pickInventoryBatchNo(newBatchNoList);
-        String newStoredBatchNo = formatBatchNoStorage(newBatchNoList);
-        BigDecimal newQuantity = dto.getPickQuantity();
-
-        // 鍒ゆ柇瑙勬牸+鎵规鎴栨暟閲忔槸鍚﹀彉鍖栵紝骞舵寜鍦烘櫙澶勭悊搴撳瓨锛�
-        // 1) 鍚岃鏍煎悓鎵规锛氭寜宸�煎鐞嗭紙澧為噺鎵e噺 / 鍑忛噺鍥為��锛夛紱
-        // 2) 瑙勬牸鎴栨壒娆″彉鍖栵細鍥為��鏃ч鏂欏悗鍐嶉噸鎻愭柊棰嗘枡銆�
-        boolean sameStockKey = Objects.equals(oldProductModelId, newProductModelId)
-                && Objects.equals(oldBatchNo, newBatchNo);
-        boolean quantityChanged = oldQuantity.compareTo(newQuantity) != 0;
-        boolean needReissuePickRecord = !sameStockKey || quantityChanged;
-        if (sameStockKey) {
-            BigDecimal deltaQuantity = newQuantity.subtract(oldQuantity);
-            if (deltaQuantity.compareTo(BigDecimal.ZERO) > 0) {
-                // 鏁伴噺澧炲姞锛屽彧鎵e噺鏂板閮ㄥ垎銆�
-                subtractInventory(oldPick.getId(), newProductModelId, newStoredBatchNo, deltaQuantity, rowNo, PICK_STOCK_OUT_RECORD_TYPE);
-            } else if (deltaQuantity.compareTo(BigDecimal.ZERO) < 0) {
-                // 鏁伴噺鍑忓皯锛屽彧鍥為��宸�奸儴鍒嗐��
-                addInventory(oldPick.getId(), oldProductModelId, oldBatchNo, deltaQuantity.abs(), PICK_RETURN_IN_RECORD_TYPE);
-            }
-        } else {
-            // 瑙勬牸鎴栨壒娆″彉鍖栵細鍏堝叏閲忓洖閫�鏃ч鏂欙紝鍐嶅叏閲忔墸鍑忔柊棰嗘枡銆�
-            addInventory(oldPick.getId(), oldProductModelId, oldBatchNo, oldQuantity, PICK_RETURN_IN_RECORD_TYPE);
-            subtractInventory(oldPick.getId(), newProductModelId, newStoredBatchNo, newQuantity, rowNo, PICK_STOCK_OUT_RECORD_TYPE);
-        }
-        if (needReissuePickRecord) {
-            // 姝e父棰嗘枡娴佹按鎸夆�滄渶鏂伴鏂欓噺鈥濋噸寤猴紝閬垮厤淇濈暀鍘嗗彶鏃у�笺��
-            deleteNormalPickRecord(oldPick.getId());
-        }
-
-        oldPick.setProductModelId(newProductModelId);
-        oldPick.setBatchNo(newStoredBatchNo);
-        oldPick.setQuantity(newQuantity);
-        oldPick.setRemark(dto.getRemark());
-        oldPick.setOperationName(dto.getOperationName());
-        oldPick.setTechnologyOperationId(dto.getTechnologyOperationId());
-        // 鏅�氭洿鏂颁篃瑕佸悓姝ラ噸绠楀疄闄呯敤閲忥紝閬垮厤娌跨敤鏃у�笺��
-        // 瑙勫垯锛氬疄闄呯敤閲� = 棰嗘枡鏁伴噺 + 琛ユ枡鏁伴噺 - 閫�鏂欐暟閲忋��
-        oldPick.setActualQty(calculateActualQty(oldPick, oldPick.getFeedingQty()));
-        if (dto.getDemandedQuantity() != null) {
-            oldPick.setDemandedQuantity(dto.getDemandedQuantity());
-        }
-        if (dto.getBom() != null) {
-            oldPick.setBom(dto.getBom());
-        }
-        int affected = baseMapper.updateById(oldPick);
-        if (affected <= 0) {
-            throw new ServiceException("绗�" + rowNo + "琛屾洿鏂板け璐ワ細鏇存柊棰嗘枡璁板綍澶辫触");
-        }
-
-        // 濡傛灉鍙戠敓棰嗘枡閲嶆彁锛岃ˉ鍐欎竴鏉℃柊鐨勬甯搁鏂欐祦姘淬��
-        if (needReissuePickRecord) {
-            insertPickRecord(oldPick.getId(),
-                    dto.getProductionOrderId(),
-                    dto.getProductionOperationTaskId(),
-                    newProductModelId,
-                    newBatchNo,
-                    newQuantity,
-                    BigDecimal.ZERO,
-                    newQuantity,
-                    dto.getPickType(),
-                    dto.getRemark(),
-                    dto.getFeedingReason());
-        }
-    }
-
-    private void insertPickRecord(Long pickId,
-                                  Long productionOrderId,
-                                  Long productionOperationTaskId,
-                                  Long productModelId,
-                                  String batchNo,
-                                  BigDecimal pickQuantity,
-                                  BigDecimal beforeQuantity,
-                                  BigDecimal afterQuantity,
-                                  Byte pickType,
-                                  String remark,
-                                  String feedingReason) {
-        // 鍐欓鏂欐祦姘磋褰曪細缁熶竴璁板綍棰嗘枡/琛ユ枡/閫�鏂欐暟閲忓彉鍖栬建杩广��
-        ProductionOrderPickRecord pickRecord = new ProductionOrderPickRecord();
-        pickRecord.setPickId(pickId);
-        pickRecord.setProductionOrderId(productionOrderId);
-        pickRecord.setProductionOperationTaskId(productionOperationTaskId);
-        pickRecord.setProductModelId(productModelId);
-        pickRecord.setBatchNo(batchNo);
-        pickRecord.setPickQuantity(defaultDecimal(pickQuantity));
-        pickRecord.setBeforeQuantity(defaultDecimal(beforeQuantity));
-        pickRecord.setAfterQuantity(defaultDecimal(afterQuantity));
-        pickRecord.setPickType(pickType == null ? PICK_TYPE_NORMAL : pickType);
-        pickRecord.setRemark(remark);
-        pickRecord.setFeedingReason(feedingReason);
-        productionOrderPickRecordMapper.insert(pickRecord);
-    }
-
-    private void deleteNormalPickRecord(Long pickId) {
-        // 鍒犻櫎璇ラ鏂欏崟鍘嗗彶涓婄殑鈥滄甯搁鏂欌�濇祦姘达紝淇濈暀琛ユ枡/閫�鏂欐祦姘淬��
-        if (pickId == null) {
-            return;
-        }
-        productionOrderPickRecordMapper.delete(
-                Wrappers.<ProductionOrderPickRecord>lambdaQuery()
-                        .eq(ProductionOrderPickRecord::getPickId, pickId)
-                        .eq(ProductionOrderPickRecord::getPickType, PICK_TYPE_NORMAL)
-        );
-    }
-
-    private void subtractInventory(Long recordId,
-                                   Long productModelId,
-                                   String batchNo,
-                                   BigDecimal quantity,
-                                   int rowNo,
-                                   String stockOutRecordType) {
-        // 鎵e噺搴撳瓨鎬绘祦绋嬶細
-        // 1) 瑙f瀽鎵规鍒楄〃锛�
-        // 2) 璁$畻姣忎釜鎵规鍙敤閲忎笌鎬诲彲鐢ㄩ噺锛�
-        // 3) 鎸夋壒娆¢『搴忛�愮瑪鈥滄柊澧炲嚭搴撹褰曞苟瀹℃壒閫氳繃鈥濓紝鐩村埌鎵e畬鐩爣鏁伴噺锛�
-        // 4) 浠讳竴姝ュけ璐ュ嵆鎶涢敊骞跺洖婊氫簨鍔°��
-        BigDecimal deductQuantity = defaultDecimal(quantity);
-        // 棰嗘枡鏁伴噺灏忎簬绛変簬0鏃讹紝涓嶉渶瑕佹墽琛屽簱瀛樻墸鍑忋��
-        if (deductQuantity.compareTo(BigDecimal.ZERO) <= 0) {
-            return;
-        }
-
-        List<String> batchNoList = parseBatchNoValue(batchNo);
-        if (batchNoList.isEmpty()) {
-            batchNoList = Collections.singletonList(null);
-        }
-
-        // 鍏堣绠楀悇鎵规鍙敤閲忥紝閬垮厤杈规墸杈圭畻瀵艰嚧鍒ゆ柇涓嶄竴鑷淬��
-        Map<String, BigDecimal> availableQuantityMap = new LinkedHashMap<>();
-        BigDecimal totalAvailableQuantity = BigDecimal.ZERO;
-        // 閬嶅巻鎵规锛岃绠楁瘡涓壒娆″彲鐢ㄥ簱瀛樸��
-        for (String currentBatchNo : batchNoList) {
-            // 鏌ヨ褰撳墠瑙勬牸+鎵规鐨勫簱瀛樿褰曘��
-            StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, currentBatchNo));
-            BigDecimal availableQuantity = BigDecimal.ZERO;
-            if (stockInventory != null) {
-                availableQuantity = defaultDecimal(stockInventory.getQualitity())
-                        .subtract(defaultDecimal(stockInventory.getLockedQuantity()));
-                if (availableQuantity.compareTo(BigDecimal.ZERO) < 0) {
-                    availableQuantity = BigDecimal.ZERO;
-                }
-            }
-            availableQuantityMap.put(currentBatchNo, availableQuantity);
-            totalAvailableQuantity = totalAvailableQuantity.add(availableQuantity);
-        }
-
-        if (deductQuantity.compareTo(totalAvailableQuantity) > 0) {
-            BigDecimal shortQuantity = deductQuantity.subtract(totalAvailableQuantity);
-            throw new ServiceException("绗�" + rowNo + "琛屾墸鍑忓簱瀛樺け璐ワ細鍙敤搴撳瓨涓嶈冻锛屽綋鍓嶅彲鐢�"
-                    + formatQuantity(totalAvailableQuantity) + "锛屼粛缂哄皯" + formatQuantity(shortQuantity));
-        }
-
-        // 鎸夋壒娆¢『搴忛�愮瑪鎵e噺搴撳瓨銆�
-        BigDecimal remainingQuantity = deductQuantity;
-        for (Map.Entry<String, BigDecimal> entry : availableQuantityMap.entrySet()) {
-            if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) {
-                break;
-            }
-            BigDecimal availableQuantity = defaultDecimal(entry.getValue());
-            if (availableQuantity.compareTo(BigDecimal.ZERO) <= 0) {
-                continue;
-            }
-            BigDecimal currentDeductQuantity = remainingQuantity.min(availableQuantity);
-            createAndApproveStockOutRecord(recordId, productModelId, entry.getKey(), currentDeductQuantity, rowNo, stockOutRecordType);
-            remainingQuantity = remainingQuantity.subtract(currentDeductQuantity);
-        }
-
-        if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) {
-            throw new ServiceException("绗�" + rowNo + "琛屾墸鍑忓簱瀛樺け璐ワ細浠嶆湁鏈墸鍑忔暟閲�" + formatQuantity(remainingQuantity));
-        }
-    }
-
-    private void createAndApproveStockOutRecord(Long recordId,
-                                                Long productModelId,
-                                                String batchNo,
-                                                BigDecimal quantity,
-                                                int rowNo,
-                                                String stockOutRecordType) {
-        // 搴撳瓨鎵e噺鏀逛负涓ゆ锛�
-        // 1) 鍏堣皟鐢� addStockOutRecordOnly 鏂板寰呭鎵瑰嚭搴撹褰曪紱
-        // 2) 鍐嶈皟鐢ㄥ嚭搴撳鎵癸紝瀹℃壒鐘舵�佸浐瀹氫紶 1锛堥�氳繃锛夈��
-        try {
-            StockInventoryDto stockInventoryDto = new StockInventoryDto();
-            stockInventoryDto.setRecordId(recordId == null ? 0L : recordId);
-            stockInventoryDto.setRecordType(stockOutRecordType);
-            stockInventoryDto.setProductModelId(productModelId);
-            stockInventoryDto.setBatchNo(batchNo);
-            stockInventoryDto.setQualitity(quantity);
-            stockInventoryService.addStockOutRecordOnly(stockInventoryDto);
-
-            LambdaQueryWrapper<StockOutRecord> recordWrapper = Wrappers.<StockOutRecord>lambdaQuery()
-                    .eq(StockOutRecord::getRecordId, stockInventoryDto.getRecordId())
-                    .eq(StockOutRecord::getRecordType, stockOutRecordType)
-                    .eq(StockOutRecord::getProductModelId, productModelId)
-                    .eq(StockOutRecord::getType, "0")
-                    .orderByDesc(StockOutRecord::getId)
-                    .last("limit 1");
-            if (StringUtils.isEmpty(batchNo)) {
-                recordWrapper.isNull(StockOutRecord::getBatchNo);
-            } else {
-                recordWrapper.eq(StockOutRecord::getBatchNo, batchNo);
-            }
-            StockOutRecord stockOutRecord = stockOutRecordService.getOne(recordWrapper, false);
-            if (stockOutRecord == null || stockOutRecord.getId() == null) {
-                throw new ServiceException("绗�" + rowNo + "琛屾墸鍑忓簱瀛樺け璐ワ細鏈壘鍒板搴斿嚭搴撶敵璇疯褰�");
-            }
-            stockOutRecordService.batchApprove(
-                    Collections.singletonList(stockOutRecord.getId()),
-                    ReviewStatusEnum.APPROVED.getCode()
-            );
-        } catch (ServiceException ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new ServiceException("绗�" + rowNo + "琛屾墸鍑忓簱瀛樺け璐ワ細" + ex.getMessage());
-        }
-    }
-
-    private void addInventory(Long recordId,
-                              Long productModelId,
-                              String batchNo,
-                              BigDecimal quantity,
-                              String stockInRecordType) {
-        // 鍥炶ˉ搴撳瓨鏀逛负涓ゆ锛�
-        // 1) 鍏堟柊澧炲叆搴撶敵璇凤紱
-        // 2) 鍐嶅鎵归�氳繃锛岀‘淇濆簱瀛樼珛鍒诲洖琛ョ敓鏁堛��
-        BigDecimal addQuantity = defaultDecimal(quantity);
-        if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
-            return;
-        }
-        try {
-            StockInventoryDto stockInventoryDto = new StockInventoryDto();
-            stockInventoryDto.setProductModelId(productModelId);
-            stockInventoryDto.setBatchNo(batchNo);
-            stockInventoryDto.setQualitity(addQuantity);
-            stockInventoryDto.setRecordType(stockInRecordType);
-            stockInventoryDto.setRecordId(recordId == null ? 0L : recordId);
-            stockInventoryService.addStockInRecordOnly(stockInventoryDto);
-
-            LambdaQueryWrapper<StockInRecord> recordWrapper = Wrappers.<StockInRecord>lambdaQuery()
-                    .eq(StockInRecord::getRecordId, stockInventoryDto.getRecordId())
-                    .eq(StockInRecord::getRecordType, stockInventoryDto.getRecordType())
-                    .eq(StockInRecord::getProductModelId, productModelId)
-                    .eq(StockInRecord::getType, "0")
-                    .orderByDesc(StockInRecord::getId)
-                    .last("limit 1");
-            if (StringUtils.isEmpty(batchNo)) {
-                recordWrapper.isNull(StockInRecord::getBatchNo);
-            } else {
-                recordWrapper.eq(StockInRecord::getBatchNo, batchNo);
-            }
-            StockInRecord stockInRecord = stockInRecordService.getOne(recordWrapper, false);
-            if (stockInRecord == null || stockInRecord.getId() == null) {
-                throw new ServiceException("鍥炶ˉ搴撳瓨澶辫触锛氭湭鎵惧埌瀵瑰簲鍏ュ簱鐢宠璁板綍");
-            }
-            stockInRecordService.batchApprove(
-                    Collections.singletonList(stockInRecord.getId()),
-                    ReviewStatusEnum.APPROVED.getCode()
-            );
-        } catch (ServiceException ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new ServiceException("鍥炶ˉ搴撳瓨澶辫触锛�" + ex.getMessage());
-        }
-    }
-
-    private void addInventoryRecordOnly(Long recordId,
-                                        Long productModelId,
-                                        String batchNo,
-                                        BigDecimal quantity,
-                                        String stockInRecordType) {
-        // 浠呰褰曞叆搴撶敵璇凤紝涓嶅仛瀹℃牳閫氳繃銆�
-        BigDecimal addQuantity = defaultDecimal(quantity);
-        if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
-            return;
-        }
-        try {
-            StockInventoryDto stockInventoryDto = new StockInventoryDto();
-            stockInventoryDto.setProductModelId(productModelId);
-            stockInventoryDto.setBatchNo(batchNo);
-            stockInventoryDto.setQualitity(addQuantity);
-            stockInventoryDto.setRecordType(stockInRecordType);
-            stockInventoryDto.setRecordId(recordId == null ? 0L : recordId);
-            stockInventoryService.addStockInRecordOnly(stockInventoryDto);
-        } catch (ServiceException ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new ServiceException("閫�鏂欏叆搴撹褰曚繚瀛樺け璐ワ細" + ex.getMessage());
-        }
-    }
-
-    private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) {
-        // 瑙f瀽鏂板鍦烘櫙鐨勯鏂欐槑缁嗛泦鍚堛��
-        if (dto == null) {
-            throw new ServiceException("鍙傛暟涓嶈兘涓虹┖");
-        }
-        if (dto.getPickList() != null && !dto.getPickList().isEmpty()) {
-            return dto.getPickList();
-        }
-        return Collections.singletonList(dto);
-    }
-
-    private List<ProductionOrderPickDto> resolveUpdateItems(ProductionOrderPickDto dto) {
-        // 瑙f瀽鏇存柊鍦烘櫙鐨勯鏂欐槑缁嗛泦鍚堛��
-        if (dto.getPickList() != null) {
-            return dto.getPickList();
-        }
-        if (isEmptyUpdateItem(dto)) {
-            return Collections.emptyList();
-        }
-        return Collections.singletonList(dto);
-    }
-
-    private boolean isEmptyUpdateItem(ProductionOrderPickDto dto) {
-        // 鍒ゆ柇鏇存柊琛屾槸鍚︿负绌虹櫧鍗犱綅琛屻��
-        return dto.getId() == null
-                && dto.getProductModelId() == null
-                && dto.getPickQuantity() == null
-                && StringUtils.isEmpty(dto.getBatchNo())
-                && (dto.getBatchNoList() == null || dto.getBatchNoList().isEmpty())
-                && dto.getPickType() == null
-                && dto.getFeedingQuantity() == null
-                && StringUtils.isEmpty(dto.getFeedingReason())
-                && dto.getReturnQty() == null
-                && dto.getActualQty() == null
-                && dto.getReturned() == null
-                && dto.getProductionOperationTaskId() == null
-                && dto.getTechnologyOperationId() == null
-                && StringUtils.isEmpty(dto.getOperationName())
-                && dto.getDemandedQuantity() == null
-                && dto.getBom() == null
-                && StringUtils.isEmpty(dto.getRemark());
-    }
-
-    private Long resolveProductionOrderId(ProductionOrderPickDto dto) {
-        // 浼樺厛浠庝富DTO瑙f瀽璁㈠崟ID锛屼笉瀛樺湪鏃跺啀浠庡瓙椤逛腑鍥為��鏌ユ壘銆�
-        if (dto.getProductionOrderId() != null) {
-            return dto.getProductionOrderId();
-        }
-        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
-            return null;
-        }
-        return dto.getPickList().stream()
-                .filter(Objects::nonNull)
-                .map(ProductionOrderPickDto::getProductionOrderId)
-                .filter(Objects::nonNull)
-                .findFirst()
-                .orElse(null);
-    }
-
-    private ProductionOrderPickDto mergeDto(ProductionOrderPickDto rootDto, ProductionOrderPickDto itemDto) {
-        // 鍚堝苟瑙勫垯锛�
-        // - itemDto 浼樺厛鎵胯浇琛岀骇杈撳叆锛�
-        // - itemDto 缂哄け瀛楁浠� rootDto 鍏滃簳缁ф壙锛�
-        // - 杈撳嚭 merged 浣滀负缁熶竴涓氬姟鍏ュ弬銆�
-        ProductionOrderPickDto merged = new ProductionOrderPickDto();
-        // 鍏堟嫹璐濊绾у瓧娈点��
-        if (itemDto != null) {
-            merged.setId(itemDto.getId());
-            merged.setProductionOrderId(itemDto.getProductionOrderId());
-            merged.setProductionOperationTaskId(itemDto.getProductionOperationTaskId());
-            merged.setProductModelId(itemDto.getProductModelId());
-            merged.setBatchNo(itemDto.getBatchNo());
-            merged.setBatchNoList(itemDto.getBatchNoList());
-            merged.setPickQuantity(itemDto.getPickQuantity());
-            merged.setPickType(itemDto.getPickType());
-            merged.setRemark(itemDto.getRemark());
-            merged.setFeedingReason(itemDto.getFeedingReason());
-            merged.setFeedingQuantity(itemDto.getFeedingQuantity());
-            merged.setTechnologyOperationId(itemDto.getTechnologyOperationId());
-            merged.setOperationName(itemDto.getOperationName());
-            merged.setDemandedQuantity(itemDto.getDemandedQuantity());
-            merged.setBom(itemDto.getBom());
-            merged.setReturnQty(itemDto.getReturnQty());
-            merged.setActualQty(itemDto.getActualQty());
-            merged.setReturned(itemDto.getReturned());
-        }
-        if (merged.getId() == null) {
-            merged.setId(rootDto.getId());
-        }
-        if (merged.getProductionOrderId() == null) {
-            merged.setProductionOrderId(rootDto.getProductionOrderId());
-        }
-        if (merged.getProductionOperationTaskId() == null) {
-            merged.setProductionOperationTaskId(rootDto.getProductionOperationTaskId());
-        }
-        if (merged.getProductModelId() == null) {
-            merged.setProductModelId(rootDto.getProductModelId());
-        }
-        if (merged.getBatchNo() == null) {
-            merged.setBatchNo(rootDto.getBatchNo());
-        }
-        if (merged.getBatchNoList() == null || merged.getBatchNoList().isEmpty()) {
-            merged.setBatchNoList(rootDto.getBatchNoList());
-        }
-        if (merged.getPickQuantity() == null) {
-            merged.setPickQuantity(rootDto.getPickQuantity());
-        }
-        if (merged.getPickType() == null) {
-            merged.setPickType(rootDto.getPickType());
-        }
-        if (merged.getRemark() == null) {
-            merged.setRemark(rootDto.getRemark());
-        }
-        if (merged.getFeedingReason() == null) {
-            merged.setFeedingReason(rootDto.getFeedingReason());
-        }
-        if (merged.getFeedingQuantity() == null) {
-            merged.setFeedingQuantity(rootDto.getFeedingQuantity());
-        }
-        if (merged.getTechnologyOperationId() == null) {
-            merged.setTechnologyOperationId(rootDto.getTechnologyOperationId());
-        }
-        if (merged.getOperationName() == null) {
-            merged.setOperationName(rootDto.getOperationName());
-        }
-        if (merged.getDemandedQuantity() == null) {
-            merged.setDemandedQuantity(rootDto.getDemandedQuantity());
-        }
-        if (merged.getBom() == null) {
-            merged.setBom(rootDto.getBom());
-        }
-        if (merged.getReturnQty() == null) {
-            merged.setReturnQty(rootDto.getReturnQty());
-        }
-        if (merged.getActualQty() == null) {
-            merged.setActualQty(rootDto.getActualQty());
-        }
-        if (merged.getReturned() == null) {
-            merged.setReturned(rootDto.getReturned());
-        }
-        return merged;
-    }
-
-    private void validatePickParam(ProductionOrderPickDto dto, int rowNo) {
-        // 鏍¢獙鏅�氶鏂欏弬鏁帮紙璁㈠崟銆佽鏍笺�佹暟閲忋�佺被鍨嬶級銆�
-        if (dto.getProductionOrderId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
-        }
-        if (dto.getProductModelId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細浜у搧瑙勬牸涓嶈兘涓虹┖");
-        }
-        if (dto.getPickQuantity() == null || dto.getPickQuantity().compareTo(BigDecimal.ZERO) < 0) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細棰嗘枡鏁伴噺涓嶈兘灏忎簬0");
-        }
-        if (dto.getPickType() != null && dto.getPickType() != PICK_TYPE_NORMAL && dto.getPickType() != PICK_TYPE_FEEDING) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細棰嗘枡绫诲瀷浠呮敮鎸�1(棰嗘枡)鎴�2(琛ユ枡)");
-        }
-    }
-
-    private void validateFeedingParam(ProductionOrderPickDto dto, int rowNo) {
-        // 鏍¢獙琛ユ枡鍙傛暟锛堣鍗曘�侀鏂橧D銆佽ˉ鏂欐暟閲忋�佺被鍨嬶級銆�
-        if (dto.getProductionOrderId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
-        }
-        if (dto.getId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細棰嗘枡璁板綍ID涓嶈兘涓虹┖");
-        }
-        if (dto.getFeedingQuantity() == null || dto.getFeedingQuantity().compareTo(BigDecimal.ZERO) < 0) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細琛ユ枡鏁伴噺涓嶈兘灏忎簬0");
-        }
-        if (!isFeedingPick(dto)) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細琛ユ枡鍦烘櫙涓嬮鏂欑被鍨嬪繀椤讳负2");
-        }
-    }
-
-    private void validateReturnParam(ProductionOrderPickDto dto, int rowNo) {
-        // 鏍¢獙閫�鏂欏弬鏁帮紙璁㈠崟銆侀鏂橧D銆侀��鏂欓噺锛夈��
-        if (dto.getProductionOrderId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
-        }
-        if (dto.getId() == null) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細棰嗘枡璁板綍ID涓嶈兘涓虹┖");
-        }
-        if (dto.getReturnQty() == null || dto.getReturnQty().compareTo(BigDecimal.ZERO) < 0) {
-            throw new ServiceException("绗�" + rowNo + "琛屽弬鏁伴敊璇細閫�鏂欐暟閲忎笉鑳藉皬浜�0");
-        }
-    }
-
-    private boolean isFeedingRequest(ProductionOrderPickDto dto) {
-        // 鍒ゆ柇褰撳墠璇锋眰鏄惁灞炰簬琛ユ枡娴佺▼銆�
-        if (isFeedingPick(dto)) {
-            return true;
-        }
-        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
-            return false;
-        }
-        return dto.getPickList().stream()
-                .filter(Objects::nonNull)
-                .anyMatch(this::isFeedingPick);
-    }
-
-    private boolean isFeedingPick(ProductionOrderPickDto dto) {
-        // 鍒ゆ柇褰撳墠琛屾槸鍚︿负琛ユ枡绫诲瀷銆�
-        return dto != null && Objects.equals(dto.getPickType(), PICK_TYPE_FEEDING);
-    }
-
-    private boolean isReturnRequest(ProductionOrderPickDto dto) {
-        // 鍒ゆ柇褰撳墠璇锋眰鏄惁灞炰簬閫�鏂欐祦绋嬨��
-        if (isReturnPick(dto)) {
-            return true;
-        }
-        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
-            return false;
-        }
-        return dto.getPickList().stream()
-                .filter(Objects::nonNull)
-                .anyMatch(this::isReturnPick);
-    }
-
-    private boolean isReturnPick(ProductionOrderPickDto dto) {
-        // 鍒ゆ柇褰撳墠琛屾槸鍚︿负閫�鏂欑被鍨嬨��
-        return dto != null && Boolean.TRUE.equals(dto.getReturned());
-    }
-
-    private BigDecimal sumFeedingQuantity(Long productionOrderId, Long pickId) {
-        // 姹囨�绘寚瀹氶鏂欏崟鐨勫巻鍙茶ˉ鏂欐�婚噺銆�
-        List<ProductionOrderPickRecord> feedingRecords = productionOrderPickRecordMapper.selectList(
-                Wrappers.<ProductionOrderPickRecord>lambdaQuery()
-                        .eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)
-                        .eq(ProductionOrderPickRecord::getPickId, pickId)
-                        .eq(ProductionOrderPickRecord::getPickType, PICK_TYPE_FEEDING));
-        return feedingRecords.stream()
-                .map(ProductionOrderPickRecord::getPickQuantity)
-                .map(this::defaultDecimal)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-    }
-
-    private BigDecimal calculateActualQty(ProductionOrderPick pick, BigDecimal feedingQty) {
-        // 鎸夆�滈鏂�+琛ユ枡-閫�鏂欌�濊绠楀疄闄呯敤閲忋��
-        return defaultDecimal(pick.getQuantity())
-                .add(defaultDecimal(feedingQty))
-                .subtract(defaultDecimal(pick.getReturnQty()));
-    }
-
-    private String normalizeBatchNo(String batchNo) {
-        // 鏍囧噯鍖栨壒娆″彿锛堝幓绌虹櫧銆佺┖涓茶浆null锛夈��
-        if (StringUtils.isEmpty(batchNo)) {
-            return null;
-        }
-        String trimBatchNo = batchNo.trim();
-        return trimBatchNo.isEmpty() ? null : trimBatchNo;
-    }
-    private List<String> resolveBatchNoList(ProductionOrderPickDto dto) {
-        // 浼樺厛瑙f瀽 batchNoList锛岀┖鍒欏洖閫�瑙f瀽 batchNo 瀛楃涓层��
-        List<String> normalizedBatchNoList = normalizeBatchNoList(dto.getBatchNoList());
-        if (!normalizedBatchNoList.isEmpty()) {
-            return normalizedBatchNoList;
-        }
-        return parseBatchNoValue(dto.getBatchNo());
-    }
-
-    private String pickInventoryBatchNo(List<String> batchNoList) {
-        // 浠庢壒娆¢泦鍚堜腑鍙栧簱瀛樻墸鍑忎娇鐢ㄧ殑鎵规銆�
-        if (batchNoList == null || batchNoList.isEmpty()) {
-            return null;
-        }
-        return batchNoList.get(0);
-    }
-
-    private String resolveInventoryBatchNoFromStored(String storedBatchNo) {
-        // 浠庢暟鎹簱瀛樺偍鎵规瀛楁涓弽瑙e彲鐢ㄦ壒娆°��
-        return pickInventoryBatchNo(parseBatchNoValue(storedBatchNo));
-    }
-
-    private String formatBatchNoStorage(List<String> batchNoList) {
-        // 灏嗘壒娆¢泦鍚堟牸寮忓寲涓烘暟鎹簱瀛樺偍鍊笺��
-        if (batchNoList == null || batchNoList.isEmpty()) {
-            return null;
-        }
-        if (batchNoList.size() == 1) {
-            return batchNoList.get(0);
-        }
-        return String.join(",", batchNoList);
-    }
-
-    private List<String> normalizeBatchNoList(List<String> batchNoList) {
-        // 鎵归噺鏍囧噯鍖栨壒娆″彿骞跺幓閲嶃��
-        if (batchNoList == null || batchNoList.isEmpty()) {
-            return Collections.emptyList();
-        }
-        LinkedHashSet<String> normalizedSet = new LinkedHashSet<>();
-        for (String batchNo : batchNoList) {
-            String normalizedBatchNo = normalizeBatchNo(batchNo);
-            if (!StringUtils.isEmpty(normalizedBatchNo)) {
-                normalizedSet.add(normalizedBatchNo);
-            }
-        }
-        return new ArrayList<>(normalizedSet);
-    }
-
-    private void fillBatchNoList(List<ProductionOrderPickVo> detailList) {
-        // 灏嗗悓璁㈠崟+鍚岃鏍�+鍚屽伐搴忕殑鏁版嵁鎸夌粍鑱氬悎鎵规锛屼究浜庡墠绔粺涓�灞曠ず銆�
-        if (detailList == null || detailList.isEmpty()) {
-            return;
-        }
-        Map<String, LinkedHashSet<String>> batchNoGroupMap = new HashMap<>();
-        for (ProductionOrderPickVo detail : detailList) {
-            String key = buildBatchNoGroupKey(detail);
-            LinkedHashSet<String> batchSet = batchNoGroupMap.computeIfAbsent(key, k -> new LinkedHashSet<>());
-            batchSet.addAll(parseBatchNoValue(detail.getBatchNo()));
-            if (detail.getBatchNoList() != null && !detail.getBatchNoList().isEmpty()) {
-                batchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
-            }
-        }
-        for (ProductionOrderPickVo detail : detailList) {
-            String key = buildBatchNoGroupKey(detail);
-            LinkedHashSet<String> batchSet = batchNoGroupMap.get(key);
-            detail.setBatchNoList(batchSet == null ? Collections.emptyList() : new ArrayList<>(batchSet));
-        }
-    }
-
-    private void fillSelectableBatchNoList(List<ProductionOrderPickVo> detailList) {
-        // 鍚堝苟鈥滃凡閫夋壒娆♀�濆拰鈥滃簱瀛樺彲閫夋壒娆♀�濓紝鐢ㄤ簬鍓嶇涓嬫媺銆�
-        if (detailList == null || detailList.isEmpty()) {
-            return;
-        }
-        // 鍏堟敹闆嗘槑缁嗕腑娑夊強鐨勮鏍糏D锛屾壒閲忔煡璇㈠簱瀛樻壒娆°��
-        Set<Long> productModelIdSet = detailList.stream()
-                .map(ProductionOrderPickVo::getProductModelId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        if (productModelIdSet.isEmpty()) {
-            return;
-        }
-        List<StockInventory> stockBatchList = stockInventoryMapper.listSelectableBatchNoByProductModelIds(
-                new ArrayList<>(productModelIdSet));
-        Map<Long, LinkedHashSet<String>> stockBatchMap = new HashMap<>();
-        for (StockInventory stockInventory : stockBatchList) {
-            if (stockInventory == null || stockInventory.getProductModelId() == null) {
-                continue;
-            }
-            String normalizedBatchNo = normalizeBatchNo(stockInventory.getBatchNo());
-            if (StringUtils.isEmpty(normalizedBatchNo)) {
-                continue;
-            }
-            stockBatchMap.computeIfAbsent(stockInventory.getProductModelId(), k -> new LinkedHashSet<>())
-                    .add(normalizedBatchNo);
-        }
-        for (ProductionOrderPickVo detail : detailList) {
-            LinkedHashSet<String> mergedBatchSet = new LinkedHashSet<>();
-            mergedBatchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
-            LinkedHashSet<String> selectableBatchSet = stockBatchMap.get(detail.getProductModelId());
-            if (selectableBatchSet != null) {
-                mergedBatchSet.addAll(selectableBatchSet);
-            }
-            detail.setBatchNoList(new ArrayList<>(mergedBatchSet));
-        }
-    }
-
-    private String buildBatchNoGroupKey(ProductionOrderPickVo detail) {
-        // 鏋勫缓鎵规鑱氬悎鍒嗙粍閿��
-        return detail.getProductionOrderId() + "|"
-                + detail.getProductModelId() + "|"
-                + detail.getTechnologyOperationId() + "|"
-                + detail.getOperationName();
-    }
-
-    private List<String> parseBatchNoValue(String rawBatchNoValue) {
-        // 鎵规瑙f瀽鍏煎涓夌鏍煎紡锛�
-        // 1) 鍗曞�硷細A001
-        // 2) 閫楀彿鍒嗛殧锛欰001,A002
-        // 3) 绫籎SON鏁扮粍瀛楃涓诧細["A001","A002"]
-        String normalizedValue = normalizeBatchNo(rawBatchNoValue);
-        if (StringUtils.isEmpty(normalizedValue)) {
-            return Collections.emptyList();
-        }
-        if (normalizedValue != null && normalizedValue.startsWith("[") && normalizedValue.endsWith("]")) {
-            String value = normalizedValue.substring(1, normalizedValue.length() - 1);
-            if (StringUtils.isEmpty(value)) {
-                return Collections.emptyList();
-            }
-            List<String> parsed = Arrays.stream(value.split(","))
-                    .map(item -> item.trim().replace("\"", "").replace("'", ""))
-                    .collect(Collectors.toList());
-            return normalizeBatchNoList(parsed);
-        }
-        if (normalizedValue != null && normalizedValue.contains(",")) {
-            List<String> parsed = Arrays.stream(normalizedValue.split(","))
-                    .map(item -> item.trim())
-                    .collect(Collectors.toList());
-            return normalizeBatchNoList(parsed);
-        }
-        return Collections.singletonList(normalizedValue);
-    }
-
-    private LambdaQueryWrapper<StockInventory> buildStockWrapper(Long productModelId, String batchNo) {
-        // 鏋勫缓搴撳瓨鏌ヨ鏉′欢锛堣鏍� + 鎵规锛夈��
-        LambdaQueryWrapper<StockInventory> wrapper = Wrappers.<StockInventory>lambdaQuery()
-                .eq(StockInventory::getProductModelId, productModelId);
-        if (StringUtils.isEmpty(batchNo)) {
-            wrapper.isNull(StockInventory::getBatchNo);
-        } else {
-            wrapper.eq(StockInventory::getBatchNo, batchNo);
-        }
-        return wrapper;
-    }
-
-    private BigDecimal defaultDecimal(BigDecimal value) {
-        // BigDecimal 绌哄�煎厹搴曪紝缁熶竴鎸�0澶勭悊銆�
-        return value == null ? BigDecimal.ZERO : value;
-    }
-
-    private String formatQuantity(BigDecimal value) {
-        // 鏁伴噺鏍煎紡鍖栬緭鍑猴紙鍘婚櫎鏈熬鏃犳晥0锛夈��
-        return defaultDecimal(value).stripTrailingZeros().toPlainString();
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
index 75d0696..af480a2 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
+++ b/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()));
-
-                // 纭畾鏍逛骇鍝佽鏍糏D
-                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());
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
index 5c103b8..c62a17e 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/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("宸ヨ壓璺嚎涓嶅瓨鍦�");
         }
-        // 璁㈠崟蹇収鎸夆�滃厛娓呭悗寤衡�濆鐞嗭紝淇濊瘉宸ヨ壓璺嚎銆佸伐搴忋�佸弬鏁般�丅OM 鍏ㄩ儴鏉ヨ嚜鍚屼竴鐗堟湰銆�
         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) {
-        // 娓呯悊璁㈠崟宸茬敓鎴愮殑宸ヨ壓涓嶣OM蹇収鏁版嵁
-        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();
-        }
-
-        // 鏌ヨ瀹屾暣鐨凚OM缁撴瀯锛堝寘鎷牴鑺傜偣锛夛紝鐢ㄤ簬璁$畻灞傜骇闇�姹傛暟閲�
-        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
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
index b00266b..56c1829 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
+++ b/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)
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index c52892a..3514da3 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/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) {
-        // 鏂板鐢熶骇鎶ュ伐涓昏褰�
+        // 鍏煎鏃ф祦绋嬶細濡傛灉娌℃湁寮�濮嬫姤宸ヨ褰旾D锛岃蛋涓�姝ユ姤宸ワ紙鑷姩鍒涘缓+缁撴潫锛�
+        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("璇蜂紶鍏ョ敓浜у伐鍗旾D");
         }
-        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("璇蜂紶鍏ョ敓浜у伐鍗旾D");
+        }
+        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) {
+        // 浠庣敓浜ц鍗曡幏鍙栦骇鍝佽鏍糏D
+        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) {
diff --git a/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java b/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java
index e82d7e4..df6b8d6 100644
--- a/src/main/java/com/ruoyi/production/util/TaskPlanQuantityUtil.java
+++ b/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);
-    }
-
-    /**
-     * 瑙f瀽宸ュ簭杈撳嚭鑺傜偣
-     */
-    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;
-    }
-
-    /**
-     * 瑙f瀽杈撳嚭浜у搧瑙勬牸ID
-     */
-    public Long resolveOutputProductModelId(ProductionBomStructure outputNode, Long rootProductModelId) {
-        if (outputNode == null) {
-            return rootProductModelId;
-        }
-        return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId;
-    }
 
     /**
      * 榛樿BigDecimal鍊�
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java
index 7b09b33..6df1cc3 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedOrderController.java
+++ b/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);
+    }
 }
diff --git a/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java b/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java
index 06fce64..22fdc35 100644
--- a/src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedOrderMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java
index a4a9209..4413542 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualifiedOrder.java
@@ -112,6 +112,15 @@
     @Schema(description = "澶囨敞")
     private String remark;
 
+    @Schema(description = "璐d换閮ㄩ棬涓荤鎰忚")
+    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;
 
diff --git a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java b/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java
index b0a4ba7..d73200a 100644
--- a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedOrderService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index dada91d..b0ece76 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/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);//宸叉彁浜�
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java
index 1c9d83a..a21682f 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedOrderServiceImpl.java
+++ b/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);
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index 61aac8b..6428453 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/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());
-            }
-
-            // 濡傛灉鏄敓浜ч��鏂欏叆搴擄紝鎭㈠閫�鏂欐暟閲忥紙鍥犱负椹冲洖鏃跺凡鎵e噺锛�
-            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);
-                }
             }
 
             // 灏嗙姸鎬佹敼涓哄緟瀹℃牳
diff --git a/src/main/resources/mapper/production/ProductionBomStructureMapper.xml b/src/main/resources/mapper/production/ProductionBomStructureMapper.xml
deleted file mode 100644
index c116f6f..0000000
--- a/src/main/resources/mapper/production/ProductionBomStructureMapper.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductionBomStructureMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionBomStructure">
-        <id column="id" property="id" />
-        <result column="parent_id" property="parentId" />
-        <result column="production_order_id" property="productionOrderId" />
-        <result column="product_model_id" property="productModelId" />
-        <result column="technology_operation_id" property="technologyOperationId" />
-        <result column="production_order_bom_id" property="productionOrderBomId" />
-        <result column="unit_quantity" property="unitQuantity" />
-        <result column="demanded_quantity" property="demandedQuantity" />
-        <result column="unit" property="unit" />
-        <result column="create_user" property="createUser" />
-        <result column="dept_id" property="deptId" />
-    </resultMap>
-
-    <select id="listByBomId" resultType="com.ruoyi.production.bean.vo.ProductionBomStructureVo">
-        select pbs.*,
-               p.product_name as productName,
-               pm.product_id as productId,
-               pm.model,
-               top1.name as operationName
-        from production_bom_structure pbs
-                 left join product_model pm on pbs.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-                 left join technology_operation top1 on pbs.technology_operation_id = top1.id
-        where pbs.production_order_bom_id = #{bomId}
-        order by pbs.id
-    </select>
-
-    <select id="pickByBomId" resultType="com.ruoyi.production.bean.vo.ProductionBomStructureVo">
-        SELECT
-            pbs.*,
-            p.product_name AS productName,
-            pm.product_id AS productId,
-            pm.model,
-            top1.NAME AS operationName
-        FROM
-            production_bom_structure pbs
-                LEFT JOIN product_model pm ON pbs.product_model_id = pm.id
-                LEFT JOIN product p ON pm.product_id = p.id
-                LEFT JOIN technology_operation top1 ON pbs.technology_operation_id = top1.id
-        WHERE
-            pbs.parent_id IS NOT NULL
-          AND pbs.production_order_bom_id = #{bomId}
-        ORDER BY
-            pbs.id
-    </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index 5847f5f..0a8cb29 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/production/ProductionOrderBomMapper.xml b/src/main/resources/mapper/production/ProductionOrderBomMapper.xml
deleted file mode 100644
index eddaa63..0000000
--- a/src/main/resources/mapper/production/ProductionOrderBomMapper.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductionOrderBomMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderBom">
-        <id column="id" property="id" />
-        <result column="parent_id" property="parentId" />
-        <result column="production_order_id" property="productionOrderId" />
-        <result column="product_model_id" property="productModelId" />
-        <result column="technology_operation_id" property="technologyOperationId" />
-        <result column="unit_quantity" property="unitQuantity" />
-        <result column="demanded_quantity" property="demandedQuantity" />
-        <result column="unit" property="unit" />
-        <result column="bom_id" property="bomId" />
-        <result column="create_user" property="createUser" />
-        <result column="dept_id" property="deptId" />
-    </resultMap>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
index 8e64413..7ca1bce 100644
--- a/src/main/resources/mapper/production/ProductionOrderMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/production/ProductionOrderPickMapper.xml b/src/main/resources/mapper/production/ProductionOrderPickMapper.xml
deleted file mode 100644
index 8b0a0d7..0000000
--- a/src/main/resources/mapper/production/ProductionOrderPickMapper.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductionOrderPickMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderPick">
-        <id column="id" property="id" />
-        <result column="product_model_id" property="productModelId" />
-        <result column="quantity" property="quantity" />
-        <result column="batch_no" property="batchNo" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-        <result column="production_order_id" property="productionOrderId" />
-        <result column="remark" property="remark" />
-        <result column="create_user" property="createUser" />
-        <result column="dept_id" property="deptId" />
-        <result column="operation_name" property="operationName" />
-        <result column="technology_operation_id" property="technologyOperationId" />
-        <result column="demanded_quantity" property="demandedQuantity" />
-        <result column="feeding_qty" property="feedingQty" />
-        <result column="return_qty" property="returnQty" />
-        <result column="actual_qty" property="actualQty" />
-        <result column="is_returned" property="returned" />
-        <result column="is_bom" property="bom" />
-    </resultMap>
-
-    <select id="listPickedDetailByOrderId" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickVo">
-        select pop.*,
-               pop.is_bom as bom,
-               pop.is_returned as returned,
-               pop.quantity as pickQuantity,
-               p.product_name as productName,
-               pm.model as model,
-               pm.unit as unit
-        from production_order_pick pop
-                 left join product_model pm on pop.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-        where pop.production_order_id = #{productionOrderId}
-        order by pop.create_time desc, pop.id desc
-    </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml b/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
deleted file mode 100644
index a80fd02..0000000
--- a/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductionOrderPickRecordMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderPickRecord">
-        <id column="id" property="id" />
-        <result column="pick_id" property="pickId" />
-        <result column="production_order_id" property="productionOrderId" />
-        <result column="production_operation_task_id" property="productionOperationTaskId" />
-        <result column="product_model_id" property="productModelId" />
-        <result column="batch_no" property="batchNo" />
-        <result column="pick_quantity" property="pickQuantity" />
-        <result column="before_quantity" property="beforeQuantity" />
-        <result column="after_quantity" property="afterQuantity" />
-        <result column="pick_type" property="pickType" />
-        <result column="remark" property="remark" />
-        <result column="feeding_reason" property="feedingReason" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-        <result column="create_user" property="createUser" />
-        <result column="dept_id" property="deptId" />
-    </resultMap>
-
-    <select id="listPickedDetailByOrderId" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickVo">
-        select popr.*,
-               poro.operation_name as operationName,
-               p.product_name as productName,
-               pm.model as model,
-               pm.unit as unit
-        from production_order_pick_record popr
-                 left join production_operation_task pot on popr.production_operation_task_id = pot.id
-                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
-                 left join product_model pm on popr.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-        where popr.production_order_id = #{productionOrderId}
-        order by popr.create_time desc, popr.id desc
-    </select>
-
-    <select id="listFeedingRecord" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo">
-        select popr.*,
-               poro.operation_name as operationName,
-               p.product_name as productName,
-               pm.model as model,
-               pm.unit as unit,
-               coalesce(su.nick_name, su.user_name) as supplementUserName,
-               popr.create_time as supplementTime
-        from production_order_pick_record popr
-                 left join production_operation_task pot on popr.production_operation_task_id = pot.id
-                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
-                 left join product_model pm on popr.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-                 left join sys_user su on popr.create_user = su.user_id
-        where popr.production_order_id = #{productionOrderId}
-          and popr.pick_id = #{pickId}
-          and popr.pick_type = 2
-        order by popr.create_time desc, popr.id desc
-    </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml b/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml
index 40be168..8f559c3 100644
--- a/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index df585f9..556a4a3 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml b/src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml
index bcbd663..4c6d256 100644
--- a/src/main/resources/mapper/quality/QualityUnqualifiedOrderMapper.xml
+++ b/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>
diff --git "a/src/main/resources/static/\344\270\215\345\220\210\346\240\274\345\223\201\345\244\204\347\220\206\345\215\225.xls" "b/src/main/resources/static/\344\270\215\345\220\210\346\240\274\345\223\201\345\244\204\347\220\206\345\215\225.xls"
new file mode 100644
index 0000000..280c123
--- /dev/null
+++ "b/src/main/resources/static/\344\270\215\345\220\210\346\240\274\345\223\201\345\244\204\347\220\206\345\215\225.xls"
Binary files differ

--
Gitblit v1.9.3