2737e108612c3ea013e8bcd0ee0f71a4969205bb..c999acf2f8fe57bdf6b97681bfdfe47ce5c102a6
2025-12-11 liding
设备待保养,待维修数据没有根据状态统计
c999ac 对比 | 目录
2025-12-11 maven
yys 修改数据过滤
58bf55 对比 | 目录
2025-12-11 maven
yys 修改大屏接口
4c8d74 对比 | 目录
2025-12-11 maven
yys 修改大屏接口
f9fb72 对比 | 目录
已添加1个文件
已修改9个文件
418 ■■■■ 文件已修改
src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java 103 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/QualityProductQualifiedRateDto.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/HomeService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceRepairMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
@@ -24,8 +24,10 @@
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@AllArgsConstructor
@Service
@@ -115,38 +117,87 @@
    @Override
    public Map<String, List<String>> analysis() {
        // èŽ·å–æœ¬å‘¨çš„æ—¶é—´èŒƒå›´
        LocalDate startOfWeek = LocalDate.now().with(DayOfWeek.MONDAY);
        LocalDate endOfWeek = LocalDate.now().with(DayOfWeek.SUNDAY);
        // èŽ·å–æœ€è¿‘å››ä¸ªæœˆï¼ˆå½“å‰æœˆ + å‰3个月)的时间范围
        LocalDate today = LocalDate.now();
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // å¹´æœˆæ ¼å¼åŒ–器
        Map<String, List<String>> result = new HashMap<>();
        List<String> days = new ArrayList<>();
        List<String> totalIncomeList = new ArrayList<>();
        List<String> totalExpenseList = new ArrayList<>();
        List<String> netIncomeList = new ArrayList<>();
        // æ ¹æ®æ—¶é—´èŒƒå›´å¾ªçŽ¯æŸ¥è¯¢æ¯ä¸€å¤©çš„æ€»æ”¶å…¥ï¼Œæ€»æ”¯å‡º,净收入(总收入-总支出)
        for (LocalDate date = startOfWeek; date.isBefore(endOfWeek) || date.isEqual(endOfWeek); date = date.plusDays(1)) {
            BigDecimal totalIncome = accountIncomeMapper.selectList(Wrappers.<AccountIncome>lambdaQuery()
                    .eq(AccountIncome::getInputTime, date.toString()))
                    .stream()
                    .map(AccountIncome::getIncomeMoney)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalExpense = accountExpenseMapper.selectList(Wrappers.<AccountExpense>lambdaQuery()
                    .eq(AccountExpense::getInputTime, date.toString()))
                    .stream()
                    .map(AccountExpense::getExpenseMoney)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        List<String> months = new ArrayList<>(); // å­˜å‚¨å¹´æœˆï¼ˆå¦‚ 2025-12、2025-11)
        List<String> totalIncomeList = new ArrayList<>(); // æ¯æœˆæ€»æ”¶å…¥
        List<String> totalExpenseList = new ArrayList<>(); // æ¯æœˆæ€»æ”¯å‡º
        List<String> netIncomeList = new ArrayList<>(); // æ¯æœˆå‡€æ”¶å…¥ï¼ˆæ”¶å…¥-支出)
        // æ­¥éª¤1:计算近4个月的年月列表(当前月、前1月、前2月、前3月)
        List<String> 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<AccountIncome> allIncomes = accountIncomeMapper.selectList(
                Wrappers.<AccountIncome>lambdaQuery()
                        .ge(AccountIncome::getIncomeDate, fourMonthsAgo.toString()) // å¤§äºŽç­‰äºŽèµ·å§‹æ—¥
                        .le(AccountIncome::getIncomeDate, currentMonthEnd.toString()) // å°äºŽç­‰äºŽç»“束日
        );
        // æ”¶å…¥æŒ‰â€œå¹´æœˆâ€åˆ†ç»„汇总(key:年月字符串,value:当月总收入)
        Map<String, BigDecimal> monthlyIncomeMap = allIncomes.stream()
                .filter(income -> income.getIncomeMoney() != null) // è¿‡æ»¤ç©ºé‡‘额
                .collect(Collectors.groupingBy(
                        income -> {
                            // å°†è¾“入时间(字符串)转换为LocalDate,再格式化为年月
                            LocalDate inputDate = income.getIncomeDate().toInstant().atZone(zoneId).toLocalDate();
                            return inputDate.format(monthFormatter);
                        },
                        Collectors.reducing(BigDecimal.ZERO, AccountIncome::getIncomeMoney, BigDecimal::add)
                ));
        // æ­¥éª¤3:一次性查询近4个月所有支出数据,按“年月”分组汇总
        List<AccountExpense> allExpenses = accountExpenseMapper.selectList(
                Wrappers.<AccountExpense>lambdaQuery()
                        .ge(AccountExpense::getExpenseDate, fourMonthsAgo.toString())
                        .le(AccountExpense::getExpenseDate, currentMonthEnd.toString())
        );
        // æ”¯å‡ºæŒ‰â€œå¹´æœˆâ€åˆ†ç»„汇总
        Map<String, BigDecimal> monthlyExpenseMap = allExpenses.stream()
                .filter(expense -> expense.getExpenseMoney() != null) // è¿‡æ»¤ç©ºé‡‘额
                .collect(Collectors.groupingBy(
                        expense -> {
                            LocalDate inputDate = expense.getExpenseDate().toInstant().atZone(zoneId).toLocalDate();
                            return inputDate.format(monthFormatter);
                        },
                        Collectors.reducing(BigDecimal.ZERO, AccountExpense::getExpenseMoney, BigDecimal::add)
                ));
        // æ­¥éª¤4:循环4个目标月份,填充统计数据(无数据时默认为0)
        for (String month : targetMonths) {
            // å½“月总收入(无数据则为0)
            BigDecimal totalIncome = monthlyIncomeMap.getOrDefault(month, BigDecimal.ZERO);
            // å½“月总支出(无数据则为0)
            BigDecimal totalExpense = monthlyExpenseMap.getOrDefault(month, BigDecimal.ZERO);
            // å½“月净收入(收入 - æ”¯å‡ºï¼‰
            BigDecimal netIncome = totalIncome.subtract(totalExpense);
            days.add(date.toString());
            // å¡«å……列表
            months.add(month);
            totalIncomeList.add(totalIncome.toString());
            totalExpenseList.add(totalExpense.toString());
            netIncomeList.add(netIncome.toString());
        }
        result.put("days", days);  //  å¤©
        result.put("totalIncome", totalIncomeList); // æ”¶å…¥
        result.put("totalExpense", totalExpenseList); // æ”¯å‡º
        result.put("netIncome", netIncomeList); // å‡€æ”¶å…¥
        // ç»„装结果
        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;
    }
src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -7,10 +7,7 @@
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.home.dto.AnalysisCustomerContractAmountsDto;
import com.ruoyi.home.dto.HomeBusinessDto;
import com.ruoyi.home.dto.QualityStatisticsDto;
import com.ruoyi.home.dto.StatisticsReceivablePayableDto;
import com.ruoyi.home.dto.*;
import com.ruoyi.home.service.HomeService;
import com.ruoyi.production.dto.SalesLedgerWorkDto;
import io.swagger.annotations.Api;
@@ -77,5 +74,12 @@
        return AjaxResult.success(statisticsReceivablePayable);
    }
    @ApiOperation("BI统计-产品合格率,库存周转率")
    @GetMapping("/qualityProductQualifiedRate")
    public AjaxResult qualityProductQualifiedRate() {
        QualityProductQualifiedRateDto qualityProductQualifiedRate = homeService.qualityProductQualifiedRate();
        return AjaxResult.success(qualityProductQualifiedRate);
    }
}
src/main/java/com/ruoyi/home/dto/QualityProductQualifiedRateDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.home.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author :yys
 * @date : 2025/12/11 13:13
 */
@Data
public class QualityProductQualifiedRateDto {
    //出厂合格率
    private BigDecimal factoryQualifiedRate = BigDecimal.ZERO;
    //过程合格率
    private BigDecimal processQualifiedRate = BigDecimal.ZERO;
    // åŽŸææ–™åˆæ ¼çŽ‡
    private BigDecimal rawMaterialQualifiedRate = BigDecimal.ZERO;
    //库存周转率
    private BigDecimal inventoryTurnoverRate = BigDecimal.ZERO;
}
src/main/java/com/ruoyi/home/service/HomeService.java
@@ -1,10 +1,7 @@
package com.ruoyi.home.service;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.home.dto.AnalysisCustomerContractAmountsDto;
import com.ruoyi.home.dto.HomeBusinessDto;
import com.ruoyi.home.dto.QualityStatisticsDto;
import com.ruoyi.home.dto.StatisticsReceivablePayableDto;
import com.ruoyi.home.dto.*;
import java.text.ParseException;
import java.util.List;
@@ -26,4 +23,6 @@
    List<ApproveProcess> todos() throws ParseException;
    StatisticsReceivablePayableDto statisticsReceivablePayable(Integer type);
    QualityProductQualifiedRateDto qualityProductQualifiedRate();
}
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -10,10 +10,8 @@
import com.ruoyi.home.service.HomeService;
import com.ruoyi.lavorissue.mapper.LavorIssueMapper;
import com.ruoyi.lavorissue.pojo.LaborIssue;
import com.ruoyi.procurementrecord.mapper.CustomStorageMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
import com.ruoyi.procurementrecord.pojo.CustomStorage;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
import com.ruoyi.project.system.domain.SysDept;
@@ -40,6 +38,7 @@
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;
@@ -67,9 +66,6 @@
    @Autowired
    private ProcurementRecordMapper procurementRecordStorageMapper;
    @Autowired
    private CustomStorageMapper customStorageMapper;
    @Autowired
    private QualityInspectMapper qualityStatisticsMapper;
@@ -100,56 +96,53 @@
        salesLedgerLambdaQueryWrapper.ge(SalesLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay())  // å¤§äºŽç­‰äºŽæœ¬æœˆç¬¬ä¸€å¤©
                .lt(SalesLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // å°äºŽä¸‹æœˆç¬¬ä¸€å¤©
        List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(salesLedgerLambdaQueryWrapper);
        if(!CollectionUtils.isEmpty(salesLedgers)){
            // åˆè®¡åˆåŒé‡‘额
            BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapper = new LambdaQueryWrapper<SalesLedgerProduct>();
            salesLedgerProductMapperLambdaQueryWrapper.eq(SalesLedgerProduct::getType, 1)
                    .in(SalesLedgerProduct::getSalesLedgerId, salesLedgers.stream().map(SalesLedger::getId).collect(Collectors.toList()));
            List<SalesLedgerProduct> 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());
        if(CollectionUtils.isEmpty(salesLedgers)){
            return homeBusinessDto;
        }
        // åˆè®¡åˆåŒé‡‘额
        BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapper = new LambdaQueryWrapper<SalesLedgerProduct>();
        salesLedgerProductMapperLambdaQueryWrapper.eq(SalesLedgerProduct::getType, 1)
                .in(SalesLedgerProduct::getSalesLedgerId, salesLedgers.stream().map(SalesLedger::getId).collect(Collectors.toList()));
        List<SalesLedgerProduct> 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<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)
                    .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)
                    .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());
        if(CollectionUtils.isEmpty(purchaseLedgers)){
            return homeBusinessDto;
        }
        LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<SalesLedgerProduct>();
        salesLedgerProductMapperLambdaQueryWrapper.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)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // ç»Ÿè®¡åº“å­˜
        List<ProcurementRecordStorage> procurementRecordStorages = procurementRecordStorageMapper.selectList(null);
        BigDecimal stockAmount = procurementRecordStorages.stream()
                .map(ProcurementRecordStorage::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è‡ªå®šä¹‰åº“å­˜
        List<CustomStorage> customStorages = customStorageMapper.selectList(null);
        BigDecimal customStockAmount = customStorages.stream()
                .map(CustomStorage::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        List<ProcurementRecordOut> procurementRecordOuts = procurementRecordOutMapper.selectList(null);
@@ -157,7 +150,7 @@
                .map(ProcurementRecordOut::getInboundNum)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal stock = stockAmount.add(customStockAmount).subtract(outboundAmount);
        BigDecimal stock = stockAmount.subtract(outboundAmount);
        // èŽ·å–å½“å¤©å…¥åº“æ•°é‡
        LambdaQueryWrapper<ProcurementRecordStorage> procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        procurementRecordStorageLambdaQueryWrapper.ge(ProcurementRecordStorage::getCreateTime, now)  // å¤§äºŽç­‰äºŽå½“天
@@ -167,6 +160,9 @@
                .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;
@@ -266,50 +262,83 @@
    @Override
    public QualityStatisticsDto qualityStatistics() {
        // èŽ·å–ä¸€å‘¨æ•°æ®
        // èŽ·å–å½“å‰æ—¶é—´
        // èŽ·å–è¿‘å››ä¸ªæœˆæ•°æ®ï¼ˆå¾€å‰æŽ¨ä¸‰ä¸ªæœˆï¼Œå…±4个完整月份)
        LocalDate today = LocalDate.now();
        // èŽ·å–æœ¬å‘¨å‘¨ä¸€
        LocalDate startOfWeek = today.with(DayOfWeek.MONDAY);
        // èŽ·å–æœ¬å‘¨å‘¨æ—¥
        LocalDate endOfWeek = today.with(DayOfWeek.SUNDAY);
        LambdaQueryWrapper<QualityInspect> qualityInspectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        qualityInspectLambdaQueryWrapper.ge(QualityInspect::getCheckTime, startOfWeek)
                .gt(QualityInspect::getCheckTime, endOfWeek);
        List<QualityInspect> qualityInspects = qualityStatisticsMapper.selectList(qualityInspectLambdaQueryWrapper);
        // å®šä¹‰æ—¥æœŸæ ¼å¼åŒ–器(用于显示“年月”格式)
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        QualityStatisticsDto qualityStatisticsDto = new QualityStatisticsDto();
        qualityStatisticsDto.setSupplierNum(qualityInspects.stream().filter(item -> item.getInspectType().equals(0)).map(QualityInspect::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add));
        qualityStatisticsDto.setProcessNum(qualityInspects.stream().filter(item -> item.getInspectType().equals(1)).map(QualityInspect::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add));
        qualityStatisticsDto.setFactoryNum(qualityInspects.stream().filter(item -> item.getInspectType().equals(2)).map(QualityInspect::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add));
        List<QualityStatisticsItem> qualityStatisticsItems = new ArrayList<>();
        for (int j = 1; j < 8; j++) {
            LocalDate endTime = startOfWeek.plusDays(j);
            LocalDate startTime = endTime.minusDays(1);
            QualityStatisticsItem qualityStatisticsItem = new QualityStatisticsItem();
            qualityStatisticsItem.setDate(startTime.toString());
            qualityStatisticsItem.setSupplierNum(qualityInspects.stream()
                    .filter(item -> item.getInspectType().equals(0) && "不合格".equals(item.getCheckResult())
                            && (startTime.isEqual(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) || startTime.isAfter(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
                            && endTime.isBefore(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
        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<QualityInspect> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.ge(QualityInspect::getCheckTime, monthStart)
                    .le(QualityInspect::getCheckTime, monthEnd); // ç­›é€‰å½“月数据
            List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper);
            BigDecimal reduce = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(0))
                    .map(QualityInspect::getQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
            );
            qualityStatisticsItem.setFactoryNum(qualityInspects.stream()
                    .filter(item -> item.getInspectType().equals(1) && "不合格".equals(item.getCheckResult())
                            && (startTime.isEqual(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) || startTime.isAfter(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
                            && endTime.isBefore(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
                    .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)
            );
            qualityStatisticsItem.setProcessNum(qualityInspects.stream()
                    .filter(item -> item.getInspectType().equals(2) && "不合格".equals(item.getCheckResult())
                            && (startTime.isEqual(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) || startTime.isAfter(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
                            && endTime.isBefore(item.getCheckTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            factoryNum= factoryNum.add(reduce1);
            BigDecimal reduce2 = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2))
                    .map(QualityInspect::getQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            qualityStatisticsItems.add(qualityStatisticsItem);
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            processNum = processNum.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;
    }
@@ -409,4 +438,61 @@
        return statisticsReceivablePayableDto;
    }
    @Override
    public QualityProductQualifiedRateDto qualityProductQualifiedRate() {
        QualityProductQualifiedRateDto qualityProductQualifiedRateDto = new QualityProductQualifiedRateDto();
        List<QualityInspect> qualityInspects = qualityStatisticsMapper.selectList(null);
        if(!CollectionUtils.isEmpty(qualityInspects)){
            // åŽŸææ–™åˆæ ¼çŽ‡
            long rawwMaterialCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 0).count();
            long count = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 0).count();
            if(count > 0){
                qualityProductQualifiedRateDto.setRawMaterialQualifiedRate(new BigDecimal(rawwMaterialCount)
                        .divide(new BigDecimal( count), 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100.0)));
            }
            // è¿‡ç¨‹åˆæ ¼çއ
            long processCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 1).count();
            long countOne = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 1).count();
            if(countOne > 0){
                qualityProductQualifiedRateDto.setProcessQualifiedRate(new BigDecimal(processCount)
                        .divide(new BigDecimal( countOne), 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100.0)));
            }
            // å‡ºåŽ‚åˆæ ¼çŽ‡
            long factoryCount = qualityInspects.stream().filter(qualityInspect -> qualityInspect.getInspectType() == 2).count();
            long countTwo = qualityInspects.stream().filter(qualityInspect -> "合格".equals(qualityInspect.getCheckResult()) && qualityInspect.getInspectType() == 2).count();
            if(countTwo > 0){
                qualityProductQualifiedRateDto.setFactoryQualifiedRate(new BigDecimal(factoryCount)
                        .divide(new BigDecimal( 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<ProcurementRecordOut> procurementRecordOuts = procurementRecordOutMapper.selectList(new LambdaQueryWrapper<ProcurementRecordOut>()
                .ge(ProcurementRecordOut::getCreateTime, startDate)
                .lt(ProcurementRecordOut::getCreateTime, endDate));
        // èŽ·å–å½“å‰æœˆå…¥åº“çš„ç‰©æ–™æ€»æ•°é‡
        List<ProcurementRecordStorage> procurementRecordStorages = procurementRecordStorageMapper.selectList(new LambdaQueryWrapper<ProcurementRecordStorage>()
                .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;
    }
}
src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
@@ -27,7 +28,10 @@
  
    @Override
    public IPage<SalesLedgerProductionAccountingDto> listPage(Page page, SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto) {
        salesLedgerProductionAccountingDto.setSchedulingUserId(SecurityUtils.getLoginUser().getUser().getUserId());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(!"admin".equals(loginUser.getUsername())){
            salesLedgerProductionAccountingDto.setSchedulingUserId(loginUser.getUserId());
        }
        IPage<SalesLedgerProductionAccountingDto> list = salesLedgerProductionAccountingMapper.listPage(page, salesLedgerProductionAccountingDto);
        list.getRecords().forEach(item -> {
            String[] split = item.getSpecificationModel().split("\\*");
src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java
@@ -292,8 +292,10 @@
    @Override
    public IPage<SalesLedgerSchedulingProcessDto> listPageProcess(Page page, SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        salesLedgerSchedulingDto.setProductionUserId(userId);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(!"admin".equals(loginUser.getUsername())){
            salesLedgerSchedulingDto.setProductionUserId(loginUser.getUserId());
        }
        IPage<SalesLedgerSchedulingProcessDto> list = salesLedgerSchedulingMapper.listPageProcess(page, salesLedgerSchedulingDto);
//        Set<Long> collect = list.getRecords().stream().map(SalesLedgerSchedulingProcessDto::getId).collect(Collectors.toSet());
//        if(CollectionUtils.isEmpty(collect)) return list;
src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java
@@ -57,7 +57,10 @@
    @Override
    public IPage<SalesLedgerWorkDto> listPage(Page page, SalesLedgerWorkDto salesLedgerWorkDto) {
        salesLedgerWorkDto.setProductionUserId(SecurityUtils.getLoginUser().getUserId());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(!"admin".equals(loginUser.getUsername())){
            salesLedgerWorkDto.setProductionUserId(loginUser.getUserId());
        }
        IPage<SalesLedgerWorkDto> iPage = salesLedgerWorkMapper.listPage(page, salesLedgerWorkDto);
        List<Loss> losses = lossMapper.selectList(null);
        if(!CollectionUtils.isEmpty(losses)){
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -41,6 +41,9 @@
            <if test="deviceMaintenanceDto.maintenanceActuallyTimeReq != null">
                and dm.maintenance_actually_time like concat('%',#{deviceMaintenanceDto.maintenanceActuallyTimeReq},'%')
            </if>
            <if test="deviceMaintenanceDto.status != null">
                and dm.status = #{deviceMaintenanceDto.status}
            </if>
        </where>
    </select>
    <select id="detailById" resultType="com.ruoyi.device.dto.DeviceMaintenanceDto">
src/main/resources/mapper/device/DeviceRepairMapper.xml
@@ -45,6 +45,9 @@
            <if test="deviceRepairDto.maintenanceTimeStr != null and deviceRepairDto.maintenanceTimeStr != '' ">
                and dr.maintenance_time like concat('%',#{deviceRepairDto.maintenanceTimeStr},'%')
            </if>
            <if test="deviceRepairDto.status != null">
                and dr.status = #{deviceRepairDto.status}
            </if>
        </where>
    </select>
    <select id="detailById" resultType="com.ruoyi.device.dto.DeviceRepairDto">