gongchunyi
6 天以前 7828b982da116070fe11526733609ecce23631b6
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -4,15 +4,13 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
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;
@@ -27,19 +25,11 @@
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.ProductProcessMapper;
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
import com.ruoyi.production.mapper.ProductionProductInputMapper;
import com.ruoyi.production.mapper.ProductionProductOutputMapper;
import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
import com.ruoyi.production.pojo.ProductProcess;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.ProductWorkOrder;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.mapper.SysDeptMapper;
@@ -145,7 +135,7 @@
    @Autowired
    private ProductProcessMapper productProcessMapper;
    @Autowired
    private AccountExpenseMapper accountExpenseMapper;
@@ -318,6 +308,47 @@
        return analysisCustomerContractAmountsDto;
    }
    private static BigDecimal nz(BigDecimal v) {
        return v == null ? BigDecimal.ZERO : v;
    }
    /**
     * 大屏/报表统计用合格数量:以 qualified_quantity
     */
    private BigDecimal inspectQualifiedQtyForStat(QualityInspect item) {
        if (item.getQualifiedQuantity() != null) {
            return item.getQualifiedQuantity();
        }
        BigDecimal qty = nz(item.getQuantity());
        if ("合格".equals(item.getCheckResult())) {
            return qty;
        }
        return BigDecimal.ZERO;
    }
    /**
     * 大屏/报表统计用不合格数量:以 unqualified_quantity
     */
    private BigDecimal inspectUnqualifiedQtyForStat(QualityInspect item) {
        if (item.getUnqualifiedQuantity() != null) {
            return item.getUnqualifiedQuantity();
        }
        BigDecimal qty = nz(item.getQuantity());
        String cr = item.getCheckResult();
        if ("不合格".equals(cr) || "部分合格".equals(cr)) {
            return qty;
        }
        return BigDecimal.ZERO;
    }
    private boolean inspectHasUnqualifiedVolume(QualityInspect item) {
        return inspectUnqualifiedQtyForStat(item).compareTo(BigDecimal.ZERO) > 0;
    }
    private static int toStatInt(BigDecimal v) {
        return nz(v).setScale(0, RoundingMode.HALF_UP).intValue();
    }
    @Override
    public QualityStatisticsDto qualityStatistics() {
        // 获取近四个月数据(往前推三个月,共4个完整月份)
@@ -365,29 +396,27 @@
            QualityStatisticsItem item = new QualityStatisticsItem();
            item.setDate(monthStart.format(monthFormatter)); // 日期显示为“年月”(如 2025-10)
            // 1. 供应商检验(类型0)- 合格数量
            BigDecimal supplierQualified = monthInspects.stream()
            // 1~3:本月「不合格数量」(仅已提交检验),按检验类别拆分——用于图表图例「××不合格数」
            BigDecimal supplierUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(0)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setSupplierNum(supplierQualified);
            item.setSupplierNum(supplierUnq);
            // 2. 工序检验(类型1)- 合格数量
            BigDecimal processQualified = monthInspects.stream()
            BigDecimal processUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(1)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setProcessNum(processQualified);
            item.setProcessNum(processUnq);
            // 3. 工厂检验(类型2)- 合格数量
            BigDecimal factoryQualified = monthInspects.stream()
            BigDecimal factoryUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setFactoryNum(factoryQualified);
            item.setFactoryNum(factoryUnq);
            qualityStatisticsItems.add(item);
        }
@@ -676,64 +705,21 @@
    @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);
        Long currentStaff = 0L;
        dto.setTotalStaff(currentStaff);
        dto.setStaffGrowthRate(calculateMoM(currentStaff, prevStaff));
        // 总客户数
        Long currentCustomers = countCustomers(currentMonthEnd);
        Long prevCustomers = countCustomers(prevMonthEnd);
        Long currentCustomers = customerMapper.selectCount(null);
        dto.setTotalCustomer(currentCustomers);
        dto.setCustomerGrowthRate(calculateMoM(currentCustomers, prevCustomers));
        // 总供应商数
        Long currentSuppliers = countSuppliers(currentMonthEnd);
        Long prevSuppliers = countSuppliers(prevMonthEnd);
        Long currentSuppliers = supplierManageMapper.selectCount(null);
        dto.setTotalSupplier(currentSuppliers);
        dto.setSupplierGrowthRate(calculateMoM(currentSuppliers, prevSuppliers));
        return dto;
    }
    private Long countStaff(LocalDateTime dateTime) {
        Long staffCountItem = staffOnJobMapper.selectCount(new LambdaQueryWrapper<StaffOnJob>()
                .isNotNull(StaffOnJob::getStaffState)
                .eq(StaffOnJob::getStaffState, 1)
                .le(StaffOnJob::getCreateTime, dateTime));
        return staffCountItem;
    }
    private Long countCustomers(LocalDateTime dateTime) {
        return customerMapper.selectCount(new LambdaQueryWrapper<Customer>()
                .le(Customer::getMaintenanceTime, dateTime.toLocalDate()));
    }
    private Long countSuppliers(LocalDateTime dateTime) {
        return supplierManageMapper.selectCount(new LambdaQueryWrapper<SupplierManage>()
                .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<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type) {
@@ -1955,17 +1941,14 @@
        BigDecimal unqualifiedCount = BigDecimal.ZERO;
        for (QualityInspect item : list) {
            if ("合格".equals(item.getCheckResult())) {
                qualifiedCount = qualifiedCount.add(item.getQuantity());
            } else {
                unqualifiedCount = unqualifiedCount.add(item.getQuantity());
            }
            qualifiedCount = qualifiedCount.add(inspectQualifiedQtyForStat(item));
            unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item));
        }
        BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
        dto.setQualifiedCount(qualifiedCount.intValue());
        dto.setUnqualifiedCount(unqualifiedCount.intValue());
        dto.setQualifiedCount(toStatInt(qualifiedCount));
        dto.setUnqualifiedCount(toStatInt(unqualifiedCount));
        if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
            dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
@@ -2228,13 +2211,8 @@
                continue;
            }
            BigDecimal quantity = item.getQuantity();
            if ("合格".equals(item.getCheckResult())) {
                dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
            } else {
                dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
            }
            dto.setQualifiedCount(dto.getQualifiedCount().add(inspectQualifiedQtyForStat(item)));
            dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(inspectUnqualifiedQtyForStat(item)));
        }
        // 计算合格率
@@ -2275,14 +2253,11 @@
            BigDecimal unqualifiedCount = BigDecimal.ZERO;
            for (QualityInspect item : items) {
                BigDecimal qty = item.getQuantity();
                BigDecimal qty = nz(item.getQuantity());
                totalCount = totalCount.add(qty);
                if ("合格".equals(item.getCheckResult())) {
                    qualifiedCount = qualifiedCount.add(qty);
                } else {
                    unqualifiedCount = unqualifiedCount.add(qty);
                }
                qualifiedCount = qualifiedCount.add(inspectQualifiedQtyForStat(item));
                unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item));
            }
            if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
@@ -2411,12 +2386,12 @@
        dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // 过程
        dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // 出厂
        // 假设 qualityInspectList 是一个 List<QualityInspect> 类型的集合
        Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream()
                .collect(Collectors.groupingBy(QualityInspect::getCheckResult));
        List<QualityInspect> qualityInspects = groupedByCheckResult.get("不合格");
        // 存在不合格数量的检验单(含按数量拆分的新数据;旧数据仍可用检测结果兜底)
        List<QualityInspect> qualityInspects = qualityInspectList.stream()
                .filter(this::inspectHasUnqualifiedVolume)
                .collect(Collectors.toList());
        if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) {
            return null;
            return dto;
        }
        // 4. 处理图表项 (Item)
        List<QualityStatisticsItem> itemList = new ArrayList<>();
@@ -2469,11 +2444,11 @@
        QualityStatisticsItem item = new QualityStatisticsItem();
        item.setDate(dateLabel);
        item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity)
        item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(this::inspectUnqualifiedQtyForStat)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity)
        item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(this::inspectUnqualifiedQtyForStat)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity)
        item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(this::inspectUnqualifiedQtyForStat)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        return item;