From bd02d873d7bbcae36a2a1262d921f2fc6b0cce09 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期三, 06 五月 2026 14:33:41 +0800
Subject: [PATCH] feat(sales): 新增发货台账详情功能并优化库存管理

---
 src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java    |   18 +++
 src/main/java/com/ruoyi/stock/service/StockInventoryService.java                 |    5 
 src/main/java/com/ruoyi/CodeGenerator.java                                       |    6 
 src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java            |   18 +++
 src/main/java/com/ruoyi/sales/service/ShippingInfoService.java                   |    2 
 src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java          |   16 +++
 src/main/resources/mapper/stock/StockInventoryMapper.xml                         |    8 +
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                       |    2 
 src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java                     |   15 +++
 src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java                           |    6 +
 src/main/resources/mapper/sales/ShippingInfoMapper.xml                           |    1 
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                  |   10 ++
 src/main/java/com/ruoyi/stock/controller/StockInventoryController.java           |    7 +
 src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java                    |   65 +++++++++++++
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java    |    2 
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java          |   32 +++++-
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                     |   21 +++
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java                   |    2 
 src/main/resources/mapper/sales/ShippingProductDetailMapper.xml                  |   14 ++
 src/main/java/com/ruoyi/approve/pojo/ApproveNode.java                            |    2 
 src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java             |    2 
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java        |    5 +
 src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java         |   17 +++
 src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java |   20 ++++
 24 files changed, 276 insertions(+), 20 deletions(-)

diff --git a/src/main/java/com/ruoyi/CodeGenerator.java b/src/main/java/com/ruoyi/CodeGenerator.java
index 50dfffc..721245b 100644
--- a/src/main/java/com/ruoyi/CodeGenerator.java
+++ b/src/main/java/com/ruoyi/CodeGenerator.java
@@ -20,11 +20,11 @@
 // 婕旂ず渚嬪瓙锛屾墽琛� main 鏂规硶鎺у埗鍙拌緭鍏ユā鍧楄〃鍚嶅洖杞﹁嚜鍔ㄧ敓鎴愬搴旈」鐩洰褰曚腑
 public class CodeGenerator {
 
-    public static String database_url = "jdbc:mysql://localhost:3306/product-inventory-management-new-pro";
+    public static String database_url = "jdbc:mysql://localhost:3300/product-inventory-management-new-pro";
     public static String database_username = "root";
-    public static String database_password= "123456";
+    public static String database_password= "root";
     public static String author = "鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃";
-    public static String model = "technology"; // 妯″潡
+    public static String model = "sales"; // 妯″潡
     public static String setParent = "com.ruoyi."+ model; // 鍖呰矾寰�
     public static String tablePrefix = ""; // 璁剧疆杩囨护琛ㄥ墠缂�
     public static void main(String[] args) {
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java
new file mode 100644
index 0000000..d7acc4d
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.approve.pojo.ApproveNode;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApproveNodeDto extends ApproveNode {
+
+
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java b/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
index 7c35578..907f3dc 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
@@ -130,6 +130,6 @@
     @TableField(fill = FieldFill.INSERT)
     private Long deptId;
 
-    @TableField(fill = FieldFill.INSERT)
+    @TableField(exist = false)
     private List<StorageBlobDTO> storageBlobDTOS;
 }
diff --git a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
index 6aecb29..367710b 100644
--- a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -8,12 +8,25 @@
 
 
     CUSTOMIZATION_STOCK_IN("0", "鍚堟牸鑷畾涔夊叆搴�"),
+    CUSTOMIZATION_STOCK_OUT("1", "鍚堟牸鑷畾涔夊嚭搴�"),
     PRODUCTION_REPORT_STOCK_IN("2", "鐢熶骇鎶ュ伐-鍏ュ簱"),
-    PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
+    PRODUCTION_REPORT_STOCK_OUT("3", "鐢熶骇鎶ュ伐-鍑哄簱"),
+    DEFECTIVE_SCRAP("4", "涓嶅悎鏍煎鐞�-鎶ュ簾"),
+    PRODUCTION_SCRAP("5", "鐢熶骇鎶ュ伐-鎶ュ簾"),
     QUALITYINSPECT_STOCK_IN("6", "璐ㄦ-鍚堟牸鍏ュ簱"),
+    PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
+    SALE_STOCK_OUT("8", "閿�鍞�-鍑哄簱"),
+    CUSTOMIZATION_UNSTOCK_IN("9", "涓嶅悎鏍艰嚜瀹氫箟鍏ュ簱"),
+    CUSTOMIZATION_UNSTOCK_OUT("10", "涓嶅悎鏍艰嚜瀹氫箟鍑哄簱"),
     DEFECTIVE_PASS("11", "涓嶅悎鏍�-璁╂鏀捐"),
+    QUALITYINSPECT_UNSTOCK_IN("12", "璐ㄦ-涓嶅悎鏍煎叆搴�"),
+    SALE_SHIP_STOCK_OUT("13", "閿�鍞�-鍙戣揣鍑哄簱"),
     RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
-    PICK_RETURN_IN("20", "閿�鍞��璐�-鍚堟牸鍏ュ簱");
+    RETURN_UNSTOCK_IN("15", "閿�鍞��璐�-涓嶅悎鏍煎叆搴�"),
+    PICK_RETURN_IN("20", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
+    PURCHASE_RETURN_STOCK_OUT("21", "閲囪喘閫�璐�");
+
+
 
 
     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 1434e24..394fd3a 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -97,6 +97,16 @@
         stockInventoryService.subtractStockInventory(stockInventoryDto);
     }
 
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId, String batchNo) {
+        StockInventoryDto stockInventoryDto = new StockInventoryDto();
+        stockInventoryDto.setRecordId(recordId);
+        stockInventoryDto.setRecordType(String.valueOf(recordType));
+        stockInventoryDto.setQualitity(quantity);
+        stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryDto.setBatchNo(batchNo);
+        stockInventoryService.subtractStockInventory(stockInventoryDto);
+    }
+
     //涓嶅悎鏍煎簱瀛樺垹闄�
     public void deleteStockInRecord(Long recordId, String recordType) {
         StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>()
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index 49ef859..46597fb 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -68,7 +68,7 @@
         // 娣诲姞鍙戣揣娑堟伅
         req.setShippingNo(sh);
         req.setStatus("寰呭鏍�");
-        boolean save = shippingInfoService.save(req);
+        boolean save = shippingInfoService.add(req);
         return save ? AjaxResult.success() : AjaxResult.error();
     }
 
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java b/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java
new file mode 100644
index 0000000..c235b3e
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.sales.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@RestController
+@RequestMapping("/shippingProductDetail")
+public class ShippingProductDetailController {
+
+}
diff --git a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
index 9ff3f09..e12149f 100644
--- a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
@@ -5,6 +5,7 @@
 import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import lombok.Data;
 
 import java.util.List;
@@ -36,4 +37,9 @@
     private List<StorageBlobDTO> storageBlobDTOs;
     private List<StorageBlobVO> storageBlobVOs;
 
+    private List<Long> batchNo;
+    private List<ShippingProductDetail> batchNoDetailList;
+
+
+
 }
diff --git a/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java b/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java
new file mode 100644
index 0000000..c277f4d
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.sales.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Mapper
+public interface ShippingProductDetailMapper extends BaseMapper<ShippingProductDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 70ffa12..c909871 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -256,4 +256,6 @@
     //閽堝閿�鍞彴璐︼紝鏄惁鐢熶骇
     private Boolean isProduction;
 
+    @TableField(exist = false)
+    private BigDecimal noQuantity;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java b/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java
new file mode 100644
index 0000000..08e7311
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java
@@ -0,0 +1,65 @@
+package com.ruoyi.sales.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Getter
+@Setter
+@ToString
+@TableName("shipping_product_detail")
+@ApiModel(value = "ShippingProductDetail瀵硅薄", description = "鍙戣揣鍙拌处璇︽儏琛�")
+public class ShippingProductDetail implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭id
+     */
+    @ApiModelProperty("涓婚敭id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 搴撳瓨琛╥d
+     */
+    @ApiModelProperty("搴撳瓨琛╥d")
+    private Long stockInventoryId;
+
+    /**
+     * 鎵规鍙�
+     */
+    @ApiModelProperty("鎵规鍙�")
+    private String batchNo;
+
+    /**
+     * 鍙戣揣鐨勬暟閲�
+     */
+    @ApiModelProperty("鍙戣揣鐨勬暟閲�")
+    private BigDecimal quantity;
+
+    /**
+     * 鍙戣揣鍙拌处id
+     */
+    @ApiModelProperty("鍙戣揣鍙拌处id")
+    private Long shippingInfoId;
+
+    @ApiModelProperty("浜у搧鍨嬪彿id")
+    private Long productModelId;
+}
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
index a701bf2..fcd6280 100644
--- a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
+++ b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
@@ -23,4 +23,6 @@
     List<SalesLedgerProductDto> getReturnManagementDtoById( Long shippingId);
 
     List<ShippingInfo> getShippingInfoByCustomerName(String customerName);
+
+    boolean add(ShippingInfoDto req);
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java b/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java
new file mode 100644
index 0000000..e874dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.sales.service;
+
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+public interface ShippingProductDetailService extends IService<ShippingProductDetail> {
+
+}
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 817bfc6..37e06bb 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -30,7 +30,6 @@
 import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
 import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
 import com.ruoyi.technology.pojo.TechnologyRouting;
-import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -116,7 +115,6 @@
                 if(shippingInfo != null){
                     item.setShippingDate(shippingInfo.getShippingDate());
                     item.setShippingCarNumber(shippingInfo.getShippingCarNumber());
-                    item.setShippingStatus(shippingInfo.getStatus());
                     item.setExpressCompany(shippingInfo.getExpressCompany());
                     item.setExpressNumber(shippingInfo.getExpressNumber());
                 }
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 08322a2..20b563a 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -16,15 +16,15 @@
 import com.ruoyi.sales.dto.ShippingInfoDto;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import com.ruoyi.sales.service.ShippingInfoService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -48,6 +48,7 @@
 
     private final ApproveProcessServiceImpl approveProcessService;
     private final FileUtil fileUtil;
+    private final ShippingProductDetailMapper shippingProductDetailMapper;
 
     @Override
     public IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req) {
@@ -66,8 +67,14 @@
         }
         //鎵e噺搴撳瓨
         if(!"宸插彂璐�".equals(byId.getStatus())){
-            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
-            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+//            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
+            List<ShippingProductDetail> shippingProductDetails = shippingProductDetailMapper.selectList(new LambdaQueryWrapper<ShippingProductDetail>().eq(ShippingProductDetail::getShippingInfoId, req.getId()));
+            if (CollectionUtils.isEmpty(shippingProductDetails)) {
+                throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
+            }
+            for (ShippingProductDetail shippingProductDetail : shippingProductDetails) {
+                stockUtils.substractStock(shippingProductDetail.getProductModelId(), shippingProductDetail.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(), shippingProductDetail.getBatchNo());
+            }
         }
         byId.setExpressNumber(req.getExpressNumber());
         byId.setExpressCompany(req.getExpressCompany());
@@ -96,15 +103,18 @@
         // 鍒犻櫎鍙戣揣瀹℃壒
         if(CollectionUtils.isNotEmpty(shippingInfos)){
             for (ShippingInfo shippingInfo : shippingInfos){
-                ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
+                List<ApproveProcess> one = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
                         .like(ApproveProcess::getApproveReason, shippingInfo.getShippingNo()));
                 if(one != null){
-                    approveProcessService.delByIds(Collections.singletonList(one.getId()));
+                    List<Long> list = one.stream().map(ApproveProcess::getId).toList();
+                    approveProcessService.delByIds(list);
                 }
             }
         }
+        //鍒犻櫎鍙戣揣鏄庣粏
+        shippingProductDetailMapper.delete(new LambdaQueryWrapper<ShippingProductDetail>().in(ShippingProductDetail::getShippingInfoId, ids));
 
-        return this.removeBatchByIds(ids);
+        return this.removeByIds(ids);
     }
 
     @Override
@@ -117,4 +127,12 @@
     public List<ShippingInfo> getShippingInfoByCustomerName(String customerName) {
         return shippingInfoMapper.getShippingInfoByCustomerName(customerName);
     }
+
+    @Override
+    public boolean add(ShippingInfoDto req) {
+        this.save( req);
+        req.getBatchNoDetailList().forEach(item -> item.setShippingInfoId(req.getId()));
+        shippingProductDetailMapper.insert(req.getBatchNoDetailList());
+        return true;
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java
new file mode 100644
index 0000000..9b31881
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.sales.service.impl;
+
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
+import com.ruoyi.sales.service.ShippingProductDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Service
+public class ShippingProductDetailServiceImpl extends ServiceImpl<ShippingProductDetailMapper, ShippingProductDetail> implements ShippingProductDetailService {
+
+}
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
index 2096b6d..44fe885 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -128,4 +128,11 @@
     public R thawStock(@RequestBody StockInventoryDto stockInventoryDto) {
         return R.ok(stockInventoryService.thawStock(stockInventoryDto));
     }
+
+
+    @GetMapping("/getByModelId")
+    @Operation(summary = "鏍规嵁浜у搧瑙勬牸ID鑾峰彇鍏ュ簱璁板綍")
+    public R getByModelId(Long productModelId) {
+        return R.ok(stockInventoryService.getByModelId(productModelId));
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 21fa421..a31cf5b 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -54,4 +54,6 @@
     BigDecimal selectPendingOutQuantity(@Param("productModelId") Long productModelId, @Param("batchNo") String batchNo, @Param("type") String type);
 
     List<StockInventory> listSelectableBatchNoByProductModelIds(@Param("productModelIds") List<Long> productModelIds);
+
+    List<StockInventory> getByModelId(@Param("productModelId") Long productModelId);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
index 008ec6a..d47cc4b 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -7,9 +7,10 @@
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.pojo.StockInventory;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.web.multipart.MultipartFile;
 
-import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
 
 /**
  * <p>
@@ -44,4 +45,6 @@
     Boolean frozenStock(StockInventoryDto stockInventoryDto);
 
     Boolean thawStock(StockInventoryDto stockInventoryDto);
+
+    List<StockInventory> getByModelId(Long modelId);
 }
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 c6b32b4..d712518 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -429,4 +429,9 @@
         stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity()));
         return this.updateById(stockInventory);
     }
+
+    @Override
+    public List<StockInventory> getByModelId(Long modelId) {
+        return stockInventoryMapper.getByModelId(modelId);
+    }
 }
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index a1d05e9..49689a1 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -8,12 +8,27 @@
         SELECT
         T1.*,
         CASE
-        WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >= IFNULL(T1.quantity, 0) THEN 1
+        WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >0 THEN 1
         ELSE 0
-        END as has_sufficient_stock
+        END as has_sufficient_stock,
+        (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) as no_quantity,
+        CASE
+        WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN '寰呭彂璐�'
+        ELSE '宸插彂璐�'
+        END as shippingStatus
         FROM
         sales_ledger_product T1
-        LEFT JOIN stock_inventory t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN (
+        SELECT product_model_id, SUM(qualitity) as qualitity, SUM(locked_quantity) as locked_quantity
+        FROM stock_inventory
+        GROUP BY product_model_id
+        ) t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN (
+        SELECT sales_ledger_product_id, IFNULL(SUM(spd.quantity), 0) as shipped_quantity
+        FROM shipping_info si
+        LEFT JOIN shipping_product_detail spd ON si.id = spd.shipping_info_id
+        GROUP BY sales_ledger_product_id
+        ) t3 ON t3.sales_ledger_product_id = T1.id
         <where>
             <if test="salesLedgerProduct.salesLedgerId != null">
                 AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
diff --git a/src/main/resources/mapper/sales/ShippingInfoMapper.xml b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
index 71bce20..048bb23 100644
--- a/src/main/resources/mapper/sales/ShippingInfoMapper.xml
+++ b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
@@ -61,6 +61,7 @@
     <select id="getReturnManagementDtoById" resultType="com.ruoyi.sales.dto.SalesLedgerProductDto">
         SELECT
         slp.*,
+        si.shipping_no,
         GREATEST(slp.quantity - COALESCE(rs.total_return_num, 0), 0) AS un_quantity,
         COALESCE(rs.total_return_num, 0) AS total_return_num
         FROM shipping_info si
diff --git a/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml b/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml
new file mode 100644
index 0000000..eabe491
--- /dev/null
+++ b/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.sales.mapper.ShippingProductDetailMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.sales.pojo.ShippingProductDetail">
+        <id column="id" property="id" />
+        <result column="stock_inventory_id" property="stockInventoryId" />
+        <result column="batch_no" property="batchNo" />
+        <result column="quantity" property="quantity" />
+        <result column="shipping_info_id" property="shippingInfoId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index d1eecb5..60fc90e 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -452,5 +452,13 @@
           and (si.qualitity - ifnull(si.locked_quantity, 0)) > 0
         order by si.product_model_id, si.batch_no
     </select>
+    <select id="getByModelId" resultType="com.ruoyi.stock.pojo.StockInventory">
+        select spd.id, spd.batch_no, spd.locked_quantity, (spd.qualitity - IFNULL(sd.qualitity, 0)) as qualitity
+        from stock_inventory spd
+                 left join (select stock_inventory_id, sum(quantity) as qualitity
+                            from shipping_product_detail
+                            group by stock_inventory_id) as sd on sd.stock_inventory_id = spd.id
+        where product_model_id = #{productModelId}
+    </select>
 
 </mapper>

--
Gitblit v1.9.3