From 5e99b5312dd1560214719252d07fa4cc2b48082a Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 30 四月 2026 17:22:25 +0800
Subject: [PATCH] feat:1.订单调整 2.领料提示 3.退料添加入库记录

---
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                  |    1 
 src/main/java/com/ruoyi/production/controller/ProductionOrderController.java            |    6 ++
 src/main/java/com/ruoyi/production/pojo/ProductionOrder.java                            |    6 +
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java     |  102 ++++++++++++++++++++++-----------
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java         |    6 ++
 src/main/java/com/ruoyi/production/service/ProductionOrderService.java                  |    2 
 src/main/resources/mapper/production/ProductionOrderMapper.xml                          |    1 
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                         |   10 ++-
 src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java               |    3 +
 src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java                |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java |    9 +++
 11 files changed, 110 insertions(+), 39 deletions(-)

diff --git a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
index df0d011..6aecb29 100644
--- a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -12,7 +12,8 @@
     PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
     QUALITYINSPECT_STOCK_IN("6", "璐ㄦ-鍚堟牸鍏ュ簱"),
     DEFECTIVE_PASS("11", "涓嶅悎鏍�-璁╂鏀捐"),
-    RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱");
+    RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
+    PICK_RETURN_IN("20", "閿�鍞��璐�-鍚堟牸鍏ュ簱");
 
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index eeeaf19..1434e24 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -32,12 +32,13 @@
 
     /**
      * 涓嶅悎鏍煎叆搴�
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
@@ -48,12 +49,13 @@
 
     /**
      * 涓嶅悎鏍煎嚭搴�
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
+    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
@@ -80,12 +82,13 @@
 
     /**
      * 鍚堟牸鍑哄簱
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void substractStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
         stockInventoryDto.setRecordType(String.valueOf(recordType));
@@ -110,6 +113,7 @@
         }
 
     }
+
     public void deleteStockOutRecord(Long recordId, String recordType) {
         StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
                 .lambda().eq(StockOutRecord::getRecordId, recordId)
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 df444bd..decdc39 100644
--- a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
@@ -34,4 +34,7 @@
 
     @Schema(description = "鎶ュ伐浜哄憳鍚嶇О锛屽涓娇鐢ㄩ�楀彿鍒嗛殧")
     private String userNames;
+
+    @Schema(description = "鏄惁缁撴潫锛�")
+    private Boolean endOrder;
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
index 45a2805..53a22a7 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
@@ -89,4 +89,10 @@
     public R<ProductionOrderWorkOrderDetailVo> getWorkOrderReportInspectDetail(@PathVariable Long productionOrderId) {
         return R.ok(productionOrderService.getWorkOrderReportInspectDetail(productionOrderId));
     }
+
+    @Operation(summary = "鏇存柊璁㈠崟鐘舵��")
+    @PostMapping("/updateOrder")
+    public R updateOrder(@RequestBody ProductionOrderDto productionOrderDto) {
+        return R.ok(productionOrderService.updateOrder(productionOrderDto));
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
index c7415b5..1f882b1 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
@@ -74,6 +74,10 @@
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planCompleteTime;
 
-    @Schema(description = "鐘舵�侊紙1.寰呭紑濮� 2.杩涜涓� 3.宸插畬鎴� 4.宸插彇娑堬級")
+    @Schema(description = "鐘舵�侊紙1.寰呭紑濮� 2.杩涜涓� 3.宸插畬鎴� 4.宸插彇娑� 5.宸茬粨鏉燂級")
     private Integer status;
+
+    @Schema(description = "鏄惁缁撴潫锛�")
+    @TableField("is_end_order")
+    private Boolean endOrder;
 }
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
index ba6f11e..7e588dc 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
@@ -33,4 +33,6 @@
     List<ProductionOrderPickVo> pick(Long productionOrderId);
 
     ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(Long productionOrderId);
+
+    int updateOrder(ProductionOrderDto productionOrderDto);
 }
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 e202ec2..aad1350 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -22,7 +22,9 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
 import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
 import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
 import com.ruoyi.production.pojo.ProductionOperationTask;
 import com.ruoyi.production.service.ProductionOperationTaskService;
 import com.ruoyi.project.system.domain.SysUser;
@@ -45,6 +47,7 @@
 public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask> implements ProductionOperationTaskService {
 
     private final SysUserMapper sysUserMapper;
+    private final ProductionOrderMapper productionOrderMapper;
 
     private final FileUtil fileUtil;
 
@@ -75,6 +78,12 @@
             return null;
         }
         ProductionOperationTaskVo vo = BeanUtil.copyProperties(item, ProductionOperationTaskVo.class);
+        if (item.getProductionOrderId() != null) {
+            ProductionOrder productionOrder = productionOrderMapper.selectById(item.getProductionOrderId());
+            if (productionOrder != null) {
+                vo.setEndOrder(productionOrder.getEndOrder());
+            }
+        }
         fillUserNames(Collections.singletonList(vo));
         return vo;
     }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
index beedbb5..72a237e 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
@@ -3,6 +3,7 @@
 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.StockInQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
@@ -18,6 +19,7 @@
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
 import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.stock.service.StockInventoryService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -46,6 +48,7 @@
     private final ProductionOperationTaskMapper productionOperationTaskMapper;
     private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
     private final StockInventoryMapper stockInventoryMapper;
+    private final StockInventoryService stockInventoryService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -59,7 +62,7 @@
             List<String> batchNoList = resolveBatchNoList(resolvedDto);
             String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
             String storedBatchNo = formatBatchNoStorage(batchNoList);
-            subtractInventory(resolvedDto.getProductModelId(), inventoryBatchNo, resolvedDto.getPickQuantity(), rowNo);
+            subtractInventory(resolvedDto.getProductModelId(), storedBatchNo, resolvedDto.getPickQuantity(), rowNo);
 
             ProductionOrderPick orderPick = new ProductionOrderPick();
             orderPick.setProductionOrderId(resolvedDto.getProductionOrderId());
@@ -234,7 +237,7 @@
         List<String> batchNoList = resolveBatchNoList(dto);
         String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
         String storedBatchNo = formatBatchNoStorage(batchNoList);
-        subtractInventory(dto.getProductModelId(), inventoryBatchNo, dto.getPickQuantity(), rowNo);
+        subtractInventory(dto.getProductModelId(), storedBatchNo, dto.getPickQuantity(), rowNo);
 
         ProductionOrderPick orderPick = new ProductionOrderPick();
         orderPick.setProductionOrderId(dto.getProductionOrderId());
@@ -296,7 +299,7 @@
         List<String> batchNoList = resolveBatchNoList(dto);
         String inventoryBatchNo = batchNoList.isEmpty()
                 ? resolveInventoryBatchNoFromStored(oldPick.getBatchNo())
-                : pickInventoryBatchNo(batchNoList);
+                : formatBatchNoStorage(batchNoList);
         BigDecimal feedingQuantity = dto.getFeedingQuantity();
 
         subtractInventory(productModelId, inventoryBatchNo, feedingQuantity, rowNo);
@@ -388,13 +391,13 @@
         if (sameStockKey) {
             BigDecimal delta = newQuantity.subtract(oldQuantity);
             if (delta.compareTo(BigDecimal.ZERO) > 0) {
-                subtractInventory(newProductModelId, newBatchNo, delta, rowNo);
+                subtractInventory(newProductModelId, newStoredBatchNo, delta, rowNo);
             } else if (delta.compareTo(BigDecimal.ZERO) < 0) {
                 addInventory(oldProductModelId, oldBatchNo, delta.abs());
             }
         } else {
             addInventory(oldProductModelId, oldBatchNo, oldQuantity);
-            subtractInventory(newProductModelId, newBatchNo, newQuantity, rowNo);
+            subtractInventory(newProductModelId, newStoredBatchNo, newQuantity, rowNo);
         }
 
         oldPick.setProductModelId(newProductModelId);
@@ -457,22 +460,61 @@
     }
 
     private void subtractInventory(Long productModelId, String batchNo, BigDecimal quantity, int rowNo) {
-        StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo));
-        if (stockInventory == null) {
-            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欏搴斿簱瀛樹笉瀛樺湪");
+        BigDecimal deductQuantity = defaultDecimal(quantity);
+        if (deductQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
         }
-        BigDecimal availableQuantity = defaultDecimal(stockInventory.getQualitity())
-                .subtract(defaultDecimal(stockInventory.getLockedQuantity()));
-        if (quantity.compareTo(availableQuantity) > 0) {
-            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欏彲鐢ㄥ簱瀛樹笉瓒�");
+
+        List<String> batchNoList = parseBatchNoValue(batchNo);
+        if (batchNoList.isEmpty()) {
+            batchNoList = Collections.singletonList(null);
         }
-        StockInventoryDto stockInventoryDto = new StockInventoryDto();
-        stockInventoryDto.setProductModelId(productModelId);
-        stockInventoryDto.setBatchNo(batchNo);
-        stockInventoryDto.setQualitity(quantity);
-        int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
-        if (affected <= 0) {
-            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐墸鍑忓簱瀛樺け璐�");
+
+        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("棰嗘枡鍙敤搴撳瓨涓嶈冻锛屽彲鐢ㄥ簱瀛樹负" + formatQuantity(totalAvailableQuantity)
+                    + "锛岃繕宸�" + formatQuantity(shortQuantity));
+        }
+
+        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);
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setProductModelId(productModelId);
+            stockInventoryDto.setBatchNo(entry.getKey());
+            stockInventoryDto.setQualitity(currentDeductQuantity);
+            int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+            if (affected <= 0) {
+                throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐墸鍑忓簱瀛樺け璐�");
+            }
+            remainingQuantity = remainingQuantity.subtract(currentDeductQuantity);
+        }
+
+        if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐墸鍑忓簱瀛樺け璐ワ紝鍓╀綑寰呮墸鍑忔暟閲忎负" + formatQuantity(remainingQuantity));
         }
     }
 
@@ -481,25 +523,13 @@
         if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
             return;
         }
-        StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo));
-        if (stockInventory == null) {
-            StockInventory newStockInventory = new StockInventory();
-            newStockInventory.setProductModelId(productModelId);
-            newStockInventory.setBatchNo(batchNo);
-            newStockInventory.setQualitity(addQuantity);
-            newStockInventory.setLockedQuantity(BigDecimal.ZERO);
-            newStockInventory.setVersion(1);
-            stockInventoryMapper.insert(newStockInventory);
-            return;
-        }
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setProductModelId(productModelId);
         stockInventoryDto.setBatchNo(batchNo);
         stockInventoryDto.setQualitity(addQuantity);
-        int affected = stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
-        if (affected <= 0) {
-            throw new ServiceException("搴撳瓨鍥為��澶辫触锛屼骇鍝佽鏍糏D=" + productModelId);
-        }
+        stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PICK_RETURN_IN.getCode()));
+        stockInventoryDto.setRecordId(0L);
+        stockInventoryService.addStockInRecordOnly(stockInventoryDto);
     }
 
     private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) {
@@ -882,4 +912,8 @@
     private BigDecimal defaultDecimal(BigDecimal value) {
         return value == null ? BigDecimal.ZERO : value;
     }
+
+    private String formatQuantity(BigDecimal value) {
+        return defaultDecimal(value).stripTrailingZeros().toPlainString();
+    }
 }
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 da921b9..90c5e5c 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -915,4 +915,10 @@
         }
         return new ArrayList<>(mergedPickMap.values());
     }
+
+    @Override
+    public int updateOrder(ProductionOrderDto productionOrderDto) {
+        productionOrderDto.setStatus(5);
+        return baseMapper.updateById(productionOrderDto);
+    }
 }
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index 31bf61b..0ccb06f 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -24,6 +24,7 @@
     <select id="pageProductionOperationTask" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo">
         select pot.*,
                po.nps_no as npsNo,
+               po.is_end_order as endOrder,
                p.product_name as productName,
                pm.model as model,
                pm.unit as unit,
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
index deb2960..2ea7d33 100644
--- a/src/main/resources/mapper/production/ProductionOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -49,6 +49,7 @@
         po_sales.customerName,
         p.product_name as productName,
         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

--
Gitblit v1.9.3