| | |
| | | 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)) |
| | | .map(QualityInspect::getQuantity) |
| | | .map(inspect -> { |
| | | BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | return qualified.add(unqualified); |
| | | }) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | supplierNum = supplierNum.add(reduce); |
| | | |
| | | BigDecimal reduce1 = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(1)) |
| | | .map(QualityInspect::getQuantity) |
| | | .map(inspect -> { |
| | | BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | return qualified.add(unqualified); |
| | | }) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | processNum = processNum.add(reduce1); |
| | | |
| | | BigDecimal reduce2 = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(2)) |
| | | .map(QualityInspect::getQuantity) |
| | | .map(inspect -> { |
| | | BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | return qualified.add(unqualified); |
| | | }) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | factoryNum = factoryNum.add(reduce2); |
| | | |
| | |
| | | |
| | | // 1. 供应商检验(类型0)- 合格数量 |
| | | BigDecimal supplierQualified = monthInspects.stream() |
| | | .filter(inspect -> inspect.getInspectType().equals(0) |
| | | && "合格".equals(inspect.getCheckResult())) |
| | | .map(QualityInspect::getQuantity) |
| | | .filter(inspect -> inspect.getInspectType().equals(0)) |
| | | .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) |
| | | .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) |
| | | .filter(inspect -> inspect.getInspectType().equals(1)) |
| | | .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) |
| | | .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) |
| | | .filter(inspect -> inspect.getInspectType().equals(2)) |
| | | .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | item.setFactoryNum(factoryQualified); |
| | | |
| | |
| | | public List<Map<String, Object>> productInOutAnalysis(Integer type) { |
| | | String targetName; |
| | | if (type == 1) { |
| | | targetName = "原材料"; |
| | | targetName = "原料"; |
| | | } else if (type == 2) { |
| | | targetName = "成品"; |
| | | } else if (type == 3) { |
| | |
| | | String endStr = endDate.atTime(LocalTime.MAX).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); |
| | | |
| | | List<ProductionTaskStatisticsDto> startList = productionOperationTaskMapper.selectTaskStartStats(startStr, endStr); |
| | | |
| | | List<ProductionProductOutputDto> outputList = productionProductOutputMapper |
| | | .selectOutputStats(startStr, endStr); |
| | | List<ProductionProductOutputDto> outputList = productionProductOutputMapper.selectOutputStats(startStr, endStr); |
| | | |
| | | Map<String, WorkOrderEfficiencyDto> dateMap = new HashMap<>(); |
| | | |
| | | // 1. 处理开工数量(统一将时间转为 LocalDate 字符串,去除时分秒) |
| | | if (!CollectionUtils.isEmpty(startList)) { |
| | | for (ProductionTaskStatisticsDto item : startList) { |
| | | if (item.getActualStartTime() != null) { |
| | | String date = item.getActualStartTime().toString(); |
| | | WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto()); |
| | | dto.setDate(date); |
| | | // 💡 关键修改:如果是 LocalDateTime,必须先 toLocalDate() 再 toString() |
| | | String dateStr = item.getActualStartTime().toString(); |
| | | WorkOrderEfficiencyDto dto = dateMap.computeIfAbsent(dateStr, k -> { |
| | | WorkOrderEfficiencyDto newDto = new WorkOrderEfficiencyDto(); |
| | | newDto.setDate(k); |
| | | newDto.setStartQuantity(BigDecimal.ZERO); |
| | | newDto.setFinishQuantity(BigDecimal.ZERO); |
| | | newDto.setYieldRate("0.00"); |
| | | return newDto; |
| | | }); |
| | | |
| | | BigDecimal qty = item.getPlanQuantity() != null ? item.getPlanQuantity() : BigDecimal.ZERO; |
| | | dto.setStartQuantity(dto.getStartQuantity() != null ? dto.getStartQuantity().add(qty) : qty); |
| | | dateMap.put(date, dto); |
| | | dto.setStartQuantity(dto.getStartQuantity().add(qty)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 完工数量和良品率 |
| | | // 2. 处理完工数量和报废数量(仅通过 1 次循环搞定,大幅提升性能) |
| | | if (!CollectionUtils.isEmpty(outputList)) { |
| | | // 定义一个临时的报废数计数器,方便后面算良品率 |
| | | Map<String, BigDecimal> scrapMap = new HashMap<>(); |
| | | |
| | | for (ProductionProductOutputDto item : outputList) { |
| | | if (item.getCreateTime() != null) { |
| | | String date = item.getCreateTime().toLocalDate().toString(); |
| | | WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto()); |
| | | dto.setDate(date); |
| | | String dateStr = item.getCreateTime().toLocalDate().toString(); |
| | | |
| | | BigDecimal finishQty = item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO; |
| | | BigDecimal scrapQty = item.getScrapQty() != null ? item.getScrapQty() : BigDecimal.ZERO; |
| | | WorkOrderEfficiencyDto dto = dateMap.computeIfAbsent(dateStr, k -> { |
| | | WorkOrderEfficiencyDto newDto = new WorkOrderEfficiencyDto(); |
| | | newDto.setDate(k); |
| | | newDto.setStartQuantity(BigDecimal.ZERO); |
| | | newDto.setFinishQuantity(BigDecimal.ZERO); |
| | | newDto.setYieldRate("0.00"); |
| | | return newDto; |
| | | }); |
| | | |
| | | dto.setFinishQuantity( |
| | | dto.getFinishQuantity() != null ? dto.getFinishQuantity().add(finishQty) : finishQty); |
| | | BigDecimal qty = item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO; |
| | | BigDecimal scrap = item.getScrapQty() != null ? item.getScrapQty() : BigDecimal.ZERO; |
| | | |
| | | // 良品数 = 总投入数 - 报废数 (对应你原代码中 finishMap 的逻辑) |
| | | BigDecimal goodQty = qty.subtract(scrap); |
| | | dto.setFinishQuantity(dto.getFinishQuantity().add(goodQty)); |
| | | |
| | | // 累加报废数 |
| | | scrapMap.put(dateStr, scrapMap.getOrDefault(dateStr, BigDecimal.ZERO).add(scrap)); |
| | | } |
| | | } |
| | | |
| | | Map<String, BigDecimal> scrapMap = outputList.stream() |
| | | .filter(i -> i.getCreateTime() != null) |
| | | .collect(Collectors.groupingBy( |
| | | i -> i.getCreateTime().toLocalDate().toString(), |
| | | Collectors.reducing(BigDecimal.ZERO, |
| | | i -> i.getScrapQty() != null ? i.getScrapQty() : BigDecimal.ZERO, |
| | | BigDecimal::add))); |
| | | |
| | | Map<String, BigDecimal> finishMap = outputList.stream() |
| | | .filter(i -> i.getCreateTime() != null) |
| | | .collect(Collectors.groupingBy( |
| | | i -> i.getCreateTime().toLocalDate().toString(), |
| | | 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()); |
| | | dto.setDate(date); |
| | | dto.setFinishQuantity(qty); |
| | | dateMap.put(date, dto); |
| | | }); |
| | | |
| | | dateMap.forEach((date, dto) -> { |
| | | BigDecimal finish = dto.getFinishQuantity() != null ? dto.getFinishQuantity() : BigDecimal.ZERO; |
| | | BigDecimal scrap = scrapMap.getOrDefault(date, BigDecimal.ZERO); |
| | | // 3. 计算良品率 |
| | | dateMap.forEach((dateStr, dto) -> { |
| | | BigDecimal finish = dto.getFinishQuantity(); |
| | | BigDecimal scrap = scrapMap.getOrDefault(dateStr, BigDecimal.ZERO); |
| | | BigDecimal total = finish.add(scrap); |
| | | |
| | | if (total.compareTo(BigDecimal.ZERO) > 0) { |
| | | BigDecimal rate = finish.divide(total, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")) |
| | | .setScale(2, RoundingMode.HALF_UP); |
| | | // 💡 延续你之前的逻辑:使用 RoundingMode.DOWN 截断,防止 99.999% 四舍五入变成 100.00 |
| | | BigDecimal rate = finish.divide(total, 4, RoundingMode.DOWN) |
| | | .multiply(new BigDecimal("100")) |
| | | .setScale(2, RoundingMode.DOWN); |
| | | dto.setYieldRate(rate.toString()); |
| | | } else { |
| | | dto.setYieldRate("0.00"); |
| | | } |
| | | |
| | | if (dto.getStartQuantity() == null) |
| | | dto.setStartQuantity(BigDecimal.ZERO); |
| | | if (dto.getFinishQuantity() == null) |
| | | dto.setFinishQuantity(BigDecimal.ZERO); |
| | | }); |
| | | } |
| | | |
| | | dateMap.values().forEach(dto -> { |
| | | if (dto.getStartQuantity() == null) |
| | | dto.setStartQuantity(BigDecimal.ZERO); |
| | | if (dto.getFinishQuantity() == null) |
| | | dto.setFinishQuantity(BigDecimal.ZERO); |
| | | if (dto.getYieldRate() == null) |
| | | dto.setYieldRate("0.00"); |
| | | }); |
| | | |
| | | // 4. 排序并输出 |
| | | return dateMap.values().stream() |
| | | .sorted(Comparator.comparing(WorkOrderEfficiencyDto::getDate)) |
| | | .collect(Collectors.toList()); |
| | |
| | | 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(item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO); |
| | | unqualifiedCount = unqualifiedCount.add(item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO); |
| | | } |
| | | |
| | | BigDecimal totalCount = qualifiedCount.add(unqualifiedCount); |
| | |
| | | } |
| | | |
| | | switch (parent.getProductName()) { |
| | | case "原材料": |
| | | case "原料": |
| | | rawMaterialCount = rawMaterialCount.add(quantity); |
| | | break; |
| | | case "半成品": |
| | |
| | | continue; |
| | | } |
| | | |
| | | BigDecimal quantity = item.getQuantity(); |
| | | BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | dto.setQualifiedCount(dto.getQualifiedCount().add(quantity)); |
| | | } else { |
| | | dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity)); |
| | | } |
| | | dto.setQualifiedCount(dto.getQualifiedCount().add(qualifiedQty)); |
| | | dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(unqualifiedQty)); |
| | | } |
| | | |
| | | // 计算合格率 |
| | |
| | | BigDecimal unqualifiedCount = BigDecimal.ZERO; |
| | | |
| | | for (QualityInspect item : items) { |
| | | BigDecimal qty = item.getQuantity(); |
| | | totalCount = totalCount.add(qty); |
| | | BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | |
| | | if ("合格".equals(item.getCheckResult())) { |
| | | qualifiedCount = qualifiedCount.add(qty); |
| | | } else { |
| | | unqualifiedCount = unqualifiedCount.add(qty); |
| | | } |
| | | totalCount = totalCount.add(qualifiedQty.add(unqualifiedQty)); |
| | | qualifiedCount = qualifiedCount.add(qualifiedQty); |
| | | unqualifiedCount = unqualifiedCount.add(unqualifiedQty); |
| | | } |
| | | |
| | | if (totalCount.compareTo(BigDecimal.ZERO) == 0) { |
| | |
| | | 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("不合格"); |
| | | if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) { |
| | | return null; |
| | | // 根据 unqualifiedQuantity > 0 筛选不合格记录 |
| | | List<QualityInspect> qualityInspects = qualityInspectList.stream() |
| | | .filter(i -> i.getUnqualifiedQuantity() != null && i.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (ObjectUtils.isEmpty(qualityInspects)) { |
| | | // 即使没有不合格记录,也应该返回统计数据,只是图表项为空 |
| | | dto.setItem(new ArrayList<>()); |
| | | return dto; |
| | | } |
| | | |
| | | // 4. 处理图表项 (Item) |
| | | List<QualityStatisticsItem> itemList = new ArrayList<>(); |
| | | |
| | |
| | | private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) { |
| | | return list.stream() |
| | | .filter(i -> i.getInspectType().equals(type)) |
| | | .map(QualityInspect::getQuantity) |
| | | .filter(Objects::nonNull) |
| | | .map(i -> { |
| | | BigDecimal qualified = i.getQualifiedQuantity() != null ? i.getQualifiedQuantity() : BigDecimal.ZERO; |
| | | BigDecimal unqualified = i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO; |
| | | return qualified.add(unqualified); |
| | | }) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | } |
| | | |
| | |
| | | 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(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) |
| | | .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(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) |
| | | .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(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | |
| | | return item; |