package com.ruoyi.home.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.pojo.SupplierManage; import com.ruoyi.collaborativeApproval.mapper.NoticeMapper; import com.ruoyi.collaborativeApproval.pojo.Notice; import com.ruoyi.common.utils.SecurityUtils; 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.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.pojo.ProductWorkOrder; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysUserDept; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysUserDeptMapper; 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.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.sales.pojo.ReceiptPayment; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.StaffOnJob; 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.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; import java.util.*; 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 ProcurementRecordMapper procurementRecordStorageMapper; @Autowired private QualityInspectMapper qualityStatisticsMapper; @Autowired private ApproveProcessMapper approveProcessMapper; @Autowired private ReceiptPaymentMapper receiptPaymentMapper; @Autowired private PaymentRegistrationMapper paymentRegistrationMapper; @Autowired private SysDeptMapper sysDeptMapper; @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 SysUserMapper sysUserMapper; @Autowired private SysUserDeptMapper sysUserDeptMapper; @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)){ // 合计合同金额 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)){ LambdaQueryWrapper salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper(); salesLedgerProductMapperLambdaQueryWrapperCopy.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); homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString()); homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString()); } // 统计库存 // List procurementRecordStorages = procurementRecordStorageMapper.selectList(null); // BigDecimal stockAmount = procurementRecordStorages.stream() // .map(ProcurementRecordStorage::getInboundNum) // .filter(Objects::nonNull) // .reduce(BigDecimal.ZERO, BigDecimal::add); // // 自定义库存 // List customStorages = customStorageMapper.selectList(null); // BigDecimal customStockAmount = customStorages.stream() // .map(CustomStorage::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.add(customStockAmount).subtract(outboundAmount); IPage productModelIPage = productModelMapper.listPageProductModel(new Page<>(1, -1), new ProductModel()); if(!CollectionUtils.isEmpty(productModelIPage.getRecords())){ //获取规格id List modelIds = productModelIPage.getRecords().stream().map(ProductModel::getId).collect(Collectors.toList()); BigDecimal stockQuantityTotal = modelIds.stream() .map(stockUtils::getStockQuantity) .map(map -> map.get("stockQuantity")) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); homeBusinessDto.setInventoryNum(stockQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString()); } // 获取当天入库数量 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.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); //staff_join_leave_record表被删除 // 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); BigDecimal receivableMoney = sumAmount(salesLedgers, SalesLedger::getContractAmount); // 应付 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); BigDecimal payableMoney = sumAmount(procurementRecords, PurchaseLedger::getContractAmount); // 预收 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); BigDecimal advanceMoney = sumAmount(receiptPayments, ReceiptPayment::getReceiptPaymentAmount); // 预付 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); BigDecimal prepayMoney = sumAmount(paymentRegistrations, PaymentRegistration::getCurrentPaymentAmount); StatisticsReceivablePayableDto statisticsReceivablePayableDto = new StatisticsReceivablePayableDto(); statisticsReceivablePayableDto.setPayableMoney(payableMoney.subtract(prepayMoney)); statisticsReceivablePayableDto.setReceivableMoney(receivableMoney.subtract(advanceMoney)); statisticsReceivablePayableDto.setAdvanceMoney(advanceMoney); statisticsReceivablePayableDto.setPrepayMoney(prepayMoney); return statisticsReceivablePayableDto; } public static BigDecimal sumAmount(List list, java.util.function.Function amountExtractor) { return list.stream() // 提取金额时,将null替换为BigDecimal.ZERO .map(item -> Optional.ofNullable(amountExtractor.apply(item)).orElse(BigDecimal.ZERO)) // 累加,初始值为0,避免空流问题 .reduce(BigDecimal.ZERO, BigDecimal::add); } @Autowired private DeviceRepairMapper deviceRepairMapper; @Override public Map approveAndDeviceTodos() { // 审批协同待办 Long aLong = approveProcessMapper.selectCount(new LambdaQueryWrapper() .eq(ApproveProcess::getApproveUserCurrentId, SecurityUtils.getUserId()) .eq(ApproveProcess::getApproveDelete, 0) .in(ApproveProcess::getApproveStatus, 0, 1, 3)); // 设备报修待办 Long aLong1 = deviceRepairMapper.selectCount(new LambdaQueryWrapper() .eq(DeviceRepair::getStatus, 0) .eq(DeviceRepair::getRepairName, SecurityUtils.getLoginUser().getNickName())); return new HashMap() {{ put("approveTodo", aLong); put("deviceRepairTodo", aLong1); }}; } @Override public Long noticesCount() { // 查询未过期的通知数量:状态为发布且过期时间大于等于当前日期 return noticeMapper.selectCount(new LambdaQueryWrapper() .eq(Notice::getStatus, 1) // 1表示发布状态 .ge(Notice::getExpirationDate, new Date())); // 过期时间大于等于当前日期 } @Override public ProductionProgressDto productionProgress() { ProductionProgressDto productionProgressDto = new ProductionProgressDto(); ProductOrderDto orderDto = new ProductOrderDto(); orderDto.setStartTime(LocalDateTime.now().minusMonths(1)); orderDto.setEndTime(LocalDateTime.now()); List productOrderDtos = productOrderMapper.pageProductOrder(new Page<>(1, -1), orderDto).getRecords(); productionProgressDto.setCompletedOrderDetails(productOrderDtos); long totalCount = productOrderDtos.size(); long count = productOrderDtos.stream().filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(productOrderDto.getQuantity()) >= 0).count(); long count2 = productOrderDtos.stream().filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(BigDecimal.ZERO) == 0).count(); productionProgressDto.setTotalOrderCount(totalCount); productionProgressDto.setCompletedOrderCount(count); productionProgressDto.setUncompletedOrderCount(count2); productionProgressDto.setPartialCompletedOrderCount(totalCount-count-count2); return productionProgressDto; } @Override public ProductionTurnoverDto workInProcessTurnover() { ProductionTurnoverDto productionTurnoverDto = new ProductionTurnoverDto(); ProductWorkOrderDto workOrder = new ProductWorkOrderDto(); workOrder.setPlanStartTime(LocalDate.now().minusMonths(1)); workOrder.setPlanEndTime(LocalDate.now()); List productWorkOrders = productWorkOrderMapper.pageProductWorkOrder(new Page<>(1, -1), workOrder).getRecords(); long sum = productWorkOrders.stream() .filter(productWorkOrder -> productWorkOrder.getPlanQuantity().compareTo(productWorkOrder.getCompleteQuantity()) > 0) .map(ProductWorkOrder::getPlanQuantity) .mapToLong(BigDecimal::longValue) .sum(); if (sum == 0)return null; productionTurnoverDto.setTotalOrderCount(sum);//总在制品数量 productionTurnoverDto.setAverageTurnoverDays(BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(ChronoUnit.DAYS.between(LocalDateTime.now().minusMonths(1), LocalDateTime.now())),2,RoundingMode.HALF_UP)); long completeQuantity = productWorkOrders.stream() .filter(productWorkOrder -> productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0) .map(ProductWorkOrder::getCompleteQuantity) .mapToLong(BigDecimal::longValue) .sum(); productionTurnoverDto.setTurnoverEfficiency(BigDecimal.valueOf(completeQuantity).divide(BigDecimal.valueOf(sum),2,RoundingMode.HALF_UP)); Map> map = productWorkOrders.stream() .filter(productWorkOrder -> productWorkOrder.getPlanQuantity().compareTo(productWorkOrder.getCompleteQuantity()) > 0) .collect(Collectors.groupingBy(ProductWorkOrderDto::getProcessName)); List strings = new ArrayList<>(); List processQuantityDetails = new ArrayList<>(); map.entrySet().stream().forEach(entry -> { String key = entry.getKey(); long completeSum = entry.getValue().stream().map(ProductWorkOrderDto::getCompleteQuantity).mapToLong(BigDecimal::longValue).sum(); strings.add(key); processQuantityDetails.add(completeSum); }); productionTurnoverDto.setProcessDetails(strings); productionTurnoverDto.setProcessQuantityDetails(processQuantityDetails); return productionTurnoverDto; } @Override public DeptStaffDistributionDto deptStaffDistribution() { DeptStaffDistributionDto dto = new DeptStaffDistributionDto(); List items = new ArrayList<>(); // 查询所有正常且未删除的部门 List depts = sysDeptMapper.selectDeptList(new SysDept()); if (CollectionUtils.isEmpty(depts)) { dto.setItems(items); return dto; } long totalUsers = 0; List> countsByDept = new ArrayList<>(); for (SysDept dept : depts) { if ("0".equals(dept.getStatus()) && "0".equals(dept.getDelFlag())) { Long count = sysUserDeptMapper.selectCount(new LambdaQueryWrapper() .eq(SysUserDept::getDeptId, dept.getDeptId())); if (count > 0) { Map map = new HashMap<>(); map.put("name", dept.getDeptName()); map.put("count", count); countsByDept.add(map); totalUsers += count; } } } if (totalUsers > 0) { BigDecimal total = BigDecimal.valueOf(totalUsers); for (Map map : countsByDept) { MapDto mapDto = new MapDto(); mapDto.setName((String) map.get("name")); Long count = (Long) map.get("count"); mapDto.setValue(count.toString()); mapDto.setRate(BigDecimal.valueOf(count).multiply(new BigDecimal("100")) .divide(total, 2, RoundingMode.HALF_UP).toString()); items.add(mapDto); } } dto.setTotal(totalUsers); dto.setItems(items); return dto; } @Override public HomeSummaryDto summaryStatistics() { HomeSummaryDto dto = new HomeSummaryDto(); LocalDate now = LocalDate.now(); YearMonth currentMonth = YearMonth.from(now); YearMonth prevMonth = currentMonth.minusMonths(1); LocalDateTime currentMonthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59); LocalDateTime prevMonthEnd = prevMonth.atEndOfMonth().atTime(23, 59, 59); // 总工作人员 Long currentStaff = countStaff(currentMonthEnd); Long prevStaff = countStaff(prevMonthEnd); dto.setTotalStaff(currentStaff); dto.setStaffGrowthRate(calculateMoM(currentStaff, prevStaff)); // 总客户数 Long currentCustomers = countCustomers(currentMonthEnd); Long prevCustomers = countCustomers(prevMonthEnd); dto.setTotalCustomer(currentCustomers); dto.setCustomerGrowthRate(calculateMoM(currentCustomers, prevCustomers)); // 总供应商数 Long currentSuppliers = countSuppliers(currentMonthEnd); Long prevSuppliers = countSuppliers(prevMonthEnd); dto.setTotalSupplier(currentSuppliers); dto.setSupplierGrowthRate(calculateMoM(currentSuppliers, prevSuppliers)); return dto; } private Long countStaff(LocalDateTime dateTime) { Long sysUserCount = sysUserMapper.selectCount(new LambdaQueryWrapper() .eq(SysUser::getDelFlag, "0") .le(SysUser::getCreateTime, dateTime)); Long staffCountItem = staffOnJobMapper.selectCount(new LambdaQueryWrapper() .le(StaffOnJob::getCreateTime, dateTime)); return sysUserCount + staffCountItem; } private Long countCustomers(LocalDateTime dateTime) { return customerMapper.selectCount(new LambdaQueryWrapper() .le(Customer::getMaintenanceTime, dateTime.toLocalDate())); } private Long countSuppliers(LocalDateTime dateTime) { return supplierManageMapper.selectCount(new LambdaQueryWrapper() .le(SupplierManage::getCreateTime, dateTime)); } private String calculateMoM(Number current, Number prev) { BigDecimal curVal = new BigDecimal(current.toString()); BigDecimal prevVal = new BigDecimal(prev.toString()); if (prevVal.compareTo(BigDecimal.ZERO) == 0) { return curVal.compareTo(BigDecimal.ZERO) > 0 ? "100.00" : "0.00"; } return curVal.subtract(prevVal) .divide(prevVal, 4, RoundingMode.HALF_UP) .multiply(new BigDecimal("100")) .setScale(2, RoundingMode.HALF_UP) .toString(); } @Override public List supplierPurchaseRanking(Integer type) { LocalDate today = LocalDate.now(); LocalDate startDate; LocalDate endDate; switch (type) { case 0: // 周 startDate = today.with(DayOfWeek.MONDAY); endDate = today.with(DayOfWeek.SUNDAY); break; case 1: // 月 startDate = today.with(TemporalAdjusters.firstDayOfMonth()); endDate = today.with(TemporalAdjusters.lastDayOfMonth()); break; case 2: // 季度 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; default: return new ArrayList<>(); } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("supplier_name", "SUM(contract_amount) as total_amount") .ge("entry_date", startDate) .le("entry_date", endDate) // .ne("approval_status", 3) .groupBy("supplier_name") .orderByDesc("total_amount") .last("LIMIT 5"); List> maps = purchaseLedgerMapper.selectMaps(queryWrapper); return maps.stream().map(map -> { SupplierPurchaseRankingDto dto = new SupplierPurchaseRankingDto(); dto.setSupplierName(map.get("supplier_name") != null ? map.get("supplier_name").toString() : ""); Object amount = map.get("total_amount"); dto.setTotalAmount(amount != null ? new BigDecimal(amount.toString()) : BigDecimal.ZERO); return dto; }).collect(Collectors.toList()); } @Override public CustomerRevenueAnalysisDto customerRevenueAnalysis(Long customerId, Integer type) { CustomerRevenueAnalysisDto dto = new CustomerRevenueAnalysisDto(); List items = new ArrayList<>(); LocalDate today = LocalDate.now(); LocalDate start; LocalDate end; boolean groupByMonth = false; switch (type) { case 0: // 周 start = today.with(DayOfWeek.MONDAY); end = today.with(DayOfWeek.SUNDAY); break; case 1: // 月 start = today.with(TemporalAdjusters.firstDayOfMonth()); end = today.with(TemporalAdjusters.lastDayOfMonth()); break; case 2: // 季度 Month firstMonthOfQuarter = today.getMonth().firstMonthOfQuarter(); start = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth()); end = today.withMonth(firstMonthOfQuarter.plus(2).getValue()).with(TemporalAdjusters.lastDayOfMonth()); groupByMonth = true; break; default: dto.setItems(items); return dto; } List list = salesLedgerMapper.selectList(new LambdaQueryWrapper() .eq(SalesLedger::getCustomerId, customerId) .ge(SalesLedger::getEntryDate, start) .le(SalesLedger::getEntryDate, end)); if (groupByMonth) { for (int i = 0; i < 3; i++) { LocalDate m = start.plusMonths(i); String monthName = m.getMonthValue() + "月"; BigDecimal sum = list.stream() .filter(l -> l.getEntryDate() != null) .filter(l -> { LocalDate ld = l.getEntryDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); return ld.getMonth() == m.getMonth() && ld.getYear() == m.getYear(); }) .map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); MapDto mapDto = new MapDto(); mapDto.setName(monthName); mapDto.setValue(sum.setScale(2, RoundingMode.HALF_UP).toString()); items.add(mapDto); } } else { long days = ChronoUnit.DAYS.between(start, end) + 1; for (int i = 0; i < days; i++) { LocalDate d = start.plusDays(i); String dayName = d.getMonthValue() + "/" + d.getDayOfMonth(); BigDecimal sum = list.stream() .filter(l -> l.getEntryDate() != null) .filter(l -> l.getEntryDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().equals(d)) .map(SalesLedger::getContractAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); MapDto mapDto = new MapDto(); mapDto.setName(dayName); mapDto.setValue(sum.setScale(2, RoundingMode.HALF_UP).toString()); items.add(mapDto); } } dto.setItems(items); return dto; } @Override public ProductCategoryDistributionDto productCategoryDistribution() { ProductCategoryDistributionDto dto = new ProductCategoryDistributionDto(); List majorItems = new ArrayList<>(); // 所有的产品大类和小类 List allProducts = productMapper.selectList(new LambdaQueryWrapper()); if (CollectionUtils.isEmpty(allProducts)) { dto.setItems(majorItems); return dto; } List majorCategories = allProducts.stream().filter(p -> p.getParentId() == null).collect(Collectors.toList()); List minorCategories = allProducts.stream().filter(p -> p.getParentId() != null).collect(Collectors.toList()); // 从 sales_ledger_product 拿到每个产品的型号库存 // 需包含规格型号以支持三级分布 List> quantityMaps = salesLedgerProductMapper.selectMaps(new QueryWrapper() .select("product_id", "specification_model", "type", "SUM(quantity) as sum_qty") .isNotNull("product_id") .groupBy("product_id", "specification_model", "type")); Map>> modelStockGroups = new HashMap<>(); for (Map map : quantityMaps) { Long productId = Long.parseLong(map.get("product_id").toString()); String model = map.get("specification_model") != null ? map.get("specification_model").toString() : "未知型号"; Integer type = Integer.parseInt(map.get("type").toString()); BigDecimal sum = map.get("sum_qty") != null ? new BigDecimal(map.get("sum_qty").toString()) : BigDecimal.ZERO; modelStockGroups.computeIfAbsent(productId, k -> new HashMap<>()) .computeIfAbsent(model, k -> new HashMap<>()) .put(type, sum); } // 库存并汇总 Map> productModelsMap = new HashMap<>(); Map productTotalStockMap = new HashMap<>(); for (Long pid : modelStockGroups.keySet()) { Map> models = modelStockGroups.get(pid); BigDecimal productStock = BigDecimal.ZERO; List modelDtos = new ArrayList<>(); for (String modelName : models.keySet()) { Map types = models.get(modelName); BigDecimal procurement = types.getOrDefault(2, BigDecimal.ZERO); BigDecimal sales = types.getOrDefault(1, BigDecimal.ZERO); BigDecimal stock = procurement.subtract(sales); if (stock.compareTo(BigDecimal.ZERO) < 0) stock = BigDecimal.ZERO; MapDto modelDto = new MapDto(); modelDto.setName(modelName); modelDto.setValue(stock.stripTrailingZeros().toPlainString()); modelDtos.add(modelDto); productStock = productStock.add(stock); } productModelsMap.put(pid, modelDtos); productTotalStockMap.put(pid, productStock); } BigDecimal totalInventory = productTotalStockMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); // 型号占比 if (totalInventory.compareTo(BigDecimal.ZERO) > 0) { for (List dtos : productModelsMap.values()) { for (MapDto m : dtos) { BigDecimal val = new BigDecimal(m.getValue()); m.setRate(val.multiply(new BigDecimal("100")) .divide(totalInventory, 2, RoundingMode.HALF_UP).toString()); } } } // 分层数据 for (Product major : majorCategories) { ProductCategoryDistributionDto.MajorCategoryDto majorDto = new ProductCategoryDistributionDto.MajorCategoryDto(); majorDto.setName(major.getProductName()); List minorDtos = new ArrayList<>(); BigDecimal majorStock = BigDecimal.ZERO; for (Product minor : minorCategories) { if (major.getId().equals(minor.getParentId())) { BigDecimal stock = productTotalStockMap.getOrDefault(minor.getId(), BigDecimal.ZERO); ProductCategoryDistributionDto.MinorCategoryDto minorDto = new ProductCategoryDistributionDto.MinorCategoryDto(); minorDto.setName(minor.getProductName()); minorDto.setValue(stock.stripTrailingZeros().toPlainString()); if (totalInventory.compareTo(BigDecimal.ZERO) > 0) { minorDto.setRate(stock.multiply(new BigDecimal("100")) .divide(totalInventory, 2, RoundingMode.HALF_UP).toString()); } else { minorDto.setRate("0.00"); } minorDto.setChildren(productModelsMap.getOrDefault(minor.getId(), new ArrayList<>())); minorDtos.add(minorDto); majorStock = majorStock.add(stock); } } majorDto.setValue(majorStock.stripTrailingZeros().toPlainString()); if (totalInventory.compareTo(BigDecimal.ZERO) > 0) { majorDto.setRate(majorStock.multiply(new BigDecimal("100")) .divide(totalInventory, 2, RoundingMode.HALF_UP).toString()); } else { majorDto.setRate("0.00"); } majorDto.setChildren(minorDtos); majorItems.add(majorDto); } dto.setItems(majorItems); return dto; } @Override public List customerContributionRanking(Integer type) { LocalDate today = LocalDate.now(); LocalDate startDate = null; LocalDate endDate = null; switch (type) { case 0: startDate = today.with(DayOfWeek.MONDAY); endDate = today.with(DayOfWeek.SUNDAY); break; case 1: startDate = today.with(TemporalAdjusters.firstDayOfMonth()); endDate = today.with(TemporalAdjusters.lastDayOfMonth()); break; case 2: 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; } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("customer_name", "SUM(contract_amount) as total_amount") .isNotNull("customer_name") .groupBy("customer_name") .orderByDesc("total_amount") .last("LIMIT 5"); if (startDate != null && endDate != null) { queryWrapper.between("entry_date", startDate, endDate); } List> maps = salesLedgerMapper.selectMaps(queryWrapper); List result = new ArrayList<>(); for (Map map : maps) { CustomerContributionRankingDto rankingDto = new CustomerContributionRankingDto(); rankingDto.setCustomerName(map.get("customer_name").toString()); rankingDto.setTotalAmount(map.get("total_amount") != null ? new BigDecimal(map.get("total_amount").toString()) : BigDecimal.ZERO); result.add(rankingDto); } return result; } }