From 7e6836f99b10cde552d2f403009bf66082535d94 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 02 四月 2026 11:58:33 +0800
Subject: [PATCH] fix: 生产统计看板能耗统计单位
---
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java | 1901 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 1,820 insertions(+), 81 deletions(-)
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 a377159..1df045f 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -2,16 +2,16 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.mapper.AccountExpenseMapper;
import com.ruoyi.account.mapper.AccountIncomeMapper;
import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.home.mapper.HomeMapper;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
import com.ruoyi.approve.mapper.ApproveProcessMapper;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
-import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.mapper.SupplierManageMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.Product;
@@ -20,44 +20,49 @@
import com.ruoyi.collaborativeApproval.pojo.Notice;
import com.ruoyi.common.enums.ApproveTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.device.mapper.DeviceRepairMapper;
import com.ruoyi.device.pojo.DeviceRepair;
import com.ruoyi.dto.MapDto;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.home.dto.*;
+import com.ruoyi.home.mapper.HomeMapper;
import com.ruoyi.home.service.HomeService;
-import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
-import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
-import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.mapper.ProductOrderMapper;
-import com.ruoyi.production.mapper.ProductWorkOrderMapper;
-import com.ruoyi.production.mapper.ProductionProductInputMapper;
-import com.ruoyi.production.mapper.ProductionProductOutputMapper;
-import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
-import com.ruoyi.production.pojo.ProductWorkOrder;
+import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.pojo.*;
+import com.ruoyi.production.service.*;
+import com.ruoyi.productionPlan.enums.AddressRegionEnum;
+import com.ruoyi.productionPlan.mapper.SalesDeliveryMapper;
+import com.ruoyi.productionPlan.pojo.SalesDelivery;
import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.SysUserDept;
+import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.mapper.SysUserDeptMapper;
-import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.mapper.SysDictDataMapper;
import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PaymentRegistration;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityUnqualified;
import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.ReceiptPayment;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.production.utils.UnitUtils;
import com.ruoyi.staff.mapper.StaffOnJobMapper;
import com.ruoyi.staff.pojo.StaffOnJob;
import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.energy.mapper.EnergyMapper;
+import com.ruoyi.energy.pojo.Energy;
+import com.ruoyi.energy.dto.EnergyCostDto;
+import com.ruoyi.energy.mapper.EnergyConsumptionDetailMapper;
+import com.ruoyi.energy.vo.EnergyStatisticsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -94,9 +99,6 @@
private StockInventoryMapper stockInventoryMapper;
@Autowired
- private ProcurementRecordMapper procurementRecordStorageMapper;
-
- @Autowired
private QualityInspectMapper qualityStatisticsMapper;
@Autowired
@@ -113,27 +115,55 @@
@Autowired
private NoticeMapper noticeMapper;
+
@Autowired
private ProductOrderMapper productOrderMapper;
+
@Autowired
private ProductWorkOrderMapper productWorkOrderMapper;
- @Autowired
- private ProductModelMapper productModelMapper;
+
@Autowired
private ProductMapper productMapper;
- @Autowired
- private StockUtils stockUtils;
+
@Autowired
private StaffOnJobMapper staffOnJobMapper;
+
@Autowired
private CustomerMapper customerMapper;
+
@Autowired
private SupplierManageMapper supplierManageMapper;
+
@Autowired
private HomeMapper homeMapper;
@Autowired
private ProductionProductOutputMapper productionProductOutputMapper;
+
+ @Autowired
+ private QualityInspectMapper qualityInspectMapper;
+
+ @Autowired
+ private EnergyConsumptionDetailMapper energyConsumptionDetailMapper;
+
+ @Autowired
+ private QualityUnqualifiedMapper qualityUnqualifiedMapper;
+
+ @Autowired
+ private ProductProcessMapper productProcessMapper;
+
+ @Autowired
+ private AccountExpenseMapper accountExpenseMapper;
+
+ @Autowired
+ private AccountIncomeMapper accountIncomeMapper;
+
+ @Autowired
+ private SalesDeliveryMapper salesDeliveryMapper;
+
+ @Autowired
+ private EnergyMapper energyMapper;
+
@Override
public HomeBusinessDto business() {
@@ -168,28 +198,31 @@
LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.ge(PurchaseLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 澶т簬绛変簬鏈湀绗竴澶�
.lt(PurchaseLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 灏忎簬涓嬫湀绗竴澶�
- // 鎵ц鏌ヨ骞惰绠楁�诲拰
+
List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(purchaseLedgers)) {
- LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<SalesLedgerProduct>();
- salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2)
+ LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<>();
+ salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2) // 閲囪喘绫诲瀷
.in(SalesLedgerProduct::getSalesLedgerId,
purchaseLedgers.stream().map(PurchaseLedger::getId).collect(Collectors.toList()));
+
List<SalesLedgerProduct> salesLedgerProductsCopy = salesLedgerProductMapper
.selectList(salesLedgerProductMapperLambdaQueryWrapperCopy);
- // 鍚堣鍚堝悓閲戦
+
+ // 鍚堣鍚堝悓鎬婚噾棰�
BigDecimal receiveAmount = purchaseLedgers.stream()
.map(PurchaseLedger::getContractAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
- // 鏈紑绁ㄩ噾棰�
+
+ // 寰呬粯娆炬�婚噾棰�
BigDecimal unReceiptPaymentAmount = salesLedgerProductsCopy.stream()
- .map(SalesLedgerProduct::getNoInvoiceAmount)
+ .map(SalesLedgerProduct::getPendingTicketsTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
+
homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString());
- homeBusinessDto
- .setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
+ homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
}
// 缁熻搴撳瓨
BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal();
@@ -320,10 +353,10 @@
// 褰撴湀鐨勭粨鏉熸棩鏈燂紙姣忔湀鏈�鍚庝竴澶╋級
LocalDate monthEnd = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth());
- // 鏋勫缓褰撴湀鐨勬煡璇㈡潯浠讹紙濡傛灉鎯充竴娆℃�ф煡鍏�4涓湀鏁版嵁鍐嶅唴瀛樼瓫閫夛紝鍙紭鍖栦负鍏堟煡鍏ㄥ啀寰幆绛涢�夛級
+ // 鏋勫缓褰撴湀鐨勬煡璇㈡潯浠�
LambdaQueryWrapper<QualityInspect> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.ge(QualityInspect::getCheckTime, monthStart)
- .le(QualityInspect::getCheckTime, monthEnd); // 绛涢�夊綋鏈堟暟鎹�
+ queryWrapper.ge(QualityInspect::getCheckTime, monthStart.toString())
+ .le(QualityInspect::getCheckTime, monthEnd.toString());
List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper);
BigDecimal reduce = monthInspects.stream()
.filter(inspect -> inspect.getInspectType().equals(0))
@@ -1021,28 +1054,20 @@
@Override
public List<MapDto> salesPurchaseStorageProductCount() {
- LocalDate now = LocalDate.now();
- DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
+ LocalDateTime lastMonth = now.minusMonths(1);
+ LocalDateTime lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
+ LocalDateTime lastMonthEnd = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
- String currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).format(dtf);
- String currentMonthNow = now.format(dtf);
-
- LocalDate lastMonth = now.minusMonths(1);
- String lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).format(dtf);
- String lastMonthEnd = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).format(dtf);
-
- // 閿�鍞�
- int currentSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, currentMonthStart,
- currentMonthNow);
+ // 閿�鍞�
+ int currentSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, currentMonthStart, now);
int lastSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, lastMonthStart, lastMonthEnd);
-
- // 閲囪喘
- int currentPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, currentMonthStart,
- currentMonthNow);
+ // 閲囪喘
+ int currentPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, currentMonthStart, now);
int lastPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, lastMonthStart, lastMonthEnd);
-
- // 鍌ㄥ瓨
- int currentStorage = stockInventoryMapper.selectStorageProductCountByDate(currentMonthStart, currentMonthNow);
+ // 鍌ㄥ瓨
+ int currentStorage = stockInventoryMapper.selectStorageProductCountByDate(currentMonthStart, now);
int lastStorage = stockInventoryMapper.selectStorageProductCountByDate(lastMonthStart, lastMonthEnd);
List<MapDto> list = new ArrayList<>();
@@ -1141,12 +1166,6 @@
public List<MapDto> productTurnoverDays() {
return homeMapper.productTurnoverDays();
}
-
- @Autowired
- private AccountExpenseMapper accountExpenseMapper;
-
- @Autowired
- private AccountIncomeMapper accountIncomeMapper;
public List<Map<String, Object>> incomeExpenseAnalysis(Integer type) {
@@ -1271,36 +1290,21 @@
String startStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String endStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
- // List<IncomeExpenseAnalysisDto> incomeList =
- // salesLedgerMapper.selectIncomeStats(startStr, endStr, dateFormat);
- List<IncomeExpenseAnalysisDto> incomeList = new ArrayList<>();
- List<IncomeExpenseAnalysisDto> purchaseList = purchaseLedgerMapper.selectPurchaseStats(startStr, endStr,
- dateFormat);
- List<IncomeExpenseAnalysisDto> expenseList = accountExpenseMapper.selectAccountExpenseStats(startStr, endStr,
- dateFormat);
+ List<IncomeExpenseAnalysisDto> incomeList = accountIncomeMapper.selectIncomeStats(startStr, endStr, dateFormat);
+ List<IncomeExpenseAnalysisDto> expenseList = accountExpenseMapper.selectAccountExpenseStats(startStr, endStr, dateFormat);
Map<String, BigDecimal> incomeMap = incomeList.stream().collect(Collectors
- .toMap(IncomeExpenseAnalysisDto::getDateStr, IncomeExpenseAnalysisDto::getAmount, BigDecimal::add));
- Map<String, BigDecimal> purchaseMap = purchaseList.stream().collect(Collectors
.toMap(IncomeExpenseAnalysisDto::getDateStr, IncomeExpenseAnalysisDto::getAmount, BigDecimal::add));
Map<String, BigDecimal> expenseMap = expenseList.stream().collect(Collectors
.toMap(IncomeExpenseAnalysisDto::getDateStr, IncomeExpenseAnalysisDto::getAmount, BigDecimal::add));
List<MapDto> result = new ArrayList<>();
-
for (String month : months) {
MapDto dto = new MapDto();
dto.setName(month);
-
BigDecimal income = incomeMap.getOrDefault(month, BigDecimal.ZERO);
-
- BigDecimal purchase = purchaseMap.getOrDefault(month, BigDecimal.ZERO);
- income = BigDecimal.ZERO;
BigDecimal expense = expenseMap.getOrDefault(month, BigDecimal.ZERO);
- BigDecimal totalExpense = purchase.add(expense);
-
- BigDecimal profit = income.subtract(totalExpense);
-
+ BigDecimal profit = income.subtract(expense);
dto.setValue(profit.setScale(2, RoundingMode.HALF_UP).toString());
result.add(dto);
}
@@ -1737,9 +1741,11 @@
.filter(i -> i.getCreateTime() != null)
.collect(Collectors.groupingBy(
i -> i.getCreateTime().toLocalDate().toString(),
- Collectors.reducing(BigDecimal.ZERO,
- i -> i.getQuantity() != null ? i.getQuantity() : BigDecimal.ZERO,
- BigDecimal::add)));
+ Collectors.reducing(BigDecimal.ZERO, i -> {
+ BigDecimal qty = (i.getQuantity() != null) ? i.getQuantity() : BigDecimal.ZERO;
+ BigDecimal scrap = (i.getScrapQty() != null) ? i.getScrapQty() : BigDecimal.ZERO;
+ return qty.subtract(scrap);
+ }, BigDecimal::add)));
finishMap.forEach((date, qty) -> {
WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
@@ -1812,7 +1818,8 @@
String endStr = endDate.plusDays(1).atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
- List<Map<String, Object>> wagesList = salesLedgerProductionAccountingMapper.selectDailyWagesStats(startStr, endStr);
+ List<Map<String, Object>> wagesList = salesLedgerProductionAccountingMapper.selectDailyWagesStats(startStr,
+ endStr);
if (CollectionUtils.isEmpty(wagesList)) {
return new ArrayList<>();
@@ -1882,4 +1889,1736 @@
return dto;
}
+ @Override
+ public QualityQualifiedAnalysisDto rawMaterialDetection(Integer type) {
+ return commonDetection(type, 0);
+ }
+
+ @Override
+ public QualityQualifiedAnalysisDto processDetection(Integer type) {
+ return commonDetection(type, 1);
+ }
+
+ @Override
+ public QualityQualifiedAnalysisDto factoryDetection(Integer type) {
+ return commonDetection(type, 2);
+ }
+
+ private QualityQualifiedAnalysisDto commonDetection(Integer type, Integer inspectType) {
+
+ LocalDate[] range = calcDateRange(type);
+ LocalDate startDate = range[0];
+ LocalDate endDate = range[1];
+
+ String startStr = startDate.toString();
+ String endStr = endDate.toString();
+
+ List<QualityInspect> list = qualityInspectMapper.selectList(
+ new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectType, inspectType)
+ .eq(QualityInspect::getInspectState, 1)
+ .ge(QualityInspect::getCheckTime, startStr)
+ .le(QualityInspect::getCheckTime, endStr));
+
+ return buildQualifiedAnalysis(list);
+ }
+
+ private LocalDate[] calcDateRange(Integer type) {
+ LocalDate today = LocalDate.now();
+ LocalDate startDate;
+ LocalDate endDate;
+
+ switch (type) {
+ case 1: // 鍛�
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ break;
+ case 2: // 鏈�
+ startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+ endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ case 3: // 瀛e害
+ int currentMonth = today.getMonthValue();
+ int startMonth = ((currentMonth - 1) / 3) * 3 + 1;
+ startDate = LocalDate.of(today.getYear(), startMonth, 1);
+ endDate = LocalDate.of(today.getYear(), startMonth + 2, 1)
+ .with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ default:
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ }
+
+ return new LocalDate[]{startDate, endDate};
+ }
+
+ private QualityQualifiedAnalysisDto buildQualifiedAnalysis(List<QualityInspect> list) {
+ List<QualityQualifiedAnalysisDto> result = new ArrayList<>();
+ QualityQualifiedAnalysisDto dto = new QualityQualifiedAnalysisDto();
+
+ if (CollectionUtils.isEmpty(list)) {
+ dto.setQualifiedCount(0);
+ dto.setUnqualifiedCount(0);
+ dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
+ dto.setUnqualifiedRate(BigDecimal.ZERO.setScale(2));
+ return dto;
+ }
+
+ BigDecimal qualifiedCount = BigDecimal.ZERO;
+ BigDecimal unqualifiedCount = BigDecimal.ZERO;
+
+ for (QualityInspect item : list) {
+ if ("鍚堟牸".equals(item.getCheckResult())) {
+ qualifiedCount = qualifiedCount.add(item.getQuantity());
+ } else {
+ unqualifiedCount = unqualifiedCount.add(item.getQuantity());
+ }
+ }
+
+ BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
+
+ dto.setQualifiedCount(qualifiedCount.intValue());
+ dto.setUnqualifiedCount(unqualifiedCount.intValue());
+
+ if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+ dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
+ dto.setUnqualifiedRate(BigDecimal.ZERO.setScale(2));
+ return dto;
+ }
+
+ BigDecimal hundred = BigDecimal.valueOf(100);
+
+ dto.setQualifiedRate(qualifiedCount.divide(totalCount, 4, RoundingMode.HALF_UP)
+ .multiply(hundred)
+ .setScale(2, RoundingMode.HALF_UP));
+
+ dto.setUnqualifiedRate(unqualifiedCount.divide(totalCount, 4, RoundingMode.HALF_UP)
+ .multiply(hundred)
+ .setScale(2, RoundingMode.HALF_UP));
+
+ return dto;
+ }
+
+ @Override
+ public QualityInspectionCountDto qualityInspectionCount() {
+ String todayStr = LocalDate.now().toString();
+ String prevDayStr = LocalDate.now().minusDays(1).toString();
+ // 鏌ヨ鍑烘埅姝粖鏃ョ殑鎬绘楠屾暟
+ List<QualityInspect> todayList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .le(QualityInspect::getCheckTime, todayStr));
+ // 鏌ヨ鍑烘埅姝㈠墠涓�澶╃殑鎬绘楠屾暟
+ List<QualityInspect> prevList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .le(QualityInspect::getCheckTime, prevDayStr));
+ // 璁$畻浠婃棩鐨勬�绘楠屾暟
+ BigDecimal todayCount = todayList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ // 璁$畻鍓嶄竴澶╃殑鎬绘楠屾暟
+ BigDecimal prevCount = prevList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ // 璁$畻浠婃棩鐩稿鏄ㄥぉ鐨勪竴涓�绘瘮澧為暱
+ BigDecimal growthRate = calcGrowthRate(todayCount, prevCount);
+
+ // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺
+ List<QualityInspect> todayPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 0)
+ .eq(QualityInspect::getCheckTime, todayStr));
+
+ // 璁$畻鍓嶄竴澶╃殑寰呭畬鎴愭暟閲�
+ List<QualityInspect> prevPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 0)
+ .eq(QualityInspect::getCheckTime, prevDayStr));
+ // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺
+ BigDecimal todayPendingCount = todayPendingList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ // 璁$畻鍓嶄竴澶╃殑寰呭畬鎴愭暟閲�
+ BigDecimal prevPendingCount = prevPendingList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺鐩稿鏄ㄥぉ鐨勪竴涓悓姣斿闀�
+ BigDecimal todayPendingCountGrowthRate = calcGrowthRate(todayPendingCount, prevPendingCount);
+ // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺
+ List<QualityInspect> todayCompletedList = qualityInspectMapper
+ .selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 1)
+ .eq(QualityInspect::getCheckTime, todayStr));
+ // 璁$畻鍓嶄竴澶╃殑宸插畬鎴愭暟閲�
+ List<QualityInspect> prevCompletedList = qualityInspectMapper
+ .selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 1)
+ .eq(QualityInspect::getCheckTime, prevDayStr));
+ // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺
+ BigDecimal todayCompletedCount = todayCompletedList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ // 璁$畻鍓嶄竴澶╃殑宸插畬鎴愭暟閲�
+ BigDecimal prevCompletedCount = prevCompletedList.stream()
+ .map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺鐩稿鏄ㄥぉ鐨勪竴涓悓姣斿闀�
+ BigDecimal todayCompletedCountGrowthRate = calcGrowthRate(todayCompletedCount, prevCompletedCount);
+ QualityInspectionCountDto dto = new QualityInspectionCountDto();
+ dto.setTotalCount(todayCount);
+ dto.setTotalCountGrowthRate(growthRate);
+ dto.setTodayPendingCount(todayPendingCount);
+ dto.setTodayPendingCountGrowthRate(todayPendingCountGrowthRate);
+ dto.setTodayCompletedCount(todayCompletedCount);
+ dto.setTodayCompletedCountGrowthRate(todayCompletedCountGrowthRate);
+ return dto;
+ }
+
+ private BigDecimal calcGrowthRate(BigDecimal today, BigDecimal prev) {
+ if (prev == null || prev.compareTo(BigDecimal.ZERO) == 0) {
+ return BigDecimal.ZERO.setScale(2);
+ }
+ return today.subtract(prev)
+ .divide(prev, 4, RoundingMode.HALF_UP)
+ .multiply(BigDecimal.valueOf(100))
+ .setScale(2, RoundingMode.HALF_UP);
+ }
+
+ @Override
+ public NonComplianceWarningDto nonComplianceWarning() {
+ String[] range = lastSevenDaysDateRange();
+ String startStr = range[0];
+ String endStr = range[1];
+
+ // 鏌ヨ杩戜竷澶╁凡澶勭悊涓嶅悎鏍兼暟鎹�
+ List<QualityUnqualified> list = qualityUnqualifiedMapper.selectList(
+ new LambdaQueryWrapper<QualityUnqualified>()
+ .eq(QualityUnqualified::getInspectState, 1)
+ .ge(QualityUnqualified::getCheckTime, startStr)
+ .le(QualityUnqualified::getCheckTime, endStr));
+
+ NonComplianceWarningDto dto = new NonComplianceWarningDto();
+
+ if (CollectionUtils.isEmpty(list)) {
+ dto.setRawMaterialRatio(BigDecimal.ZERO);
+ dto.setSemiFinishedProductRatio(BigDecimal.ZERO);
+ dto.setFinishedProductRatio(BigDecimal.ZERO);
+ dto.setChildren(new ArrayList<>());
+ return dto;
+ }
+
+ // 鏌ヨ鎵�鏈変骇鍝�
+ List<Product> products = productMapper.selectList(null);
+
+ Map<Long, Product> productMap = products.stream()
+ .collect(Collectors.toMap(Product::getId, p -> p));
+
+ BigDecimal rawMaterialCount = BigDecimal.ZERO;
+ BigDecimal semiFinishedCount = BigDecimal.ZERO;
+ BigDecimal finishedCount = BigDecimal.ZERO;
+
+ List<NonComplianceWarningDto.Item> children = new ArrayList<>();
+
+ for (QualityUnqualified item : list) {
+
+ BigDecimal quantity = item.getQuantity();
+ Long productId = item.getProductId();
+
+ Product product = productMap.get(productId);
+ if (product == null) {
+ continue;
+ }
+
+ // 鎵惧埌浜у搧澶х被
+ Product parent = product.getParentId() == null
+ ? product
+ : productMap.get(product.getParentId());
+
+ if (parent == null) {
+ continue;
+ }
+
+ switch (parent.getProductName()) {
+ case "鍘熸潗鏂�":
+ rawMaterialCount = rawMaterialCount.add(quantity);
+ break;
+ case "鍗婃垚鍝�":
+ semiFinishedCount = semiFinishedCount.add(quantity);
+ break;
+ case "鎴愬搧":
+ finishedCount = finishedCount.add(quantity);
+ break;
+ default:
+ break;
+ }
+
+ // 缁勮鏄庣粏
+ NonComplianceWarningDto.Item child = new NonComplianceWarningDto.Item();
+ // child.setProductTitle(item.getProductName());
+ child.setParentProductTitle(parent.getProductName());
+ child.setProductTitle(item.getProductName());
+ child.setDescription(item.getDefectivePhenomena());
+ child.setDate(formatDate(item.getCheckTime()));
+ children.add(child);
+ }
+
+ BigDecimal total = rawMaterialCount
+ .add(semiFinishedCount)
+ .add(finishedCount);
+
+ dto.setRawMaterialRatio(calcRate(rawMaterialCount, total));
+ dto.setSemiFinishedProductRatio(calcRate(semiFinishedCount, total));
+ dto.setFinishedProductRatio(calcRate(finishedCount, total));
+ dto.setChildren(children);
+
+ return dto;
+ }
+
+ private BigDecimal calcRate(BigDecimal part, BigDecimal total) {
+ if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
+ return BigDecimal.ZERO.setScale(2);
+ }
+ return part.divide(total, 4, RoundingMode.HALF_UP)
+ .multiply(BigDecimal.valueOf(100))
+ .setScale(2, RoundingMode.HALF_UP);
+ }
+
+ public static String formatDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return date.toInstant()
+ .atZone(ZoneId.systemDefault())
+ .toLocalDate()
+ .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+ }
+
+ /**
+ * 鑾峰彇杩戜竷澶╃殑鏃ユ湡鍖洪棿锛堜粎鍚勾鏈堟棩锛�
+ */
+ public static String[] lastSevenDaysDateRange() {
+ LocalDate today = LocalDate.now();
+ return new String[]{today.minusDays(6).toString(), today.toString()};
+ }
+
+ @Override
+ public List<CompletedInspectionCountDto> completedInspectionCount() {
+ String[] range = lastSevenDaysDateRange();
+ String startStr = range[0];
+ String endStr = range[1];
+
+ // 鏌ヨ杩戜竷澶╁凡瀹屾垚鐨勬楠屾暟鎹�
+ List<QualityInspect> list = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 1)
+ .ge(QualityInspect::getCheckTime, startStr)
+ .le(QualityInspect::getCheckTime, endStr));
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
+
+ Map<String, CompletedInspectionCountDto> resultMap = new LinkedHashMap<>();
+
+ for (int i = 6; i >= 0; i--) {
+ LocalDate date = LocalDate.now().minusDays(i);
+ String dateStr = date.format(formatter);
+
+ CompletedInspectionCountDto dto = new CompletedInspectionCountDto();
+ dto.setDateStr(dateStr);
+ dto.setQualifiedCount(BigDecimal.ZERO);
+ dto.setUnqualifiedCount(BigDecimal.ZERO);
+ dto.setPassRate(BigDecimal.ZERO);
+
+ resultMap.put(dateStr, dto);
+ }
+
+ // 绱姞鍚堟牸 / 涓嶅悎鏍兼暟閲�
+ for (QualityInspect item : list) {
+
+ String dateStr = item.getCheckTime()
+ .toInstant()
+ .atZone(ZoneId.systemDefault())
+ .toLocalDate()
+ .format(formatter);
+
+ CompletedInspectionCountDto dto = resultMap.get(dateStr);
+ if (dto == null) {
+ continue;
+ }
+
+ BigDecimal quantity = item.getQuantity();
+
+ if ("鍚堟牸".equals(item.getCheckResult())) {
+ dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
+ } else {
+ dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
+ }
+ }
+
+ // 璁$畻鍚堟牸鐜�
+ for (CompletedInspectionCountDto dto : resultMap.values()) {
+ BigDecimal total = dto.getQualifiedCount().add(dto.getUnqualifiedCount());
+ dto.setPassRate(calcRate(dto.getQualifiedCount(), total));
+ }
+
+ return new ArrayList<>(resultMap.values());
+ }
+
+ @Override
+ public List<UnqualifiedProductRankDto> unqualifiedProductRanking() {
+
+ List<QualityInspect> list = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 1));
+
+ if (CollectionUtils.isEmpty(list)) {
+ return new ArrayList<>();
+ }
+
+ Map<Long, String> productNameMap = productMapper.selectList(null)
+ .stream()
+ .collect(Collectors.toMap(Product::getId, Product::getProductName));
+
+ Map<Long, List<QualityInspect>> groupMap = list.stream()
+ .collect(Collectors.groupingBy(QualityInspect::getProductId));
+
+ List<UnqualifiedProductRankDto> resultList = new ArrayList<>();
+
+ for (Map.Entry<Long, List<QualityInspect>> entry : groupMap.entrySet()) {
+
+ Long productId = entry.getKey();
+ List<QualityInspect> items = entry.getValue();
+
+ BigDecimal totalCount = BigDecimal.ZERO;
+ BigDecimal qualifiedCount = BigDecimal.ZERO;
+ BigDecimal unqualifiedCount = BigDecimal.ZERO;
+
+ for (QualityInspect item : items) {
+ BigDecimal qty = item.getQuantity();
+ totalCount = totalCount.add(qty);
+
+ if ("鍚堟牸".equals(item.getCheckResult())) {
+ qualifiedCount = qualifiedCount.add(qty);
+ } else {
+ unqualifiedCount = unqualifiedCount.add(qty);
+ }
+ }
+
+ if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+ continue;
+ }
+
+ BigDecimal passRate = qualifiedCount
+ .divide(totalCount, 4, RoundingMode.HALF_UP)
+ .multiply(new BigDecimal("100"))
+ .setScale(2, RoundingMode.HALF_UP);
+
+ UnqualifiedProductRankDto dto = new UnqualifiedProductRankDto();
+ dto.setProductName(productNameMap.get(productId));
+ dto.setTotalCount(totalCount);
+ dto.setCompletedCount(qualifiedCount);
+ dto.setPassRate(passRate);
+
+ resultList.add(dto);
+ }
+
+ resultList.sort(Comparator.comparing(UnqualifiedProductRankDto::getPassRate));
+
+ return resultList.stream().limit(5).collect(Collectors.toList());
+ }
+
+ @Override
+ public List<MapDto> unqualifiedProductProcessingAnalysis() {
+
+ List<QualityUnqualified> list = qualityUnqualifiedMapper.selectList(null);
+ if (CollectionUtils.isEmpty(list)) {
+ return new ArrayList<>();
+ }
+
+ // 缁熻姣忕澶勭悊缁撴灉鐨勬暟閲�
+ Map<String, BigDecimal> countMap = new HashMap<>();
+ for (QualityUnqualified item : list) {
+ if (StringUtils.isEmpty(item.getDealResult()) || item.getQuantity() == null) {
+ continue;
+ }
+ countMap.merge(item.getDealResult(), item.getQuantity(), BigDecimal::add);
+ }
+
+ if (countMap.isEmpty()) {
+ return new ArrayList<>();
+ }
+
+ // 璁$畻鎬绘暟
+ BigDecimal totalCount = countMap.values()
+ .stream()
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+ return new ArrayList<>();
+ }
+
+ // 鎸夋暟閲忓�掑簭鎺掑簭
+ List<Map.Entry<String, BigDecimal>> sortedList = countMap.entrySet()
+ .stream()
+ .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
+ .collect(Collectors.toList());
+
+ List<MapDto> result = new ArrayList<>();
+
+ int limit = Math.min(3, sortedList.size());
+ BigDecimal otherCount = BigDecimal.ZERO;
+
+ for (int i = 0; i < sortedList.size(); i++) {
+ Map.Entry<String, BigDecimal> entry = sortedList.get(i);
+
+ if (i < limit) {
+ MapDto dto = new MapDto();
+ dto.setName(entry.getKey());
+ dto.setValue(entry.getValue().setScale(2, RoundingMode.HALF_UP).toPlainString());
+ dto.setRate(calcRate(entry.getValue(), totalCount).toString());
+ result.add(dto);
+ } else {
+ otherCount = otherCount.add(entry.getValue());
+ }
+ }
+
+ if (otherCount.compareTo(BigDecimal.ZERO) > 0) {
+ MapDto otherDto = new MapDto();
+ otherDto.setName("鍏朵粬");
+ otherDto.setValue(otherCount.setScale(2, RoundingMode.HALF_UP).toPlainString());
+ otherDto.setRate(calcRate(otherCount, totalCount).toString());
+ result.add(otherDto);
+ }
+
+ return result;
+ }
+
+ @Override
+ public QualityStatisticsDto qualityInspectionStatistics(Integer type) {
+ LocalDate today = LocalDate.now();
+ LocalDate startDate;
+ LocalDate endDate;
+
+ switch (type) {
+ case 1: // 鏈懆
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ break;
+ case 2: // 鏈湀
+ startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+ endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ case 3: // 鏈搴�
+ int currentMonth = today.getMonthValue();
+ int startMonth = ((currentMonth - 1) / 3) * 3 + 1;
+ startDate = LocalDate.of(today.getYear(), startMonth, 1);
+ endDate = startDate.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ default:
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ }
+
+ List<QualityInspect> qualityInspectList = qualityInspectMapper
+ .selectList(new LambdaQueryWrapper<QualityInspect>()
+ .ge(QualityInspect::getCheckTime, startDate.toString())
+ .le(QualityInspect::getCheckTime, endDate.toString())
+ .eq(QualityInspect::getInspectState, 1));
+
+ QualityStatisticsDto dto = new QualityStatisticsDto();
+ dto.setSupplierNum(sumQuantity(qualityInspectList, 0)); // 鍘熸潗鏂�
+ dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // 杩囩▼
+ dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // 鍑哄巶
+
+ // 鍋囪 qualityInspectList 鏄竴涓� List<QualityInspect> 绫诲瀷鐨勯泦鍚�
+ Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream()
+ .collect(Collectors.groupingBy(QualityInspect::getCheckResult));
+ List<QualityInspect> qualityInspects = groupedByCheckResult.get("涓嶅悎鏍�");
+ if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) {
+ return null;
+ }
+ // 4. 澶勭悊鍥捐〃椤� (Item)
+ List<QualityStatisticsItem> itemList = new ArrayList<>();
+
+ Map<QualityInspect, LocalDate> dateMap = qualityInspectList.stream()
+ .collect(Collectors.toMap(
+ i -> i,
+ i -> i.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()));
+ if (type == 3) {
+ // 瀛e害妯″紡锛氭寜鏈堝垎缁�
+ Map<String, List<QualityInspect>> groupByMonth = qualityInspects.stream()
+ .collect(Collectors.groupingBy(i -> {
+ LocalDate ld = dateMap.get(i);
+ return ld.format(DateTimeFormatter.ofPattern("yyyy-MM"));
+ }));
+
+ for (int i = 0; i < 3; i++) {
+ LocalDate monthDate = startDate.plusMonths(i);
+ String monthStr = monthDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
+ itemList.add(buildItem(monthStr, groupByMonth.getOrDefault(monthStr, new ArrayList<>())));
+ }
+ } else {
+ // 鍛ㄦ垨鏈堟ā寮忥細鎸夊ぉ鍒嗙粍
+ Map<String, List<QualityInspect>> groupByDay = qualityInspects.stream()
+ .collect(Collectors.groupingBy(i -> {
+ LocalDate ld = dateMap.get(i);
+ return ld.format(DateTimeFormatter.ofPattern("MM/dd"));
+ }));
+ long days = ChronoUnit.DAYS.between(startDate, endDate);
+ for (int i = 0; i <= days; i++) {
+ LocalDate tempDay = startDate.plusDays(i);
+ String dayStr = tempDay.format(DateTimeFormatter.ofPattern("MM/dd"));
+ itemList.add(buildItem(dayStr, groupByDay.getOrDefault(dayStr, new ArrayList<>())));
+ }
+ }
+
+ dto.setItem(itemList);
+ return dto;
+ }
+
+ private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) {
+ return list.stream()
+ .filter(i -> i.getInspectType().equals(type))
+ .map(QualityInspect::getQuantity)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+
+ private QualityStatisticsItem buildItem(String dateLabel, List<QualityInspect> list) {
+ QualityStatisticsItem item = new QualityStatisticsItem();
+ item.setDate(dateLabel);
+
+ item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add));
+ item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add));
+ item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity)
+ .reduce(BigDecimal.ZERO, BigDecimal::add));
+
+ return item;
+ }
+
+ @Override
+ public List<processDataProductionStatisticsDto> processDataProductionStatistics(Integer type,
+ List<Long> processIds) {
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ Long userId = SecurityUtils.isAdmin(loginUser.getUserId()) ? null : loginUser.getUserId();
+
+ LocalDate today = LocalDate.now();
+ LocalDate startDate;
+ LocalDate endDate;
+
+ switch (type) {
+ case 1:
+ startDate = today;
+ endDate = today;
+ break;
+ case 2:
+ startDate = today.with(DayOfWeek.MONDAY);
+ endDate = today.with(DayOfWeek.SUNDAY);
+ break;
+ case 3:
+ startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+ endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+ break;
+ default:
+ startDate = today;
+ endDate = today;
+ }
+
+ LocalDateTime startDateTime = startDate.atStartOfDay();
+ LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);
+
+ return productProcessMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
+ }
+
+ @Override
+ public Map<String, Long> total() {
+ Map<String, Long> map = new HashMap<>();
+ List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(null);
+ //鎬婚攢鍞噾棰�
+ BigDecimal sum = salesDeliveries.stream()
+ .map(item -> item.getPrice() != null ? new BigDecimal(item.getPrice().toString()) : BigDecimal.ZERO)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ long finalPrice = sum.divide(new BigDecimal("10000"), 0, RoundingMode.HALF_UP).longValue();
+ map.put("price", finalPrice);//鍗曚綅w
+ //鎬诲彂璐у崟
+ map.put("delivery", (long) salesDeliveries.size());
+ //鎬婚攢鍞柟鏁�
+ BigDecimal volume = salesDeliveries.stream()
+ .map(item -> item.getVolume() != null ? new BigDecimal(item.getVolume().toString()) : BigDecimal.ZERO)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ long finalVolume = volume.divide(new BigDecimal("1000"), 0, RoundingMode.HALF_UP).longValue();
+ map.put("volume", finalVolume);
+ //绱瀹㈡埛
+ Long count = customerMapper.selectCount(null);
+ map.put("customer", count);
+ return map;
+ }
+
+ @Override
+ public SalesTotalDto salesAnalysis(SalesDeliveryDto salesDeliveryDto) {
+ SalesTotalDto salesTotalDto = new SalesTotalDto();
+ List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays());
+ List<Map<String, Long>> maps = new ArrayList<>();
+ List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery()
+ .eq(SalesDelivery::getProductName, salesDeliveryDto.getType()));
+ for (LocalDate date : dates) {
+ LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
+ LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
+ if (salesDeliveryDto.getDays().equals("骞�")) {
+ lastDay = date.with(TemporalAdjusters.lastDayOfYear());
+ }
+ LocalDate finalLastDay = lastDay;
+ salesDeliveries = salesDeliveries
+ .stream()
+ .filter(delivery -> {
+ LocalDate deliveryDate = delivery.getDeliveryDate();
+ return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay);
+ })
+ .collect(Collectors.toList());
+ Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values())
+ .collect(Collectors.toMap(
+ AddressRegionEnum::getRegionName, // 鍖哄煙鍚嶄綔涓簁ey
+ enumItem -> 0L // 鍒濆鍊煎叏閮ㄤ负0
+ ));
+ if (!CollectionUtils.isEmpty(salesDeliveries)) {
+ // 鎸夊尯鍩熷垎缁勶紝缁熻姣忎釜鍖哄煙鐨勯攢閲忔�诲拰
+ regionCountMap = salesDeliveries.stream()
+ .filter(delivery -> delivery.getDeliveryPlace() != null)
+ .collect(Collectors.groupingBy(
+ delivery -> {
+ AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace());
+ return regionEnum != null ? regionEnum.getRegionName() : null;
+ },
+ Collectors.summingLong(delivery -> delivery.getVolume() != null ? delivery.getVolume().longValue() : 0L)
+ ));
+ }
+ regionCountMap.put("鍏ㄩ儴", salesDeliveries.stream()
+ .mapToLong(item -> item.getVolume() != null ? item.getVolume().longValue() : 0L)
+ .sum());
+ maps.add(regionCountMap);
+ }
+ salesTotalDto.setDates(dates);
+ salesTotalDto.setCustomerTrends(maps);
+ return salesTotalDto;
+ }
+
+ @Override
+ public List<SalesTotalDetailDto> salesRanking(SalesDeliveryDto salesDeliveryDto) {
+ List<SalesTotalDetailDto> salesTotalDetailDtos = new ArrayList<>();
+ List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays());
+ List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery()
+ .eq(SalesDelivery::getProductName, salesDeliveryDto.getType()));
+ for (LocalDate date : dates) {
+ LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
+ LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
+ if (salesDeliveryDto.getDays().equals("骞�")) {
+ lastDay = date.with(TemporalAdjusters.lastDayOfYear());
+ }
+ LocalDate finalLastDay = lastDay;
+ salesDeliveries = salesDeliveries
+ .stream()
+ .filter(delivery -> {
+ LocalDate deliveryDate = delivery.getDeliveryDate();
+ return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay);
+ })
+ .collect(Collectors.toList());
+ Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values())
+ .collect(Collectors.toMap(
+ AddressRegionEnum::getRegionName, // 鍖哄煙鍚嶄綔涓簁ey
+ enumItem -> 0L // 鍒濆鍊煎叏閮ㄤ负0
+ ));
+ if (!CollectionUtils.isEmpty(salesDeliveries)) {
+ // 鎸夊尯鍩熷垎缁勶紝缁熻姣忎釜鍖哄煙鐨勯攢閲忔�诲拰
+ regionCountMap = salesDeliveries.stream()
+ .filter(delivery -> delivery.getDeliveryPlace() != null)
+ .collect(Collectors.groupingBy(
+ delivery -> {
+ AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace());
+ return regionEnum != null ? regionEnum.getRegionName() : null;
+ },
+ Collectors.summingLong(delivery -> delivery.getVolume() != null ? delivery.getVolume().longValue() : 0L)
+ ));
+ }
+ regionCountMap.put("鍏ㄩ儴", salesDeliveries.stream()
+ .mapToLong(item -> item.getVolume() != null ? item.getVolume().longValue() : 0L)
+ .sum());
+ SalesTotalDetailDto salesTotalDetailDto = new SalesTotalDetailDto();
+ salesTotalDetailDto.setDate(date);
+ salesTotalDetailDto.setType(salesDeliveryDto.getType());
+ salesTotalDetailDtos.add(salesTotalDetailDto);
+ }
+ return salesTotalDetailDtos;
+ }
+
+ @Override
+ public SalesTotalDto salesAmount(SalesDeliveryDto salesDeliveryDto) {
+ SalesTotalDto salesTotalDto = new SalesTotalDto();
+ List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays());
+ List<Map<String, Long>> maps = new ArrayList<>();
+ List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery()
+ .eq(SalesDelivery::getProductName, salesDeliveryDto.getType()));
+ for (LocalDate date : dates) {
+ LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
+ LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
+ if (salesDeliveryDto.getDays().equals("骞�")) {
+ lastDay = date.with(TemporalAdjusters.lastDayOfYear());
+ }
+ LocalDate finalLastDay = lastDay;
+ salesDeliveries = salesDeliveries
+ .stream()
+ .filter(delivery -> {
+ LocalDate deliveryDate = delivery.getDeliveryDate();
+ return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay);
+ })
+ .collect(Collectors.toList());
+ Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values())
+ .collect(Collectors.toMap(
+ AddressRegionEnum::getRegionName, // 鍖哄煙鍚嶄綔涓簁ey
+ enumItem -> 0L // 鍒濆鍊煎叏閮ㄤ负0
+ ));
+ if (!CollectionUtils.isEmpty(salesDeliveries)) {
+ // 鎸夊尯鍩熷垎缁勶紝缁熻姣忎釜鍖哄煙鐨勯攢閲忔�诲拰
+ regionCountMap = salesDeliveries.stream()
+ .filter(delivery -> delivery.getDeliveryPlace() != null)
+ .collect(Collectors.groupingBy(
+ delivery -> {
+ AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace());
+ return regionEnum != null ? regionEnum.getRegionName() : null;
+ },
+ Collectors.summingLong(delivery -> delivery.getPrice() != null ? delivery.getPrice().longValue() : 0L)
+ ));
+ }
+ regionCountMap.put("鍏ㄩ儴", salesDeliveries.stream()
+ .mapToLong(item -> item.getPrice() != null ? item.getPrice().longValue() : 0L)
+ .sum());
+ maps.add(regionCountMap);
+ }
+ salesTotalDto.setDates(dates);
+ salesTotalDto.setCustomerTrends(maps);
+ return salesTotalDto;
+ }
+
+ @Override
+ public List<SalesTotalDetailDto> salesDataRanking(SalesDeliveryDto salesDeliveryDto) {
+ List<SalesTotalDetailDto> salesTotalDetailDtos = new ArrayList<>();
+ List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays());
+
+ return salesTotalDetailDtos;
+ }
+
+ @Override
+ public SalesTotalDto customerTrends(SalesDeliveryDto salesDeliveryDto) {
+ SalesTotalDto salesTotalDto = new SalesTotalDto();
+ List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays());
+ List<Map<String, Long>> maps = new ArrayList<>();
+ for (LocalDate date : dates) {
+ LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
+ LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
+ if (salesDeliveryDto.getDays().equals("骞�")) {
+ lastDay = date.with(TemporalAdjusters.lastDayOfYear());
+ }
+ Date startDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant());
+ Date endDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());
+ List<Customer> customers = customerMapper.selectList(Wrappers.<Customer>lambdaQuery()
+ .between(Customer::getMaintenanceTime, startDate, endDate));
+ Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values())
+ .collect(Collectors.toMap(
+ AddressRegionEnum::getRegionName, // 鍖哄煙鍚嶄綔涓簁ey
+ enumItem -> 0L // 鍒濆鍊煎叏閮ㄤ负0
+ ));
+ if (!CollectionUtils.isEmpty(customers)) {
+ regionCountMap = customers.stream()
+ // 璋冪敤鏂规硶灏嗗師濮嬪湴鍧�杞崲涓虹洰鏍囧尯鍩�
+ .map(customer -> AddressRegionEnum.matchRegion(customer.getCompanyAddress()).getRegionName())
+ // 杩囨护鎺夎浆鎹㈠け璐�/绌虹殑鍖哄煙锛堝彲閫夛紝鏍规嵁涓氬姟闇�姹傦級
+ .filter(region -> region != null && !region.isEmpty())
+ // 鎸夊尯鍩熷垎缁勶紝缁熻姣忎釜鍖哄煙鐨勬暟閲�
+ .collect(Collectors.groupingBy(
+ region -> region, // 鍒嗙粍渚濇嵁锛氳浆鎹㈠悗鐨勫尯鍩�
+ Collectors.counting() // 璁℃暟
+ ));
+ }
+ regionCountMap.put("鍏ㄩ儴", customers.stream().count());
+ maps.add(regionCountMap);
+ }
+ salesTotalDto.setDates(dates);
+ salesTotalDto.setCustomerTrends(maps);
+ return salesTotalDto;
+ }
+
+ /**
+ * 鏍规嵁鍓嶇浼犲弬 骞�/鏈� 杞崲涓哄搴擫ocalDate鍒楄〃
+ *
+ * @param days 鍓嶇鍙傛暟锛�"骞�" / "鏈�"
+ * @return List<LocalDate>
+ */
+ public static List<LocalDate> convertDateList(String days) {
+ List<LocalDate> resultList = new ArrayList<>();
+ LocalDate now = LocalDate.now();
+ int currentYear = now.getYear();
+
+ if ("骞�".equals(days)) {
+ // 闇�姹傦細杩�5骞� 鈫� 姣忓勾鐨� 1鏈�1鏃�
+ for (int i = 0; i < 5; i++) {
+ resultList.add(LocalDate.of(currentYear - i, 1, 1));
+ }
+ } else if ("鏈�".equals(days)) {
+ // 闇�姹傦細褰撳勾12涓湀 鈫� 姣忔湀1鏃�
+ for (int month = 1; month <= 12; month++) {
+ resultList.add(LocalDate.of(currentYear, month, 1));
+ }
+ }
+ return resultList;
+ }
+
+ @Autowired
+ private ProductionProductMainService productionProductMainService;
+
+ @Autowired
+ private ProductOrderService productOrderService;
+
+ @Autowired
+ private ProductionProductInputService productionProductInputService;
+
+ @Autowired
+ private ProductionProductOutputService productionProductOutputService;
+
+ @Autowired
+ private IProductionOrderRouteService productionOrderRouteService;
+
+ @Autowired
+ private SysDictDataMapper sysDictDataMapper;
+
+ @Override
+ public Map<String, List<MaterialProductionAnalysisDto>> materialProductionAnalysis(productionStatisticsDto dto) {
+ if (dto == null) {
+ dto = new productionStatisticsDto();
+ dto.setMaterialName("鍏ㄩ儴");
+ dto.setDateType(1);
+ }
+
+ LocalDate now = LocalDate.now();
+ LocalDate startDate = null;
+
+ if (dto.getDateType() == 1) { // 鏈湀鑷充粖
+ startDate = now.withDayOfMonth(1);
+ } else { // 鏈勾鑷充粖
+ startDate = now.withDayOfYear(1);
+ }
+
+ List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type");
+ Set<Long> blockDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鐮屽潡"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+ Set<Long> plateDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鏉挎潗"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+
+ // 鏌ヨ鎶ュ伐涓昏〃鏁版嵁
+ List<ProductionProductMain> productionProductMainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .between(ProductionProductMain::getReportingTime,
+ startDate.atStartOfDay(),
+ now.atTime(LocalTime.MAX)));
+
+ if (CollectionUtils.isEmpty(productionProductMainList)) {
+ return Collections.emptyMap();
+ }
+
+ List<Long> productionMainIds = productionProductMainList.stream()
+ .map(ProductionProductMain::getId)
+ .collect(Collectors.toList());
+
+ // 鑾峰彇浜у嚭鏄庣粏
+ List<ProductionProductOutput> productionProductOutputs = productionProductOutputService.list(new LambdaQueryWrapper<ProductionProductOutput>()
+ .in(ProductionProductOutput::getProductMainId, productionMainIds));
+
+ Map<Long, ProductionProductMain> mainMap = productionProductMainList.stream()
+ .collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+ // 鑾峰彇璁㈠崟宸ヨ壓
+ List<Long> productionOrderIds = productionProductMainList.stream()
+ .map(ProductionProductMain::getProductOrderId)
+ .distinct()
+ .collect(Collectors.toList());
+
+ Map<Long, Long> orderRouteMap = new HashMap<>();
+ if (!CollectionUtils.isEmpty(productionOrderIds)) {
+ List<ProductionOrderRoute> routes = productionOrderRouteService.list(Wrappers.<ProductionOrderRoute>lambdaQuery()
+ .in(ProductionOrderRoute::getOrderId, productionOrderIds));
+ orderRouteMap = routes.stream()
+ .filter(r -> r.getOrderId() != null && r.getDictCode() != null)
+ .collect(Collectors.toMap(ProductionOrderRoute::getOrderId, ProductionOrderRoute::getDictCode, (v1, v2) -> v1));
+ }
+
+ List<String> dateLabels = new ArrayList<>();
+ DateTimeFormatter formatter;
+ if (dto.getDateType() == 1) { // 鏈湀鎸夊ぉ
+ formatter = DateTimeFormatter.ofPattern("MM-dd");
+ long days = ChronoUnit.DAYS.between(startDate, now) + 1;
+ for (int i = 0; i < days; i++) {
+ dateLabels.add(startDate.plusDays(i).format(formatter));
+ }
+ } else { // 鏈勾鎸夋湀
+ formatter = DateTimeFormatter.ofPattern("yy-M");
+ int currentMonth = now.getMonthValue();
+ for (int i = 1; i <= currentMonth; i++) {
+ dateLabels.add(startDate.withMonth(i).format(formatter));
+ }
+ }
+
+ Map<String, Map<String, BigDecimal>> aggregateData = new HashMap<>();
+ String[] categories = {"鍏ㄩ儴", "鐮屽潡", "鏉挎潗"};
+ for (String cat : categories) {
+ Map<String, BigDecimal> dayMap = new LinkedHashMap<>();
+ for (String label : dateLabels) {
+ dayMap.put(label, BigDecimal.ZERO);
+ }
+ aggregateData.put(cat, dayMap);
+ }
+
+ // 绱姞鏁版嵁
+ for (ProductionProductOutput output : productionProductOutputs) {
+ ProductionProductMain main = mainMap.get(output.getProductMainId());
+ if (main == null || main.getReportingTime() == null) continue;
+ String label = main.getReportingTime().format(formatter);
+ if (!aggregateData.get("鍏ㄩ儴").containsKey(label)) continue;
+ BigDecimal qty = output.getQuantity() != null ? output.getQuantity() : BigDecimal.ZERO;
+ // 绱姞鎬讳骇鍑�
+ aggregateData.get("鍏ㄩ儴").merge(label, qty, BigDecimal::add);
+ // 鍒嗙被绱姞
+ Long dictCode = orderRouteMap.get(main.getProductOrderId());
+ if (dictCode != null) {
+ if (blockDictCodes.contains(dictCode)) {
+ aggregateData.get("鐮屽潡").merge(label, qty, BigDecimal::add);
+ } else if (plateDictCodes.contains(dictCode)) {
+ aggregateData.get("鏉挎潗").merge(label, qty, BigDecimal::add);
+ }
+ }
+ }
+
+ Map<String, List<MaterialProductionAnalysisDto>> result = new LinkedHashMap<>();
+ for (String category : categories) {
+ List<MaterialProductionAnalysisDto> dtoList = new ArrayList<>();
+ for (String label : dateLabels) {
+ MaterialProductionAnalysisDto item = new MaterialProductionAnalysisDto();
+ item.setDateStr(label);
+ item.setTotalOutput(BigDecimal.ZERO);
+ item.setBlockOutput(BigDecimal.ZERO);
+ item.setPlateOutput(BigDecimal.ZERO);
+ BigDecimal val = aggregateData.get(category).get(label);
+ switch (category) {
+ case "鍏ㄩ儴":
+ item.setTotalOutput(val);
+ break;
+ case "鐮屽潡":
+ item.setBlockOutput(val);
+ break;
+ case "鏉挎潗":
+ item.setPlateOutput(val);
+ break;
+ }
+ dtoList.add(item);
+ }
+ result.put(category, dtoList);
+ }
+
+ return result;
+ }
+
+ @Autowired
+ private IProductionOrderStructureService productionOrderStructureService;
+
+ @Autowired
+ private ProductMaterialService productMaterialService;
+
+ @Autowired
+ private ProductMaterialSkuService productMaterialSkuService;
+
+ @Override
+ public List<String> getMaterials(Integer materialType) {
+ // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+ List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type");
+ Set<Long> targetDictCodes;
+ if (materialType != null && materialType == 1) { // 鐮屽潡
+ targetDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鐮屽潡"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+ } else if (materialType != null && materialType == 2) { // 鏉挎潗
+ targetDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鏉挎潗"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+ } else {
+ return Collections.emptyList();
+ }
+
+ if (CollectionUtils.isEmpty(targetDictCodes)) {
+ return Collections.emptyList();
+ }
+
+ // 鏍规嵁浜у搧绫诲瀷瀛楀吀缂栫爜鎵惧埌瀵瑰簲鐨勭敓浜ц鍗旾D
+ List<ProductionOrderRoute> routes = productionOrderRouteService.list(Wrappers.<ProductionOrderRoute>lambdaQuery()
+ .in(ProductionOrderRoute::getDictCode, targetDictCodes));
+ List<Long> orderIds = routes.stream().map(ProductionOrderRoute::getOrderId).distinct().collect(Collectors.toList());
+
+ if (CollectionUtils.isEmpty(orderIds)) {
+ return Collections.emptyList();
+ }
+
+ // 鏍规嵁鐢熶骇璁㈠崟ID鏌ヨBOM缁撴瀯涓殑鐗╂枡SKU ID
+ List<ProductionOrderStructure> structures = productionOrderStructureService.list(Wrappers.<ProductionOrderStructure>lambdaQuery()
+ .in(ProductionOrderStructure::getOrderId, orderIds));
+ List<Long> skuIds = structures.stream()
+ .map(ProductionOrderStructure::getProductModelId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+
+ if (CollectionUtils.isEmpty(skuIds)) {
+ return Collections.emptyList();
+ }
+
+ // 鏍规嵁SKU ID鑾峰彇鐗╂枡琛↖D
+ List<ProductMaterialSku> skus = productMaterialSkuService.list(Wrappers.<ProductMaterialSku>lambdaQuery()
+ .in(ProductMaterialSku::getId, skuIds));
+ List<Long> productIds = skus.stream()
+ .map(ProductMaterialSku::getProductId)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+
+ if (CollectionUtils.isEmpty(productIds)) {
+ return Collections.emptyList();
+ }
+
+ // 鏍规嵁鐗╂枡涓昏〃ID鑾峰彇鐗╂枡鍚嶇О
+ List<ProductMaterial> materials = productMaterialService.list(Wrappers.<ProductMaterial>lambdaQuery()
+ .in(ProductMaterial::getId, productIds));
+
+ return materials.stream()
+ .map(ProductMaterial::getProductName)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List<ProductionCostAnalysisDto> productionCostAnalysis(productionStatisticsDto dto, Integer materialType) {
+ // 鑾峰彇鍔ㄦ�佸瓧鍏窱D
+ List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type");
+ Set<Long> targetDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains(materialType == 1 ? "鐮屽潡" : "鏉挎潗"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+
+ if (CollectionUtils.isEmpty(targetDictCodes)) return Collections.emptyList();
+
+ // 鑾峰彇璇ョ被鍨嬬殑璁㈠崟
+ List<ProductionOrderRoute> routes = productionOrderRouteService.list(Wrappers.<ProductionOrderRoute>lambdaQuery()
+ .in(ProductionOrderRoute::getDictCode, targetDictCodes));
+ List<Long> orderIds = routes.stream().map(ProductionOrderRoute::getOrderId).distinct().collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(orderIds)) return Collections.emptyList();
+
+ // 鏃堕棿鑼冨洿澶勭悊
+ LocalDate now = LocalDate.now();
+ LocalDateTime yearStart = now.withDayOfYear(1).atStartOfDay();
+ LocalDateTime monthStart = now.withDayOfMonth(1).atStartOfDay();
+
+ LocalDateTime trendStart;
+ DateTimeFormatter trendFormatter;
+ int points;
+ if (dto.getDateType() != null && dto.getDateType() == 1) {
+ trendStart = monthStart;
+ trendFormatter = DateTimeFormatter.ofPattern("MM-dd");
+ points = now.getDayOfMonth();
+ } else {
+ trendStart = yearStart;
+ trendFormatter = DateTimeFormatter.ofPattern("yy-MM");
+ points = now.getMonthValue();
+ }
+
+ // 鏌ヨ鎶ュ伐鏁版嵁
+ List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .in(ProductionProductMain::getProductOrderId, orderIds)
+ .ge(ProductionProductMain::getReportingTime, yearStart));
+ if (CollectionUtils.isEmpty(mainList)) return Collections.emptyList();
+
+ List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+ Map<Long, ProductionProductMain> mainMap = mainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+ // 鏌ヨ鎶曞叆鍜屼骇鍑�
+ List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+ .in(ProductionProductInput::getProductMainId, mainIds));
+ List<ProductionProductOutput> allOutputs = productionProductOutputService.list(Wrappers.<ProductionProductOutput>lambdaQuery()
+ .in(ProductionProductOutput::getProductMainId, mainIds));
+
+ // 鑾峰彇鎶曞叆鐗╂枡鐨勫熀纭�淇℃伅
+ Set<Long> inputSkuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Set<Long> outputSkuIds = allOutputs.stream().map(ProductionProductOutput::getProductModelId).filter(Objects::nonNull).collect(Collectors.toSet());
+
+ Map<Long, ProductMaterial> inputSkuToMatMap = new HashMap<>();
+ if (!inputSkuIds.isEmpty()) {
+ List<ProductMaterialSku> inputSkus = productMaterialSkuService.listByIds(inputSkuIds);
+ Set<Long> inputActualProdIds = inputSkus.stream().map(ProductMaterialSku::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, ProductMaterial> materialMap = productMaterialService.listByIds(inputActualProdIds).stream()
+ .collect(Collectors.toMap(ProductMaterial::getId, m -> m));
+ inputSkuToMatMap = inputSkus.stream().collect(Collectors.toMap(ProductMaterialSku::getId, s -> materialMap.get(s.getProductId())));
+ }
+
+ Map<Long, String> outputSkuToUnitMap = new HashMap<>();
+ if (!outputSkuIds.isEmpty()) {
+ List<ProductMaterialSku> outSkus = productMaterialSkuService.listByIds(outputSkuIds);
+ Set<Long> outProdIds = outSkus.stream().map(ProductMaterialSku::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, String> matUnitMap = productMaterialService.listByIds(outProdIds).stream().collect(Collectors.toMap(ProductMaterial::getId, ProductMaterial::getUnit));
+ outputSkuToUnitMap = outSkus.stream().collect(Collectors.toMap(ProductMaterialSku::getId, s -> matUnitMap.getOrDefault(s.getProductId(), "鍚�")));
+ }
+
+ // 鎸夌墿鏂欏垎缁勮仛鍚�
+ Map<Long, ProductMaterial> finalSkuToMatMap = inputSkuToMatMap;
+ Map<String, List<ProductionProductInput>> inputByMaterial = allInputs.stream()
+ .filter(i -> finalSkuToMatMap.containsKey(i.getProductId()) && finalSkuToMatMap.get(i.getProductId()) != null)
+ .collect(Collectors.groupingBy(i -> finalSkuToMatMap.get(i.getProductId()).getProductName()));
+
+ if (dto.getMaterialName() != null && !"鍏ㄩ儴".equals(dto.getMaterialName())) {
+ String target = dto.getMaterialName();
+ inputByMaterial = inputByMaterial.entrySet().stream()
+ .filter(e -> e.getKey().equals(target))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ }
+
+ List<ProductionCostAnalysisDto> resultList = new ArrayList<>();
+
+ for (Map.Entry<String, List<ProductionProductInput>> entry : inputByMaterial.entrySet()) {
+ String materialName = entry.getKey();
+ List<ProductionProductInput> materialInputs = entry.getValue();
+
+ ProductionCostAnalysisDto analysisDto = new ProductionCostAnalysisDto();
+ analysisDto.setMaterialName(materialName);
+
+ Set<Long> relatedMainIds = materialInputs.stream().map(ProductionProductInput::getProductMainId).collect(Collectors.toSet());
+ List<ProductionProductOutput> relatedOutputs = allOutputs.stream()
+ .filter(o -> relatedMainIds.contains(o.getProductMainId()))
+ .collect(Collectors.toList());
+
+ BigDecimal monthInputSum = BigDecimal.ZERO;
+ BigDecimal monthOutputSum = BigDecimal.ZERO;
+ BigDecimal yearInputSum = BigDecimal.ZERO;
+ BigDecimal yearOutputSum = BigDecimal.ZERO;
+
+ Map<String, InputOutputAnalysisDto> trendMap = new LinkedHashMap<>();
+ for (int i = 0; i < points; i++) {
+ String label;
+ if (dto.getDateType() != null && dto.getDateType() == 1) {
+ label = now.withDayOfMonth(i + 1).format(trendFormatter);
+ } else {
+ label = now.withMonth(i + 1).format(trendFormatter);
+ }
+ InputOutputAnalysisDto trendDto = new InputOutputAnalysisDto();
+ trendDto.setDate(label);
+ trendDto.setInputSum(BigDecimal.ZERO);
+ trendDto.setOutputSum(BigDecimal.ZERO);
+ trendMap.put(label, trendDto);
+ }
+
+ for (ProductionProductInput input : materialInputs) {
+ BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+ yearInputSum = yearInputSum.add(qty);
+ LocalDateTime repTime = mainMap.get(input.getProductMainId()).getReportingTime();
+ if (repTime != null && (repTime.isAfter(monthStart) || repTime.isEqual(monthStart))) {
+ monthInputSum = monthInputSum.add(qty);
+ }
+ if (repTime != null && (repTime.isAfter(trendStart) || repTime.isEqual(trendStart))) {
+ String label = repTime.format(trendFormatter);
+ if (trendMap.containsKey(label)) {
+ trendMap.get(label).setInputSum(trendMap.get(label).getInputSum().add(qty));
+ }
+ }
+ }
+
+ for (ProductionProductOutput output : relatedOutputs) {
+ String unit = outputSkuToUnitMap.getOrDefault(output.getProductModelId(), "鍚�");
+ BigDecimal qty = UnitUtils.convertValueToTon(output.getQuantity(), unit);
+ yearOutputSum = yearOutputSum.add(qty);
+ LocalDateTime repTime = mainMap.get(output.getProductMainId()).getReportingTime();
+ if (repTime != null && (repTime.isAfter(monthStart) || repTime.isEqual(monthStart))) {
+ monthOutputSum = monthOutputSum.add(qty);
+ }
+ if (repTime != null && (repTime.isAfter(trendStart) || repTime.isEqual(trendStart))) {
+ String label = repTime.format(trendFormatter);
+ if (trendMap.containsKey(label)) {
+ trendMap.get(label).setOutputSum(trendMap.get(label).getOutputSum().add(qty));
+ }
+ }
+ }
+
+ analysisDto.setMonthlyConsumption(formatRatio(monthInputSum, monthOutputSum));
+ analysisDto.setYearlyConsumption(formatRatio(yearInputSum, yearOutputSum));
+ analysisDto.setChartData(new ArrayList<>(trendMap.values()));
+ resultList.add(analysisDto);
+ }
+
+ return resultList;
+ }
+
+ private String formatRatio(BigDecimal input, BigDecimal output) {
+ String inputStr = input.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+ String outputStr = output.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+ return inputStr + "/" + outputStr;
+ }
+
+ @Override
+ public ProductionStatisticsMiddleDto middle() {
+ LocalDate now = LocalDate.now();
+ LocalDate monthStart = now.withDayOfMonth(1);
+ LocalDate yearStart = now.withDayOfYear(1);
+
+ // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+ List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type");
+ Set<Long> blockDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鐮屽潡"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+ Set<Long> plateDictCodes = sysDictDataList.stream()
+ .filter(d -> d.getDictLabel() != null && d.getDictLabel().contains("鏉挎潗"))
+ .map(SysDictData::getDictCode)
+ .collect(Collectors.toSet());
+
+ // 鏌ヨ鏈勾鎶ュ伐涓昏〃
+ List<ProductionProductMain> yearMainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .ge(ProductionProductMain::getReportingTime, yearStart.atStartOfDay()));
+ if (CollectionUtils.isEmpty(yearMainList)) return new ProductionStatisticsMiddleDto();
+
+ List<Long> mainIds = yearMainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+ Map<Long, ProductionProductMain> mainMap = yearMainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+ // 鑾峰彇璁㈠崟淇℃伅
+ List<Long> orderIds = yearMainList.stream().map(ProductionProductMain::getProductOrderId).distinct().collect(Collectors.toList());
+ 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<ProductionProductOutput> allOutputs = productionProductOutputService.list(Wrappers.<ProductionProductOutput>lambdaQuery()
+ .in(ProductionProductOutput::getProductMainId, mainIds));
+
+ // 鑾峰彇鎶曞叆鏄庣粏锛堢敤浜庣矇鐓ょ伆銆佺煶鑶忓鐞嗛噺锛�
+ List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+ .in(ProductionProductInput::getProductMainId, mainIds));
+
+ // 缁熶竴澶勭悊瑙勬牸/鐗╂枡鍚嶇О鏄犲皠
+ Set<Long> allSkuIds = new HashSet<>();
+ allOutputs.forEach(o -> allSkuIds.add(o.getProductModelId()));
+ allInputs.forEach(i -> allSkuIds.add(i.getProductId()));
+ allSkuIds.remove(null);
+
+ Map<Long, String> skuToMaterialNameMap = new HashMap<>();
+ if (!allSkuIds.isEmpty()) {
+ List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(allSkuIds);
+ 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())));
+ }
+
+ ProductionStatisticsMiddleDto result = new ProductionStatisticsMiddleDto();
+ LocalDateTime monthStartDt = monthStart.atStartOfDay();
+
+ // 缁熻鍥哄簾澶勭悊閲�,浠庢姇鍏ヨ幏鍙栨暟鎹�
+ for (ProductionProductInput input : allInputs) {
+ ProductionProductMain main = mainMap.get(input.getProductMainId());
+ if (main == null || main.getReportingTime() == null) continue;
+
+ BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+ boolean isCurrentMonth = !main.getReportingTime().isBefore(monthStartDt);
+ String materialName = skuToMaterialNameMap.get(input.getProductId());
+
+ if ("绮夌叅鐏�".equals(materialName)) {
+ result.setFlyAshYear(result.getFlyAshYear().add(qty));
+ if (isCurrentMonth) result.setFlyAshMonth(result.getFlyAshMonth().add(qty));
+ } else if ("鐭宠啅".equals(materialName)) {
+ result.setGypsumYear(result.getGypsumYear().add(qty));
+ if (isCurrentMonth) result.setGypsumMonth(result.getGypsumMonth().add(qty));
+ }
+ }
+
+ // 缁熻椤圭洰浜ч噺,浠庝骇鍑鸿幏鍙栨暟鎹�
+ for (ProductionProductOutput output : allOutputs) {
+ ProductionProductMain main = mainMap.get(output.getProductMainId());
+ if (main == null || main.getReportingTime() == null) continue;
+
+ BigDecimal qty = UnitUtils.convertValueToTon(output.getQuantity(), "鍚�"); // 浜у嚭鏂归噺閫氬父涓哄惃
+ boolean isCurrentMonth = !main.getReportingTime().isBefore(monthStartDt);
+
+ Long dictCode = orderRouteMap.get(main.getProductOrderId());
+ if (dictCode != null) {
+ if (blockDictCodes.contains(dictCode)) {
+ result.setBlockYear(result.getBlockYear().add(qty));
+ if (isCurrentMonth) result.setBlockMonth(result.getBlockMonth().add(qty));
+ } else if (plateDictCodes.contains(dictCode)) {
+ result.setPlateYear(result.getPlateYear().add(qty));
+ if (isCurrentMonth) result.setPlateMonth(result.getPlateMonth().add(qty));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public List<SolidWasteStatisticsDto> solidWaste(productionStatisticsDto dto) {
+ if (dto == null) {
+ dto = new productionStatisticsDto();
+ dto.setDateType(1);
+ }
+
+ LocalDate now = LocalDate.now();
+ LocalDate startDate = null;
+
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鑷充粖
+ startDate = now.withDayOfMonth(1);
+ } else { // 鏈勾鑷充粖
+ startDate = now.withDayOfYear(1);
+ }
+
+ List<String> dateLabels = new ArrayList<>();
+ DateTimeFormatter formatter;
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鎸夊ぉ
+ formatter = DateTimeFormatter.ofPattern("MM-dd");
+ long days = ChronoUnit.DAYS.between(startDate, now) + 1;
+ for (int i = 0; i < days; i++) {
+ dateLabels.add(startDate.plusDays(i).format(formatter));
+ }
+ } else { // 鏈勾鎸夋湀
+ formatter = DateTimeFormatter.ofPattern("yy-MM");
+ int currentMonth = now.getMonthValue();
+ for (int i = 1; i <= currentMonth; i++) {
+ dateLabels.add(startDate.withMonth(i).format(formatter));
+ }
+ }
+
+ // 鏌ヨ鏃堕棿鑼冨洿鍐呯殑鎶ュ伐鏁版嵁
+ List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .ge(ProductionProductMain::getReportingTime, startDate.atStartOfDay()));
+ if (CollectionUtils.isEmpty(mainList)) return new ArrayList<>();
+
+ List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+ Map<Long, ProductionProductMain> mainMap = mainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+ // 鑾峰彇鎶曞叆鏄庣粏
+ List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+ .in(ProductionProductInput::getProductMainId, mainIds));
+ if (CollectionUtils.isEmpty(allInputs)) return new ArrayList<>();
+
+ // 鑾峰彇瑙勬牸鍜岀墿鏂欏悕绉�
+ Set<Long> skuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, String> skuToMaterialNameMap = new HashMap<>();
+ if (!skuIds.isEmpty()) {
+ List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(skuIds);
+ 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())));
+ }
+
+ Map<String, SolidWasteStatisticsDto> resultData = new LinkedHashMap<>();
+ for (String label : dateLabels) {
+ SolidWasteStatisticsDto item = new SolidWasteStatisticsDto();
+ item.setDateStr(label);
+ resultData.put(label, item);
+ }
+
+ // 鎸夋棩鏈熷拰鐗╂枡
+ for (ProductionProductInput input : allInputs) {
+ ProductionProductMain main = mainMap.get(input.getProductMainId());
+ if (main == null || main.getReportingTime() == null) continue;
+ String label = main.getReportingTime().format(formatter);
+ if (!resultData.containsKey(label)) continue;
+
+ BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+ String materialName = skuToMaterialNameMap.get(input.getProductId());
+
+ SolidWasteStatisticsDto dayDto = resultData.get(label);
+ if ("绮夌叅鐏�".equals(materialName)) {
+ dayDto.setFlyAsh(dayDto.getFlyAsh().add(qty));
+ } else if ("鐭宠啅".equals(materialName)) {
+ dayDto.setGypsum(dayDto.getGypsum().add(qty));
+ } else if ("鐭崇伆".equals(materialName)) {
+ dayDto.setLime(dayDto.getLime().add(qty));
+ }
+ dayDto.setTotal(dayDto.getTotal().add(qty));
+ }
+
+ return new ArrayList<>(resultData.values());
+ }
+
+ @Override
+ public List<HomeEnergyStatisticsDto> energy(productionStatisticsDto dto) {
+ if (dto == null) {
+ dto = new productionStatisticsDto();
+ dto.setDateType(1);
+ }
+
+ LocalDate now = LocalDate.now();
+ LocalDate startDate = null;
+
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鑷充粖
+ startDate = now.withDayOfMonth(1);
+ } else { // 鏈勾鑷充粖
+ startDate = now.withDayOfYear(1);
+ }
+
+ EnergyStatisticsVo vo = new EnergyStatisticsVo();
+ vo.setStartDate(startDate);
+ vo.setEndDate(now);
+
+ List<EnergyCostDto> costDtos;
+ String labelPattern;
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鎸夊ぉ
+ costDtos = energyConsumptionDetailMapper.energyCostDtos1(vo);
+ labelPattern = "MM-dd";
+ } else { // 鏈勾鎸夋湀
+ costDtos = energyConsumptionDetailMapper.energyCostDtos2(vo);
+ labelPattern = "yy-MM";
+ }
+
+ List<String> dateLabels = new ArrayList<>();
+ DateTimeFormatter labelFormatter = DateTimeFormatter.ofPattern(labelPattern);
+ if (dto.getDateType() != null && dto.getDateType() == 1) {
+ long days = ChronoUnit.DAYS.between(startDate, now) + 1;
+ for (int i = 0; i < days; i++) {
+ dateLabels.add(startDate.plusDays(i).format(labelFormatter));
+ }
+ } else {
+ int currentMonth = now.getMonthValue();
+ for (int i = 1; i <= currentMonth; i++) {
+ dateLabels.add(startDate.withMonth(i).format(labelFormatter));
+ }
+ }
+
+ Map<String, HomeEnergyStatisticsDto> resultData = new LinkedHashMap<>();
+ for (String label : dateLabels) {
+ HomeEnergyStatisticsDto item = new HomeEnergyStatisticsDto();
+ item.setDateStr(label);
+ resultData.put(label, item);
+ }
+
+ if (!CollectionUtils.isEmpty(costDtos)) {
+ // 鑾峰彇鍗曚綅
+ List<Energy> energies = energyMapper.selectList(Wrappers.<Energy>lambdaQuery()
+ .in(Energy::getEnergyTyep, Arrays.asList("姘�", "鐢�", "姘�")));
+ String waterUnit = energies.stream().filter(e -> "姘�".equals(e.getEnergyTyep())).map(Energy::getUnit).findFirst().orElse("");
+ String electricityUnit = energies.stream().filter(e -> "鐢�".equals(e.getEnergyTyep())).map(Energy::getUnit).findFirst().orElse("");
+ String steamUnit = energies.stream().filter(e -> "姘�".equals(e.getEnergyTyep())).map(Energy::getUnit).findFirst().orElse("");
+
+ for (EnergyCostDto costDto : costDtos) {
+ String dateStr = costDto.getMeterReadingDate();
+ String label = "";
+ try {
+ if (dto.getDateType() == 1) {
+ label = LocalDate.parse(dateStr).format(labelFormatter);
+ } else {
+ // yyyy-MM 杞寲涓� yy-MM
+ label = YearMonth.parse(dateStr).format(labelFormatter);
+ }
+ } catch (Exception e) {
+ label = dateStr;
+ }
+
+ if (resultData.containsKey(label)) {
+ HomeEnergyStatisticsDto dayDto = resultData.get(label);
+ BigDecimal water = costDto.getWaterConsumption() != null ? costDto.getWaterConsumption() : BigDecimal.ZERO;
+ BigDecimal electricity = costDto.getElectricityConsumption() != null ? costDto.getElectricityConsumption() : BigDecimal.ZERO;
+ BigDecimal steam = costDto.getGasConsumption() != null ? costDto.getGasConsumption() : BigDecimal.ZERO;
+ dayDto.setWater(water);
+ dayDto.setElectricity(electricity);
+ dayDto.setSteam(steam);
+ dayDto.setWaterUnit(waterUnit);
+ dayDto.setElectricityUnit(electricityUnit);
+ dayDto.setSteamUnit(steamUnit);
+ }
+ }
+ }
+
+ return new ArrayList<>(resultData.values());
+ }
+
+ @Override
+ public SolidWasteCoreIndicatorsDto coreIndicators(productionStatisticsDto dto) {
+ if (dto == null) {
+ dto = new productionStatisticsDto();
+ dto.setDateType(1);
+ }
+
+ LocalDate now = LocalDate.now();
+ LocalDate startDate = null;
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鑷充粖
+ startDate = now.withDayOfMonth(1);
+ } else { // 鏈勾鑷充粖
+ startDate = now.withDayOfYear(1);
+ }
+
+ // 绱娑堢撼閲忎粠2022-01-01寮�濮�
+ LocalDate cumulativeStartDate = LocalDate.of(2022, 1, 1);
+ // 鏌ヨ浠�2022-01-01鑷充粖鐨勬墍鏈夋姤宸ユ暟鎹�
+ List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .ge(ProductionProductMain::getReportingTime, cumulativeStartDate.atStartOfDay()));
+ if (CollectionUtils.isEmpty(mainList)) return new SolidWasteCoreIndicatorsDto();
+
+ List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+ Map<Long, ProductionProductMain> mainMap = mainList.stream().collect(Collectors.toMap(ProductionProductMain::getId, m -> m));
+
+ // 鑾峰彇鎶曞叆鏄庣粏
+ List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+ .in(ProductionProductInput::getProductMainId, mainIds));
+ if (CollectionUtils.isEmpty(allInputs)) return new SolidWasteCoreIndicatorsDto();
+
+ // 鑾峰彇瑙勬牸鍜岀墿鏂欏悕绉�
+ Set<Long> skuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, String> skuToMaterialNameMap = new HashMap<>();
+ if (!skuIds.isEmpty()) {
+ List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(skuIds);
+ 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 totalAmount = BigDecimal.ZERO;
+ BigDecimal cumulativeAmount = BigDecimal.ZERO;
+
+ Set<String> targetMaterials = new HashSet<>(Arrays.asList("绮夌叅鐏�", "鐭宠啅", "鐭崇伆"));
+
+ for (ProductionProductInput input : allInputs) {
+ String materialName = skuToMaterialNameMap.get(input.getProductId());
+ if (materialName == null || !targetMaterials.contains(materialName)) continue;
+
+ ProductionProductMain main = mainMap.get(input.getProductMainId());
+ if (main == null || main.getReportingTime() == null) continue;
+
+ BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+ // 绱姞绱娑堢撼閲�
+ cumulativeAmount = cumulativeAmount.add(qty);
+
+ if (!main.getReportingTime().toLocalDate().isBefore(startDate)) {
+ totalAmount = totalAmount.add(qty);
+ }
+ }
+
+ SolidWasteCoreIndicatorsDto result = new SolidWasteCoreIndicatorsDto();
+ result.setTotalAmount(totalAmount.setScale(2, RoundingMode.HALF_UP));
+ result.setCumulativeAmount(cumulativeAmount.setScale(2, RoundingMode.HALF_UP));
+ return result;
+ }
+
+ @Override
+ public List<SolidWasteStatisticsDto> trends(productionStatisticsDto dto) {
+ return solidWaste(dto);
+ }
+
+ @Override
+ public List<MapDto> typeDistribution(productionStatisticsDto dto) {
+ if (dto == null) {
+ dto = new productionStatisticsDto();
+ dto.setDateType(1);
+ }
+
+ LocalDate now = LocalDate.now();
+ LocalDate startDate = null;
+ if (dto.getDateType() != null && dto.getDateType() == 1) { // 鏈湀鑷充粖
+ startDate = now.withDayOfMonth(1);
+ } else { // 鏈勾鑷充粖
+ startDate = now.withDayOfYear(1);
+ }
+
+ // 鏌ヨ鎶ュ伐涓昏〃
+ List<ProductionProductMain> mainList = productionProductMainService.list(Wrappers.<ProductionProductMain>lambdaQuery()
+ .ge(ProductionProductMain::getReportingTime, startDate.atStartOfDay()));
+ if (CollectionUtils.isEmpty(mainList)) return new ArrayList<>();
+
+ List<Long> mainIds = mainList.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+
+ // 鑾峰彇鎶曞叆鏄庣粏
+ List<ProductionProductInput> allInputs = productionProductInputService.list(Wrappers.<ProductionProductInput>lambdaQuery()
+ .in(ProductionProductInput::getProductMainId, mainIds));
+ if (CollectionUtils.isEmpty(allInputs)) return new ArrayList<>();
+
+ // 鑾峰彇瑙勬牸鍜岀墿鏂欏悕绉�
+ Set<Long> skuIds = allInputs.stream().map(ProductionProductInput::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
+ Map<Long, String> skuToMaterialNameMap = new HashMap<>();
+ if (!skuIds.isEmpty()) {
+ List<ProductMaterialSku> skus = productMaterialSkuService.listByIds(skuIds);
+ 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())));
+ }
+
+ Map<String, BigDecimal> countMap = new HashMap<>();
+ countMap.put("绮夌叅鐏�", BigDecimal.ZERO);
+ countMap.put("鐭宠啅", BigDecimal.ZERO);
+ countMap.put("鐭崇伆", BigDecimal.ZERO);
+
+ BigDecimal total = BigDecimal.ZERO;
+
+ for (ProductionProductInput input : allInputs) {
+ String materialName = skuToMaterialNameMap.get(input.getProductId());
+ if (materialName == null || !countMap.containsKey(materialName)) continue;
+
+ BigDecimal qty = UnitUtils.convertValueToTon(input.getQuantity(), input.getUnit());
+ countMap.put(materialName, countMap.get(materialName).add(qty));
+ total = total.add(qty);
+ }
+
+ List<MapDto> result = new ArrayList<>();
+ for (Map.Entry<String, BigDecimal> entry : countMap.entrySet()) {
+ MapDto mapDto = new MapDto();
+ mapDto.setName(entry.getKey());
+ BigDecimal value = entry.getValue().setScale(2, RoundingMode.HALF_UP);
+ mapDto.setValue(value.toString());
+
+ if (total.compareTo(BigDecimal.ZERO) > 0) {
+ BigDecimal rate = entry.getValue().divide(total, 4, RoundingMode.HALF_UP)
+ .multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
+ mapDto.setRate(rate.toString());
+ } else {
+ mapDto.setRate("0.00");
+ }
+ result.add(mapDto);
+ }
+
+ return result;
+ }
+
+ @Override
+ public Map<String, Long> manage() {
+ Map<String, Long> map = new HashMap<>();
+ //鐢熶骇璁㈠崟鎬绘暟
+ Long total = productOrderMapper.selectCount(new QueryWrapper<ProductOrder>().ne("status", 4));
+ map.put("total", total);
+ //宸插畬鎴愯鍗曟暟
+ Long completed = productOrderMapper.selectCount(new QueryWrapper<ProductOrder>().eq("status", 3));
+ map.put("completed", completed);
+ //鏈畬鎴愯鍗曟暟
+ Long uncompleted = productOrderMapper.selectCount(new QueryWrapper<ProductOrder>().eq("status", 1));
+ map.put("uncompleted", uncompleted);
+ //閮ㄥ垎瀹屾垚璁㈠崟鏁�
+ Long partialCompleted = productOrderMapper.selectCount(new QueryWrapper<ProductOrder>().eq("status", 2));
+ map.put("partialCompleted", partialCompleted);
+ //鏉ユ枡妫�鎬绘暟
+ Long materialInspection = qualityInspectMapper.selectCount(new QueryWrapper<QualityInspect>().eq("inspect_type", 0));
+ map.put("materialInspection", materialInspection);
+ return map;
+ }
}
--
Gitblit v1.9.3