liyong
7 小时以前 1cf91e355038837f30f2d727507b2229263d7de7
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -16,6 +16,7 @@
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.collaborativeApproval.mapper.NoticeMapper;
import com.ruoyi.collaborativeApproval.pojo.Notice;
import com.ruoyi.common.enums.ApproveTypeEnum;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.device.mapper.DeviceRepairMapper;
import com.ruoyi.device.pojo.DeviceRepair;
@@ -32,9 +33,11 @@
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.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;
@@ -44,13 +47,12 @@
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 com.ruoyi.stock.mapper.StockInventoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -123,6 +125,7 @@
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserDeptMapper sysUserDeptMapper;
    private StockInventoryMapper stockInventoryMapper;
    @Override
    public HomeBusinessDto business() {
@@ -135,7 +138,7 @@
        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)){
        if (!CollectionUtils.isEmpty(salesLedgers)) {
            // 合计合同金额
            BigDecimal contractAmount = salesLedgers.stream().map(SalesLedger::getContractAmount)
                    .filter(Objects::nonNull)
@@ -157,7 +160,7 @@
                .lt(PurchaseLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天
        // 执行查询并计算总和
        List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(queryWrapper);
        if(!CollectionUtils.isEmpty(purchaseLedgers)){
        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()));
@@ -193,17 +196,9 @@
//                .filter(Objects::nonNull)
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
//        BigDecimal stock = stockAmount.add(customStockAmount).subtract(outboundAmount);
        IPage<ProductModel> productModelIPage = productModelMapper.listPageProductModel(new Page<>(1, -1), new ProductModel());
        if(!CollectionUtils.isEmpty(productModelIPage.getRecords())){
            //获取规格id
            List<Long> 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());
        }
        BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal();
        homeBusinessDto.setInventoryNum(stockQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString());
        // 获取当天入库数量
        LambdaQueryWrapper<ProcurementRecordStorage> procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>();
@@ -253,9 +248,9 @@
        BigDecimal subtract = weekContractAmount.subtract(lastYearWeekContractAmount);
        String weekYny = "";
        // 周同比
        if(subtract.compareTo(BigDecimal.ZERO) == 0 || lastYearWeekContractAmount.compareTo(BigDecimal.ZERO) == 0){
        if (subtract.compareTo(BigDecimal.ZERO) == 0 || lastYearWeekContractAmount.compareTo(BigDecimal.ZERO) == 0) {
            weekYny = "0.00";
        }else{
        } else {
            weekYny = String.format("%.2f", subtract.divide(lastYearWeekContractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
        }
@@ -278,9 +273,9 @@
        BigDecimal subtract1 = todayContractAmount.subtract(lastYearYesterdayContractAmount); // 修改:使用 todayContractAmount 而不是 yesterdayContractAmount
        // 日环比
        String chain = "";
        if(subtract1.compareTo(BigDecimal.ZERO) == 0 || lastYearYesterdayContractAmount.compareTo(BigDecimal.ZERO) == 0){
        if (subtract1.compareTo(BigDecimal.ZERO) == 0 || lastYearYesterdayContractAmount.compareTo(BigDecimal.ZERO) == 0) {
            chain = "0.00";
        }else{
        } else {
            chain = String.format("%.2f", subtract1.divide(lastYearYesterdayContractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
        }
@@ -294,14 +289,14 @@
        Map<String, BigDecimal> collect = salesLedgers.stream().collect(Collectors.groupingBy(SalesLedger::getCustomerName, Collectors.reducing(BigDecimal.ZERO,
                SalesLedger::getContractAmount, BigDecimal::add)));
        List<MapDto> mapDtos = new ArrayList<>();
        collect.forEach((k,v)->{
        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){
            if (contractAmount.compareTo(new BigDecimal(0)) == 0) {
                mapDto.setRate("0");
            }else{
            } else {
                mapDto.setRate(String.format("%.2f", v.divide(contractAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))));
            }
            mapDtos.add(mapDto);
@@ -347,7 +342,7 @@
                    .filter(inspect -> inspect.getInspectType().equals(1))
                    .map(QualityInspect::getQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            processNum= processNum.add(reduce1);
            processNum = processNum.add(reduce1);
            BigDecimal reduce2 = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2))
                    .map(QualityInspect::getQuantity)
@@ -402,9 +397,15 @@
                .ne(ApproveProcess::getApproveStatus, 2);
//                .eq(ApproveProcess::getTenantId, loginUser.getTenantId());
        List<ApproveProcess> approveProcesses = approveProcessMapper.selectList(approveProcessLambdaQueryWrapper);
        if(CollectionUtils.isEmpty(approveProcesses)){
        if (CollectionUtils.isEmpty(approveProcesses)) {
            approveProcesses = new ArrayList<>();
        }
        approveProcesses.forEach(a -> {
            if (a.getApproveType() != null) {
                a.setApproveTypeName(ApproveTypeEnum.getNameByCode(a.getApproveType()));
            }
        });
//        // 查询未领用劳保记录
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//
@@ -422,11 +423,12 @@
//                approveProcesses.add(approveProcess);
//            }
//        }
        return approveProcesses;
    }
    /**
     *
     * @param type 1-周 2-月 3-季度
     * @return
     */
@@ -435,7 +437,7 @@
        LocalDate today = LocalDate.now();
        LocalDate startDate = null;
        LocalDate endDate = null;
        switch (type){
        switch (type) {
            case 1:
                // 获取本周周一
                startDate = today.with(DayOfWeek.MONDAY);
@@ -493,6 +495,7 @@
        return statisticsReceivablePayableDto;
    }
    public static <T> BigDecimal sumAmount(List<T> list, java.util.function.Function<T, BigDecimal> amountExtractor) {
        return list.stream()
                // 提取金额时,将null替换为BigDecimal.ZERO
@@ -500,6 +503,7 @@
                // 累加,初始值为0,避免空流问题
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    @Autowired
    private DeviceRepairMapper deviceRepairMapper;
@@ -542,9 +546,10 @@
        productionProgressDto.setTotalOrderCount(totalCount);
        productionProgressDto.setCompletedOrderCount(count);
        productionProgressDto.setUncompletedOrderCount(count2);
        productionProgressDto.setPartialCompletedOrderCount(totalCount-count-count2);
        productionProgressDto.setPartialCompletedOrderCount(totalCount - count - count2);
        return productionProgressDto;
    }
    @Override
    public ProductionTurnoverDto workInProcessTurnover() {
        ProductionTurnoverDto productionTurnoverDto = new ProductionTurnoverDto();
@@ -557,15 +562,15 @@
                .map(ProductWorkOrder::getPlanQuantity)
                .mapToLong(BigDecimal::longValue)
                .sum();
        if (sum == 0)return null;
        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));
        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));
        productionTurnoverDto.setTurnoverEfficiency(BigDecimal.valueOf(completeQuantity).divide(BigDecimal.valueOf(sum), 2, RoundingMode.HALF_UP));
        Map<String, List<ProductWorkOrderDto>> map = productWorkOrders.stream()
                .filter(productWorkOrder -> productWorkOrder.getPlanQuantity().compareTo(productWorkOrder.getCompleteQuantity()) > 0)
                .collect(Collectors.groupingBy(ProductWorkOrderDto::getProcessName));
@@ -699,15 +704,15 @@
        LocalDate startDate;
        LocalDate endDate;
        switch (type) {
            case 0: // 周
            case 1: // 周
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 1: // 月
            case 2: // 月
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2: // 季度
            case 3: // 季度
                Month currentMonth = today.getMonth();
                Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
                Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
@@ -749,15 +754,15 @@
        boolean groupByMonth = false;
        switch (type) {
            case 0: // 周
            case 1: // 周
                start = today.with(DayOfWeek.MONDAY);
                end = today.with(DayOfWeek.SUNDAY);
                break;
            case 1: // 月
            case 2: // 月
                start = today.with(TemporalAdjusters.firstDayOfMonth());
                end = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2: // 季度
            case 3: // 季度
                Month firstMonthOfQuarter = today.getMonth().firstMonthOfQuarter();
                start = today.withMonth(firstMonthOfQuarter.getValue()).with(TemporalAdjusters.firstDayOfMonth());
                end = today.withMonth(firstMonthOfQuarter.plus(2).getValue()).with(TemporalAdjusters.lastDayOfMonth());
@@ -818,109 +823,54 @@
        ProductCategoryDistributionDto dto = new ProductCategoryDistributionDto();
        List<ProductCategoryDistributionDto.MajorCategoryDto> majorItems = new ArrayList<>();
        //  所有的产品大类和小类
        List<Product> allProducts = productMapper.selectList(new LambdaQueryWrapper<Product>());
        // 查询所有的产品类别
        List<Product> allProducts = productMapper.selectList(new LambdaQueryWrapper<>());
        if (CollectionUtils.isEmpty(allProducts)) {
            dto.setItems(majorItems);
            return dto;
        }
        List<Product> majorCategories = allProducts.stream().filter(p -> p.getParentId() == null).collect(Collectors.toList());
        List<Product> minorCategories = allProducts.stream().filter(p -> p.getParentId() != null).collect(Collectors.toList());
        // 分离大类和小类
        List<Product> majorCategories = allProducts.stream()
                .filter(p -> p.getParentId() == null)
                .collect(Collectors.toList());
        List<Product> minorCategories = allProducts.stream()
                .filter(p -> p.getParentId() != null)
                .collect(Collectors.toList());
        //  从 sales_ledger_product 拿到每个产品的型号库存
        // 需包含规格型号以支持三级分布
        List<Map<String, Object>> quantityMaps = salesLedgerProductMapper.selectMaps(new QueryWrapper<SalesLedgerProduct>()
                .select("product_id", "specification_model", "type", "SUM(quantity) as sum_qty")
                .isNotNull("product_id")
                .groupBy("product_id", "specification_model", "type"));
        // 按父类ID对小类进行分组
        Map<Long, List<Product>> minorGroupMap = minorCategories.stream()
                .collect(Collectors.groupingBy(Product::getParentId));
        Map<Long, Map<String, Map<Integer, BigDecimal>>> modelStockGroups = new HashMap<>();
        for (Map<String, Object> 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;
        int totalMinorCount = minorCategories.size();
            modelStockGroups.computeIfAbsent(productId, k -> new HashMap<>())
                    .computeIfAbsent(model, k -> new HashMap<>())
                    .put(type, sum);
        }
        //  库存并汇总
        Map<Long, List<MapDto>> productModelsMap = new HashMap<>();
        Map<Long, BigDecimal> productTotalStockMap = new HashMap<>();
        for (Long pid : modelStockGroups.keySet()) {
            Map<String, Map<Integer, BigDecimal>> models = modelStockGroups.get(pid);
            BigDecimal productStock = BigDecimal.ZERO;
            List<MapDto> modelDtos = new ArrayList<>();
            for (String modelName : models.keySet()) {
                Map<Integer, BigDecimal> 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<MapDto> 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<ProductCategoryDistributionDto.MinorCategoryDto> minorDtos = new ArrayList<>();
            BigDecimal majorStock = BigDecimal.ZERO;
            List<Product> children = minorGroupMap.getOrDefault(major.getId(), new ArrayList<>());
            int childrenSize = children.size();
            // 设置小类的总数
            majorDto.setValue(String.valueOf(childrenSize));
            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());
            // 计算占比
            if (totalMinorCount > 0) {
                BigDecimal rate = BigDecimal.valueOf(childrenSize)
                        .multiply(new BigDecimal("100"))
                        .divide(BigDecimal.valueOf(totalMinorCount), 2, RoundingMode.HALF_UP);
                majorDto.setRate(rate.toString());
            } else {
                majorDto.setRate("0.00");
            }
            List<ProductCategoryDistributionDto.MinorCategoryDto> minorDtos = new ArrayList<>();
            for (Product minor : children) {
                ProductCategoryDistributionDto.MinorCategoryDto minorDto = new ProductCategoryDistributionDto.MinorCategoryDto();
                minorDto.setName(minor.getProductName());
                minorDto.setValue("0");
                minorDto.setRate("0.00");
                minorDto.setChildren(new ArrayList<>());
                minorDtos.add(minorDto);
            }
            majorDto.setChildren(minorDtos);
            majorItems.add(majorDto);
@@ -936,15 +886,15 @@
        LocalDate startDate = null;
        LocalDate endDate = null;
        switch (type) {
            case 0:
            case 1:
                startDate = today.with(DayOfWeek.MONDAY);
                endDate = today.with(DayOfWeek.SUNDAY);
                break;
            case 1:
            case 2:
                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
                break;
            case 2:
            case 3:
                Month currentMonth = today.getMonth();
                Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
                Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);