liding
2026-03-20 d5b6dcdeb9980b7b4cdafdc6324efc7b791c3357
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,15 +3,13 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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;
@@ -21,37 +19,30 @@
import com.ruoyi.common.enums.ApproveTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.consumables.mapper.ConsumablesInventoryMapper;
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.mapper.*;
import com.ruoyi.production.pojo.ProductWorkOrder;
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.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
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.mapper.RawMaterialMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityUnqualified;
import com.ruoyi.quality.pojo.RawMaterial;
import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
@@ -95,6 +86,9 @@
    @Autowired
    private StockInventoryMapper stockInventoryMapper;
    @Autowired
    private ConsumablesInventoryMapper consumablesInventoryMapper;
    @Autowired
    private QualityInspectMapper qualityStatisticsMapper;
@@ -142,7 +136,19 @@
    private QualityInspectMapper qualityInspectMapper;
    @Autowired
    private RawMaterialMapper rawMaterialMapper;
    @Autowired
    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
    @Autowired
    private ProductProcessMapper productProcessMapper;
    @Autowired
    private AccountExpenseMapper accountExpenseMapper;
    @Autowired
    private AccountIncomeMapper accountIncomeMapper;
    @Override
    public HomeBusinessDto business() {
@@ -177,36 +183,43 @@
        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();
        BigDecimal consumablesQuantityTotal = consumablesInventoryMapper.selectTotal();
        homeBusinessDto.setInventoryNum(stockQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString());
        homeBusinessDto.setConsumablesQuantityTotal(consumablesQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString());
        // 获取当天入库数量
        BigDecimal bigDecimal = stockInventoryMapper.selectTotalByDate(LocalDate.now());
        BigDecimal consumablesTodayNum = consumablesInventoryMapper.selectTotalByDate(LocalDate.now());
        homeBusinessDto.setTodayInventoryNum(bigDecimal.setScale(2, RoundingMode.HALF_UP).toString());
        homeBusinessDto.setConsumablesTodayNum(consumablesTodayNum.setScale(2, RoundingMode.HALF_UP).toString());
        return homeBusinessDto;
    }
@@ -329,10 +342,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))
@@ -1030,28 +1043,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<>();
@@ -1150,12 +1155,6 @@
    public List<MapDto> productTurnoverDays() {
        return homeMapper.productTurnoverDays();
    }
    @Autowired
    private AccountExpenseMapper accountExpenseMapper;
    @Autowired
    private AccountIncomeMapper accountIncomeMapper;
    public List<Map<String, Object>> incomeExpenseAnalysis(Integer type) {
@@ -1280,36 +1279,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);
        }
@@ -1746,9 +1730,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());
@@ -1892,7 +1878,6 @@
        return dto;
    }
    @Override
    public QualityQualifiedAnalysisDto rawMaterialDetection(Integer type) {
        return commonDetection(type, 0);
@@ -1914,10 +1899,8 @@
        LocalDate startDate = range[0];
        LocalDate endDate = range[1];
        String startStr = startDate.atStartOfDay()
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String endStr = endDate.atTime(LocalTime.MAX)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String startStr = startDate.toString();
        String endStr = endDate.toString();
        List<QualityInspect> list = qualityInspectMapper.selectList(
                new LambdaQueryWrapper<QualityInspect>()
@@ -2007,20 +1990,14 @@
    @Override
    public QualityInspectionCountDto qualityInspectionCount() {
        // 获取今天的开始和结束日期,包含时分秒
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime todayEnd = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(0);
        // 获取前一天的开始和结束日期,包含时分秒
        LocalDateTime prevStart = todayStart.minusDays(1);
        LocalDateTime prevEnd = todayEnd.minusDays(1);
        String todayStr = LocalDate.now().toString();
        String prevDayStr = LocalDate.now().minusDays(1).toString();
        // 查询出截止今日的总检验数
        List<QualityInspect> todayList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
                // .eq(QualityInspect::getInspectState, 1)
                .le(QualityInspect::getCheckTime, todayEnd));
                .le(QualityInspect::getCheckTime, todayStr));
        // 查询出截止前一天的总检验数
        List<QualityInspect> prevList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
                // .eq(QualityInspect::getInspectState, 1)
                .le(QualityInspect::getCheckTime, prevEnd));
                .le(QualityInspect::getCheckTime, prevDayStr));
        // 计算今日的总检验数
        BigDecimal todayCount = todayList.stream()
                .map(QualityInspect::getQuantity)
@@ -2036,14 +2013,12 @@
        // 计算今天的待完成数量
        List<QualityInspect> todayPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
                .eq(QualityInspect::getInspectState, 0)
                .ge(QualityInspect::getCheckTime, todayStart)
                .le(QualityInspect::getCheckTime, todayEnd));
                .eq(QualityInspect::getCheckTime, todayStr));
        // 计算前一天的待完成数量
        List<QualityInspect> prevPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
                .eq(QualityInspect::getInspectState, 0)
                .ge(QualityInspect::getCheckTime, prevStart)
                .le(QualityInspect::getCheckTime, prevEnd));
                .eq(QualityInspect::getCheckTime, prevDayStr));
        // 计算今天的待完成数量
        BigDecimal todayPendingCount = todayPendingList.stream()
                .map(QualityInspect::getQuantity)
@@ -2059,14 +2034,12 @@
        List<QualityInspect> todayCompletedList = qualityInspectMapper
                .selectList(new LambdaQueryWrapper<QualityInspect>()
                        .eq(QualityInspect::getInspectState, 1)
                        .ge(QualityInspect::getCheckTime, todayStart)
                        .le(QualityInspect::getCheckTime, todayEnd));
                        .eq(QualityInspect::getCheckTime, todayStr));
        // 计算前一天的已完成数量
        List<QualityInspect> prevCompletedList = qualityInspectMapper
                .selectList(new LambdaQueryWrapper<QualityInspect>()
                        .eq(QualityInspect::getInspectState, 1)
                        .ge(QualityInspect::getCheckTime, prevStart)
                        .le(QualityInspect::getCheckTime, prevEnd));
                        .eq(QualityInspect::getCheckTime, prevDayStr));
        // 计算今天的已完成数量
        BigDecimal todayCompletedCount = todayCompletedList.stream()
                .map(QualityInspect::getQuantity)
@@ -2099,18 +2072,16 @@
    @Override
    public NonComplianceWarningDto nonComplianceWarning() {
        // 近七天时间区间
        LocalDateTime[] range = lastSevenDaysRange();
        LocalDateTime startTime = range[0];
        LocalDateTime endTime = range[1];
        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, startTime)
                        .le(QualityUnqualified::getCheckTime, endTime));
                        .ge(QualityUnqualified::getCheckTime, startStr)
                        .le(QualityUnqualified::getCheckTime, endStr));
        NonComplianceWarningDto dto = new NonComplianceWarningDto();
@@ -2209,29 +2180,24 @@
    }
    /**
     * 获取近七天的时间区间(包含今天)
     * 获取近七天的日期区间(仅含年月日)
     */
    public static LocalDateTime[] lastSevenDaysRange() {
    public static String[] lastSevenDaysDateRange() {
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.minusDays(6).atStartOfDay();
        LocalDateTime endTime = today.atTime(23, 59, 59);
        return new LocalDateTime[]{startTime, endTime};
        return new String[]{today.minusDays(6).toString(), today.toString()};
    }
    @Override
    public List<CompletedInspectionCountDto> completedInspectionCount() {
        // 近七天时间区间
        LocalDateTime[] range = lastSevenDaysRange();
        LocalDateTime startTime = range[0];
        LocalDateTime endTime = range[1];
        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, startTime)
                .le(QualityInspect::getCheckTime, endTime));
                .ge(QualityInspect::getCheckTime, startStr)
                .le(QualityInspect::getCheckTime, endStr));
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
@@ -2352,7 +2318,7 @@
            return new ArrayList<>();
        }
        //  统计每种处理结果的数量
        // 统计每种处理结果的数量
        Map<String, BigDecimal> countMap = new HashMap<>();
        for (QualityUnqualified item : list) {
            if (StringUtils.isEmpty(item.getDealResult()) || item.getQuantity() == null) {
@@ -2365,7 +2331,7 @@
            return new ArrayList<>();
        }
        //  计算总数
        // 计算总数
        BigDecimal totalCount = countMap.values()
                .stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);
@@ -2374,7 +2340,7 @@
            return new ArrayList<>();
        }
        //  按数量倒序排序
        // 按数量倒序排序
        List<Map.Entry<String, BigDecimal>> sortedList = countMap.entrySet()
                .stream()
                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
@@ -2410,4 +2376,149 @@
        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<RawMaterial> rawMaterialList = rawMaterialMapper
                .selectList(new LambdaQueryWrapper<RawMaterial>()
                        .ge(RawMaterial::getCheckTime, startDate.toString())
                        .le(RawMaterial::getCheckTime, endDate.toString())
                        .eq(RawMaterial::getInspectState, 1));
        QualityStatisticsDto dto = new QualityStatisticsDto();
        Map<Integer, BigDecimal> countMap = rawMaterialList.stream()
                .collect(Collectors.groupingBy(
                        RawMaterial::getCheckType,
                        Collectors.collectingAndThen(
                                Collectors.counting(),
                                count -> BigDecimal.valueOf(count)
                        )
                ));
        dto.setSupplierNum(countMap.getOrDefault(0, BigDecimal.ZERO)); // 入厂
        dto.setProcessNum(countMap.getOrDefault(1, BigDecimal.ZERO));  // 车间
        dto.setFactoryNum(countMap.getOrDefault(2, BigDecimal.ZERO));  // 出厂
        // 3. 筛选不合格的记录(check_result = 0)
        List<RawMaterial> unqualifiedList = rawMaterialList.stream()
                .filter(i -> i.getCheckResult() == 0)  // 0表示不合格
                .collect(Collectors.toList());
        // 4. 处理图表项 (Item)
        List<RawMaterial> itemList = new ArrayList<>();
        if (type == 3) {
            // 季度模式:按月分组
            Map<String, List<RawMaterial>> groupByMonth = unqualifiedList.isEmpty() ?
                    new HashMap<>() :
                    unqualifiedList.stream()
                            .collect(Collectors.groupingBy(i -> {
                                LocalDate ld = i.getCheckTime().toInstant()
                                        .atZone(ZoneId.systemDefault()).toLocalDate();
                                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"));
                List<RawMaterial> monthData = groupByMonth.getOrDefault(monthStr, new ArrayList<>());
                itemList.add(buildItem(monthStr, monthData));
            }
        } else {
            // 周或月模式:按天分组
            Map<String, List<RawMaterial>> groupByDay = unqualifiedList.isEmpty() ?
                    new HashMap<>() :
                    unqualifiedList.stream()
                            .collect(Collectors.groupingBy(i -> {
                                LocalDate ld = i.getCheckTime().toInstant()
                                        .atZone(ZoneId.systemDefault()).toLocalDate();
                                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"));
                List<RawMaterial> dayData = groupByDay.getOrDefault(dayStr, new ArrayList<>());
                itemList.add(buildItem(dayStr, dayData));
            }
        }
        dto.setRawItem(itemList);
        return dto;
    }
    private RawMaterial buildItem(String dateLabel, List<RawMaterial> list) {
        RawMaterial item = new RawMaterial();
        item.setDate(dateLabel);
        item.setSupplierNum(
                BigDecimal.valueOf(list.stream().filter(i -> i.getCheckType() == 0).count())
        );
        item.setProcessNum(
                BigDecimal.valueOf(list.stream().filter(i -> i.getCheckType() == 1).count())
        );
        item.setFactoryNum(
                BigDecimal.valueOf(list.stream().filter(i -> i.getCheckType() == 2).count())
        );
        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);
    }
}