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;
/**
*
* 生产成本核算服务接口实现类
*
*
* @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 getProductAggregationPage(Page page, ProductionCostAccountDto dto) {
dto.setGroupType(1); // 按产品汇总
List fullList = getCostAggregationList(dto);
return getMemoryPage(page, fullList);
}
@Override
public IPage getOrderAggregationPage(Page page, ProductionCostAccountDto dto) {
dto.setGroupType(2); // 按订单汇总
List fullList = getCostAggregationList(dto);
return getMemoryPage(page, fullList);
}
@Override
public List getProductTop(ProductionCostAccountDto dto) {
dto.setGroupType(1);
List fullList = getCostAggregationList(dto);
if (fullList.isEmpty()) {
return new ArrayList<>();
}
Map 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 getOrderTop(ProductionCostAccountDto dto) {
dto.setGroupType(2);
List fullList = getCostAggregationList(dto);
if (fullList.isEmpty()) {
return new ArrayList<>();
}
Map 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 getCostAggregationList(ProductionCostAccountDto dto) {
if (dto.getEndDate() != null) {
dto.setEndDate(dto.getEndDate().plusDays(1));
}
List 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 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 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 IPage getMemoryPage(Page page, List list) {
int total = list.size();
long size = page.getSize();
long current = page.getCurrent();
if (size == -1 || current == -1) {
page.setTotal(total);
page.setRecords(list);
return page;
}
int fromIndex = (int) ((current - 1) * size);
int toIndex = Math.min(fromIndex + (int) size, total);
List subList;
if (fromIndex >= 0 && fromIndex < total) {
subList = list.subList(fromIndex, toIndex);
} else {
subList = new ArrayList<>();
}
page.setTotal(total);
page.setRecords(subList);
return page;
}
}