From 255930c3226e8990edc6ad44447893001d3c1add Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 22 一月 2026 14:08:38 +0800
Subject: [PATCH] feat(sales): 物料消耗查询接口

---
 src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java             |   24 ++++++++
 src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java    |    7 ++
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml           |   51 ++++++++++++-----
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java |   38 ++++++++----
 src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java     |    5 +
 src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java         |    4 +
 6 files changed, 100 insertions(+), 29 deletions(-)

diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index ad0b5e2..a36619d 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -9,6 +9,7 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.framework.web.page.TableDataInfo;
 import com.ruoyi.sales.dto.InvoiceLedgerDto;
 import com.ruoyi.sales.dto.SalesLedgerDto;
@@ -284,4 +285,10 @@
 
         return iPage;
     }
+
+    @ApiOperation("鏌ヨ閿�鍞彴璐︽秷鑰楃墿鏂欎俊鎭�")
+    @GetMapping("/getSalesLedgerWithProducts")
+    public R getSalesLedgerWithProductsLoss(Long salesLedgerId) {
+        return R.ok(salesLedgerService.getSalesLedgerWithProductsLoss(salesLedgerId));
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java b/src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java
new file mode 100644
index 0000000..29706a8
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/dto/LossProductModelDto.java
@@ -0,0 +1,24 @@
+package com.ruoyi.sales.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class LossProductModelDto {
+
+    private String productName;
+
+    private String model;
+
+    private String unit;
+
+    //娑堣�楁�婚噺
+    private BigDecimal lossNum;
+
+    //鍗曚綅鐢ㄩ噺
+    private BigDecimal unitQuantity;
+
+    //鍗曚釜鐢ㄩ噺
+    private BigDecimal singleQuantity;
+}
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
index e765f71..514f6cd 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -3,11 +3,14 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.config.MyBaseMapper;
+import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
+import com.ruoyi.sales.dto.LossProductModelDto;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -26,4 +29,6 @@
     IPage<SalesLedgerProductDto> listPagePurchaseLedger(Page page,@Param("req") SalesLedgerProductDto salesLedgerProduct);
 
     IPage<ProcurementBusinessSummaryDto> procurementBusinessSummaryListPage(Page page,@Param("req") ProcurementBusinessSummaryDto procurementBusinessSummaryDto);
+
+    List<LossProductModelDto> selectProductBomStructure(@Param("salesLedegerId") Long salesLedegerId);
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index cb1f2e0..8c973b3 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.sales.dto.LossProductModelDto;
 import com.ruoyi.sales.dto.MonthlyAmountDto;
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.pojo.SalesLedger;
@@ -39,4 +40,7 @@
     IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
 
     AjaxResult importData(MultipartFile file);
+
+    List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId);
+
 }
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 e297168..85d05cc 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -35,10 +35,7 @@
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.sales.dto.MonthlyAmountDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
-import com.ruoyi.sales.dto.SalesLedgerImportDto;
-import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
+import com.ruoyi.sales.dto.*;
 import com.ruoyi.sales.mapper.*;
 import com.ruoyi.sales.pojo.*;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
@@ -234,8 +231,8 @@
         // 鏌ヨ鍘熷鏁版嵁
         LambdaQueryWrapper<SalesLedger> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.select(SalesLedger::getCustomerId,
-                SalesLedger::getCustomerName,
-                SalesLedger::getContractAmount)
+                        SalesLedger::getCustomerName,
+                        SalesLedger::getContractAmount)
                 .orderByDesc(SalesLedger::getContractAmount);
         List<SalesLedger> records = salesLedgerMapper.selectList(queryWrapper);
 
@@ -243,7 +240,7 @@
         Map<Long, GroupedCustomer> groupedMap = new LinkedHashMap<>(); // 浣跨敤LinkedHashMap淇濇寔鎺掑簭
         for (SalesLedger record : records) {
             groupedMap.computeIfAbsent(record.getCustomerId(),
-                    k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName()))
+                            k -> new GroupedCustomer(record.getCustomerId(), record.getCustomerName()))
                     .addAmount(record.getContractAmount());
         }
 
@@ -350,13 +347,13 @@
         try {
             InputStream inputStream = file.getInputStream();
             ExcelUtil<SalesLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
-            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("閿�鍞彴璐︽暟鎹�","閿�鍞骇鍝佹暟鎹�"), inputStream, 0);
-            if(CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("閿�鍞〃鏍间负绌猴紒");
+            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("閿�鍞彴璐︽暟鎹�", "閿�鍞骇鍝佹暟鎹�"), inputStream, 0);
+            if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("閿�鍞〃鏍间负绌猴紒");
             // 涓氬姟灞傚悎骞�
             List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("閿�鍞彴璐︽暟鎹�");
-            if(CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("閿�鍞彴璐︽暟鎹负绌猴紒");
+            if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("閿�鍞彴璐︽暟鎹负绌猴紒");
             List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("閿�鍞骇鍝佹暟鎹�");
-            if(CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("閿�鍞骇鍝佹暟鎹负绌猴紒");
+            if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("閿�鍞骇鍝佹暟鎹负绌猴紒");
             // 瀹㈡埛鏁版嵁
             List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
                     salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).toArray(String[]::new)));
@@ -388,14 +385,16 @@
                         .findFirst()
                         .map(SysUser::getUserId)
                         .orElse(null);
-                if(aLong == null) throw new RuntimeException("褰曞叆浜�:"+salesLedger.getEntryPerson()+",鏃犲搴旂敤鎴凤紒");
+                if (aLong == null)
+                    throw new RuntimeException("褰曞叆浜�:" + salesLedger.getEntryPerson() + ",鏃犲搴旂敤鎴凤紒");
                 salesLedger.setEntryPerson(aLong.toString());
                 salesLedgerMapper.insert(salesLedger);
                 // 閿�鍞骇鍝佹暟鎹粦瀹氾紝閫氳繃閿�鍞崟鍙疯幏鍙栧搴旈攢鍞骇鍝佹暟鎹�
                 List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
                         .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo()))
                         .collect(Collectors.toList());
-                if(CollectionUtils.isEmpty(salesLedgerProductImportDtos)) throw new RuntimeException("閿�鍞崟鍙�:"+salesLedgerImportDto.getSalesContractNo()+",鏃犲搴斾骇鍝佹暟鎹紒");
+                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
+                    throw new RuntimeException("閿�鍞崟鍙�:" + salesLedgerImportDto.getSalesContractNo() + ",鏃犲搴斾骇鍝佹暟鎹紒");
                 for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
                     SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct();
                     BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
@@ -427,12 +426,23 @@
             }
 
             return AjaxResult.success("瀵煎叆鎴愬姛");
-        }catch (Exception e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
         return AjaxResult.success("瀵煎叆澶辫触");
     }
 
+    @Override
+    public List<LossProductModelDto> getSalesLedgerWithProductsLoss(Long salesLedgerId) {
+
+
+        List<LossProductModelDto> lossProductModelDtos = salesLedgerProductMapper.selectProductBomStructure(salesLedgerId);
+
+
+        return lossProductModelDtos;
+    }
+
+
     // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
     private static class GroupedCustomer {
         private final Long customerId;
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 2579a18..67c56c7 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -15,10 +15,10 @@
         <where>
             1=1
             <if test="salesLedgerProduct.salesLedgerId != null and salesLedgerProduct.salesLedgerId != '' ">
-                AND  T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
+                AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
             </if>
             <if test="salesLedgerProduct.type != null and salesLedgerProduct.type != '' ">
-                AND  T1.type = #{salesLedgerProduct.type}
+                AND T1.type = #{salesLedgerProduct.type}
             </if>
         </where>
     </select>
@@ -27,7 +27,7 @@
         from quality_inspect qi
                  left join production_product_main ppm on qi.product_main_id = ppm.id
                  left join product_work_order pwo on ppm.work_order_id = pwo.id
-                 left join product_order  po on pwo.product_order_id = po.id
+                 left join product_order po on pwo.product_order_id = po.id
                  left join sales_ledger_product slp on po.product_model_id = slp.id
         where qi.product_main_id = #{productMainId}
 
@@ -44,22 +44,22 @@
         <where>
             slp.type = 1
             <if test="req.salesContractNo != null and req.salesContractNo != '' ">
-                AND  sl.sales_contract_no like concat('%',#{req.salesContractNo},'%')
+                AND sl.sales_contract_no like concat('%',#{req.salesContractNo},'%')
             </if>
             <if test="req.customerContractNo != null and req.customerContractNo != '' ">
-                AND  sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
+                AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
             </if>
             <if test="req.projectName != null and req.projectName != '' ">
-                AND  sl.project_name like concat('%',#{req.projectName},'%')
+                AND sl.project_name like concat('%',#{req.projectName},'%')
             </if>
             <if test="req.customerName != null and req.customerName != '' ">
-                AND  sl.customer_name like concat('%',#{req.customerName},'%')
+                AND sl.customer_name like concat('%',#{req.customerName},'%')
             </if>
             <if test="req.productCategory != null and req.productCategory != '' ">
-                AND  slp.product_category like concat('%',#{req.productCategory},'%')
+                AND slp.product_category like concat('%',#{req.productCategory},'%')
             </if>
             <if test="req.status != null and req.status ">
-                AND  slp.pending_invoice_total &gt; 0
+                AND slp.pending_invoice_total &gt; 0
             </if>
         </where>
         order by slp.register_date desc
@@ -76,22 +76,22 @@
         <where>
             slp.type = 2
             <if test="req.purchaseContractNumber != null and req.purchaseContractNumber != '' ">
-                AND  sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
+                AND sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
             </if>
             <if test="req.customerContractNo != null and req.customerContractNo != '' ">
-                AND  sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
+                AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
             </if>
             <if test="req.projectName != null and req.projectName != '' ">
-                AND  sl.project_name like concat('%',#{req.projectName},'%')
+                AND sl.project_name like concat('%',#{req.projectName},'%')
             </if>
             <if test="req.customerName != null and req.customerName != '' ">
-                AND  sl.customer_name like concat('%',#{req.customerName},'%')
+                AND sl.customer_name like concat('%',#{req.customerName},'%')
             </if>
             <if test="req.productCategory != null and req.productCategory != '' ">
-                AND  slp.product_category like concat('%',#{req.productCategory},'%')
+                AND slp.product_category like concat('%',#{req.productCategory},'%')
             </if>
             <if test="req.status != null and req.status ">
-                AND  slp.pending_invoice_total &gt; 0
+                AND slp.pending_invoice_total &gt; 0
             </if>
         </where>
         order by slp.register_date desc
@@ -126,4 +126,25 @@
         <!-- 鎸変骇鍝佸ぇ绫绘帓搴� -->
         ORDER BY slp.product_category
     </select>
+    <select id="selectProductBomStructure" resultType="com.ruoyi.sales.dto.LossProductModelDto">
+        select
+            a.model,
+            a.product_name,
+            a.unit,
+            sum(a.single_quantity) AS loss_num
+        from (SELECT ps.unit,
+                     ps.unit_quantity,
+                     pm1.model,
+                     p.product_name,
+                     ps.unit_quantity * slp.quantity AS single_quantity
+              FROM sales_ledger sl
+                       LEFT JOIN sales_ledger_product slp ON slp.sales_ledger_id = sl.id
+                       LEFT JOIN product_model pm ON pm.id = slp.product_model_id
+                       LEFT JOIN product_bom pb ON pb.product_model_id = pm.id
+                       LEFT JOIN product_structure ps ON pb.id = ps.bom_id
+                       LEFT JOIN product_model pm1 ON pm1.id = ps.product_model_id
+                       LEFT JOIN product p ON p.id = pm1.product_id
+              WHERE sl.id = #{salesLedegerId}) A
+        group by a.model, a.product_name, a.unit
+    </select>
 </mapper>
\ No newline at end of file

--
Gitblit v1.9.3