From fe1b02a121c173e9b2d56bbe5a1982e0e69e0548 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期二, 28 四月 2026 18:06:08 +0800
Subject: [PATCH] feat(production): 新增生产工单管理功能 - 创建 ProductionOperationTask 实体类定义工单数据结构 - 实现 ProductionOperationTaskController 提供工单的增删改查接口 - 开发 ProductionOperationTaskService 和实现类处理业务逻辑 - 配置 ProductionOperationTaskMapper 及 XML 文件实现数据库操作 - 添加 ProductionOperationTaskVo 视图对象用于数据展示 - 扩展 ProductionOrder 实体类增加生产订单相关属性 - 更新 ProductionOrderMapper.xml 完善订单查询映射配置 - 优化 ProductionOrderPickRecordMapper.xml 记录物料领取明细 - 新增 ProductionOrderRoutingOperationParam 参数配置实体 - 完善 工序参数处理逻辑

---
 src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml                        |    4 
 src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java                             |    3 
 src/main/resources/mapper/production/ProductionProductInputMapper.xml                           |    5 
 src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java            |    8 
 src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java                       |   53 ++--
 src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java             |    5 
 src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java              |    9 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java         |   21 +
 src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java                            |    4 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                                    |   13 +
 src/main/resources/mapper/production/ProductionProductOutputMapper.xml                          |    2 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java |    6 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java               |   59 ++++-
 src/main/resources/mapper/quality/QualityTestStandardMapper.xml                                 |    4 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java                 |   49 +++-
 src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java               |    3 
 src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java                                       |   13 -
 src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java                            |    4 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java           |  137 ++++++++++++-
 src/main/resources/mapper/production/ProductionOrderMapper.xml                                  |   37 +++
 src/main/resources/mapper/quality/QualityInspectMapper.xml                                      |   18 +
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                          |   57 ++++-
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java                 |    2 
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                            |   38 ++-
 src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java                  |    2 
 src/main/java/com/ruoyi/production/pojo/ProductionOrder.java                                    |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java                    |    7 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java                       |   26 ++
 28 files changed, 427 insertions(+), 164 deletions(-)

diff --git a/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java b/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java
index 03d933e..27e5a6b 100644
--- a/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java
+++ b/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java
@@ -1,24 +1,15 @@
 package com.ruoyi.ai.config;
 
 import com.ruoyi.ai.store.MongoChatMemoryStore;
-import dev.langchain4j.data.document.Document;
-import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
-import dev.langchain4j.data.segment.TextSegment;
 import dev.langchain4j.memory.chat.ChatMemoryProvider;
 import dev.langchain4j.memory.chat.MessageWindowChatMemory;
 import dev.langchain4j.model.embedding.EmbeddingModel;
 import dev.langchain4j.rag.content.retriever.ContentRetriever;
 import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
 import dev.langchain4j.store.embedding.EmbeddingStore;
-import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
-import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-
-import java.util.Collections;
-import java.util.List;
 
 /**
  * @author :yys
@@ -35,8 +26,8 @@
     @Autowired
     private EmbeddingModel embeddingModel;
 
-    @Value("${knowledge.one}")
-    private String one;
+//    @Value("${knowledge.one}")
+//    private String one;
 //
 //    @Value("${knowledge.two}")
 //    private String two;
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 e5754bf..1721e81 100644
--- a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
@@ -1,67 +1,68 @@
 package com.ruoyi.production.bean.dto;
 
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.pojo.ProductionProductMain;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.util.List;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
-public class ProductionProductMainDto {
-    @Schema(description = "涓婚敭ID")
-    private Long id;
-    @Schema(description = "浜у搧缂栧彿")
-    private String productNo;
-    @Schema(description = "鐢ㄦ埛ID")
-    private Long userId;
-    @Schema(description = "鐢ㄦ埛鍚嶇О")
-    private String userName;
+@Schema(name = "ProductionProductMainDto", description = "鐢熶骇鎶ュ伐鏌ヨ瀵硅薄")
+public class ProductionProductMainDto extends ProductionProductMain {
+
     @Schema(description = "浜у搧宸ヨ壓璺嚎鏄庣粏ID")
     private Long productProcessRouteItemId;
-    @Schema(description = "宸ュ崟ID")
-    private Long workOrderId;
-    @Schema(description = "鐢熶骇宸ュ簭浠诲姟ID")
-    private Long productionOperationTaskId;
-    @Schema(description = "鐘舵��")
-    private Integer status;
-    @Schema(description = "鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-    @Schema(description = "鏇存柊鏃堕棿")
-    private LocalDateTime updateTime;
+
+    @Schema(description = "鐢熶骇鎶ュ伐琛╥d")
+    private Long productMainId;
+
     @Schema(description = "绉熸埛ID")
     private Long tenantId;
-    @Schema(description = "鍒涘缓浜�")
-    private Integer createUser;
-    @Schema(description = "鏇存柊浜�")
-    private Integer updateUser;
-    @Schema(description = "閮ㄩ棬ID")
-    private Long deptId;
 
     @Schema(description = "宸ュ崟缂栧彿")
     private String workOrderNo;
+
     @Schema(description = "宸ュ崟鐘舵��")
     private String workOrderStatus;
+
     @Schema(description = "鏄电О")
     private String nickName;
+
     @Schema(description = "鏁伴噺")
     private BigDecimal quantity;
+
     @Schema(description = "鎶ュ簾鏁伴噺")
     private BigDecimal scrapQty;
+
     @Schema(description = "浜у搧鍚嶇О")
     private String productName;
+
     @Schema(description = "浜у搧鍨嬪彿鍚嶇О")
     private String productModelName;
+
     @Schema(description = "鍗曚綅")
     private String unit;
+
     @Schema(description = "閿�鍞悎鍚岀紪鍙�")
     private String salesContractNo;
+
     @Schema(description = "鎺掍骇鏃ユ湡")
     private LocalDate schedulingDate;
+
     @Schema(description = "鎺掍骇浜哄憳鍚嶇О")
     private String schedulingUserName;
+
     @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
+
     @Schema(description = "宸ュ簭")
     private String process;
+
+    @Schema(description = "宸ュ簭鍙傛暟鍒楄〃")
+    private List<ProductionOrderRoutingOperationParam> productionOperationParamList;
 }
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
index eed3a31..0b56788 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
@@ -1,8 +1,34 @@
 package com.ruoyi.production.bean.vo;
 
 import com.ruoyi.production.pojo.ProductionOperationTask;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
+import java.math.BigDecimal;
+
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class ProductionOperationTaskVo extends ProductionOperationTask {
+
+    @Schema(description = "璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "宸ュ崟绫诲瀷 姝e父 /杩斿伐杩斾慨")
+    private String workOrderType;
+
+    @Schema(description = "瀹屾垚杩涘害")
+    private BigDecimal completionStatus;
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
index 52a4357..e2c23ab 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
 import com.ruoyi.production.pojo.ProductionOperationTask;
 import com.ruoyi.production.service.ProductionOperationTaskService;
+import io.swagger.annotations.ApiOperation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Operation;
 import lombok.RequiredArgsConstructor;
@@ -63,4 +64,11 @@
     public R<Boolean> remove(@RequestBody List<Long> ids) {
         return R.ok(productionOperationTaskService.removeProductionOperationTask(ids));
     }
+
+    @Operation(summary = "浜у搧宸ュ崟鏇存柊")
+    @PostMapping("/updateProductWorkOrder")
+    public R updateProductWorkOrder(@RequestBody ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.updateProductWorkOrder(dto));
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
index c1d7b91..7f61dbf 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
@@ -6,12 +6,11 @@
 import com.ruoyi.production.service.ProductionProductInputService;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@RequestMapping("productionProductInput")
+@RequestMapping("/productionProductInput")
 @RestController
 @Tag(name = "鐢熶骇鎶曞叆")
 @AllArgsConstructor
@@ -19,7 +18,7 @@
 
     private ProductionProductInputService productionProductInputService;
 
-    @GetMapping("listPage")
+    @GetMapping("/listPage")
     public R page(Page<ProductionProductInputDto> page, ProductionProductInputDto productionProductInputDto) {
         return R.ok(productionProductInputService.listPageProductionProductInputDto(page, productionProductInputDto));
     }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
index 2dc751e..97fb2df 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
@@ -5,16 +5,15 @@
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.production.bean.dto.ProductionProductMainDto;
 import com.ruoyi.production.service.ProductionProductMainService;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
-@RequestMapping("productionProductMain")
+@RequestMapping("/productionProductMain")
 @RestController
 @Tag(name = "鐢熶骇鎶ュ伐")
 @AllArgsConstructor
@@ -28,7 +27,7 @@
      * @param productionProductMainDto
      * @return
      */
-    @GetMapping("listPage")
+    @GetMapping("/listPage")
     public R page(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
         return R.ok(productionProductMainService.listPageProductionProductMainDto(page, productionProductMainDto));
     }
@@ -50,7 +49,7 @@
      * @param productionProductMainDto
      * @return
      */
-    @PostMapping("addProductMain")
+    @PostMapping("/addProductMain")
     public R addProductMain(@RequestBody ProductionProductMainDto productionProductMainDto) {
         return R.ok(productionProductMainService.addProductMain(productionProductMainDto));
     }
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
index c3c6d3b..e23b611 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
@@ -1,8 +1,12 @@
 package com.ruoyi.production.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.home.dto.ProductionTaskStatisticsDto;
 import com.ruoyi.home.dto.processDataProductionStatisticsDto;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
 import com.ruoyi.production.pojo.ProductionOperationTask;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -22,6 +26,9 @@
 @Mapper
 public interface ProductionOperationTaskMapper extends BaseMapper<ProductionOperationTask> {
 
+    IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskVo> page,
+                                                                 @Param("c") ProductionOperationTaskDto dto);
+
     List<ProductionTaskStatisticsDto> selectTaskStatisticsByDate(@Param("startDate") LocalDate startDate,
                                                                  @Param("endDate") LocalDate endDate);
 
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java b/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
index 5ae58d9..08399e9 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
@@ -28,8 +28,8 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @Schema(description = "宸ヨ壓璺嚎宸ュ簭琛╥d")
-    private Long technologyRoutingOperationId;
+    @Schema(description = "鐢熶骇宸ヨ壓璺嚎宸ュ簭琛╥d")
+    private Long productionOrderRoutingOperationId;
 
     @Schema(description = "褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
index 9e29fe8..c7415b5 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
@@ -74,6 +74,6 @@
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planCompleteTime;
 
-    @Schema(description = "鐘舵�侊紙1.寰呭紑濮嬨��2.杩涜涓��3.宸插畬鎴愩��4.宸插彇娑堬級")
+    @Schema(description = "鐘舵�侊紙1.寰呭紑濮� 2.杩涜涓� 3.宸插畬鎴� 4.宸插彇娑堬級")
     private Integer status;
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
index ef0df4d..752a839 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
@@ -85,6 +85,9 @@
     @Schema(description = "鏍囧噯鍊�")
     private String standardValue;
 
+    @Schema(description = "杈撳叆鍊�")
+    private String inputValue;
+
     @Schema(description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭ID")
     private Long productionOrderRoutingOperationId;
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
index 0526bc1..9c6e9d1 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -37,9 +37,6 @@
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @Schema(description = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
     @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
index 47629f1..badf048 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
@@ -34,10 +34,6 @@
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @Schema(description = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
     @Schema(description = "鎶ュ簾鏁伴噺")
     private BigDecimal scrapQty;
     @Schema(description = "鍒涘缓鐢ㄦ埛")
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
index 8897c4e..4ff1e16 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -21,4 +21,6 @@
     boolean saveProductionOperationTask(ProductionOperationTask productionOperationTask);
 
     boolean removeProductionOperationTask(List<Long> ids);
+
+    int updateProductWorkOrder(ProductionOperationTaskDto dto);
 }
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 66e1aaa..8553869 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -18,14 +18,14 @@
 
 @Service
 @RequiredArgsConstructor
-public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask>
-        implements ProductionOperationTaskService {
+public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask> implements ProductionOperationTaskService {
+
+
 
     @Override
-    public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page,
-                                                                         ProductionOperationTaskDto dto) {
-        Page<ProductionOperationTask> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
-        return this.page(entityPage, buildQueryWrapper(dto)).convert(item -> BeanUtil.copyProperties(item, ProductionOperationTaskVo.class));
+    public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) {
+        Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        return baseMapper.pageProductionOperationTask(voPage, dto);
     }
 
     @Override
@@ -54,11 +54,16 @@
         return Wrappers.<ProductionOperationTask>lambdaQuery()
                 .eq(query.getId() != null, ProductionOperationTask::getId, query.getId())
                 .eq(query.getProductionOrderId() != null, ProductionOperationTask::getProductionOrderId, query.getProductionOrderId())
-                .eq(query.getTechnologyRoutingOperationId() != null,
-                        ProductionOperationTask::getTechnologyRoutingOperationId, query.getTechnologyRoutingOperationId())
+                .eq(query.getProductionOrderRoutingOperationId() != null,
+                        ProductionOperationTask::getProductionOrderRoutingOperationId, query.getProductionOrderRoutingOperationId())
                 .eq(query.getStatus() != null, ProductionOperationTask::getStatus, query.getStatus())
                 .like(query.getWorkOrderNo() != null && !query.getWorkOrderNo().trim().isEmpty(),
                         ProductionOperationTask::getWorkOrderNo, query.getWorkOrderNo())
                 .orderByDesc(ProductionOperationTask::getId);
     }
+
+    @Override
+    public int updateProductWorkOrder(ProductionOperationTaskDto dto) {
+        return baseMapper.updateById(dto);
+    }
 }
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 9b5953b..886da11 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
@@ -90,7 +90,7 @@
             }
             String workOrderNoStr = "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
             ProductionOperationTask productionOperationTask = new ProductionOperationTask();
-            productionOperationTask.setTechnologyRoutingOperationId(productionOrderRoutingOperation.getId());
+            productionOperationTask.setProductionOrderRoutingOperationId(productionOrderRoutingOperation.getId());
             productionOperationTask.setProductionOrderId(productionOrderRoutingOperation.getProductionOrderId());
             productionOperationTask.setPlanQuantity(BigDecimal.ZERO);
             productionOperationTask.setCompleteQuantity(BigDecimal.ZERO);
@@ -106,7 +106,7 @@
         try {
             ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectOne(
                     new LambdaQueryWrapper<ProductionOperationTask>()
-                            .eq(ProductionOperationTask::getTechnologyRoutingOperationId, id)
+                            .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, id)
                             .last("limit 1"));
             if (productionOperationTask == null) {
                 throw new RuntimeException("鍒犻櫎澶辫触锛氭湭鎵惧埌鍏宠仈鐨勭敓浜у伐鍗�");
@@ -128,7 +128,7 @@
                 routingId = deleteItem.getOrderRoutingId();
             }
             productionOperationTaskMapper.delete(new LambdaQueryWrapper<ProductionOperationTask>()
-                    .eq(ProductionOperationTask::getTechnologyRoutingOperationId, id));
+                    .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, id));
             productionOrderRoutingOperationMapper.deleteById(id);
             if (routingId != null) {
                 List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList(
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 31affd2..f994bb6 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -242,7 +242,7 @@
             productionOrderRoutingOperationMapper.insert(targetOperation);
 
             ProductionOperationTask task = new ProductionOperationTask();
-            task.setTechnologyRoutingOperationId(targetOperation.getId());
+            task.setProductionOrderRoutingOperationId(targetOperation.getId());
             task.setProductionOrderId(productionOrder.getId());
             task.setPlanQuantity(defaultDecimal(productionOrder.getQuantity()));
             task.setCompleteQuantity(BigDecimal.ZERO);
@@ -450,6 +450,12 @@
         if (productionPlans.size() != planIds.size()) {
             throw new ServiceException("閮ㄥ垎鐢熶骇璁″垝涓嶅瓨鍦�");
         }
+        Map<Long, ProductionPlan> planMap = productionPlans.stream()
+                .collect(Collectors.toMap(ProductionPlan::getId, item -> item, (left, right) -> left));
+        ProductionPlan mainPlan = planMap.get(planIds.get(0));
+        if (mainPlan == null) {
+            throw new ServiceException("涓荤敓浜ц鍒掍笉瀛樺湪");
+        }
         Set<Long> productModelIds = productionPlans.stream()
                 .map(ProductionPlan::getProductModelId)
                 .collect(Collectors.toSet());
@@ -459,7 +465,7 @@
         if (productionPlans.stream().anyMatch(item -> item.getStatus() != null && item.getStatus() == 2)) {
             throw new ServiceException("鎵�閫夌敓浜ц鍒掑凡涓嬪彂");
         }
-        ProductionPlan firstPlan = productionPlans.get(0);
+        ProductionPlan firstPlan = mainPlan;
         if (productionOrder.getProductModelId() == null) {
             productionOrder.setProductModelId(firstPlan.getProductModelId());
         } else if (!Objects.equals(productionOrder.getProductModelId(), firstPlan.getProductModelId())) {
@@ -698,28 +704,33 @@
             }
         }
 
-        List<ProductionOrderPickVo> result = new ArrayList<>(bomStructureList.size());
+        Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
         for (ProductionBomStructureVo structure : bomStructureList) {
             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);
-            result.add(vo);
+            String mergeKey = String.valueOf(structure.getTechnologyOperationId()) + "#" + productModelId;
+            ProductionOrderPickVo vo = mergedPickMap.get(mergeKey);
+            if (vo == null) {
+                vo = new ProductionOrderPickVo();
+                vo.setProductModelId(productModelId);
+                vo.setOperationName(structure.getOperationName());
+                vo.setTechnologyOperationId(structure.getTechnologyOperationId());
+                vo.setProductName(structure.getProductName());
+                vo.setModel(structure.getModel());
+                vo.setDemandedQuantity(BigDecimal.ZERO);
+                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);
+                mergedPickMap.put(mergeKey, vo);
+            }
+            vo.setDemandedQuantity(defaultDecimal(vo.getDemandedQuantity()).add(defaultDecimal(structure.getDemandedQuantity())));
         }
-        return result;
+        return new ArrayList<>(mergedPickMap.values());
     }
 }
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 044998a..abbc525 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -40,8 +40,10 @@
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @Service
@@ -63,7 +65,10 @@
     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;
     private final TechnologyOperationMapper technologyOperationMapper;
     private final StockUtils stockUtils;
@@ -87,7 +92,8 @@
 
     @Override
     public Boolean addProductMain(ProductionProductMainDto dto) {
-        if (dto.getProductionOperationTaskId() == null) {
+        Long taskId = resolveTaskId(dto);
+        if (taskId == null) {
             throw new ServiceException("璇蜂紶鍏ョ敓浜у伐鍗旾D");
         }
         return addProductMainByProductionTask(dto);
@@ -109,12 +115,16 @@
 
     private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) {
         // 鎶ュ伐浠ヨ鍗曞伐搴忓揩鐓т负鍑嗭紝閬垮厤宸ヨ壓涓绘暟鎹彉鏇村悗褰卞搷鍘嗗彶宸ュ崟鎵ц銆�
+        Long taskId = resolveTaskId(dto);
+        if (taskId == null) {
+            throw new ServiceException("productionOperationTaskId can not be null");
+        }
         SysUser user = userMapper.selectUserById(dto.getUserId());
-        ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(dto.getProductionOperationTaskId());
+        ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId);
         if (productionOperationTask == null) {
             throw new ServiceException("鐢熶骇宸ュ崟涓嶅瓨鍦�");
         }
-        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getTechnologyRoutingOperationId());
+        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId());
         if (routingOperation == null) {
             throw new ServiceException("璁㈠崟宸ヨ壓璺嚎宸ュ簭涓嶅瓨鍦�");
         }
@@ -122,6 +132,7 @@
         if (productionOrder == null) {
             throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
         }
+        syncOperationParamInputValue(dto, routingOperation.getId());
         TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId());
         TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null
                 : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId());
@@ -133,17 +144,17 @@
 
         ProductionProductMain productionProductMain = new ProductionProductMain();
         productionProductMain.setProductNo(generateProductNo());
-        productionProductMain.setUserId(dto.getUserId());
-        productionProductMain.setUserName(dto.getUserName());
-        productionProductMain.setProductionOperationTaskId(productionOperationTask.getId());
+        productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId());
+        productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName());
+        productionProductMain.setProductionOperationTaskId(taskId);
         productionProductMain.setStatus(0);
         productionProductMainMapper.insert(productionProductMain);
 
-        List<ProductStructureDto> productStructureDtos = new ArrayList<>();
-        ProductStructureDto productStructureDto = new ProductStructureDto();
-        productStructureDto.setProductModelId(productModel.getId());
-        productStructureDto.setUnitQuantity(BigDecimal.ONE);
-        productStructureDtos.add(productStructureDto);
+        List<ProductStructureDto> productStructureDtos = resolveInputStructures(
+                productionOrder.getId(), routingOperation, productModel.getId());
+        if (productStructureDtos.isEmpty()) {
+            throw new ServiceException("鏈壘鍒板綋鍓嶅伐搴忓搴旂殑BOM鎶曞叆鑺傜偣");
+        }
         for (ProductStructureDto item : productStructureDtos) {
             // 褰撳墠瀹炵幇鎸夊伐搴忔垚鍝佺洿鎺ヤ綔涓烘姇鍏ワ紝鍚庣画鑻ユ帴鍏ラ鏂欒褰曞彲鍦ㄨ繖閲屾浛鎹㈡潵婧愩��
             ProductionProductInput productionProductInput = new ProductionProductInput();
@@ -153,8 +164,6 @@
             productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity())));
             productionProductInput.setQuantity(productionProductInput.getInputQuantity());
             productionProductInputMapper.insert(productionProductInput);
-            stockUtils.substractStock(item.getProductModelId(), productionProductInput.getInputQuantity(),
-                    StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
         }
 
         ProductionProductOutput productionProductOutput = new ProductionProductOutput();
@@ -261,6 +270,99 @@
         return true;
     }
 
+    private void syncOperationParamInputValue(ProductionProductMainDto dto, Long productionOrderRoutingOperationId) {
+        if (dto == null || productionOrderRoutingOperationId == null) {
+            return;
+        }
+        List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList();
+        if (paramList == null || paramList.isEmpty()) {
+            return;
+        }
+        List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, productionOrderRoutingOperationId));
+        if (dbParamList == null || dbParamList.isEmpty()) {
+            return;
+        }
+        Map<Long, ProductionOrderRoutingOperationParam> dbParamMap = dbParamList.stream()
+                .filter(item -> item != null && item.getId() != null)
+                .collect(Collectors.toMap(ProductionOrderRoutingOperationParam::getId, item -> item, (left, right) -> left));
+        for (ProductionOrderRoutingOperationParam param : paramList) {
+            if (param == null || param.getId() == null) {
+                continue;
+            }
+            ProductionOrderRoutingOperationParam dbParam = dbParamMap.get(param.getId());
+            if (dbParam == null) {
+                throw new ServiceException("宸ュ簭鍙傛暟涓嶅瓨鍦ㄦ垨涓嶅睘浜庡綋鍓嶅伐鍗曞伐搴忥紝ID=" + param.getId());
+            }
+            if (Objects.equals(dbParam.getInputValue(), param.getInputValue())) {
+                continue;
+            }
+            ProductionOrderRoutingOperationParam updateParam = new ProductionOrderRoutingOperationParam();
+            updateParam.setId(dbParam.getId());
+            updateParam.setInputValue(param.getInputValue());
+            productionOrderRoutingOperationParamMapper.updateById(updateParam);
+        }
+    }
+
+    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) {
         // 鍒犻櫎鎶ュ伐闇�瑕佸悓姝ュ洖婊氳川妫�銆佸簱瀛樸�佸伐鏃舵牳绠楀拰璁㈠崟/宸ュ崟杩涘害銆�
         List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
@@ -295,7 +397,7 @@
             productionOperationTaskMapper.updateById(productionOperationTask);
 
             ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId());
-            ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getTechnologyRoutingOperationId());
+            ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId());
             if (productionOrder != null && routingOperation != null) {
                 // 鍙湁鏈�鍚庝竴閬撳伐搴忕殑鎶ュ伐鎵嶄細褰卞搷鐢熶骇璁㈠崟瀹屽伐鏁伴噺銆�
                 List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList(
@@ -362,6 +464,13 @@
         return value == null ? BigDecimal.ZERO : value;
     }
 
+    private Long resolveTaskId(ProductionProductMainDto dto) {
+        if (dto == null) {
+            return null;
+        }
+        return dto.getProductionOperationTaskId();
+    }
+
     @Override
     public ArrayList<Long> listMain(List<Long> idList) {
         return productionProductMainMapper.listMain(idList);
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
index 5a9865d..0296ef4 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -169,7 +169,7 @@
             productionOrderRoutingOperationMapper.insert(newOperation);
 
             ProductionOperationTask newTask = new ProductionOperationTask();
-            newTask.setTechnologyRoutingOperationId(newOperation.getId());
+            newTask.setProductionOrderRoutingOperationId(newOperation.getId());
             newTask.setProductionOrderId(newOrder.getId());
             newTask.setPlanQuantity(newOrder.getQuantity());
             newTask.setCompleteQuantity(BigDecimal.ZERO);
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
index d225f7c..a5c8fcc 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
@@ -1,7 +1,6 @@
 package com.ruoyi.technology.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,20 +9,8 @@
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
 import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
-import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
-import com.ruoyi.technology.mapper.TechnologyOperationMapper;
-import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
-import com.ruoyi.technology.mapper.TechnologyParamMapper;
-import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
-import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
-import com.ruoyi.technology.mapper.TechnologyRoutingOperationParamMapper;
-import com.ruoyi.technology.pojo.TechnologyBomStructure;
-import com.ruoyi.technology.pojo.TechnologyOperation;
-import com.ruoyi.technology.pojo.TechnologyOperationParam;
-import com.ruoyi.technology.pojo.TechnologyParam;
-import com.ruoyi.technology.pojo.TechnologyRouting;
-import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
-import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import com.ruoyi.technology.mapper.*;
+import com.ruoyi.technology.pojo.*;
 import com.ruoyi.technology.service.TechnologyRoutingService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
@@ -31,6 +18,7 @@
 
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -126,7 +114,7 @@
         }
         List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList(
                 Wrappers.<TechnologyBomStructure>lambdaQuery()
-                        .eq(TechnologyBomStructure::getBomId, Long.valueOf(technologyRouting.getBomId()))
+                        .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId())
                         .isNotNull(TechnologyBomStructure::getOperationId)
                         .orderByAsc(TechnologyBomStructure::getId)
         );
@@ -135,16 +123,24 @@
         }
 
         // 鍚屼竴涓� BOM 涓彲鑳介噸澶嶅紩鐢ㄧ浉鍚屽伐搴忥紝杩欓噷鎸夐娆″嚭鐜伴『搴忓幓閲嶃��
-        Map<Long, TechnologyBomStructure> uniqueOperationMap = new LinkedHashMap<>();
+        Map<Long, TechnologyBomStructure> structureById = new HashMap<>();
         for (TechnologyBomStructure bomStructure : bomStructures) {
-            uniqueOperationMap.putIfAbsent(bomStructure.getOperationId(), bomStructure);
+            if (bomStructure != null && bomStructure.getId() != null) {
+                structureById.put(bomStructure.getId(), bomStructure);
+            }
+        }
+
+        Map<String, TechnologyBomStructure> uniqueOperationMap = new LinkedHashMap<>();
+        for (TechnologyBomStructure bomStructure : bomStructures) {
+            Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId());
+            uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
         }
 
         int dragSort = 1;
         for (TechnologyBomStructure bomStructure : uniqueOperationMap.values()) {
             TechnologyRoutingOperation routingOperation = new TechnologyRoutingOperation();
             routingOperation.setTechnologyRoutingId(technologyRouting.getId());
-            routingOperation.setProductModelId(technologyRouting.getProductModelId());
+            routingOperation.setProductModelId(resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId()));
             routingOperation.setTechnologyOperationId(bomStructure.getOperationId());
             routingOperation.setDragSort(dragSort++);
             routingOperation.setIsQuality(getOperationQuality(bomStructure.getOperationId()));
@@ -153,6 +149,31 @@
         }
     }
 
+    private String buildBomOperationDedupKey(TechnologyBomStructure bomStructure, Long outputProductModelId) {
+        Long operationId = bomStructure == null ? null : bomStructure.getOperationId();
+        Long parentId = bomStructure == null ? null : bomStructure.getParentId();
+        return operationId + "#"
+                + outputProductModelId + "#"
+                + parentId;
+    }
+
+    private Long resolveOutputProductModelId(TechnologyBomStructure bomStructure,
+                                             Map<Long, TechnologyBomStructure> structureById,
+                                             Long routingProductModelId) {
+        if (bomStructure == null) {
+            return routingProductModelId;
+        }
+        Long parentId = bomStructure.getParentId();
+        if (parentId == null) {
+            return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
+        }
+        TechnologyBomStructure parent = structureById.get(parentId);
+        if (parent != null && parent.getProductModelId() != null) {
+            return parent.getProductModelId();
+        }
+        return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
+    }
+
     private void syncRoutingOperationParams(Long technologyRoutingOperationId, Long technologyOperationId) {
         List<TechnologyOperationParam> operationParamList = technologyOperationParamMapper.selectList(
                 Wrappers.<TechnologyOperationParam>lambdaQuery()
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index 5a40417..ebafa7a 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -5,7 +5,7 @@
     <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
     <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOperationTask">
         <id column="id" property="id" />
-        <result column="technology_routing_operation_id" property="technologyRoutingOperationId" />
+        <result column="production_order_routing_operation_id" property="productionOrderRoutingOperationId" />
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
         <result column="work_order_no" property="workOrderNo" />
@@ -21,6 +21,43 @@
         <result column="dept_id" property="deptId" />
     </resultMap>
 
+    <select id="pageProductionOperationTask" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo">
+        select pot.*,
+               po.nps_no as npsNo,
+               p.product_name as productName,
+               pm.model as model,
+               pm.unit as unit,
+               poro.operation_name as operationName,
+        ROUND(pot.complete_quantity / pot.plan_quantity * 100, 2) AS completionStatus,
+        CASE
+            WHEN pot.work_order_no LIKE 'FG%' THEN '杩斿伐杩斾慨'
+            ELSE '姝e父'
+            END AS work_order_type
+        from production_operation_task pot
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 left join product p on pm.product_id = p.id
+        <where>
+            <if test="c != null and c.id != null">
+                and pot.id = #{c.id}
+            </if>
+            <if test="c != null and c.productionOrderId != null">
+                and pot.production_order_id = #{c.productionOrderId}
+            </if>
+            <if test="c != null and c.productionOrderRoutingOperationId != null">
+                and pot.production_order_routing_operation_id = #{c.productionOrderRoutingOperationId}
+            </if>
+            <if test="c != null and c.status != null">
+                and pot.status = #{c.status}
+            </if>
+            <if test="c != null and c.workOrderNo != null and c.workOrderNo != ''">
+                and pot.work_order_no like concat('%', #{c.workOrderNo}, '%')
+            </if>
+        </where>
+        order by pot.id desc
+    </select>
+
     <select id="selectTaskStatisticsByDate" resultType="com.ruoyi.home.dto.ProductionTaskStatisticsDto">
         select pot.id,
                pot.work_order_no,
@@ -30,17 +67,16 @@
                pot.actual_end_time as actualEndTime,
                pot.plan_quantity as planQuantity,
                ifnull(pot.complete_quantity, 0) as completeQuantity,
-               top2.name as processName,
+               poro.operation_name as processName,
                p.product_name as productName,
                pm.model,
                pm.unit,
                po.nps_no as productOrderNpsNo
         from production_operation_task pot
                  left join production_order po on pot.production_order_id = po.id
-                 left join product_model pm on po.product_model_id = pm.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
                  left join product p on pm.product_id = p.id
-                 left join technology_routing_operation tro on pot.technology_routing_operation_id = tro.id
-                 left join technology_operation top2 on tro.technology_operation_id = top2.id
         where date(pot.create_time) between #{startDate} and #{endDate}
         order by pot.create_time desc
     </select>
@@ -55,16 +91,15 @@
     </select>
 
     <select id="calculateProductionStatistics" resultType="com.ruoyi.home.dto.processDataProductionStatisticsDto">
-        select top2.name as processName,
+        select poro.operation_name as processName,
                sum(ifnull(ppi.input_quantity, 0)) as totalInput,
                sum(ifnull(ppo.scrap_qty, 0)) as totalScrap,
                sum(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0)) as totalOutput
         from production_product_output ppo
                  inner join production_product_main ppm on ppo.production_product_main_id = ppm.id
                  inner join production_operation_task pot on ppm.production_operation_task_id = pot.id
-                 inner join technology_routing_operation tro on pot.technology_routing_operation_id = tro.id
-                 inner join technology_operation top2 on tro.technology_operation_id = top2.id
-                 left join production_product_input ppi on ppi.production_product_main_id = ppm.id
+        left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+        left join production_product_input ppi on ppi.production_product_main_id = ppm.id
         <where>
             <if test="startDateTime != null">
                 and ppo.create_time &gt;= #{startDateTime}
@@ -76,13 +111,13 @@
                 and ppm.create_user = #{userId}
             </if>
             <if test="processIds != null and processIds.size() > 0">
-                and top2.id in
+                and poro.technology_operation_id in
                 <foreach collection="processIds" item="id" open="(" separator="," close=")">
                     #{id}
                 </foreach>
             </if>
         </where>
-        group by top2.id, top2.name
+        group by poro.technology_operation_id, poro.operation_name
     </select>
 
 </mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
index c799d3d..b279001 100644
--- a/src/main/resources/mapper/production/ProductionOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -45,6 +45,8 @@
         po.dept_id,
         po.plan_complete_time,
         po.status,
+        po_sales.salesContractNo,
+        po_sales.customerName,
         p.product_name as productName,
         pm.model as model,
         tr.process_route_code as processRouteCode,
@@ -53,6 +55,18 @@
 
     <sql id="ProductionOrderVoFrom">
         from production_order po
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName,
+                   group_concat(distinct sl2.project_name order by sl2.project_name separator ',') as projectName,
+                   min(sl2.delivery_date) as deliveryDate
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
                  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
@@ -131,9 +145,9 @@
 
     <select id="selectProgressOrders" resultType="com.ruoyi.home.dto.ProductionProgressOrderDto">
         select po.nps_no,
-               sl.sales_contract_no,
-               sl.project_name,
-               sl.customer_name,
+               po_sales.salesContractNo,
+               po_sales.projectName,
+               po_sales.customerName,
                p.product_name as productCategory,
                pm.model as specificationModel,
                tr.process_route_code as processRouteCode,
@@ -141,11 +155,22 @@
                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(sl.delivery_date, curdate()) as deliveryDaysDiff,
-               sl.delivery_date,
+               datediff(po_sales.deliveryDate, curdate()) as deliveryDaysDiff,
+               po_sales.deliveryDate as deliveryDate,
                false as isFh
         from production_order po
-                 left join sales_ledger sl on po.sales_ledger_id = sl.id
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName,
+                   group_concat(distinct sl2.project_name order by sl2.project_name separator ',') as projectName,
+                   min(sl2.delivery_date) as deliveryDate
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
                  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
diff --git a/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml b/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
index 4614ef7..a80fd02 100644
--- a/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
@@ -30,7 +30,7 @@
                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.technology_routing_operation_id = poro.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}
@@ -47,7 +47,7 @@
                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.technology_routing_operation_id = poro.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
diff --git a/src/main/resources/mapper/production/ProductionProductInputMapper.xml b/src/main/resources/mapper/production/ProductionProductInputMapper.xml
index 506ec70..fe88ae3 100644
--- a/src/main/resources/mapper/production/ProductionProductInputMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductInputMapper.xml
@@ -24,7 +24,7 @@
                  left join production_product_main ppm on ppi.production_product_main_id = ppm.id
                  left join production_operation_task pot on ppm.production_operation_task_id = pot.id
                  left join production_order po on pot.production_order_id = po.id
-                 left join product_model pm on po.product_model_id = pm.id
+                 left join product_model pm on ppi.product_model_id = pm.id
                  left join product p on pm.product_id = p.id
         <where>
             <if test="c.productNo != null and c.productNo != ''">
@@ -36,6 +36,9 @@
             <if test="c.productName != null and c.productName != ''">
                 and p.product_name like concat('%', #{c.productName}, '%')
             </if>
+            <if test="c.productMainId != null and c.productMainId != ''">
+                and ppm.id = #{c.productMainId}
+            </if>
         </where>
         order by ppi.create_time desc
     </select>
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index e9200b9..8dd4613 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -30,19 +30,27 @@
                p.product_name as productName,
                pm.model as productModelName,
                pm.unit,
-               sl.sales_contract_no as salesContractNo,
+               po_sales.salesContractNo,
                date(ppm.create_time) as schedulingDate,
                su.nick_name as schedulingUserName,
-               sl.customer_name as customerName,
-               top2.name as process
+               po_sales.customerName,
+               poro.operation_name as process
         from production_product_main ppm
                  left join production_operation_task pot on ppm.production_operation_task_id = pot.id
                  left join production_order po on pot.production_order_id = po.id
-                 left join sales_ledger sl on po.sales_ledger_id = sl.id
-                 left join product_model pm on po.product_model_id = pm.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
                  left join product p on pm.product_id = p.id
-                 left join technology_routing_operation tro on pot.technology_routing_operation_id = tro.id
-                 left join technology_operation top2 on tro.technology_operation_id = top2.id
                  left join sys_user su on ppm.create_user = su.user_id
                  left join production_product_output ppo on ppo.production_product_main_id = ppm.id
         <where>
@@ -53,10 +61,10 @@
                 and pot.work_order_no like concat('%', #{c.workOrderNo}, '%')
             </if>
             <if test="c.salesContractNo != null and c.salesContractNo != ''">
-                and sl.sales_contract_no like concat('%', #{c.salesContractNo}, '%')
+                and po_sales.salesContractNo like concat('%', #{c.salesContractNo}, '%')
             </if>
             <if test="c.customerName != null and c.customerName != ''">
-                and sl.customer_name like concat('%', #{c.customerName}, '%')
+                and po_sales.customerName like concat('%', #{c.customerName}, '%')
             </if>
             <if test="c.productName != null and c.productName != ''">
                 and p.product_name like concat('%', #{c.productName}, '%')
@@ -65,10 +73,13 @@
                 and pm.model like concat('%', #{c.productModelName}, '%')
             </if>
             <if test="c.process != null and c.process != ''">
-                and top2.name like concat('%', #{c.process}, '%')
+                and poro.operation_name like concat('%', #{c.process}, '%')
             </if>
             <if test="c.schedulingDate != null">
                 and date(ppm.create_time) = #{c.schedulingDate}
+            </if>
+            <if test="c.productMainId != null">
+                and ppm.id = #{c.productMainId}
             </if>
         </where>
         order by ppm.create_time desc
@@ -84,16 +95,15 @@
                p.product_name as productName,
                pm.model as productModelName,
                pm.unit,
-               top2.name as process,
+               poro.operation_name as process,
                ifnull(ppo.quantity, 0) as quantity,
                ifnull(ppo.scrap_qty, 0) as scrapQty
         from production_product_main ppm
                  left join production_operation_task pot on ppm.production_operation_task_id = pot.id
                  left join production_order po on pot.production_order_id = po.id
-                 left join product_model pm on po.product_model_id = pm.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
                  left join product p on pm.product_id = p.id
-                 left join technology_routing_operation tro on pot.technology_routing_operation_id = tro.id
-                 left join technology_operation top2 on tro.technology_operation_id = top2.id
                  left join production_product_output ppo on ppo.production_product_main_id = ppm.id
         order by ppm.create_time desc
     </select>
diff --git a/src/main/resources/mapper/production/ProductionProductOutputMapper.xml b/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
index 6dc9682..f31ca01 100644
--- a/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
@@ -23,7 +23,7 @@
                  left join production_product_main ppm on ppo.production_product_main_id = ppm.id
                  left join production_operation_task pot on ppm.production_operation_task_id = pot.id
                  left join production_order po on pot.production_order_id = po.id
-                 left join product_model pm on po.product_model_id = pm.id
+                 left join product_model pm on ppo.product_model_id = pm.id
         <where>
             <if test="c.productNo != null and c.productNo != ''">
                 and ppm.product_no like concat('%', #{c.productNo}, '%')
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index e5ce119..f252881 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -9,8 +9,8 @@
                 pl.purchase_contract_number as purchase_contract_no
             </when>
             <otherwise>
-                pwo.work_order_no,
-                sl.sales_contract_no
+                pot.work_order_no,
+                po_sales.sales_contract_no
             </otherwise>
         </choose>
         FROM
@@ -21,9 +21,17 @@
             </when>
             <otherwise>
                 LEFT JOIN production_product_main ppm ON qi.product_main_id = ppm.id
-                LEFT JOIN product_work_order pwo ON ppm.work_order_id = pwo.id
-                left join product_order po ON po.id = pwo.product_order_id
-                left join sales_ledger sl ON sl.id = po.sales_ledger_id
+                LEFT JOIN production_operation_task pot ON ppm.production_operation_task_id = pot.id
+                left join production_order po ON po.id = pot.production_order_id
+                left join (
+                    select po2.id as order_id,
+                           group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+                    from production_order po2
+                             left join production_plan pp2
+                                       on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                             left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+                    group by po2.id
+                ) po_sales ON po_sales.order_id = po.id
             </otherwise>
         </choose>
         WHERE
diff --git a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
index 5c20733..f326a66 100644
--- a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
+++ b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
@@ -24,11 +24,11 @@
         SELECT qts.*
         FROM quality_test_standard qts
                  left join quality_test_standard_binding qtsb on qtsb.test_standard_id = qts.id
-                 left join product_process pp on qts.process_id = pp.id
+                 left join technology_operation toper on qts.process_id = toper.id
         WHERE qtsb.product_id = #{productId}
           AND qts.inspect_type = #{inspectType}
         <if test="process!='' and process!=null">
-            and pp.name = #{process}
+            and toper.name = #{process}
         </if>
         order by qts.id desc
     </select>
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 251cf64..a1d05e9 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -29,10 +29,17 @@
         select slp.*
         from quality_inspect qi
                  left join production_product_main ppm on qi.product_main_id = ppm.id
-                 left join product_work_order pwo on ppm.work_order_id = pwo.id
-                 left join product_order po on pwo.product_order_id = po.id
-                 left join sales_ledger_product slp on po.sales_ledger_product_id = slp.id and slp.type = 1
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_plan pp_main
+                           on find_in_set(pp_main.id, replace(replace(replace(po.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                 left join sales_ledger_product slp on slp.sales_ledger_id = pp_main.sales_ledger_id
+            and slp.product_model_id = po.product_model_id
+            and slp.type = 1
         where qi.product_main_id = #{productMainId}
+          and slp.id is not null
+        order by slp.id desc
+        limit 1
 
 
     </select>

--
Gitblit v1.9.3