From 6d3a76f894052209cad136ec9bff6ddcd43fc4e7 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 20 四月 2026 17:55:48 +0800
Subject: [PATCH] feat: 扫码时做限制,若采购台账已全部质检入库,APP扫码 入库时提示已入库。并且联动质检

---
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java     |  124 +++++++++++
 src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java                    |    5 
 src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java                     |    7 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java    |  186 ++++++++++++++++
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                      |    4 
 src/main/java/com/ruoyi/common/enums/StockInUnQualifiedRecordTypeEnum.java      |    4 
 src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml                     |   15 +
 doc/河南鹤壁天沐钢化玻璃厂.sql                                                             |   18 +
 src/main/resources/mapper/quality/QualityInspectMapper.xml                      |    2 
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java        |   12 +
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java   |  127 +++++++++++
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java |   22 +
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java         |   17 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                    |    2 
 src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java     |   10 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java          |   49 ++++
 src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java            |   13 
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java       |   10 
 src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java        |    5 
 src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java                       |    5 
 20 files changed, 599 insertions(+), 38 deletions(-)

diff --git "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql" "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
index 17e9e2a..65026b2 100644
--- "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
+++ "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
@@ -138,4 +138,20 @@
 
 ALTER TABLE `sales_ledger_product`
     ADD COLUMN `unqualified_stocked_quantity` decimal(18, 2) DEFAULT '0.00' COMMENT '涓嶅悎鏍煎叆搴撴暟閲�' AFTER `stocked_quantity`,
-    ADD COLUMN `unqualified_shipped_quantity` decimal(18, 2) DEFAULT '0.00' COMMENT '涓嶅悎鏍煎嚭搴撴暟閲�' AFTER `shipped_quantity`;
\ No newline at end of file
+    ADD COLUMN `unqualified_shipped_quantity` decimal(18, 2) DEFAULT '0.00' COMMENT '涓嶅悎鏍煎嚭搴撴暟閲�' AFTER `shipped_quantity`;
+
+ALTER TABLE `product-inventory-management-hbtmblc`.`purchase_ledger`
+    ADD COLUMN `stock_status` tinyint(1) NULL DEFAULT 0 COMMENT '鍏ュ簱鐘舵�侊細0-鏈叆搴擄紝1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�' AFTER `approve_user_ids`;
+
+ALTER TABLE `product-inventory-management-hbtmblc`.`sales_ledger_product`
+    MODIFY COLUMN `actual_piece_area` decimal(20, 4) NULL DEFAULT NULL COMMENT '瀹為檯鍗曠墖闈㈢Н(銕�)' AFTER `is_checked`,
+    MODIFY COLUMN `actual_total_area` decimal(20, 4) NULL DEFAULT NULL COMMENT '瀹為檯鎬婚潰绉�(銕�)' AFTER `actual_piece_area`,
+    MODIFY COLUMN `settle_piece_area` decimal(20, 4) NULL DEFAULT NULL COMMENT '缁撶畻鍗曠墖闈㈢Н(銕�)' AFTER `actual_total_area`,
+    MODIFY COLUMN `settle_total_area` decimal(20, 4) NULL DEFAULT NULL COMMENT '缁撶畻鎬婚潰绉�(銕�)' AFTER `settle_piece_area`,
+    MODIFY COLUMN `width` decimal(20, 4) NULL DEFAULT NULL COMMENT '瀹�' AFTER `settle_total_area`,
+    MODIFY COLUMN `height` decimal(20, 4) NULL DEFAULT NULL COMMENT '楂�' AFTER `width`,
+    MODIFY COLUMN `perimeter` decimal(20, 4) NULL DEFAULT NULL COMMENT '鍛ㄩ暱' AFTER `remark`,
+    MODIFY COLUMN `heavy_box` decimal(20, 4) NULL DEFAULT NULL COMMENT '閲嶇' AFTER `perimeter`;
+
+ALTER TABLE `product-inventory-management-hbtmblc`.`quality_unqualified`
+    ADD COLUMN `product_model_id` bigint NULL COMMENT '浜у搧瑙勬牸ID' AFTER `inspect_id`;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
index d8802c7..f9b6d0f 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -13,7 +13,6 @@
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.device.mapper.DeviceRepairMapper;
 import com.ruoyi.device.pojo.DeviceRepair;
@@ -39,6 +38,7 @@
 import org.springframework.util.CollectionUtils;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -208,16 +208,26 @@
                     purchaseLedger.setApprovalStatus(3);
                     List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
                             .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2));
+                    boolean hasCheckedProduct = false;
                     for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
                         // 璐ㄦ
                         if (salesLedgerProduct.getIsChecked()) {
+                            hasCheckedProduct = true;
                             purchaseLedgerServiceImpl.addQualityInspect(purchaseLedger, salesLedgerProduct);
                         }else {
                             //鐩存帴鍏ュ簱
                             stockUtils.addStock(null, salesLedgerProduct.getId(), salesLedgerProduct.getProductModelId(),
                                     salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), salesLedgerProduct.getId());
+                            BigDecimal oldStocked = salesLedgerProduct.getStockedQuantity() == null ? BigDecimal.ZERO : salesLedgerProduct.getStockedQuantity();
+                            BigDecimal orderQty = salesLedgerProduct.getQuantity() == null ? BigDecimal.ZERO : salesLedgerProduct.getQuantity();
+                            BigDecimal newStocked = oldStocked.add(orderQty);
+                            salesLedgerProduct.setStockedQuantity(newStocked);
+                            salesLedgerProduct.setProductStockStatus(2);
+                            salesLedgerProduct.fillRemainingQuantity();
+                            salesLedgerProductMapper.updateById(salesLedgerProduct);
                         }
                     }
+                    purchaseLedger.setStockStatus(hasCheckedProduct ? 0 : 2);
                 } else if (status.equals(3)) {
                     // 鎷掔粷
                     purchaseLedger.setApprovalStatus(4);
diff --git a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
index 5349ab7..95fbedc 100644
--- a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -7,14 +7,13 @@
 public enum StockInQualifiedRecordTypeEnum implements BaseEnum<String> {
 
     CUSTOMIZATION_STOCK_IN("0", "鍚堟牸鑷畾涔夊叆搴�"),
-    PRODUCTION_REPORT_STOCK_IN("2", "鐢熶骇鎶ュ伐-鍏ュ簱"),
     PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
     QUALITYINSPECT_STOCK_IN("6", "璐ㄦ-鍚堟牸鍏ュ簱"),
     DEFECTIVE_PASS("11", "涓嶅悎鏍�-璁╂鏀捐"),
-    RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
     SALE_STOCK_IN("15", "閿�鍞鍗�-鍚堟牸鍏ュ簱"),
     SALE_SCAN_STOCK_IN("17", "閿�鍞鍗曟壂鐮�-鍚堟牸鍏ュ簱"),
-    PURCHASE_SCAN_STOCK_IN("18", "閲囪喘璁㈠崟鎵爜-鍚堟牸鍏ュ簱");
+    PURCHASE_SCAN_STOCK_IN("18", "閲囪喘璁㈠崟鎵爜-鍚堟牸鍏ュ簱"),
+    PURCHASE_SCAN_QUALITY_STOCK_IN("19", "鎵爜鍏ュ簱璐ㄦ-鍚堟牸鍏ュ簱");
 
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/common/enums/StockInUnQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockInUnQualifiedRecordTypeEnum.java
index 1c6db55..8655be8 100644
--- a/src/main/java/com/ruoyi/common/enums/StockInUnQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockInUnQualifiedRecordTypeEnum.java
@@ -11,9 +11,9 @@
     PRODUCTION_SCRAP("5", "鐢熶骇鎶ュ伐-鎶ュ簾"),
     CUSTOMIZATION_UNSTOCK_IN("9", "涓嶅悎鏍艰嚜瀹氫箟鍏ュ簱"),
     QUALITYINSPECT_UNSTOCK_IN("12", "璐ㄦ-涓嶅悎鏍煎叆搴�"),
-    RETURN_UNSTOCK_IN("15", "閿�鍞��璐�-涓嶅悎鏍煎叆搴�"),
     SALES_SCAN_UNSTOCK_IN("16", "閿�鍞鍗曟壂鐮�-涓嶅悎鏍煎叆搴�"),
-    PURCHASE_SCAN_UNSTOCK_IN("19", "閲囪喘璁㈠崟鎵爜-涓嶅悎鏍煎叆搴�");
+    PURCHASE_SCAN_UNSTOCK_IN("19", "閲囪喘璁㈠崟鎵爜-涓嶅悎鏍煎叆搴�"),
+    PURCHASE_SCAN_QUALITY_UNSTOCK_IN("20", "鎵爜鍏ュ簱璐ㄦ-涓嶅悎鏍煎叆搴�");
 
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
index c8ea3f5..ec6ddc0 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -193,6 +193,13 @@
     private String paymentMethod;
     @ApiModelProperty("瀹℃壒鐘舵��")
     private Integer approvalStatus;
+
+    @ApiModelProperty("閲囪喘璁㈠崟鍏ュ簱鐘舵�侊細0-鏈叆搴擄紝1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�")
+    private Integer stockStatus;
+
+    @ApiModelProperty("閲囪喘璁㈠崟浜у搧鍏ュ簱鐘舵�侊細0-鏈叆搴擄紝1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�")
+    private Integer productStockStatus;
+
     @ApiModelProperty(value = "妯℃澘鍚嶇О")
     private String templateName;
     @ApiModelProperty(value = "瀹℃壒浜篿d")
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
index e01db26..90ffc91 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -159,4 +159,9 @@
     @ApiModelProperty(value = "瀹℃壒浜篿d")
     private String approveUserIds;
 
+    /**
+     * 鍏ュ簱鐘舵�侊細0-鏈叆搴擄紝1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�
+     */
+    private Integer stockStatus;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index 3e3bafc..935cb78 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -141,6 +141,8 @@
     @Autowired
     private QualityInspectMapper qualityInspectMapper;
     @Autowired
+    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
+    @Autowired
     private CommonFileServiceImpl commonFileService;
     @Autowired
     private QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
@@ -212,6 +214,7 @@
         purchaseLedger.setRecorderName(sysUser.getNickName());
         purchaseLedger.setPhoneNumber(sysUser.getPhonenumber());
         purchaseLedger.setApprovalStatus(1);
+        purchaseLedger.setStockStatus(0);
         // 3. 鏂板鎴栨洿鏂颁富琛�
         if (purchaseLedger.getId() == null) {
             purchaseLedgerMapper.insert(purchaseLedger);
@@ -336,6 +339,7 @@
         if (!updateList.isEmpty()) {
             for (SalesLedgerProduct product : updateList) {
                 product.setType(type);
+                product.setProductStockStatus(calculateProductStockStatus(product));
                 product.fillRemainingQuantity();
                 salesLedgerProductMapper.updateById(product);
             }
@@ -351,6 +355,7 @@
                 salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
                 salesLedgerProduct.setFutureTicketsAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProduct.setPendingTicketsTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
+                salesLedgerProduct.setProductStockStatus(calculateProductStockStatus(salesLedgerProduct));
                 salesLedgerProduct.fillRemainingQuantity();
                 salesLedgerProductMapper.insert(salesLedgerProduct);
             }
@@ -481,7 +486,8 @@
                                         .in(StockInRecord::getSalesLedgerProductId, productIds)
                                         .or(q -> q.in(StockInRecord::getRecordId, productIds)
                                                 .in(StockInRecord::getRecordType, Arrays.asList(
-                                                        StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_UNSTOCK_IN.getCode()
+                                                        StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_UNSTOCK_IN.getCode(),
+                                                        StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_QUALITY_UNSTOCK_IN.getCode()
                                                 ))))
                                 .select(StockInRecord::getId))
                         .stream().map(StockInRecord::getId).collect(Collectors.toList());
@@ -567,7 +573,7 @@
         productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
                 .eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType());
         List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
-        products.forEach(SalesLedgerProduct::fillRemainingQuantity);
+        applyQualityInboundToProducts(purchaseLedger.getId(), products);
 
         // 3.鏌ヨ涓婁紶鏂囦欢
         LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
@@ -837,7 +843,7 @@
         productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
                 .eq(SalesLedgerProduct::getType, 2);
         List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
-        products.forEach(SalesLedgerProduct::fillRemainingQuantity);
+        applyQualityInboundToProducts(purchaseLedger.getId(), products);
 
         // 4. 杞崲 DTO
         PurchaseLedgerDto resultDto = new PurchaseLedgerDto();
@@ -908,7 +914,57 @@
             if (dbProduct.getProductModelId() == null) {
                 throw new ServiceException("鍏ュ簱澶辫触,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
             }
+            BigDecimal orderQty = dbProduct.getQuantity() == null ? BigDecimal.ZERO : dbProduct.getQuantity();
+            if (orderQty.compareTo(BigDecimal.ZERO) <= 0) {
+                throw new ServiceException("鍏ュ簱澶辫触,閲囪喘浜у搧鏁伴噺寮傚父");
+            }
+            //  闇�瑕佽川妫�锛氭壂鐮佸叆搴撹繘鍏ュ師鏉愭枡妫�楠岋紝涓嶇洿鎺ュ叆鍚堟牸搴撳瓨
+            if (Boolean.TRUE.equals(dbProduct.getIsChecked())) {
+                //  瀛樺湪鏈�氳繃/鏈鐞嗙殑鍘熸潗鏂欐楠屽崟锛屽垯绂佹缁х画鎵爜鍏ュ簱
+                Long pendingInspectCount = qualityInspectMapper.selectCount(new LambdaQueryWrapper<QualityInspect>()
+                        .eq(QualityInspect::getInspectType, 0)
+                        .eq(QualityInspect::getPurchaseLedgerId, purchaseId)
+                        .eq(QualityInspect::getProductModelId, dbProduct.getProductModelId())
+                        .and(w -> w
+                                .isNull(QualityInspect::getInspectState)
+                                .or(q0 -> q0.eq(QualityInspect::getInspectState, 0))
+                                // inspect_state=1 涔熻涓衡�滄湭澶勭悊鈥�
+                                .or(q1 -> q1.eq(QualityInspect::getInspectState, 1)
+                                        .isNull(QualityInspect::getCheckResult))));
+                if (pendingInspectCount != null && pendingInspectCount > 0) {
+                    throw new ServiceException("鍏ュ簱澶辫触,瀛樺湪鏈�氳繃鎴栨湭澶勭悊鐨勮川妫�璁板綍,璇峰厛澶勭悊鍚庡啀鎵爜鍏ュ簱");
+                }
+                //  闇�瑕佽川妫�鏃讹紝鎸夆�滃緟妫�/宸插悎鏍尖�濈殑妫�楠屾暟閲忔帶鍒舵壂鐮佷笂闄�
+                BigDecimal inspectQty = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                                .eq(QualityInspect::getInspectType, 0)
+                                .eq(QualityInspect::getPurchaseLedgerId, purchaseId)
+                                .eq(QualityInspect::getProductModelId, dbProduct.getProductModelId())
+                                .and(w -> w
+                                        .isNull(QualityInspect::getInspectState)
+                                        .or(q0 -> q0.eq(QualityInspect::getInspectState, 0))
+                                        .or(q1 -> q1.eq(QualityInspect::getInspectState, 1)
+                                                .and(r -> r.isNull(QualityInspect::getCheckResult)
+                                                        .or()
+                                                        .eq(QualityInspect::getCheckResult, "鍚堟牸")))))
+                        .stream()
+                        .map(QualityInspect::getQuantity)
+                        .filter(Objects::nonNull)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+                if (inspectQty.add(inboundThisLine).compareTo(orderQty) > 0) {
+                    throw new ServiceException("鍏ュ簱澶辫触,鎵爜鍚堟牸鍏ュ簱鏁伴噺涓嶈兘瓒呰繃閲囪喘浜у搧鏁伴噺");
+                }
+                SalesLedgerProduct scanInspectProduct = new SalesLedgerProduct();
+                BeanUtils.copyProperties(dbProduct, scanInspectProduct);
+                scanInspectProduct.setQuantity(inboundThisLine);
+                addQualityInspect(purchaseLedger, scanInspectProduct);
+                continue;
+            }
+
+            // 涓嶉渶瑕佽川妫�锛氭壂鐮佺洿鎺ュ叆搴擄紙鍏佽澶氬叆搴擄紝涓嶅仛涓婇檺闄愬埗锛�
             BigDecimal oldStocked = dbProduct.getStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getStockedQuantity();
+            if (oldStocked.add(inboundThisLine).compareTo(orderQty) > 0) {
+                throw new ServiceException("鍏ュ簱澶辫触,鎵爜鍚堟牸鍏ュ簱鏁伴噺涓嶈兘瓒呰繃閲囪喘浜у搧鏁伴噺");
+            }
             BigDecimal newStocked = oldStocked.add(inboundThisLine);
 
             StockInventoryDto stockInventoryDto = new StockInventoryDto();
@@ -920,7 +976,6 @@
             stockInventoryDto.setSalesLedgerProductId(dbProduct.getId());
             stockInventoryService.addstockInventory(stockInventoryDto);
 
-            BigDecimal orderQty = dbProduct.getQuantity() == null ? BigDecimal.ZERO : dbProduct.getQuantity();
             int lineStockStatus;
             if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
                 lineStockStatus = 0;
@@ -934,6 +989,7 @@
             dbProduct.fillRemainingQuantity();
             salesLedgerProductMapper.updateById(dbProduct);
         }
+        refreshPurchaseLedgerStockStatus(purchaseLedger.getId());
     }
 
     @Override
@@ -1051,7 +1107,28 @@
                 throw new ServiceException("涓嶅悎鏍煎叆搴撳け璐�,浜у搧瑙勬牸鏈淮鎶�,鏃犳硶鍏ュ簱");
             }
             stockUtils.addUnStock(null, null, dbProduct.getProductModelId(), inboundThisLine,
-                    StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_UNSTOCK_IN.getCode(), dbProduct.getId());
+                    Boolean.TRUE.equals(dbProduct.getIsChecked())
+                            ? StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_QUALITY_UNSTOCK_IN.getCode()
+                            : StockInUnQualifiedRecordTypeEnum.PURCHASE_SCAN_UNSTOCK_IN.getCode(),
+                    dbProduct.getId());
+
+            // 閲囪喘涓嶅悎鏍煎叆搴撳悗锛岃嚜鍔ㄨ繘鍏ヤ笉鍚堟牸绠$悊锛岀瓑寰呯敤鎴峰鐞�
+            QualityUnqualified qualityUnqualified = new QualityUnqualified();
+            qualityUnqualified.setInspectType(0); // 鍘熸潗鏂欎笉鍚堟牸
+            qualityUnqualified.setInspectState(0); // 寰呭鐞�
+            qualityUnqualified.setCheckTime(new Date());
+            LoginUser loginUser = SecurityUtils.getLoginUser();
+            if (loginUser != null && loginUser.getUser() != null) {
+                qualityUnqualified.setCheckName(loginUser.getUser().getNickName());
+            }
+            qualityUnqualified.setProductId(dbProduct.getProductId());
+            qualityUnqualified.setProductModelId(dbProduct.getProductModelId());
+            qualityUnqualified.setProductName(dbProduct.getProductCategory());
+            qualityUnqualified.setModel(dbProduct.getSpecificationModel());
+            qualityUnqualified.setUnit(dbProduct.getUnit());
+            qualityUnqualified.setQuantity(inboundThisLine);
+            qualityUnqualified.setDefectivePhenomena("閲囪喘璁㈠崟鎵爜涓嶅悎鏍煎叆搴擄紝寰呭鐞�");
+            qualityUnqualifiedMapper.insert(qualityUnqualified);
 
             BigDecimal oldUnStocked = dbProduct.getUnqualifiedStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedStockedQuantity();
             dbProduct.setUnqualifiedStockedQuantity(oldUnStocked.add(inboundThisLine));
@@ -1124,6 +1201,105 @@
         }
     }
 
+    private void applyQualityInboundToProducts(Long purchaseLedgerId, List<SalesLedgerProduct> products) {
+        if (CollectionUtils.isEmpty(products)) {
+            return;
+        }
+        Map<Long, BigDecimal> qualityInboundQtyByLine = getQualifiedInspectInboundQtyByLine(purchaseLedgerId);
+        for (SalesLedgerProduct product : products) {
+            product.fillRemainingQuantity();
+            if (!Boolean.TRUE.equals(product.getIsChecked())) {
+                continue;
+            }
+            BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+            BigDecimal scanInboundQty = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
+            BigDecimal qualityInboundQty = qualityInboundQtyByLine.getOrDefault(product.getId(), BigDecimal.ZERO);
+            BigDecimal totalQualifiedInbound = qualityInboundQty.add(scanInboundQty);
+            BigDecimal remainingInbound = orderQty.subtract(totalQualifiedInbound);
+            product.setRemainingQuantity(remainingInbound.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : remainingInbound);
+            BigDecimal shippedQty = product.getShippedQuantity() == null ? BigDecimal.ZERO : product.getShippedQuantity();
+            BigDecimal remainingShipped = totalQualifiedInbound.subtract(shippedQty);
+            product.setRemainingShippedQuantity(remainingShipped.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : remainingShipped);
+        }
+    }
+
+    private Map<Long, BigDecimal> getQualifiedInspectInboundQtyByLine(Long purchaseLedgerId) {
+        Map<Long, BigDecimal> qualityInboundByModel = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                        .eq(QualityInspect::getInspectType, 0)
+                        .eq(QualityInspect::getPurchaseLedgerId, purchaseLedgerId)
+                        .eq(QualityInspect::getInspectState, 1)
+                        .eq(QualityInspect::getCheckResult, "鍚堟牸"))
+                .stream()
+                .filter(qualityInspect -> qualityInspect.getProductModelId() != null && qualityInspect.getQuantity() != null)
+                .collect(Collectors.groupingBy(QualityInspect::getProductModelId,
+                        Collectors.reducing(BigDecimal.ZERO, QualityInspect::getQuantity, BigDecimal::add)));
+        if (qualityInboundByModel.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<SalesLedgerProduct> purchaseProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerId)
+                .eq(SalesLedgerProduct::getType, PURCHASE.getCode()));
+        Map<Long, BigDecimal> qualityInboundByLine = new HashMap<>();
+        for (SalesLedgerProduct product : purchaseProducts) {
+            if (product.getId() == null || product.getProductModelId() == null) {
+                continue;
+            }
+            qualityInboundByLine.put(product.getId(), qualityInboundByModel.getOrDefault(product.getProductModelId(), BigDecimal.ZERO));
+        }
+        return qualityInboundByLine;
+    }
+
+    private void refreshPurchaseLedgerStockStatus(Long purchaseLedgerId) {
+        if (purchaseLedgerId == null) {
+            return;
+        }
+        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerId)
+                .eq(SalesLedgerProduct::getType, PURCHASE.getCode()));
+        if (CollectionUtils.isEmpty(products)) {
+            return;
+        }
+        Map<Long, BigDecimal> qualityInboundQtyByLine = getQualifiedInspectInboundQtyByLine(purchaseLedgerId);
+        boolean allInbound = true;
+        boolean anyInbound = false;
+        for (SalesLedgerProduct product : products) {
+            BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+            BigDecimal scanInboundQty = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
+            BigDecimal qualityInboundQty = qualityInboundQtyByLine.getOrDefault(product.getId(), BigDecimal.ZERO);
+            BigDecimal totalInboundQty = scanInboundQty.add(qualityInboundQty);
+            if (totalInboundQty.compareTo(BigDecimal.ZERO) > 0) {
+                anyInbound = true;
+            }
+            if (totalInboundQty.compareTo(orderQty) < 0) {
+                allInbound = false;
+            }
+        }
+        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerId);
+        if (purchaseLedger == null) {
+            return;
+        }
+        int targetStockStatus = allInbound ? 2 : (anyInbound ? 1 : 0);
+        if (!Objects.equals(purchaseLedger.getStockStatus(), targetStockStatus)) {
+            purchaseLedger.setStockStatus(targetStockStatus);
+            purchaseLedgerMapper.updateById(purchaseLedger);
+        }
+    }
+
+    private Integer calculateProductStockStatus(SalesLedgerProduct product) {
+        if (product == null) {
+            return 0;
+        }
+        BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+        BigDecimal stockedQty = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
+        if (stockedQty.compareTo(BigDecimal.ZERO) <= 0) {
+            return 0;
+        }
+        if (orderQty.compareTo(BigDecimal.ZERO) > 0 && stockedQty.compareTo(orderQty) < 0) {
+            return 1;
+        }
+        return 2;
+    }
+
     /**
      * 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
      */
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
index d2f8e88..4d80c5a 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
@@ -63,6 +63,11 @@
     private Long productId;
 
     /**
+     * 浜у搧瑙勬牸ID
+     */
+    private Long productModelId;
+
+    /**
      * 浜у搧鍚嶇О
      */
     @Excel(name = "浜у搧鍚嶇О")
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index 8a1e066..28a76e0 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -2,6 +2,7 @@
 
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,7 +10,6 @@
 import com.deepoove.poi.XWPFTemplate;
 import com.deepoove.poi.config.Configure;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
@@ -23,7 +23,10 @@
 import com.ruoyi.quality.pojo.QualityUnqualified;
 import com.ruoyi.quality.service.IQualityInspectParamService;
 import com.ruoyi.quality.service.IQualityInspectService;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
@@ -32,9 +35,11 @@
 import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.math.BigDecimal;
 import java.net.URLEncoder;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @AllArgsConstructor
@@ -52,6 +57,8 @@
     private QualityUnqualifiedMapper qualityUnqualifiedMapper;
 
     private SalesLedgerProductMapper salesLedgerProductMapper;
+
+    private PurchaseLedgerMapper purchaseLedgerMapper;
 
     private ProcurementRecordService procurementRecordService;
 
@@ -99,9 +106,13 @@
         } else {
             //鍚堟牸鐩存帴鍏ュ簱
             stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
+            // 閲囪喘鍘熸潗鏂欐楠岋細鍚堟牸鍏ュ簱鍚庡悓姝ュ埌閲囪喘浜у搧鈥滃凡鍏ュ簱鏁伴噺鈥濓紝涓庢壂鐮佸叆搴撳叡鐢ㄤ竴浠芥暟鎹彛寰�
+            syncQualifiedInboundToPurchaseProducts(qualityInspect);
         }
         qualityInspect.setInspectState(1);//宸叉彁浜�
-        return qualityInspectMapper.updateById(qualityInspect);
+        int updated = qualityInspectMapper.updateById(qualityInspect);
+        refreshPurchaseLedgerStockStatusByInspect(qualityInspect.getPurchaseLedgerId());
+        return updated;
     }
 
     /*鐢熸垚妫�楠屾姤鍛�*/
@@ -193,5 +204,114 @@
 
     }
 
+    private void refreshPurchaseLedgerStockStatusByInspect(Long purchaseLedgerId) {
+        if (purchaseLedgerId == null) {
+            return;
+        }
+        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedgerId)
+                .eq(SalesLedgerProduct::getType, 2));
+        if (products == null || products.isEmpty()) {
+            return;
+        }
+        boolean allInbound = true;
+        boolean anyInbound = false;
+        for (SalesLedgerProduct product : products) {
+            BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
+            BigDecimal totalInboundQty = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
+            if (totalInboundQty.compareTo(BigDecimal.ZERO) > 0) {
+                anyInbound = true;
+            }
+            if (totalInboundQty.compareTo(orderQty) < 0) {
+                allInbound = false;
+            }
+        }
+        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerId);
+        if (purchaseLedger == null) {
+            return;
+        }
+        int targetStockStatus = allInbound ? 2 : (anyInbound ? 1 : 0);
+        if (!Objects.equals(purchaseLedger.getStockStatus(), targetStockStatus)) {
+            purchaseLedger.setStockStatus(targetStockStatus);
+            purchaseLedgerMapper.updateById(purchaseLedger);
+        }
+    }
+
+    private void syncQualifiedInboundToPurchaseProducts(QualityInspect qualityInspect) {
+        if (qualityInspect == null) {
+            return;
+        }
+        if (!Objects.equals(qualityInspect.getInspectType(), 0) || qualityInspect.getPurchaseLedgerId() == null) {
+            return;
+        }
+        if (qualityInspect.getProductModelId() == null || qualityInspect.getQuantity() == null) {
+            return;
+        }
+        BigDecimal inboundQty = qualityInspect.getQuantity();
+        if (inboundQty.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+
+        List<SalesLedgerProduct> lines = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, qualityInspect.getPurchaseLedgerId())
+                .eq(SalesLedgerProduct::getType, 2)
+                .eq(SalesLedgerProduct::getProductModelId, qualityInspect.getProductModelId())
+                .eq(SalesLedgerProduct::getIsChecked, true)
+                .orderByAsc(SalesLedgerProduct::getId));
+        if (lines == null || lines.isEmpty()) {
+            return;
+        }
+
+        BigDecimal remaining = inboundQty;
+        SalesLedgerProduct fallbackLine = null;
+        for (SalesLedgerProduct line : lines) {
+            if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+                break;
+            }
+            BigDecimal orderQty = line.getQuantity() == null ? BigDecimal.ZERO : line.getQuantity();
+            BigDecimal stocked = line.getStockedQuantity() == null ? BigDecimal.ZERO : line.getStockedQuantity();
+            BigDecimal canFill = orderQty.subtract(stocked);
+            if (canFill.compareTo(BigDecimal.ZERO) <= 0) {
+                fallbackLine = line;
+                continue;
+            }
+            BigDecimal add = canFill.min(remaining);
+            BigDecimal newStocked = stocked.add(add);
+            int status;
+            if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
+                status = 0;
+            } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
+                status = 1;
+            } else {
+                status = 2;
+            }
+            line.setStockedQuantity(newStocked);
+            line.setProductStockStatus(status);
+            line.fillRemainingQuantity();
+            salesLedgerProductMapper.updateById(line);
+            remaining = remaining.subtract(add);
+            fallbackLine = line;
+        }
+
+        // 鍏佽澶氬叆搴擄細鑻ヤ粛鏈夊墿浣欙紝绱鍒版渶鍚庝竴琛岋紝纭繚 remaining_shipped_quantity 鑳藉悓姝ュ闀�
+        if (remaining.compareTo(BigDecimal.ZERO) > 0 && fallbackLine != null) {
+            BigDecimal orderQty = fallbackLine.getQuantity() == null ? BigDecimal.ZERO : fallbackLine.getQuantity();
+            BigDecimal stocked = fallbackLine.getStockedQuantity() == null ? BigDecimal.ZERO : fallbackLine.getStockedQuantity();
+            BigDecimal newStocked = stocked.add(remaining);
+            int status;
+            if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
+                status = 0;
+            } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
+                status = 1;
+            } else {
+                status = 2;
+            }
+            fallbackLine.setStockedQuantity(newStocked);
+            fallbackLine.setProductStockStatus(status);
+            fallbackLine.fillRemainingQuantity();
+            salesLedgerProductMapper.updateById(fallbackLine);
+        }
+    }
+
 
 }
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 1650690..3272508 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -63,8 +63,16 @@
     @Override
     public int deal(QualityUnqualified qualityUnqualified) {
         QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
-        QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
-        if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) {
+        if (ObjectUtils.isNull(unqualified)) {
+            throw new RuntimeException("涓嶅悎鏍艰褰曚笉瀛樺湪");
+        }
+        QualityInspect qualityInspect = null;
+        if (ObjectUtils.isNotNull(unqualified.getInspectId())) {
+            qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
+        }
+        if (ObjectUtils.isNotNull(unqualified.getInspectId())
+                && ObjectUtils.isNotNull(qualityInspect)
+                && qualityInspect.getInspectType() != 0) {
             switch (qualityUnqualified.getDealResult()) {
                 case "杩斾慨":
                 case "杩斿伐":
@@ -137,8 +145,14 @@
                     break;
             }
         } else {
-            //鏌ヨ瀵瑰簲鐨勮鏍煎瀷鍙穒d
-            Long modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel());
+            // 鎵爜涓嶅悎鏍间紭鍏堜娇鐢� productModelId
+            Long modelId = unqualified.getProductModelId();
+            if (ObjectUtils.isNull(modelId)) {
+                modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel());
+            }
+            if (ObjectUtils.isNull(modelId)) {
+                throw new RuntimeException("澶勭悊澶辫触,鏈壘鍒板搴斾骇鍝佽鏍�,璇锋鏌ヤ骇鍝佸悕绉板拰瑙勬牸鍨嬪彿");
+            }
             switch (qualityUnqualified.getDealResult()) {
                 case "鎶ュ簾":
                     //璋冪敤涓嶅悎鏍煎簱瀛樻帴鍙� 鍏ヤ笉鍚堟牸搴�
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index 4f00394..5bc6aa7 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -28,7 +28,6 @@
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 // import com.ruoyi.sales.pojo.ShipmentApproval;
 import com.ruoyi.sales.pojo.ShippingInfo;
-import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.sales.service.ISalesLedgerService;
 import com.ruoyi.sales.service.ShippingInfoService;
 // import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
@@ -67,9 +66,6 @@
     // private StockUtils stockUtils;
 
     @Autowired
-    private ISalesLedgerProductService salesLedgerProductService;
-
-    @Autowired
     private ISalesLedgerService salesLedgerService;
 
     @Autowired
@@ -99,6 +95,15 @@
             return AjaxResult.error("鍏宠仈璁㈠崟涓嶅瓨鍦�");
         }
 
+        // 鍙戣揣鍓嶅繀椤讳繚璇佽璁㈠崟鎵�鏈変骇鍝佸凡鍏ュ簱
+        List<SalesLedgerProduct> notStocked = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId())
+                .eq(SalesLedgerProduct::getType, 1)
+                .ne(SalesLedgerProduct::getProductStockStatus, 2));
+        if (CollectionUtils.isNotEmpty(notStocked)) {
+            return AjaxResult.error("鍙戣揣澶辫触,璇ラ攢鍞鍗曞瓨鍦ㄦ湭鍏ュ簱浜у搧,璇峰厛瀹屾垚鍏ㄩ儴鍏ュ簱鍚庡啀鍙戣揣");
+        }
+
         // 妫�鏌ユ槸鍚﹀凡缁忓湪瀹℃壒涓垨宸插彂璐�
         if (salesLedger.getDeliveryStatus() != null && salesLedger.getDeliveryStatus() >= 2 && !salesLedger.getDeliveryStatus().equals(3)) {
              return AjaxResult.error("璇ヨ鍗曞凡鍦ㄥ鎵逛腑鎴栧凡鍙戣揣锛屾棤娉曢噸澶嶅彂璧�");
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 58132a9..446b5a8 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -340,6 +340,10 @@
     @TableField(exist = false)
     private Integer hasSufficientStock;
 
+    @TableField(exist = false)
+    @ApiModelProperty("閲囪喘璁㈠崟鍏ュ簱鐘舵�侊細0-鏈叆搴擄紝1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�")
+    private Integer purchaseStockStatus;
+
     // 閫�璐ф暟閲�
     @TableField(exist = false)
     private BigDecimal returnQuality;
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index ac28c29..2afc5dc 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -9,6 +9,7 @@
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -32,6 +33,9 @@
 import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.pojo.StockInRecord;
 import com.ruoyi.stock.pojo.StockInventory;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -88,6 +92,8 @@
     private ShippingInfoServiceImpl shippingInfoService;
 
     private StockUtils stockUtils;
+
+    private StockInRecordMapper stockInRecordMapper;
 
     private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
 
@@ -294,9 +300,32 @@
             result = salesLedgerProductMapper.insert(salesLedgerProduct);
             addProductionData(salesLedgerProduct);
         } else {
+            SalesLedgerProduct dbBefore = salesLedgerProductMapper.selectById(salesLedgerProduct.getId());
+            if (dbBefore == null) {
+                throw new RuntimeException("閿�鍞骇鍝佷笉瀛樺湪锛屾棤娉曠紪杈�");
+            }
+            // 涓嶈兘鎶婅鍗曟暟閲忔敼鍒板皬浜庡凡鍙戣揣鏁伴噺锛屽惁鍒欒处瀹炰笉涓�鑷�
+            BigDecimal shipped = dbBefore.getShippedQuantity() == null ? BigDecimal.ZERO : dbBefore.getShippedQuantity();
+            BigDecimal newOrderQty = salesLedgerProduct.getQuantity() == null ? BigDecimal.ZERO : salesLedgerProduct.getQuantity();
+            if (newOrderQty.compareTo(shipped) < 0) {
+                throw new RuntimeException("缂栬緫澶辫触,璁㈠崟鏁伴噺涓嶈兘灏忎簬宸插彂璐ф暟閲�");
+            }
             //鏌ヨ鍘熸湰鐨勪骇鍝佸瀷鍙穒d
             salesLedgerProduct.setFutureTickets(salesLedgerProduct.getQuantity());
             result = salesLedgerProductMapper.updateById(salesLedgerProduct);
+
+            // 鍏佽鈥滃鍏ュ簱鈥濓細褰撹鍗曟暟閲忚涓嬭皟鏃讹紝鍙洖閫�鈥滀笅璋冨樊棰濃�濆搴旂殑鍏ュ簱鏁伴噺
+            // 渚嬶細鍘熻鍗�100锛屽凡鍏ュ簱120锛涙敼涓�50 -> 鍙洖閫�50锛屾渶缁堝凡鍏ュ簱70锛堜笉寮哄帇鍒�50锛�
+            BigDecimal oldOrderQty = dbBefore.getQuantity() == null ? BigDecimal.ZERO : dbBefore.getQuantity();
+            BigDecimal stocked = dbBefore.getStockedQuantity() == null ? BigDecimal.ZERO : dbBefore.getStockedQuantity();
+            BigDecimal reduced = oldOrderQty.subtract(newOrderQty);
+            if (reduced.compareTo(BigDecimal.ZERO) > 0) {
+                BigDecimal rollbackQty = stocked.min(reduced);
+                if (rollbackQty.compareTo(BigDecimal.ZERO) > 0) {
+                    rollbackExcessStockIn(dbBefore, rollbackQty);
+                }
+            }
+
             /*鍒犻櫎瀵瑰簲鐨勭敓浜ф暟鎹苟閲嶆柊鏂板*/
             deleteProductionData(Arrays.asList(salesLedgerProduct.getId()));
             // 鍒犻櫎鐢熶骇鏍哥畻鏁版嵁
@@ -333,10 +362,108 @@
 
             //  娓呯┖閿�鍞骇鍝佺粦瀹氱殑鍔犲伐
             salesLedgerProductProcessBindService.updateProductProcessBind(salesLedgerProduct.getSalesProductProcessList(), salesLedgerProduct.getId());
+
+            // 鏂板/缂栬緫浜у搧鍚庯紝鍒锋柊閿�鍞富鍗曞叆搴撶姸鎬侊紙閬垮厤鍥犳柊澧炴湭鍏ュ簱琛屽鑷寸姸鎬佷笉鍑嗭級
+            refreshSalesLedgerStockStatus(salesLedgerId);
         }
         return result;
     }
 
+    private void rollbackExcessStockIn(SalesLedgerProduct dbBefore, BigDecimal rollbackQtyTotal) {
+        if (dbBefore == null || rollbackQtyTotal == null || rollbackQtyTotal.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        if (dbBefore.getProductModelId() == null) {
+            throw new RuntimeException("鍥為��鍏ュ簱澶辫触,浜у搧瑙勬牸鏈淮鎶�");
+        }
+        Long productId = dbBefore.getId();
+        //  鍊掑簭鍥為��锛氫紭鍏堝洖閫�鈥滄壂鐮佸叆搴撯�濓紝鍐嶅洖閫�鈥滄墜鍔ㄥ叆搴撯��
+        List<String> recordTypes = Arrays.asList(
+                StockInQualifiedRecordTypeEnum.SALE_SCAN_STOCK_IN.getCode(),
+                StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode()
+        );
+        List<StockInRecord> records = stockInRecordMapper.selectList(new LambdaQueryWrapper<StockInRecord>()
+                .eq(StockInRecord::getSalesLedgerProductId, productId)
+                .eq(StockInRecord::getType, "0")
+                .in(StockInRecord::getRecordType, recordTypes)
+                .orderByDesc(StockInRecord::getCreateTime));
+        BigDecimal remaining = rollbackQtyTotal;
+        for (StockInRecord r : records) {
+            if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+                break;
+            }
+            BigDecimal inNum = r.getStockInNum() == null ? BigDecimal.ZERO : r.getStockInNum();
+            if (inNum.compareTo(BigDecimal.ZERO) <= 0) {
+                continue;
+            }
+            BigDecimal rollbackQty = inNum.min(remaining);
+
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setProductModelId(dbBefore.getProductModelId());
+            stockInventoryDto.setQualitity(rollbackQty);
+            int affectRows = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+            if (affectRows <= 0) {
+                throw new RuntimeException("鍥為��鍏ュ簱澶辫触,褰撳墠搴撳瓨涓嶈冻,鏃犳硶鎵e洖瓒呭叆搴撴暟閲�");
+            }
+
+            BigDecimal newInNum = inNum.subtract(rollbackQty);
+            if (newInNum.compareTo(BigDecimal.ZERO) <= 0) {
+                stockInRecordMapper.deleteById(r.getId());
+            } else {
+                r.setStockInNum(newInNum);
+                stockInRecordMapper.updateById(r);
+            }
+            remaining = remaining.subtract(rollbackQty);
+        }
+        if (remaining.compareTo(BigDecimal.ZERO) > 0) {
+            throw new RuntimeException("鍥為��鍏ュ簱澶辫触,鏈壘鍒拌冻澶熺殑鍏ュ簱璁板綍鐢ㄤ簬鎵e洖瓒呭叆搴撴暟閲�");
+        }
+
+        //  鍥炲啓浜у搧琛屽凡鍏ュ簱鏁伴噺涓庣姸鎬�
+        SalesLedgerProduct fresh = salesLedgerProductMapper.selectById(dbBefore.getId());
+        if (fresh == null) {
+            return;
+        }
+        BigDecimal newStocked = (fresh.getStockedQuantity() == null ? BigDecimal.ZERO : fresh.getStockedQuantity()).subtract(rollbackQtyTotal);
+        if (newStocked.compareTo(BigDecimal.ZERO) < 0) {
+            newStocked = BigDecimal.ZERO;
+        }
+        BigDecimal orderQty = fresh.getQuantity() == null ? BigDecimal.ZERO : fresh.getQuantity();
+        int stockStatus;
+        if (newStocked.compareTo(BigDecimal.ZERO) <= 0) stockStatus = 0;
+        else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) stockStatus = 1;
+        else stockStatus = 2;
+        fresh.setStockedQuantity(newStocked);
+        fresh.setProductStockStatus(stockStatus);
+        fresh.fillRemainingQuantity();
+        salesLedgerProductMapper.updateById(fresh);
+    }
+
+    private void refreshSalesLedgerStockStatus(Long salesLedgerId) {
+        if (salesLedgerId == null) {
+            return;
+        }
+        SalesLedger ledger = salesLedgerMapper.selectById(salesLedgerId);
+        if (ledger == null) {
+            return;
+        }
+        List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)
+                .eq(SalesLedgerProduct::getType, 1));
+        if (CollectionUtils.isEmpty(allProducts)) {
+            ledger.setStockStatus(0);
+            salesLedgerMapper.updateById(ledger);
+            return;
+        }
+        boolean anyInbound = allProducts.stream().anyMatch(p -> {
+            BigDecimal sq = p.getStockedQuantity();
+            return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+        });
+        boolean allFull = allProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
+        ledger.setStockStatus(allFull ? 2 : (anyInbound ? 1 : 0));
+        salesLedgerMapper.updateById(ledger);
+    }
+
     /**
      * 鏂板鐢熶骇鏁版嵁
      */
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 1a371f9..4d7e21f 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1006,7 +1006,15 @@
         if (!updateList.isEmpty()) {
             for (SalesLedgerProduct product : updateList) {
                 product.setType(type.getCode());
-                product.setProductStockStatus(0);
+                SalesLedgerProduct db = salesLedgerProductMapper.selectById(product.getId());
+                if (db != null) {
+                    BigDecimal stockedQty = product.getStockedQuantity() != null ? product.getStockedQuantity() : db.getStockedQuantity();
+                    BigDecimal orderQty = product.getQuantity() != null ? product.getQuantity() : db.getQuantity();
+                    product.setStockedQuantity(stockedQty);
+                    product.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
+                } else {
+                    product.setProductStockStatus(0);
+                }
                 product.fillRemainingQuantity();
                 salesLedgerProductMapper.updateById(product);
                 //  娓呯┖閿�鍞骇鍝佺粦瀹氱殑鍔犲伐
@@ -1020,7 +1028,9 @@
                 salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                 salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
-                salesLedgerProduct.setProductStockStatus(0);
+                BigDecimal stockedQty = salesLedgerProduct.getStockedQuantity();
+                BigDecimal orderQty = salesLedgerProduct.getQuantity();
+                salesLedgerProduct.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
                 salesLedgerProduct.fillRemainingQuantity();
                 salesLedgerProductMapper.insert(salesLedgerProduct);
                 //  缁戝畾浜у搧棰濆鍔犲伐
@@ -1030,6 +1040,41 @@
 //                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
             }
         }
+        refreshSalesLedgerStockStatus(salesLedgerId);
+    }
+
+    private int calculateProductStockStatus(BigDecimal stockedQty, BigDecimal orderQty) {
+        BigDecimal stocked = stockedQty == null ? BigDecimal.ZERO : stockedQty;
+        BigDecimal order = orderQty == null ? BigDecimal.ZERO : orderQty;
+        if (stocked.compareTo(BigDecimal.ZERO) <= 0) {
+            return 0;
+        }
+        if (order.compareTo(BigDecimal.ZERO) > 0 && stocked.compareTo(order) < 0) {
+            return 1;
+        }
+        return 2;
+    }
+
+    private void refreshSalesLedgerStockStatus(Long salesLedgerId) {
+        if (salesLedgerId == null) return;
+        SalesLedger ledger = baseMapper.selectById(salesLedgerId);
+        if (ledger == null) return;
+        List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(
+                Wrappers.<SalesLedgerProduct>lambdaQuery()
+                        .eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)
+                        .eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
+        if (CollectionUtils.isEmpty(allProducts)) {
+            ledger.setStockStatus(0);
+            baseMapper.updateById(ledger);
+            return;
+        }
+        boolean anyInbound = allProducts.stream().anyMatch(p -> {
+            BigDecimal sq = p.getStockedQuantity();
+            return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
+        });
+        boolean allFull = allProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
+        ledger.setStockStatus(allFull ? 2 : (anyInbound ? 1 : 0));
+        baseMapper.updateById(ledger);
     }
 
     private SalesLedger convertToEntity(SalesLedgerDto dto) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index 521222f..c062391 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -19,15 +19,9 @@
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.ShippingInfoService;
 import com.ruoyi.sales.mapper.SalesLedgerMapper;
-import com.ruoyi.stock.mapper.StockInventoryMapper;
-import com.ruoyi.stock.pojo.StockInventory;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.Map;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -64,9 +58,6 @@
     @Autowired
     private SalesLedgerMapper salesLedgerMapper;
 
-    @Autowired
-    private StockInventoryMapper stockInventoryMapper;
-
     @Override
     public IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req) {
         IPage<ShippingInfoDto> listPage = shippingInfoMapper.listPage(page, req);
@@ -83,6 +74,14 @@
         if (byId == null) {
             throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
         }
+        //  鍙戣揣鎵e簱瀛樺墠蹇呴』淇濊瘉璇ヨ鍗曟墍鏈変骇鍝佸凡鍏ュ簱
+        List<SalesLedgerProduct> notStocked = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, byId.getSalesLedgerId())
+                .eq(SalesLedgerProduct::getType, 1)
+                .ne(SalesLedgerProduct::getProductStockStatus, 2));
+        if (CollectionUtils.isNotEmpty(notStocked)) {
+            throw new RuntimeException("鍙戣揣澶辫触,璇ラ攢鍞鍗曞瓨鍦ㄦ湭鍏ュ簱浜у搧,璇峰厛瀹屾垚鍏ㄩ儴鍏ュ簱鍚庡啀鍙戣揣");
+        }
         //鎵e噺搴撳瓨
         if (!"宸插彂璐�".equals(byId.getStatus())) {
             SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index c1743d4..8baa113 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -79,7 +79,10 @@
         stockInRecordService.add(stockInRecordDto);
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+        List<StockInventory> stockInventories = stockInventoryMapper.selectList(new QueryWrapper<StockInventory>().lambda()
+                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
+                .orderByDesc(StockInventory::getId));
+        StockInventory oldStockInventory = (stockInventories == null || stockInventories.isEmpty()) ? null : stockInventories.get(0);
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             StockInventory newStockInventory = new StockInventory();
             newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
@@ -109,7 +112,10 @@
         stockOutRecordDto.setSalesLedgerId(stockInventoryDto.getSalesLedgerId());
         stockOutRecordDto.setSalesLedgerProductId(stockInventoryDto.getSalesLedgerProductId());
         stockOutRecordService.add(stockOutRecordDto);
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+        List<StockInventory> stockInventories = stockInventoryMapper.selectList(new QueryWrapper<StockInventory>().lambda()
+                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
+                .orderByDesc(StockInventory::getId));
+        StockInventory oldStockInventory = (stockInventories == null || stockInventories.isEmpty()) ? null : stockInventories.get(0);
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
         }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
index 6fb76e6..cfa9044 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -59,7 +59,10 @@
         stockInRecordService.add(stockInRecordDto);
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
-        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
+        List<StockUninventory> stockUninventories = stockUninventoryMapper.selectList(new QueryWrapper<StockUninventory>().lambda()
+                .eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId())
+                .orderByDesc(StockUninventory::getId));
+        StockUninventory oldStockUnInventory = (stockUninventories == null || stockUninventories.isEmpty()) ? null : stockUninventories.get(0);
         if (ObjectUtils.isEmpty(oldStockUnInventory)) {
             StockUninventory newStockUnInventory = new StockUninventory();
             newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
@@ -87,7 +90,10 @@
         stockOutRecordDto.setSalesLedgerId(stockUninventoryDto.getSalesLedgerId());
         stockOutRecordDto.setSalesLedgerProductId(stockUninventoryDto.getSalesLedgerProductId());
         stockOutRecordService.add(stockOutRecordDto);
-        StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
+        List<StockUninventory> stockUninventories = stockUninventoryMapper.selectList(new QueryWrapper<StockUninventory>().lambda()
+                .eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId())
+                .orderByDesc(StockUninventory::getId));
+        StockUninventory oldStockInventory = (stockUninventories == null || stockUninventories.isEmpty()) ? null : stockUninventories.get(0);
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
         }else {
diff --git a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
index 1aed9b4..8e85e40 100644
--- a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -29,6 +29,8 @@
         pl.approve_user_ids,
         sm.is_white,
         pl.approval_status,
+        pl.stock_status,
+        IFNULL(ps.product_stock_status, 0) AS product_stock_status,
         pl.payment_method,
         pl.remarks
         FROM purchase_ledger pl
@@ -40,6 +42,19 @@
         GROUP BY purchase_ledger_id
         ) tr_sum ON pl.id = tr_sum.purchase_ledger_id
         LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id
+        LEFT JOIN (
+        SELECT
+        sales_ledger_id,
+        CASE
+        WHEN COUNT(1) = 0 THEN 0
+        WHEN SUM(CASE WHEN IFNULL(product_stock_status, 0) = 2 THEN 1 ELSE 0 END) = COUNT(1) THEN 2
+        WHEN SUM(CASE WHEN IFNULL(product_stock_status, 0) > 0 THEN 1 ELSE 0 END) > 0 THEN 1
+        ELSE 0
+        END AS product_stock_status
+        FROM sales_ledger_product
+        WHERE type = 2
+        GROUP BY sales_ledger_id
+        ) ps ON pl.id = ps.sales_ledger_id
         <where>
             <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''">
                 AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%')
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index 57f8b42..99d6df1 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -47,7 +47,7 @@
         <if test="qualityInspect.entryDateEnd != null and qualityInspect.entryDateEnd != '' ">
             AND qi.check_time &lt;= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d')
         </if>
-        ORDER BY qi.check_time DESC
+        ORDER BY qi.id DESC
     </select>
 
     <select id="qualityInspectExport" resultType="com.ruoyi.quality.pojo.QualityInspect">
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index d95a38d..64adc3f 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -7,6 +7,7 @@
     <select id="selectSalesLedgerProductList" resultType="com.ruoyi.sales.pojo.SalesLedgerProduct">
         SELECT
         T1.*,
+        pl.stock_status AS purchase_stock_status,
         CASE
         WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >= IFNULL(T1.quantity, 0) THEN 1
         ELSE 0
@@ -14,6 +15,7 @@
         FROM
         sales_ledger_product T1
         LEFT JOIN stock_inventory t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN purchase_ledger pl ON T1.sales_ledger_id = pl.id AND T1.type = 2
         <where>
             <if test="salesLedgerProduct.salesLedgerId != null">
                 AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}

--
Gitblit v1.9.3