package com.ruoyi.home.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.account.pojo.AccountExpense; import com.ruoyi.account.pojo.AccountIncome; import com.ruoyi.approve.mapper.ApproveProcessMapper; import com.ruoyi.approve.pojo.ApproveProcess; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.dto.MapDto; import com.ruoyi.framework.security.LoginUser; import com.ruoyi.home.dto.*; import com.ruoyi.home.service.HomeService; import com.ruoyi.lavorissue.mapper.LavorIssueMapper; import com.ruoyi.lavorissue.pojo.LaborIssue; import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; import com.ruoyi.production.mapper.SalesLedgerWorkMapper; import com.ruoyi.production.pojo.SalesLedgerWork; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.mapper.SysDeptMapper; 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.pojo.QualityInspect; 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 lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** * @author :yys * @date : 2025/7/25 9:23 */ @Service @Slf4j public class HomeServiceImpl implements HomeService { @Autowired private SalesLedgerMapper salesLedgerMapper; @Autowired private PurchaseLedgerMapper purchaseLedgerMapper; @Autowired private SalesLedgerProductMapper salesLedgerProductMapper; @Autowired private ProcurementRecordOutMapper procurementRecordOutMapper; @Autowired private ProcurementRecordMapper procurementRecordStorageMapper; @Autowired private QualityInspectMapper qualityStatisticsMapper; @Autowired private ApproveProcessMapper approveProcessMapper; @Autowired private ReceiptPaymentMapper receiptPaymentMapper; @Autowired private PaymentRegistrationMapper paymentRegistrationMapper; @Autowired private LavorIssueMapper lavorIssueMapper; @Autowired private SysDeptMapper sysDeptMapper; @Autowired private SalesLedgerWorkMapper salesLedgerWorkMapper;; @Override public HomeBusinessDto business() { // 构建结果 HomeBusinessDto homeBusinessDto = new HomeBusinessDto(); LocalDate now = LocalDate.now(); YearMonth currentMonth = YearMonth.from(now); // 创建LambdaQueryWrapper LambdaQueryWrapper salesLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>(); salesLedgerLambdaQueryWrapper.ge(SalesLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 大于等于本月第一天 .lt(SalesLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天 List salesLedgers = salesLedgerMapper.selectList(salesLedgerLambdaQueryWrapper); if(CollectionUtils.isEmpty(salesLedgers)){ return homeBusinessDto; } // 合计合同金额 BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); LambdaQueryWrapper salesLedgerProductMapperLambdaQueryWrapper = new LambdaQueryWrapper(); salesLedgerProductMapperLambdaQueryWrapper.eq(SalesLedgerProduct::getType, 1) .in(SalesLedgerProduct::getSalesLedgerId, salesLedgers.stream().map(SalesLedger::getId).collect(Collectors.toList())); List salesLedgerProducts = salesLedgerProductMapper.selectList(salesLedgerProductMapperLambdaQueryWrapper); // 未开票金额 BigDecimal noInvoiceAmountTotal = salesLedgerProducts.stream().map(SalesLedgerProduct::getNoInvoiceAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); homeBusinessDto.setMonthSaleMoney(contractAmount.setScale(2, RoundingMode.HALF_UP).toString()); homeBusinessDto.setMonthSaleHaveMoney(noInvoiceAmountTotal.setScale(2, RoundingMode.HALF_UP).toString()); // 创建LambdaQueryWrapper LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.ge(PurchaseLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 大于等于本月第一天 .lt(PurchaseLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天 // 执行查询并计算总和 List purchaseLedgers = purchaseLedgerMapper.selectList(queryWrapper); if(CollectionUtils.isEmpty(purchaseLedgers)){ return homeBusinessDto; } LambdaQueryWrapper salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper(); salesLedgerProductMapperLambdaQueryWrapper.eq(SalesLedgerProduct::getType, 2) .in(SalesLedgerProduct::getSalesLedgerId, purchaseLedgers.stream().map(PurchaseLedger::getId).collect(Collectors.toList())); List 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) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 统计库存 List procurementRecordStorages = procurementRecordStorageMapper.selectList(null); BigDecimal stockAmount = procurementRecordStorages.stream() .map(ProcurementRecordStorage::getInboundNum) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); List procurementRecordOuts = procurementRecordOutMapper.selectList(null); BigDecimal outboundAmount = procurementRecordOuts.stream() .map(ProcurementRecordOut::getInboundNum) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal stock = stockAmount.subtract(outboundAmount); // 获取当天入库数量 LambdaQueryWrapper procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>(); procurementRecordStorageLambdaQueryWrapper.ge(ProcurementRecordStorage::getCreateTime, now) // 大于等于当天 .lt(ProcurementRecordStorage::getCreateTime, now.plusDays(1)); // 小于明天 List procurementRecordStorages1 = procurementRecordStorageMapper.selectList(procurementRecordStorageLambdaQueryWrapper); BigDecimal stockAmount1 = procurementRecordStorages1.stream() .map(ProcurementRecordStorage::getInboundNum) .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.setInventoryNum(stock.setScale(2, RoundingMode.HALF_UP).toString()); homeBusinessDto.setTodayInventoryNum(stockAmount1.setScale(2, RoundingMode.HALF_UP).toString()); return homeBusinessDto; } @Override public AnalysisCustomerContractAmountsDto analysisCustomerContractAmounts() { List salesLedgers = salesLedgerMapper.selectList(null); // 合计合同金额 BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 计算周同比 // 获取当前时间 LocalDate today = LocalDate.now(); // 获取本周周一 LocalDate startOfWeek = today.with(DayOfWeek.MONDAY); // 获取本周周日 LocalDate endOfWeek = today.with(DayOfWeek.SUNDAY); List salesLedgers1 = salesLedgerMapper.selectList(new LambdaQueryWrapper() .ge(SalesLedger::getEntryDate, startOfWeek) // 大于等于本周周一 .lt(SalesLedger::getEntryDate, endOfWeek.plusDays(1))); // 修改:使用 lt 并加上一天来包含周日 BigDecimal weekContractAmount = salesLedgers1.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); // 获取去年本周时间 LocalDate lastYearStartOfWeek = today.minusYears(1).with(DayOfWeek.MONDAY); LocalDate lastYearEndOfWeek = today.minusYears(1).with(DayOfWeek.SUNDAY); List salesLedgers2 = salesLedgerMapper.selectList(new LambdaQueryWrapper() .ge(SalesLedger::getEntryDate, lastYearStartOfWeek) // 大于等于去年本周周一 .lt(SalesLedger::getEntryDate, lastYearEndOfWeek.plusDays(1))); // 修改:使用 lt 并加上一天来包含周日 BigDecimal lastYearWeekContractAmount = salesLedgers2.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal subtract = weekContractAmount.subtract(lastYearWeekContractAmount); String weekYny = ""; // 周同比 if(subtract.compareTo(BigDecimal.ZERO) == 0 || lastYearWeekContractAmount.compareTo(BigDecimal.ZERO) == 0){ weekYny = "0.00"; }else{ weekYny = String.format("%.2f", subtract.divide(lastYearWeekContractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))); } // 计算日环比 LocalDate yesterday = today.minusDays(1); LocalDate plusDays = today.plusDays(1); List salesLedgers3 = salesLedgerMapper.selectList(new LambdaQueryWrapper() .ge(SalesLedger::getEntryDate, today) // 大于等于今天 .lt(SalesLedger::getEntryDate, plusDays)); // 修改:使用 lt 并加上一天来包含当天 BigDecimal todayContractAmount = salesLedgers3.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); List salesLedgers4 = salesLedgerMapper.selectList(new LambdaQueryWrapper() .ge(SalesLedger::getEntryDate, yesterday) // 大于等于昨天 .lt(SalesLedger::getEntryDate, today)); // 修改:使用 lt 而不是 gt BigDecimal lastYearYesterdayContractAmount = salesLedgers4.stream().map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal subtract1 = todayContractAmount.subtract(lastYearYesterdayContractAmount); // 修改:使用 todayContractAmount 而不是 yesterdayContractAmount // 日环比 String chain = ""; if(subtract1.compareTo(BigDecimal.ZERO) == 0 || lastYearYesterdayContractAmount.compareTo(BigDecimal.ZERO) == 0){ chain = "0.00"; }else{ chain = String.format("%.2f", subtract1.divide(lastYearYesterdayContractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))); } AnalysisCustomerContractAmountsDto analysisCustomerContractAmountsDto = new AnalysisCustomerContractAmountsDto(); // 修改:将合同金额保留两位小数 analysisCustomerContractAmountsDto.setSum(contractAmount.setScale(2, RoundingMode.HALF_UP).toString()); analysisCustomerContractAmountsDto.setYny(weekYny); analysisCustomerContractAmountsDto.setChain(chain); Map collect = salesLedgers.stream().collect(Collectors.groupingBy(SalesLedger::getCustomerName, Collectors.reducing(BigDecimal.ZERO, SalesLedger::getContractAmount, BigDecimal::add))); List mapDtos = new ArrayList<>(); collect.forEach((k,v)->{ MapDto mapDto = new MapDto(); mapDto.setName(k); // 修改:将金额值保留两位小数 mapDto.setValue(v.setScale(2, RoundingMode.HALF_UP).toString()); if(contractAmount.compareTo(new BigDecimal(0)) == 0){ mapDto.setRate("0"); }else{ mapDto.setRate(String.format("%.2f", v.divide(contractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")))); } mapDtos.add(mapDto); }); analysisCustomerContractAmountsDto.setItem(mapDtos); return analysisCustomerContractAmountsDto; } @Override public QualityStatisticsDto qualityStatistics() { // 获取近四个月数据(往前推三个月,共4个完整月份) LocalDate today = LocalDate.now(); // 定义日期格式化器(用于显示“年月”格式) DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); QualityStatisticsDto qualityStatisticsDto = new QualityStatisticsDto(); List qualityStatisticsItems = new ArrayList<>(); BigDecimal supplierNum = new BigDecimal(0); BigDecimal factoryNum = new BigDecimal(0); BigDecimal processNum = new BigDecimal(0); // 循环4次,分别统计近4个月的数据(当前月、前1个月、前2个月、前3个月) for (int i = 3; i >= 0; i--) { // 计算当前循环对应的月份(i=0:当前月,i=1:前1个月,以此类推) LocalDate currentMonth = today.minusMonths(i); // 当月的开始日期(每月1号) LocalDate monthStart = currentMonth.withDayOfMonth(1); // 当月的结束日期(每月最后一天) LocalDate monthEnd = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth()); // 构建当月的查询条件(如果想一次性查全4个月数据再内存筛选,可优化为先查全再循环筛选) LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.ge(QualityInspect::getCheckTime, monthStart) .le(QualityInspect::getCheckTime, monthEnd); // 筛选当月数据 List monthInspects = qualityStatisticsMapper.selectList(queryWrapper); BigDecimal reduce = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0)) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); supplierNum = supplierNum.add(reduce); BigDecimal reduce1 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1)) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); processNum= processNum.add(reduce1); BigDecimal reduce2 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2)) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); factoryNum = factoryNum.add(reduce2); // 构建当月统计项 QualityStatisticsItem item = new QualityStatisticsItem(); item.setDate(monthStart.format(monthFormatter)); // 日期显示为“年月”(如 2025-10) // 1. 供应商检验(类型0)- 合格数量 BigDecimal supplierQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0) && "合格".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSupplierNum(supplierQualified); // 2. 工序检验(类型1)- 合格数量 BigDecimal processQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1) && "合格".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setProcessNum(processQualified); // 3. 工厂检验(类型2)- 合格数量 BigDecimal factoryQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2) && "合格".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setFactoryNum(factoryQualified); qualityStatisticsItems.add(item); } // 统计近4个月总数据(所有月份汇总) qualityStatisticsDto.setProcessNum(processNum); qualityStatisticsDto.setSupplierNum(supplierNum); qualityStatisticsDto.setFactoryNum(factoryNum); qualityStatisticsDto.setItem(qualityStatisticsItems); return qualityStatisticsDto; } @Override public List todos() throws ParseException { LoginUser loginUser = SecurityUtils.getLoginUser(); LambdaQueryWrapper approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>(); approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveDelete, 0) .eq(ApproveProcess::getApproveUserCurrentId, loginUser.getUserId()) .ne(ApproveProcess::getApproveStatus, 2) .eq(ApproveProcess::getTenantId, loginUser.getTenantId()); List approveProcesses = approveProcessMapper.selectList(approveProcessLambdaQueryWrapper); if(CollectionUtils.isEmpty(approveProcesses)){ approveProcesses = new ArrayList<>(); } // 查询未领用劳保记录 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); LaborIssue laborIssue1 = new LaborIssue(); laborIssue1.setAdoptedDate(new Date()); laborIssue1.setIssueDate(sdf.parse(sdf.format(new Date()))); List laborIssues = lavorIssueMapper.list(laborIssue1); if(!CollectionUtils.isEmpty(laborIssues)){ for (LaborIssue laborIssue : laborIssues) { ApproveProcess approveProcess = new ApproveProcess(); approveProcess.setApproveId(laborIssue.getOrderNo()); approveProcess.setApproveDeptName(sysDeptMapper.selectDeptById(loginUser.getTenantId()).getDeptName()); approveProcess.setApproveTime(laborIssue.getIssueDate()); approveProcess.setApproveReason(laborIssue.getDictTypeName() + "-" + laborIssue.getDictName() + "超时未领取"); approveProcesses.add(approveProcess); } } return approveProcesses; } /** * * @param type 1-周 2-月 3-季度 * @return */ @Override public StatisticsReceivablePayableDto statisticsReceivablePayable(Integer type) { LocalDate today = LocalDate.now(); LocalDate startDate = null; LocalDate endDate = null; 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: Month currentMonth = today.getMonth(); Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter(); Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2); startDate = today.withMonth(firstMonthOfQuarter.getValue()) .with(TemporalAdjusters.firstDayOfMonth()); endDate = today.withMonth(lastMonthOfQuarter.getValue()) .with(TemporalAdjusters.lastDayOfMonth()); break; } // 应收 List salesLedgers = salesLedgerMapper.selectList(new LambdaQueryWrapper() // .ge(SalesLedger::getEntryDate, startDate) // .lt(SalesLedger::getEntryDate, endDate) ); BigDecimal receivableMoney = salesLedgers.stream().map(SalesLedger::getContractAmount).reduce(BigDecimal.ZERO, BigDecimal::add); // 应付 List procurementRecords = purchaseLedgerMapper.selectList(new LambdaQueryWrapper() // .ge(PurchaseLedger::getEntryDate, startDate) // .lt(PurchaseLedger::getEntryDate, endDate) ); BigDecimal payableMoney = procurementRecords.stream().map(PurchaseLedger::getContractAmount).reduce(BigDecimal.ZERO, BigDecimal::add); // 预收 List receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper() // .ge(ReceiptPayment::getReceiptPaymentDate, startDate) // .lt(ReceiptPayment::getReceiptPaymentDate, endDate) ); BigDecimal advanceMoney = receiptPayments.stream().map(ReceiptPayment::getReceiptPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); // 预付 List paymentRegistrations = paymentRegistrationMapper.selectList(new LambdaQueryWrapper() // .ge(PaymentRegistration::getPaymentDate, startDate) // .lt(PaymentRegistration::getPaymentDate, endDate) ); BigDecimal prepayMoney = paymentRegistrations.stream().map(PaymentRegistration::getCurrentPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); StatisticsReceivablePayableDto statisticsReceivablePayableDto = new StatisticsReceivablePayableDto(); statisticsReceivablePayableDto.setPayableMoney(payableMoney.subtract(prepayMoney)); statisticsReceivablePayableDto.setReceivableMoney(receivableMoney.subtract(advanceMoney)); statisticsReceivablePayableDto.setAdvanceMoney(advanceMoney); statisticsReceivablePayableDto.setPrepayMoney(prepayMoney); return statisticsReceivablePayableDto; } @Override public QualityProductQualifiedRateDto qualityProductQualifiedRate() { QualityProductQualifiedRateDto qualityProductQualifiedRateDto = new QualityProductQualifiedRateDto(); List qualityInspects = qualityStatisticsMapper.selectList(null); if(!CollectionUtils.isEmpty(qualityInspects)){ // 原材料合格率 BigDecimal rawwMaterialCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 0) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal count = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 0) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); if(count.compareTo(BigDecimal.ZERO) != 0){ qualityProductQualifiedRateDto.setRawMaterialQualifiedRate(rawwMaterialCount .divide(count, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100.0))); } // 过程合格率 BigDecimal processCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 1) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal countOne = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 1) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); if(countOne.compareTo(BigDecimal.ZERO) != 0){ qualityProductQualifiedRateDto.setProcessQualifiedRate(processCount .divide(countOne, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100.0))); } // 出厂合格率 BigDecimal factoryCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 2) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal countTwo = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 2) .map(QualityInspect::getQuantity) .reduce(BigDecimal.ZERO, BigDecimal::add); if(countTwo.compareTo(BigDecimal.ZERO) != 0){ qualityProductQualifiedRateDto.setFactoryQualifiedRate(factoryCount .divide(countTwo, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100.0))); } } // 库存周转率统计当月出库(使用)的物料总数量÷平均的库存物料总数量×100%。) // 获取当前月 LocalDate today = LocalDate.now(); LocalDate startDate = today.with(TemporalAdjusters.firstDayOfMonth()); LocalDate endDate = today.with(TemporalAdjusters.lastDayOfMonth()); // 获取当前月出库(使用)的物料总数量 List procurementRecordOuts = procurementRecordOutMapper.selectList(new LambdaQueryWrapper() .ge(ProcurementRecordOut::getCreateTime, startDate) .lt(ProcurementRecordOut::getCreateTime, endDate)); // 获取当前月入库的物料总数量 List procurementRecordStorages = procurementRecordStorageMapper.selectList(new LambdaQueryWrapper() .ge(ProcurementRecordStorage::getCreateTime, startDate) .lt(ProcurementRecordStorage::getCreateTime, endDate)); BigDecimal reduce = procurementRecordOuts.stream() .map(ProcurementRecordOut::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal reduceOne = procurementRecordStorages.stream() .map(ProcurementRecordStorage::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); if(reduce.compareTo(BigDecimal.ZERO) > 0){ qualityProductQualifiedRateDto.setInventoryTurnoverRate(reduceOne.divide(reduce, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100.0))); } return qualityProductQualifiedRateDto; } @Override public QualityStatisticsDto inventoryStatistics() { // 获取近四个月数据(往前推三个月,共4个完整月份) LocalDate today = LocalDate.now(); // 定义日期格式化器(用于显示“年月”格式) DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); QualityStatisticsDto qualityStatisticsDto = new QualityStatisticsDto(); List qualityStatisticsItems = new ArrayList<>(); BigDecimal supplierNum = new BigDecimal(0); //入库数量 BigDecimal factoryNum = new BigDecimal(0); //出库数量 // 循环4次,分别统计近4个月的数据(当前月、前1个月、前2个月、前3个月) for (int i = 3; i >= 0; i--) { // 计算当前循环对应的月份(i=0:当前月,i=1:前1个月,以此类推) LocalDate currentMonth = today.minusMonths(i); // 当月的开始日期(每月1号) LocalDate monthStart = currentMonth.withDayOfMonth(1); // 当月的结束日期(每月最后一天) LocalDate monthEnd = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth()); // 入库数量 // 构建当月的查询条件(如果想一次性查全4个月数据再内存筛选,可优化为先查全再循环筛选) LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.ge(ProcurementRecordStorage::getCreateTime, monthStart) .le(ProcurementRecordStorage::getCreateTime, monthEnd); // 筛选当月数据 List monthInspects = procurementRecordStorageMapper.selectList(queryWrapper); // 出库数量 LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); queryWrapper1.ge(ProcurementRecordOut::getCreateTime, monthStart) .le(ProcurementRecordOut::getCreateTime, monthEnd); List monthInspects1 = procurementRecordOutMapper.selectList(queryWrapper1); BigDecimal reduce = monthInspects.stream() .map(ProcurementRecordStorage::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); supplierNum = supplierNum.add(reduce); BigDecimal reduce1 = monthInspects1.stream() .map(ProcurementRecordOut::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); factoryNum= factoryNum.add(reduce1); // 构建当月统计项 QualityStatisticsItem item = new QualityStatisticsItem(); item.setDate(monthStart.format(monthFormatter)); // 日期显示为“年月”(如 2025-10) // 1. 供应商检验(类型0)- 合格数量 BigDecimal supplierQualified = monthInspects.stream() .map(ProcurementRecordStorage::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSupplierNum(supplierQualified); // 3. 工厂检验(类型2)- 合格数量 BigDecimal factoryQualified = monthInspects1.stream() .map(ProcurementRecordOut::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setFactoryNum(factoryQualified); qualityStatisticsItems.add(item); } // 统计近4个月总数据(所有月份汇总) qualityStatisticsDto.setSupplierNum(supplierNum); qualityStatisticsDto.setFactoryNum(factoryNum); qualityStatisticsDto.setItem(qualityStatisticsItems); return qualityStatisticsDto; } @Override public Map> productionStatistics() { // 获取最近四个月(当前月 + 前3个月)的时间范围 LocalDate today = LocalDate.now(); DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // 年月格式化器 Map> result = new HashMap<>(); List months = new ArrayList<>(); // 存储年月(如 2025-12、2025-11) List totalIncomeList = new ArrayList<>(); // 每月总收入 List totalExpenseList = new ArrayList<>(); // 每月总支出 List netIncomeList = new ArrayList<>(); // 每月净收入(收入-支出) // 步骤1:计算近4个月的年月列表(当前月、前1月、前2月、前3月) List targetMonths = new ArrayList<>(); for (int i = 0; i < 4; i++) { LocalDate currentMonth = today.minusMonths(i); String monthStr = currentMonth.format(monthFormatter); targetMonths.add(monthStr); } // 反转列表,确保顺序为「前3月 → 当前月」(可选,按需求调整顺序) Collections.reverse(targetMonths); // 步骤2:一次性查询近4个月所有收入数据,按“年月”分组汇总 LocalDate fourMonthsAgo = today.minusMonths(3).withDayOfMonth(1); // 近4个月起始日(前3月1号) LocalDate currentMonthEnd = today.withDayOfMonth(today.lengthOfMonth()); // 当前月结束日 ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // 查询近4个月所有收入 List allIncomes = salesLedgerWorkMapper.selectList( Wrappers.lambdaQuery() .ge(SalesLedgerWork::getSchedulingDate, fourMonthsAgo.toString()) // 大于等于起始日 .le(SalesLedgerWork::getSchedulingDate, currentMonthEnd.toString()) // 小于等于结束日 ); // 待生产 Map monthlyIncomeMap = allIncomes.stream() .filter(income -> income.getSchedulingNum() != null && income.getStatus().equals(1)) // 过滤空金额 .collect(Collectors.groupingBy( income -> { // 将输入时间(字符串)转换为LocalDate,再格式化为年月 return income.getSchedulingDate().format(monthFormatter); }, Collectors.reducing(BigDecimal.ZERO, SalesLedgerWork::getSchedulingNum, BigDecimal::add) )); // 生产中 Map monthlyExpenseMap = allIncomes.stream() .filter(income -> income.getSchedulingNum() != null && income.getStatus().equals(2)) // 过滤空金额 .collect(Collectors.groupingBy( income -> { // 将输入时间(字符串)转换为LocalDate,再格式化为年月 return income.getSchedulingDate().format(monthFormatter); }, Collectors.reducing(BigDecimal.ZERO, SalesLedgerWork::getSchedulingNum, BigDecimal::add) )); // 已报工 Map successIncomeMap = allIncomes.stream() .filter(income -> income.getSchedulingNum() != null && income.getStatus().equals(3)) // 过滤空金额 .collect(Collectors.groupingBy( income -> { // 将输入时间(字符串)转换为LocalDate,再格式化为年月 return income.getSchedulingDate().format(monthFormatter); }, Collectors.reducing(BigDecimal.ZERO, SalesLedgerWork::getSchedulingNum, BigDecimal::add) )); // 步骤4:循环4个目标月份,填充统计数据(无数据时默认为0) for (String month : targetMonths) { // 待生产 BigDecimal totalIncome = monthlyIncomeMap.getOrDefault(month, BigDecimal.ZERO); // 生产中 BigDecimal totalExpense = monthlyExpenseMap.getOrDefault(month, BigDecimal.ZERO); // 已报工 BigDecimal netIncome = successIncomeMap.getOrDefault(month, BigDecimal.ZERO); // 填充列表 months.add(month); totalIncomeList.add(totalIncome.toString()); totalExpenseList.add(totalExpense.toString()); netIncomeList.add(netIncome.toString()); } // 组装结果 result.put("days", months); // 年月(如 ["2025-09", "2025-10", "2025-11", "2025-12"]) result.put("totalIncome", totalIncomeList); // 待生产 result.put("totalExpense", totalExpenseList); // 生产中 result.put("netIncome", netIncomeList); // 已报工 return result; } }