From fe4d8530e45569a8b17886f4bd050e96e187fb8d Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 30 三月 2026 16:26:24 +0800
Subject: [PATCH] feat: 生产成品核算报表接口,生产订单绑定工艺路线
---
src/main/java/com/ruoyi/production/dto/ProductionCostAccountDto.java | 42 ++
src/main/java/com/ruoyi/production/utils/UnitUtils.java | 66 ++++
src/main/java/com/ruoyi/production/mapper/ProductionOrderRouteMapper.java | 16 +
src/main/java/com/ruoyi/production/controller/ProductionCostAccountController.java | 72 ++++
src/main/java/com/ruoyi/production/vo/ProductionCostSummaryVo.java | 33 ++
src/main/java/com/ruoyi/production/controller/ProductionOrderRouteController.java | 20 +
src/main/resources/mapper/production/ProductionOrderRouteMapper.xml | 20 +
src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java | 194 ++++++++++++
src/main/java/com/ruoyi/production/dto/GroupKeyDto.java | 61 +++
src/main/java/com/ruoyi/production/vo/ProductionCostAggregationVo.java | 46 ++
src/main/java/com/ruoyi/production/vo/ProductionCostDetailVo.java | 51 +++
src/main/resources/mapper/production/ProductOrderMapper.xml | 2
doc/宁夏-中盛建材.sql | 24 +
src/main/java/com/ruoyi/production/mapper/ProductionCostMapper.java | 31 +
src/main/java/com/ruoyi/production/service/impl/ProductionOrderRouteServiceImpl.java | 20 +
src/main/java/com/ruoyi/production/service/impl/ProductionOrderAppendixServiceImpl.java | 56 ++
src/main/java/com/ruoyi/production/service/ProductionCostService.java | 46 ++
src/main/java/com/ruoyi/production/service/IProductionOrderRouteService.java | 16 +
src/main/resources/mapper/production/ProductionCostMapper.xml | 89 +++++
19 files changed, 889 insertions(+), 16 deletions(-)
diff --git "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql" "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
index 7ea4756..9f95867 100644
--- "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
+++ "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
@@ -446,4 +446,26 @@
DROP COLUMN `dict_code`;
ALTER TABLE `product-inventory-management-zsjc`.`production_product_output`
- ADD COLUMN `total_quantity` decimal(20, 15) NULL COMMENT '鎬绘暟閲�' AFTER `scrap_qty`;
\ No newline at end of file
+ ADD COLUMN `total_quantity` decimal(20, 15) NULL COMMENT '鎬绘暟閲�' AFTER `scrap_qty`;
+
+CREATE TABLE `production_order_route`
+(
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+ `order_id` bigint NOT NULL COMMENT '鍏宠仈鐢熶骇璁㈠崟ID (production_order.id)',
+ `process_route_id` bigint DEFAULT NULL COMMENT '鍘熷宸ヨ壓璺嚎ID (process_route.id)',
+ `product_model_id` bigint DEFAULT '0' COMMENT '浜у搧id',
+ `process_route_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '宸ヨ壓璺嚎缂栫爜',
+ `bom_id` int DEFAULT NULL COMMENT '鍏宠仈bom鐨刬d',
+ `dict_code` bigint NOT NULL COMMENT '浜у搧绫诲瀷瀛楀吀缂栫爜',
+ `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '鎻忚堪',
+ `tenant_id` bigint NOT NULL COMMENT '绉熸埛id',
+ `create_by` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` datetime DEFAULT NULL COMMENT '褰曞叆鏃堕棿',
+ `update_by` varchar(64) DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+ `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+ PRIMARY KEY (`id`) USING BTREE,
+ KEY `idx_order_id` (`order_id`) USING BTREE
+) ENGINE = InnoDB
+ DEFAULT CHARSET = utf8mb4
+ COLLATE = utf8mb4_0900_ai_ci COMMENT ='鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃';
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionCostAccountController.java b/src/main/java/com/ruoyi/production/controller/ProductionCostAccountController.java
new file mode 100644
index 0000000..359bd5c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionCostAccountController.java
@@ -0,0 +1,72 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.production.dto.ProductionCostAccountDto;
+import com.ruoyi.production.service.ProductionCostService;
+import com.ruoyi.production.vo.ProductionCostAggregationVo;
+import com.ruoyi.production.vo.ProductionCostDetailVo;
+import com.ruoyi.production.vo.ProductionCostSummaryVo;
+import io.swagger.annotations.ApiModel;
+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.RestController;
+import java.util.List;
+
+/**
+ * <br>
+ * 鎴愭湰鏍哥畻鎺у埗灞�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@RestController
+@RequestMapping("/cost")
+@ApiModel(value = "ProductionCostAccountController绫�", description = "鎴愭湰鏍哥畻鎺у埗灞�")
+public class ProductionCostAccountController {
+
+ @Autowired
+ private ProductionCostService productionCostService;
+
+ //**************************************************** 鐢熶骇鎴愬搧鏍哥畻 ***************************************************** //
+
+ @GetMapping("/productionCost/summary")
+ @ApiOperation("椤堕儴缁熻鍗$墖鏁版嵁")
+ public AjaxResult getCostSummary(ProductionCostAccountDto dto) {
+ ProductionCostSummaryVo costSummary = productionCostService.getCostSummary(dto);
+ return AjaxResult.success(costSummary);
+ }
+
+ @GetMapping("/productionCost/aggregate/product")
+ @ApiOperation("鎸変骇鍝佺墿鏂欐眹鎬�(鍒嗛〉)")
+ public AjaxResult getProductAggregation(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto) {
+ IPage<ProductionCostAggregationVo> aggregation = productionCostService.getProductAggregationPage(page, dto);
+ return AjaxResult.success(aggregation);
+ }
+
+ @GetMapping("/productionCost/aggregate/order")
+ @ApiOperation("鎸夌敓浜ц鍗曟眹鎬�(鍒嗛〉)")
+ public AjaxResult getOrderAggregation(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto) {
+ IPage<ProductionCostAggregationVo> aggregation = productionCostService.getOrderAggregationPage(page, dto);
+ return AjaxResult.success(aggregation);
+ }
+
+ @GetMapping("/productionCost/top/product")
+ @ApiOperation("娑堣�楁帓琛屾-浜у搧鐗╂枡Top10")
+ public AjaxResult getProductTop10(ProductionCostAccountDto dto) {
+ List<ProductionCostAggregationVo> list = productionCostService.getProductTop(dto);
+ return AjaxResult.success(list);
+ }
+
+ @GetMapping("/productionCost/top/order")
+ @ApiOperation("鎴愭湰鎺掕姒�-鐢熶骇璁㈠崟Top10")
+ public AjaxResult getOrderTop10(ProductionCostAccountDto dto) {
+ List<ProductionCostAggregationVo> list = productionCostService.getOrderTop(dto);
+ return AjaxResult.success(list);
+ }
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderRouteController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderRouteController.java
new file mode 100644
index 0000000..4d12d2e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderRouteController.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@RestController
+@RequestMapping("/production-order-route")
+public class ProductionOrderRouteController {
+
+}
diff --git a/src/main/java/com/ruoyi/production/dto/GroupKeyDto.java b/src/main/java/com/ruoyi/production/dto/GroupKeyDto.java
new file mode 100644
index 0000000..afda6c4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/dto/GroupKeyDto.java
@@ -0,0 +1,61 @@
+package com.ruoyi.production.dto;
+
+import com.ruoyi.production.service.impl.ProductionCostServiceImpl;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+/**
+ * <br>
+ * 鑱氬悎鍒嗙粍 Key 瀵硅薄
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30 16:16
+ */
+@ApiModel(value = "GroupKeyDto绫�", description = "鑱氬悎鍒嗙粍 Key 瀵硅薄")
+public class GroupKeyDto {
+
+ @ApiModelProperty("鏃ユ湡")
+ private final LocalDateTime date;
+
+ @ApiModelProperty("绫诲埆/璁㈠崟鍚嶇О")
+ private final String name;
+
+ @ApiModelProperty("瑙勬牸鍨嬪彿")
+ private final String model;
+
+ @ApiModelProperty("浜у搧绫诲瀷/寮哄害")
+ private final String strength;
+
+ @ApiModelProperty("鍗曚綅")
+ private final String unit;
+
+ public GroupKeyDto(LocalDateTime date, String name, String model, String strength, String unit) {
+ this.date = date;
+ this.name = name;
+ this.model = model;
+ this.strength = strength;
+ this.unit = unit;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ GroupKeyDto groupKey = (GroupKeyDto) o;
+ return Objects.equals(date, groupKey.date) &&
+ Objects.equals(name, groupKey.name) &&
+ Objects.equals(model, groupKey.model) &&
+ Objects.equals(strength, groupKey.strength) &&
+ Objects.equals(unit, groupKey.unit);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(date, name, model, strength, unit);
+ }
+}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionCostAccountDto.java b/src/main/java/com/ruoyi/production/dto/ProductionCostAccountDto.java
new file mode 100644
index 0000000..e0db06c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/dto/ProductionCostAccountDto.java
@@ -0,0 +1,42 @@
+package com.ruoyi.production.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+/**
+ * <br>
+ * 鎴愭湰鏍哥畻Dto
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@Data
+@ApiModel(value = "ProductionCostAccountDto绫�", description = "鎴愭湰鏍哥畻Dto")
+public class ProductionCostAccountDto {
+
+ @ApiModelProperty("璧峰鏃堕棿")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+ private LocalDate startDate;
+
+ @ApiModelProperty("鎴鏃ユ湡")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+ private LocalDate endDate;
+
+ @ApiModelProperty("浜у搧绫诲埆瀛楀吀")
+ private Long dictCode;
+
+ @ApiModelProperty("鐢熶骇璁㈠崟Id")
+ private Long productOrderId;
+
+ @ApiModelProperty("鍒嗙粍绫诲瀷锛�1: 鎸変骇鍝佺被鍒眹鎬�, 2: 鎸夌敓浜ц鍗曟眹鎬伙級")
+ private Integer groupType;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionCostMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionCostMapper.java
new file mode 100644
index 0000000..2ca31d9
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionCostMapper.java
@@ -0,0 +1,31 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.production.dto.ProductionCostAccountDto;
+import com.ruoyi.production.vo.ProductionCostAggregationVo;
+import com.ruoyi.production.vo.ProductionCostDetailVo;
+import com.ruoyi.production.vo.ProductionCostSummaryVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface ProductionCostMapper {
+
+ /**
+ * 鏌ヨ鐢熶骇鎴愭湰姹囨��
+ */
+ ProductionCostSummaryVo selectCostSummary(@Param("dto") ProductionCostAccountDto dto);
+
+ /**
+ * 鎸変骇鍝佺被鍒眹鎬绘垚鏈�
+ */
+ List<ProductionCostAggregationVo> selectCostAggregationByCategory(@Param("dto") ProductionCostAccountDto dto);
+
+ /**
+ * 鎸夌敓浜ц鍗曟眹鎬绘垚鏈�
+ */
+ List<ProductionCostAggregationVo> selectCostAggregationByOrder(@Param("dto") ProductionCostAccountDto dto);
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderRouteMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRouteMapper.java
new file mode 100644
index 0000000..54e595e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRouteMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.mapper;
+
+import com.ruoyi.production.pojo.ProductionOrderRoute;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface ProductionOrderRouteMapper extends BaseMapper<ProductionOrderRoute> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/IProductionOrderRouteService.java b/src/main/java/com/ruoyi/production/service/IProductionOrderRouteService.java
new file mode 100644
index 0000000..2fbcb67
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/IProductionOrderRouteService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.service;
+
+import com.ruoyi.production.pojo.ProductionOrderRoute;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface IProductionOrderRouteService extends IService<ProductionOrderRoute> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionCostService.java b/src/main/java/com/ruoyi/production/service/ProductionCostService.java
new file mode 100644
index 0000000..2c9e5e3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionCostService.java
@@ -0,0 +1,46 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.dto.ProductionCostAccountDto;
+import com.ruoyi.production.vo.ProductionCostAggregationVo;
+import com.ruoyi.production.vo.ProductionCostDetailVo;
+import com.ruoyi.production.vo.ProductionCostSummaryVo;
+import java.util.List;
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰鏍哥畻鏈嶅姟鎺ュ彛
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30 11:20
+ */
+public interface ProductionCostService {
+
+ /**
+ * 鑾峰彇姹囨�诲崱鐗囨暟鎹�
+ */
+ ProductionCostSummaryVo getCostSummary(ProductionCostAccountDto dto);
+
+ /**
+ * 鎸変骇鍝佺被鍒垎椤佃幏鍙栬仛鍚堟眹鎬绘暟鎹�
+ */
+ IPage<ProductionCostAggregationVo> getProductAggregationPage(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto);
+
+ /**
+ * 鎸夎鍗曞垎椤佃幏鍙栬仛鍚堟眹鎬绘暟鎹�
+ */
+ IPage<ProductionCostAggregationVo> getOrderAggregationPage(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto);
+
+ /**
+ * 鑾峰彇娑堣�楁渶楂樼殑鍓�10鍚嶄骇鍝佺墿鏂�
+ */
+ List<ProductionCostAggregationVo> getProductTop(ProductionCostAccountDto dto);
+
+ /**
+ * 鑾峰彇鎴愭湰鏈�楂樼殑鍓�10涓敓浜ц鍗�
+ */
+ List<ProductionCostAggregationVo> getOrderTop(ProductionCostAccountDto dto);
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
new file mode 100644
index 0000000..25a32aa
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
@@ -0,0 +1,194 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.dto.GroupKeyDto;
+import com.ruoyi.production.dto.ProductionCostAccountDto;
+import com.ruoyi.production.mapper.ProductionCostMapper;
+import com.ruoyi.production.service.ProductionCostService;
+import com.ruoyi.production.utils.UnitUtils;
+import com.ruoyi.production.vo.ProductionCostAggregationVo;
+import com.ruoyi.production.vo.ProductionCostSummaryVo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰鏍哥畻鏈嶅姟鎺ュ彛瀹炵幇绫�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30 11:21
+ */
+@Slf4j
+@Service
+public class ProductionCostServiceImpl implements ProductionCostService {
+
+ @Autowired
+ private ProductionCostMapper productionCostMapper;
+
+ @Override
+ public ProductionCostSummaryVo getCostSummary(ProductionCostAccountDto dto) {
+ if (dto.getEndDate() != null) {
+ dto.setEndDate(dto.getEndDate().plusDays(1));
+ }
+ return productionCostMapper.selectCostSummary(dto);
+ }
+
+ @Override
+ public IPage<ProductionCostAggregationVo> getProductAggregationPage(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto) {
+ dto.setGroupType(1); // 鎸変骇鍝佹眹鎬�
+ List<ProductionCostAggregationVo> fullList = getCostAggregationList(dto);
+ return getMemoryPage(page, fullList);
+ }
+
+ @Override
+ public IPage<ProductionCostAggregationVo> getOrderAggregationPage(Page<ProductionCostAggregationVo> page, ProductionCostAccountDto dto) {
+ dto.setGroupType(2); // 鎸夎鍗曟眹鎬�
+ List<ProductionCostAggregationVo> fullList = getCostAggregationList(dto);
+ return getMemoryPage(page, fullList);
+ }
+
+ @Override
+ public List<ProductionCostAggregationVo> getProductTop(ProductionCostAccountDto dto) {
+ dto.setGroupType(1);
+ List<ProductionCostAggregationVo> fullList = getCostAggregationList(dto);
+ if (fullList.isEmpty()) {
+ return new ArrayList<>();
+ }
+
+ Map<String, ProductionCostAggregationVo> topMap = new HashMap<>();
+ for (ProductionCostAggregationVo vo : fullList) {
+ String name = vo.getName();
+ if (topMap.containsKey(name)) {
+ ProductionCostAggregationVo existing = topMap.get(name);
+ existing.setTotalCost(existing.getTotalCost().add(vo.getTotalCost()));
+ existing.setQuantity(existing.getQuantity().add(vo.getQuantity()));
+ } else {
+ ProductionCostAggregationVo clone = new ProductionCostAggregationVo();
+ clone.setName(name);
+ clone.setTotalCost(vo.getTotalCost());
+ clone.setQuantity(vo.getQuantity());
+ clone.setUnit(vo.getUnit());
+ topMap.put(name, clone);
+ }
+ }
+
+ return topMap.values().stream()
+ .sorted(Comparator.comparing(ProductionCostAggregationVo::getTotalCost).reversed())
+ .limit(10)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<ProductionCostAggregationVo> getOrderTop(ProductionCostAccountDto dto) {
+ dto.setGroupType(2);
+ List<ProductionCostAggregationVo> fullList = getCostAggregationList(dto);
+ if (fullList.isEmpty()) {
+ return new ArrayList<>();
+ }
+
+ Map<String, ProductionCostAggregationVo> topMap = new HashMap<>();
+ for (ProductionCostAggregationVo vo : fullList) {
+ String orderNo = vo.getName();
+ if (topMap.containsKey(orderNo)) {
+ ProductionCostAggregationVo existing = topMap.get(orderNo);
+ existing.setTotalCost(existing.getTotalCost().add(vo.getTotalCost()));
+ } else {
+ ProductionCostAggregationVo clone = new ProductionCostAggregationVo();
+ clone.setName(orderNo);
+ clone.setTotalCost(vo.getTotalCost());
+ clone.setStrength(vo.getStrength());
+ topMap.put(orderNo, clone);
+ }
+ }
+
+ return topMap.values().stream()
+ .sorted(Comparator.comparing(ProductionCostAggregationVo::getTotalCost).reversed())
+ .limit(10)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 鑾峰彇鍏ㄩ噺鑱氬悎姹囨�绘暟鎹�
+ */
+ private List<ProductionCostAggregationVo> getCostAggregationList(ProductionCostAccountDto dto) {
+ if (dto.getEndDate() != null) {
+ dto.setEndDate(dto.getEndDate().plusDays(1));
+ }
+
+ List<ProductionCostAggregationVo> rawList;
+ boolean isOrderAggregation = (dto.getGroupType() != null && dto.getGroupType() == 2);
+ if (isOrderAggregation) {
+ rawList = productionCostMapper.selectCostAggregationByOrder(dto);
+ } else {
+ rawList = productionCostMapper.selectCostAggregationByCategory(dto);
+ }
+
+ if (rawList == null || rawList.isEmpty()) {
+ return rawList != null ? rawList : new ArrayList<>();
+ }
+
+ Map<GroupKeyDto, ProductionCostAggregationVo> aggregationMap = new LinkedHashMap<>();
+ for (ProductionCostAggregationVo vo : rawList) {
+ String originalUnit = vo.getUnit();
+ String normalizedUnit = UnitUtils.normalizeUnit(originalUnit);
+ BigDecimal convertedQty = UnitUtils.convertValueToTon(vo.getQuantity(), originalUnit);
+
+ // 鏍规嵁姹囨�绘ā寮忚缃� Key 鍜屾樉绀哄垪
+ GroupKeyDto key;
+ if (isOrderAggregation) {
+ // 鎸夎鍗曟眹鎬伙細Key = 鏃ユ湡 + 璁㈠崟鍙� + 鍘熸枡鍚� + 鍘熸枡瑙勬牸 + 鍗曚綅
+ key = new GroupKeyDto(vo.getDate(), vo.getName(), vo.getModel(), vo.getStrength(), normalizedUnit);
+ } else {
+ // 鎸変骇鍝佹眹鎬伙細Key = 鏃ユ湡 + 鍘熸枡鍚� + 鍘熸枡瑙勬牸 + 鍗曚綅
+ key = new GroupKeyDto(vo.getDate(), vo.getName(), vo.getModel(), null, normalizedUnit);
+ vo.setStrength(null);
+ }
+
+ if (aggregationMap.containsKey(key)) {
+ ProductionCostAggregationVo existing = aggregationMap.get(key);
+ existing.setQuantity(existing.getQuantity().add(convertedQty));
+ existing.setTotalCost(existing.getTotalCost().add(vo.getTotalCost()));
+ } else {
+ vo.setUnit(normalizedUnit);
+ vo.setQuantity(convertedQty);
+ aggregationMap.put(key, vo);
+ }
+ }
+
+ List<ProductionCostAggregationVo> resultList = new ArrayList<>(aggregationMap.values());
+ for (ProductionCostAggregationVo vo : resultList) {
+ if (vo.getQuantity() != null) {
+ vo.setQuantity(vo.getQuantity().setScale(2, RoundingMode.HALF_UP));
+ }
+ if (vo.getTotalCost() != null) {
+ vo.setTotalCost(vo.getTotalCost().setScale(2, RoundingMode.HALF_UP));
+ }
+ }
+
+ return resultList;
+ }
+
+ private <T> IPage<T> getMemoryPage(Page<T> page, List<T> list) {
+ int total = list.size();
+ int size = (int) page.getSize();
+ int current = (int) page.getCurrent();
+ int fromIndex = (current - 1) * size;
+ int toIndex = Math.min(fromIndex + size, total);
+
+ List<T> subList = (fromIndex < total && fromIndex >= 0) ? list.subList(fromIndex, toIndex) : new ArrayList<>();
+
+ page.setTotal(total);
+ page.setRecords(subList);
+ return page;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderAppendixServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderAppendixServiceImpl.java
index bc6d03e..65b79bb 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderAppendixServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderAppendixServiceImpl.java
@@ -57,6 +57,9 @@
@Resource
private ProductOrderService productOrderService;
+ @Resource
+ private IProductionOrderRouteService productionOrderRouteService;
+
@Override
public Long populateBlocks(Long orderId, ProductionPlanDto productionPlanDto) {
if (productionPlanDto == null) {
@@ -70,8 +73,12 @@
log.info("涓嬪彂浜у搧銆恵}銆戞湭鏌ヨ鍑哄伐鑹鸿矾绾�", productionPlanDto.getProductName());
return null;
}
- migration(orderId, processRoute);
- return processRoute.getId();
+
+ // 鍒涘缓宸ヨ壓璺嚎
+ ProductionOrderRoute productionOrderRoute = createOrderRouteSnapshot(orderId, processRoute);
+ migration(orderId, processRoute, productionOrderRoute.getId());
+
+ return productionOrderRoute.getId();
}
@Override
@@ -85,8 +92,12 @@
log.info("涓嬪彂浜у搧銆恵}銆戞湭鏌ヨ鍑哄伐鑹鸿矾绾�", productionPlanDto.getProductName());
return null;
}
- migration(orderId, processRoute);
- return processRoute.getId();
+
+ // 鍒涘缓宸ヨ壓璺嚎
+ ProductionOrderRoute productionOrderRoute = createOrderRouteSnapshot(orderId, processRoute);
+ migration(orderId, processRoute, productionOrderRoute.getId());
+
+ return productionOrderRoute.getId();
}
@Override
@@ -101,14 +112,27 @@
if (processRoute == null) {
throw new ServiceException("璇ュ伐鑹鸿矾绾夸笉瀛樺湪,缁戝畾澶辫触");
}
- migration(productOrder.getId(), processRoute);
- // 鍥炲啓宸ヨ壓璺嚎id鍒扮敓浜ц鍗�
+ // 鍒涘缓宸ヨ壓璺嚎
+ ProductionOrderRoute productionOrderRoute = createOrderRouteSnapshot(productOrder.getId(), processRoute);
+ migration(productOrder.getId(), processRoute, productionOrderRoute.getId());
+
+ // 鍥炲啓鏂扮殑宸ヨ壓璺嚎ID鍒扮敓浜ц鍗�
+ productOrder.setRouteId(productionOrderRoute.getId());
productOrderService.updateById(productOrder);
}
+ private ProductionOrderRoute createOrderRouteSnapshot(Long orderId, ProcessRoute processRoute) {
+ ProductionOrderRoute snapshot = new ProductionOrderRoute();
+ BeanUtils.copyProperties(processRoute, snapshot, "id", "createTime", "updateTime", "tenantId");
+ snapshot.setOrderId(orderId);
+ snapshot.setProcessRouteId(processRoute.getId());
+ productionOrderRouteService.save(snapshot);
+ return snapshot;
+ }
+
@Override
- public void deleteData(Long orderId, Long processRouteId) {
+ public void deleteData(Long orderId, Long snapshotRouteId) {
// 鍒犻櫎宸ヨ壓璺嚎宸ュ簭鍙傛暟闄勮〃
productionOrderRouteItemParamService.remove(new LambdaQueryWrapper<ProductionOrderRouteItemParam>()
.eq(ProductionOrderRouteItemParam::getOrderId, orderId));
@@ -116,25 +140,28 @@
// 鍒犻櫎宸ヨ壓璺嚎瀛愰泦闄勮〃
productionOrderRouteItemService.remove(new LambdaQueryWrapper<ProductionOrderRouteItem>()
.eq(ProductionOrderRouteItem::getOrderId, orderId)
- .eq(ProductionOrderRouteItem::getRouteId, processRouteId));
+ .eq(ProductionOrderRouteItem::getRouteId, snapshotRouteId));
+
+ // 鍒犻櫎宸ヨ壓璺嚎
+ productionOrderRouteService.removeById(snapshotRouteId);
// 鍒犻櫎BOM瀛愰泦闄勮〃
- ProcessRoute processRoute = processRouteService.getById(processRouteId);
- if (processRoute != null && processRoute.getBomId() != null) {
+ ProductionOrderRoute snapshot = productionOrderRouteService.getById(snapshotRouteId);
+ if (snapshot != null && snapshot.getBomId() != null) {
productionOrderStructureService.remove(new LambdaQueryWrapper<ProductionOrderStructure>()
.eq(ProductionOrderStructure::getOrderId, orderId)
- .eq(ProductionOrderStructure::getBomId, processRoute.getBomId()));
+ .eq(ProductionOrderStructure::getBomId, snapshot.getBomId().longValue()));
}
}
/**
* 鏍规嵁宸ヨ壓璺嚎杩佺Щ闄勮〃鏁版嵁
*/
- private void migration(Long orderId, ProcessRoute processRoute) {
+ private void migration(Long orderId, ProcessRoute processRoute, Long newRouteId) {
// 杩佺Щ宸ヨ壓璺嚎瀛愰泦琛ㄦ暟鎹紝杩斿洖鏃d->鏂癷nstance鏄犲皠
List<ProcessRouteItem> processRouteItemList = processRouteItemService.list(
new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
- Map<Long, ProductionOrderRouteItem> routeItemOldIdMap = migrationProcessRouteItem(orderId, processRouteItemList);
+ Map<Long, ProductionOrderRouteItem> routeItemOldIdMap = migrationProcessRouteItem(orderId, newRouteId, processRouteItemList);
// 杩佺Щ宸ヨ壓璺嚎鍐呯粦瀹氱殑宸ュ簭鍙傛暟
if (processRouteItemList != null && !processRouteItemList.isEmpty()) {
@@ -156,7 +183,7 @@
}
}
- private Map<Long, ProductionOrderRouteItem> migrationProcessRouteItem(Long orderId, List<ProcessRouteItem> list) {
+ private Map<Long, ProductionOrderRouteItem> migrationProcessRouteItem(Long orderId, Long newRouteId, List<ProcessRouteItem> list) {
Map<Long, ProductionOrderRouteItem> oldIdMap = new HashMap<>();
if (list == null || list.isEmpty()) {
return oldIdMap;
@@ -166,6 +193,7 @@
BeanUtils.copyProperties(item, instance, "id");
instance.setIsQuality(item.getIsQuality() != null && item.getIsQuality() ? 1 : 0);
instance.setOrderId(orderId);
+ instance.setRouteId(newRouteId);
if (item.getId() != null) {
oldIdMap.put(item.getId(), instance);
}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRouteServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRouteServiceImpl.java
new file mode 100644
index 0000000..d11b470
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRouteServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.service.impl;
+
+import com.ruoyi.production.pojo.ProductionOrderRoute;
+import com.ruoyi.production.mapper.ProductionOrderRouteMapper;
+import com.ruoyi.production.service.IProductionOrderRouteService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@Service
+public class ProductionOrderRouteServiceImpl extends ServiceImpl<ProductionOrderRouteMapper, ProductionOrderRoute> implements IProductionOrderRouteService {
+
+}
diff --git a/src/main/java/com/ruoyi/production/utils/UnitUtils.java b/src/main/java/com/ruoyi/production/utils/UnitUtils.java
new file mode 100644
index 0000000..6faf806
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/utils/UnitUtils.java
@@ -0,0 +1,66 @@
+package com.ruoyi.production.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <br>
+ * 鍗曚綅杞崲宸ュ叿绫�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30 15:07
+ */
+public class UnitUtils {
+
+ private static final Set<String> WEIGHT_UNITS = new HashSet<>(Arrays.asList(
+ "鍗冨厠", "鍏枻", "kg", "KG", "kG",
+ "鍏�", "g", "G",
+ "鍚�", "t", "T"
+ ));
+
+ private static final Set<String> KG_UNITS = new HashSet<>(Arrays.asList("鍗冨厠", "鍏枻", "kg", "KG", "kG"));
+ private static final Set<String> G_UNITS = new HashSet<>(Arrays.asList("鍏�", "g", "G"));
+ private static final Set<String> TON_UNITS = new HashSet<>(Arrays.asList("鍚�", "t", "T"));
+
+ /**
+ * 鍒ゆ柇鏄惁涓洪噸閲忓崟浣�
+ */
+ public static boolean isWeightUnit(String unit) {
+ return unit != null && WEIGHT_UNITS.contains(unit.trim());
+ }
+
+ /**
+ * 濡傛灉鏄噸閲忓崟浣嶏紝缁熶竴杩斿洖鈥滃惃鈥濓紝鍚﹀垯杩斿洖鍘熷崟浣�
+ */
+ public static String normalizeUnit(String unit) {
+ if (isWeightUnit(unit)) {
+ return "鍚�";
+ }
+ return unit != null ? unit.trim() : "鏈煡鍗曚綅";
+ }
+
+ /**
+ * 濡傛灉鏄噸閲忓崟浣嶏紝鎶樼畻涓衡�滃惃鈥濓紝鍚﹀垯杩斿洖鍘熷��
+ */
+ public static BigDecimal convertValueToTon(BigDecimal value, String unit) {
+ if (value == null || unit == null) {
+ return value != null ? value : BigDecimal.ZERO;
+ }
+
+ String trimmedUnit = unit.trim();
+ if (KG_UNITS.contains(trimmedUnit)) {
+ return value.divide(new BigDecimal("1000"), 6, RoundingMode.HALF_UP);
+ } else if (G_UNITS.contains(trimmedUnit)) {
+ return value.divide(new BigDecimal("1000000"), 6, RoundingMode.HALF_UP);
+ } else if (TON_UNITS.contains(trimmedUnit)) {
+ return value;
+ }
+
+ return value;
+ }
+}
diff --git a/src/main/java/com/ruoyi/production/vo/ProductionCostAggregationVo.java b/src/main/java/com/ruoyi/production/vo/ProductionCostAggregationVo.java
new file mode 100644
index 0000000..3366770
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/vo/ProductionCostAggregationVo.java
@@ -0,0 +1,46 @@
+package com.ruoyi.production.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰鑱氬悎姹囨�籚O
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@Data
+@ApiModel("鐢熶骇鎴愭湰鑱氬悎姹囨�籚O")
+public class ProductionCostAggregationVo {
+
+ @ApiModelProperty("鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDateTime date;
+
+ @ApiModelProperty("绫诲埆/璁㈠崟鍚嶇О")
+ private String name;
+
+ @ApiModelProperty("瑙勬牸鍨嬪彿")
+ private String model;
+
+ @ApiModelProperty("浜у搧绫诲瀷/寮哄害")
+ private String strength;
+
+ @ApiModelProperty("鐢ㄩ噺")
+ private BigDecimal quantity;
+
+ @ApiModelProperty("鍗曚綅")
+ private String unit;
+
+ @ApiModelProperty("鎬绘垚鏈�(鍏�)")
+ private BigDecimal totalCost;
+}
diff --git a/src/main/java/com/ruoyi/production/vo/ProductionCostDetailVo.java b/src/main/java/com/ruoyi/production/vo/ProductionCostDetailVo.java
new file mode 100644
index 0000000..2d442be
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/vo/ProductionCostDetailVo.java
@@ -0,0 +1,51 @@
+package com.ruoyi.production.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰鍒嗛〉鏄庣粏VO
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@Data
+@ApiModel("鐢熶骇鎴愭湰鍒嗛〉鏄庣粏VO")
+public class ProductionCostDetailVo {
+
+ @ApiModelProperty("鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDateTime date;
+
+ @ApiModelProperty("浜у搧鍚嶇О")
+ private String productName;
+
+ @ApiModelProperty("浜у搧绫诲瀷")
+ private String categoryLabel;
+
+ @ApiModelProperty("瑙勬牸鍨嬪彿")
+ private String model;
+
+ @ApiModelProperty("浜у搧绫诲瀷/寮哄害")
+ private String strength;
+
+ @ApiModelProperty("鐢熶骇璁㈠崟")
+ private String orderNo;
+
+ @ApiModelProperty("鐢ㄩ噺")
+ private BigDecimal quantity;
+
+ @ApiModelProperty("鍗曚綅")
+ private String unit;
+
+ @ApiModelProperty("鎴愭湰(鍏�)")
+ private BigDecimal cost;
+}
diff --git a/src/main/java/com/ruoyi/production/vo/ProductionCostSummaryVo.java b/src/main/java/com/ruoyi/production/vo/ProductionCostSummaryVo.java
new file mode 100644
index 0000000..61e3b3b
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/vo/ProductionCostSummaryVo.java
@@ -0,0 +1,33 @@
+package com.ruoyi.production.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰缁熻姹囨�籚O
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@Data
+@ApiModel("鐢熶骇鎴愭湰缁熻姹囨�籚O")
+public class ProductionCostSummaryVo {
+
+ @ApiModelProperty("鎬荤敓浜ф垚鏈�")
+ @JsonFormat(shape = JsonFormat.Shape.STRING)
+ private BigDecimal totalCost;
+
+ @ApiModelProperty("姣忚鍗曞钩鍧囨垚鏈�")
+ @JsonFormat(shape = JsonFormat.Shape.STRING)
+ private BigDecimal averageOrderCost;
+
+ @ApiModelProperty("璁㈠崟鏁伴噺")
+ private Long orderCount;
+}
\ No newline at end of file
diff --git a/src/main/resources/mapper/production/ProductOrderMapper.xml b/src/main/resources/mapper/production/ProductOrderMapper.xml
index 5f8d566..201652f 100644
--- a/src/main/resources/mapper/production/ProductOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -52,7 +52,7 @@
pms.material_code AS materialCode,
pms.id AS productId
FROM product_order po
- LEFT JOIN process_route pr ON po.route_id = pr.id
+ LEFT JOIN production_order_route pr ON po.route_id = pr.id
LEFT JOIN product_bom pb ON pr.bom_id = pb.id
LEFT JOIN product_material_sku pms ON pms.id = po.product_material_sku_id
LEFT JOIN product_material pm ON pm.id = pms.product_id
diff --git a/src/main/resources/mapper/production/ProductionCostMapper.xml b/src/main/resources/mapper/production/ProductionCostMapper.xml
new file mode 100644
index 0000000..dcf503d
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionCostMapper.xml
@@ -0,0 +1,89 @@
+<?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.production.mapper.ProductionCostMapper">
+
+ <sql id="baseCostQuery">
+ SELECT
+ ppi.quantity,
+ pos.unit_price,
+ (ppi.quantity * IFNULL(pos.unit_price, 0)) as calculated_cost,
+ ppi.unit as unit,
+ ppm.product_order_id,
+ ppm.reporting_time as log_date,
+ po.nps_no as order_no,
+ pm_mat.product_name as material_name,
+ pms_mat.model as material_model,
+ po.strength as strength,
+ sdd_type.dict_label as category_label
+ FROM production_product_input ppi
+ JOIN production_product_main ppm ON ppi.product_main_id = ppm.id
+ JOIN product_order po ON ppm.product_order_id = po.id
+ LEFT JOIN production_order_route pr ON po.route_id = pr.id
+ LEFT JOIN sys_dict_data sdd_type ON pr.dict_code = sdd_type.dict_code
+ LEFT JOIN production_order_structure pos ON ppm.product_order_id = pos.order_id
+ AND ppi.product_id = pos.product_model_id
+ AND ppi.bom_id = pos.bom_id
+ LEFT JOIN product_material_sku pms_mat ON ppi.product_id = pms_mat.id
+ LEFT JOIN product_material pm_mat ON pms_mat.product_id = pm_mat.id
+ <where>
+ <if test="dto.startDate != null">
+ AND ppm.reporting_time >= #{dto.startDate}
+ </if>
+ <if test="dto.endDate != null">
+ AND ppm.reporting_time < #{dto.endDate}
+ </if>
+ <if test="dto.dictCode != null">
+ AND pr.dict_code = #{dto.dictCode}
+ </if>
+ <if test="dto.productOrderId != null">
+ AND ppm.product_order_id = #{dto.productOrderId}
+ </if>
+ </where>
+ </sql>
+
+ <select id="selectCostSummary" resultType="com.ruoyi.production.vo.ProductionCostSummaryVo">
+ SELECT
+ ROUND(IFNULL(SUM(calculated_cost), 0), 2) as totalCost,
+ COUNT(DISTINCT product_order_id) as orderCount,
+ CASE
+ WHEN COUNT(DISTINCT product_order_id) > 0
+ THEN ROUND(SUM(calculated_cost) / COUNT(DISTINCT product_order_id), 2)
+ ELSE 0
+ END as averageOrderCost
+ FROM (
+ <include refid="baseCostQuery"/>
+ ) t
+ </select>
+
+ <select id="selectCostAggregationByCategory" resultType="com.ruoyi.production.vo.ProductionCostAggregationVo">
+ SELECT
+ log_date as date,
+ IFNULL(material_name, '鏈煡浜у搧') as name,
+ material_model as model,
+ unit,
+ ROUND(IFNULL(SUM(quantity), 0), 6) as quantity,
+ ROUND(IFNULL(SUM(calculated_cost), 0), 2) as totalCost
+ FROM (
+ <include refid="baseCostQuery"/>
+ ) t
+ GROUP BY log_date, material_name, material_model, unit
+ </select>
+
+ <select id="selectCostAggregationByOrder" resultType="com.ruoyi.production.vo.ProductionCostAggregationVo">
+ SELECT
+ log_date as date,
+ IFNULL(order_no, '鏈煡鍗曞彿') as name,
+ material_name as model,
+ category_label as strength,
+ unit,
+ ROUND(IFNULL(SUM(quantity), 0), 6) as quantity,
+ ROUND(IFNULL(SUM(calculated_cost), 0), 2) as totalCost
+ FROM (
+ <include refid="baseCostQuery"/>
+ ) t
+ GROUP BY log_date, order_no, material_name, category_label, unit
+ </select>
+
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/production/ProductionOrderRouteMapper.xml b/src/main/resources/mapper/production/ProductionOrderRouteMapper.xml
new file mode 100644
index 0000000..e35e54e
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderRouteMapper.xml
@@ -0,0 +1,20 @@
+<?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.production.mapper.ProductionOrderRouteMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderRoute">
+ <id column="id" property="id"/>
+ <result column="order_id" property="orderId"/>
+ <result column="process_route_id" property="processRouteId"/>
+ <result column="product_model_id" property="productModelId"/>
+ <result column="process_route_code" property="processRouteCode"/>
+ <result column="bom_id" property="bomId"/>
+ <result column="dict_code" property="dictCode"/>
+ <result column="description" property="description"/>
+ <result column="tenant_id" property="tenantId"/>
+ <result column="create_time" property="createTime"/>
+ <result column="update_time" property="updateTime"/>
+ <result column="remark" property="remark"/>
+ </resultMap>
+
+</mapper>
--
Gitblit v1.9.3