From 3faea5bad90c8e55e8bf83f7a9c603f789ed6c84 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 10 四月 2026 11:41:46 +0800
Subject: [PATCH] feat: 原料生产统计单耗表接口

---
 src/main/java/com/ruoyi/home/controller/HomeController.java    |   13 ++-
 src/main/java/com/ruoyi/home/service/HomeService.java          |    2 
 src/main/java/com/ruoyi/home/dto/RawMaterialProductionDto.java |   42 ++++++++++
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java |  149 +++++++++++++++++++++++++++++++++++++
 4 files changed, 202 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/ruoyi/home/controller/HomeController.java b/src/main/java/com/ruoyi/home/controller/HomeController.java
index b3702c2..9e20d0e 100644
--- a/src/main/java/com/ruoyi/home/controller/HomeController.java
+++ b/src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -12,10 +12,7 @@
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.text.ParseException;
 import java.util.List;
@@ -425,4 +422,12 @@
         return AjaxResult.success(list);
     }
 
+
+    @GetMapping("/rawMaterialProductions/{month}")
+    @ApiOperation("鎴愭湰鏍哥畻-鍘熸枡鐢熶骇缁熻鍗曡�楄〃")
+    public AjaxResult rawMaterialProductions(@PathVariable String month){
+        List<RawMaterialProductionDto> list = homeService.rawMaterialProductions(month);
+        return AjaxResult.success(list);
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/home/dto/RawMaterialProductionDto.java b/src/main/java/com/ruoyi/home/dto/RawMaterialProductionDto.java
new file mode 100644
index 0000000..1e8ebbc
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/RawMaterialProductionDto.java
@@ -0,0 +1,42 @@
+package com.ruoyi.home.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鎴愭湰鏍哥畻-鍘熸枡鐢熶骇缁熻鍗曡�楄〃 DTO
+ */
+@Data
+@ApiModel("鎴愭湰鏍哥畻-鍘熸枡鐢熶骇缁熻鍗曡�楄〃璁板綍")
+public class RawMaterialProductionDto {
+
+    @ApiModelProperty("椤圭洰鍚嶇О")
+    private String itemName;
+
+    @ApiModelProperty("3.5 鐢ㄩ噺/浜ч噺")
+    private BigDecimal usage35;
+
+    @ApiModelProperty("3.5 鍗曡��")
+    private BigDecimal unitConsumption35;
+
+    @ApiModelProperty("5.0 鐢ㄩ噺/浜ч噺")
+    private BigDecimal usage50;
+
+    @ApiModelProperty("5.0 鍗曡��")
+    private BigDecimal unitConsumption50;
+
+    @ApiModelProperty("鏉挎潗 鐢ㄩ噺/浜ч噺")
+    private BigDecimal usagePlate;
+
+    @ApiModelProperty("鏉挎潗 鍗曡��")
+    private BigDecimal unitConsumptionPlate;
+
+    @ApiModelProperty("鏈堝疄闄呯敤閲�/鎬讳骇閲�")
+    private BigDecimal totalUsage;
+
+    @ApiModelProperty("鐮屽潡鍚堣锛�3.5 + 5.0锛�")
+    private BigDecimal blockTotalUsage;
+}
diff --git a/src/main/java/com/ruoyi/home/service/HomeService.java b/src/main/java/com/ruoyi/home/service/HomeService.java
index 21eb624..e5dba40 100644
--- a/src/main/java/com/ruoyi/home/service/HomeService.java
+++ b/src/main/java/com/ruoyi/home/service/HomeService.java
@@ -125,4 +125,6 @@
     Map<String,Long> manage();
 
     List<PlanTrendsDto> planTrends(Integer type);
+
+    List<RawMaterialProductionDto> rawMaterialProductions(String month);
 }
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index cc1445b..acd2b54 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3645,5 +3645,154 @@
 
         return new ArrayList<>(resultMap.values());
     }
+    @Override
+    public List<RawMaterialProductionDto> rawMaterialProductions(String month) {
+        YearMonth yearMonth;
+        try {
+            yearMonth = YearMonth.parse(month);
+        } catch (Exception e) {
+            log.error("瑙f瀽鏈堜唤澶辫触: {}", month);
+            return Collections.emptyList();
+        }
+        LocalDateTime monthStart = yearMonth.atDay(1).atStartOfDay();
+        LocalDateTime monthEnd = yearMonth.atEndOfMonth().atTime(LocalTime.MAX);
+
+        //  鑾峰彇浜у搧绫诲瀷瀛楀吀
+        List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type");
+        Map<Long, String> dictCodeToLabelMap = sysDictDataList.stream()
+                .filter(d -> d.getDictCode() != null && d.getDictLabel() != null)
+                .collect(Collectors.toMap(SysDictData::getDictCode, SysDictData::getDictLabel));
+
+        //  鏌ヨ褰撴湀鎶ュ伐涓昏〃
+        List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+                .between(ProductionProductMain::getReportingTime, monthStart, monthEnd));
+
+        if (CollectionUtils.isEmpty(mainList)) {
+            return Collections.emptyList();
+        }
+
+        List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+        List<Long> orderIds = mainList.stream().map(ProductionProductMain::getProductOrderId).distinct().collect(Collectors.toList());
+        Map<Long, ProductionProductMain> mainMap = mainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+        //  鑾峰彇璁㈠崟瀵瑰簲鐨勪骇鍝佺被鍨�
+        Map<Long, Long> orderRouteMap = new HashMap<>();
+        if (!CollectionUtils.isEmpty(orderIds)) {
+            List<ProductionOrderRoute> routes = productionOrderRouteService.list(Wrappers.<ProductionOrderRoute>lambdaQuery()
+                    .in(ProductionOrderRoute::getOrderId, orderIds));
+            orderRouteMap = routes.stream()
+                    .filter(r -> r.getOrderId() != null && r.getDictCode() != null)
+                    .collect(Collectors.toMap(ProductionOrderRoute::getOrderId, ProductionOrderRoute::getDictCode, (v1, v2) -> v1));
+        }
+
+        //  鑾峰彇鎶曞叆鍜屼骇鍑烘槑缁�
+        List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+                .in(ProductionProductInput::getProductMainId, mainIds));
+        List<ProductionProductOutput> allOutputs = productionProductOutputService.list(Wrappers.<ProductionProductOutput>lambdaQuery()
+                .in(ProductionProductOutput::getProductMainId, mainIds));
+
+        //  鑾峰彇 SKU 鐨勭墿鏂欏悕绉�
+        Set<Long> inputSkuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+        Map<Long, String> skuToMaterialNameMap = new HashMap<>();
+        if (!inputSkuIds.isEmpty()) {
+            List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(inputSkuIds);
+            Set<Long> productIds = skus.stream().map(ProductMaterialSku::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+            Map<Long, String> materialNameMap = productMaterialService.listByIds(productIds).stream()
+                    .collect(Collectors.toMap(ProductMaterial::getId, ProductMaterial::getProductName));
+            skuToMaterialNameMap = skus.stream()
+                    .filter(s -> s.getProductId() != null && materialNameMap.containsKey(s.getProductId()))
+                    .collect(Collectors.toMap(ProductMaterialSku::getId, s -> materialNameMap.get(s.getProductId())));
+        }
+
+        BigDecimal yield35 = BigDecimal.ZERO;
+        BigDecimal yield50 = BigDecimal.ZERO;
+        BigDecimal yieldPlate = BigDecimal.ZERO;
+
+        // 鏉愯川鍚嶇О -> [3.5鐢ㄩ噺, 5.0鐢ㄩ噺, 鏉挎潗鐢ㄩ噺]
+        Map<String, BigDecimal[]> materialConsumptionMap = new LinkedHashMap<>();
+
+        //  缁熻浜ч噺
+        for (ProductionProductOutput output : allOutputs) {
+            ProductionProductMain main = mainMap.get(output.getProductMainId());
+            if (main == null) continue;
+            Long dictCode = orderRouteMap.get(main.getProductOrderId());
+            String label = dictCodeToLabelMap.get(dictCode);
+            BigDecimal qty = output.getQuantity() != null ? output.getQuantity() : BigDecimal.ZERO;
+
+            if (label != null) {
+                if (label.contains("3.5")) yield35 = yield35.add(qty);
+                else if (label.contains("5.0")) yield50 = yield50.add(qty);
+                else if (label.contains("鏉挎潗")) yieldPlate = yieldPlate.add(qty);
+            }
+        }
+
+        //  缁熻娑堣�楅噺
+        for (ProductionProductInput input : allInputs) {
+            ProductionProductMain main = mainMap.get(input.getProductMainId());
+            if (main == null) continue;
+            Long dictCode = orderRouteMap.get(main.getProductOrderId());
+            String label = dictCodeToLabelMap.get(dictCode);
+            String materialName = skuToMaterialNameMap.get(input.getProductId());
+            if (materialName == null) continue;
+
+            BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+
+            materialConsumptionMap.putIfAbsent(materialName, new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO});
+            BigDecimal[] consumptions = materialConsumptionMap.get(materialName);
+
+            if (label != null) {
+                if (label.contains("3.5")) consumptions[0] = consumptions[0].add(qty);
+                else if (label.contains("5.0")) consumptions[1] = consumptions[1].add(qty);
+                else if (label.contains("鏉挎潗")) consumptions[2] = consumptions[2].add(qty);
+            }
+        }
+
+        List<RawMaterialProductionDto> result = new ArrayList<>();
+
+        // 浜ч噺琛�
+        RawMaterialProductionDto yieldRow = new RawMaterialProductionDto();
+        yieldRow.setItemName("浜ч噺");
+        yieldRow.setUsage35(yield35);
+        yieldRow.setUsage50(yield50);
+        yieldRow.setUsagePlate(yieldPlate);
+        yieldRow.setTotalUsage(yield35.add(yield50).add(yieldPlate));
+        yieldRow.setBlockTotalUsage(yield35.add(yield50));
+        result.add(yieldRow);
+
+        // 鐗╂枡琛�
+        List<String> targetMaterials = Arrays.asList(
+                "绮夌叅鐏�", "姘存偿", "鐭崇伆", "閾濈矇", "鐭宠啅", "鑴辨ā鍓�",
+                "鎵撳寘甯�", "鍐锋嫈涓�", "姘у寲闀�", "鍗℃墸", "闃茶厫鍓�"
+        );
+
+        for (String materialName : targetMaterials) {
+            BigDecimal[] consumptions = materialConsumptionMap.getOrDefault(materialName, 
+                    new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO});
+
+            RawMaterialProductionDto row = new RawMaterialProductionDto();
+            row.setItemName(materialName);
+            row.setUsage35(consumptions[0]);
+            row.setUsage50(consumptions[1]);
+            row.setUsagePlate(consumptions[2]);
+            
+            // 璁$畻鍗曡��
+            row.setUnitConsumption35(calculateUnitConsumption(consumptions[0], yield35));
+            row.setUnitConsumption50(calculateUnitConsumption(consumptions[1], yield50));
+            row.setUnitConsumptionPlate(calculateUnitConsumption(consumptions[2], yieldPlate));
+
+            row.setTotalUsage(consumptions[0].add(consumptions[1]).add(consumptions[2]));
+            row.setBlockTotalUsage(consumptions[0].add(consumptions[1]));
+            result.add(row);
+        }
+
+        return result;
+    }
+
+    private BigDecimal calculateUnitConsumption(BigDecimal usage, BigDecimal yield) {
+        if (yield == null || yield.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO;
+        }
+        return usage.divide(yield, 4, RoundingMode.HALF_UP);
+    }
 
 }

--
Gitblit v1.9.3