package com.ruoyi.production.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.basic.mapper.ProductMapper; import com.ruoyi.basic.mapper.ProductModelMapper; import com.ruoyi.basic.mapper.SupplierManageMapper; import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.pojo.SupplierManage; import com.ruoyi.home.dto.processDataProductionStatisticsDto; import com.ruoyi.production.dto.ProductionStatisticDto; 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.pojo.ProductProcess; import com.ruoyi.production.pojo.ProductWorkOrder; import com.ruoyi.production.pojo.ProductionProductInput; import com.ruoyi.production.pojo.ProductionProductOutput; import com.ruoyi.production.service.ProductionStatisticService; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.pojo.QualityInspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.time.ZoneId; import java.util.Date; import java.util.Set; import java.util.TreeSet; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 生产统计服务实现类 */ @Service public class ProductionStatisticServiceImpl implements ProductionStatisticService { @Autowired private ProductProcessMapper productProcessMapper; @Autowired private ProductWorkOrderMapper productWorkOrderMapper; @Autowired private ProductionProductOutputMapper productionProductOutputMapper; @Autowired private ProductionProductInputMapper productionProductInputMapper; @Autowired private QualityInspectMapper qualityInspectMapper; @Autowired private SupplierManageMapper supplierManageMapper; @Autowired private ProductModelMapper productModelMapper; @Autowired private ProductMapper productMapper; @Override public ProductionStatisticDto getWorkOrderCount() { ProductionStatisticDto dto = new ProductionStatisticDto(); // 查询工单总数 Long totalCount = productWorkOrderMapper.selectCount(null); dto.setTotalCount(totalCount); // 查询进行中工单(完成数量小于需求数量) Long inProgressCount = productWorkOrderMapper.selectCount( new LambdaQueryWrapper() .apply("complete_quantity < plan_quantity and complete_quantity > 0") ); dto.setInProgressCount(inProgressCount); // 查询已完成工单(完成数量大于等于需求数量) Long completedCount = productWorkOrderMapper.selectCount( new LambdaQueryWrapper() .apply("complete_quantity >= plan_quantity and complete_quantity > 0") ); dto.setCompletedCount(completedCount); // 查询待完成工单(完成数量为0) Long pendingCount = productWorkOrderMapper.selectCount( new LambdaQueryWrapper() .eq(ProductWorkOrder::getCompleteQuantity, 0) ); dto.setPendingCount(pendingCount); return dto; } @Override public Map getQualityStatistics() { Map result = new HashMap<>(); // 查询所有报工记录 List outputList = productionProductOutputMapper.selectList(null); // 计算报工总数、报废总数和不良总数 BigDecimal totalOutput = BigDecimal.ZERO; BigDecimal totalScrap = BigDecimal.ZERO; BigDecimal totalDefect = BigDecimal.ZERO; for (ProductionProductOutput output : outputList) { // 报工总数 if (output.getQuantity() != null) { totalOutput = totalOutput.add(output.getQuantity()); } // 报废数量 if (output.getScrapQty() != null) { totalScrap = totalScrap.add(output.getScrapQty()); } // 不良数量(从QualityInspect表查询) List qualityInspects = qualityInspectMapper.selectList( new LambdaQueryWrapper() .eq(QualityInspect::getProductMainId, output.getProductMainId()) ); for (QualityInspect inspect : qualityInspects) { if (inspect.getDefectiveQuantity() != null) { totalDefect = totalDefect.add(inspect.getDefectiveQuantity()); } } } // 计算合格数量 BigDecimal qualifiedQuantity = totalOutput.subtract(totalScrap).subtract(totalDefect); // 计算合格率和不良率 double qualifiedRate = 0.0; double defectRate = 0.0; if (totalOutput.compareTo(BigDecimal.ZERO) > 0) { // 使用BigDecimal确保精度 BigDecimal qualifiedRateBD = qualifiedQuantity.divide(totalOutput, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)); BigDecimal defectRateBD = totalDefect.divide(totalOutput, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)); // 保留两位小数 qualifiedRate = qualifiedRateBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); defectRate = defectRateBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); } result.put("qualifiedRate", qualifiedRate); // 合格率 result.put("defectRate", defectRate); // 不良率 result.put("scrapCount", totalScrap.intValue()); // 报废总数 return result; } @Override public Map getProductionStatistics() { Map result = new HashMap<>(); // 获取当前月份和上一个月份的开始和结束时间 LocalDateTime now = LocalDateTime.now(); YearMonth currentMonth = YearMonth.from(now); LocalDateTime currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); LocalDateTime currentMonthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59); LocalDateTime lastMonth = now.minusMonths(1); LocalDateTime lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); LocalDateTime lastMonthEnd = currentMonthStart.minusDays(1).withHour(23).withMinute(59).withSecond(59); // 计算生产总产出(当前月) List currentOutputList = productionProductOutputMapper.selectList( new LambdaQueryWrapper() .ge(ProductionProductOutput::getCreateTime, currentMonthStart) .le(ProductionProductOutput::getCreateTime, currentMonthEnd) ); BigDecimal currentProductionOutput = BigDecimal.ZERO; for (ProductionProductOutput output : currentOutputList) { if (output.getQuantity() != null) { currentProductionOutput = currentProductionOutput.add(output.getQuantity()); } } // 计算生产总产出(上月) List lastOutputList = productionProductOutputMapper.selectList( new LambdaQueryWrapper() .ge(ProductionProductOutput::getCreateTime, lastMonthStart) .le(ProductionProductOutput::getCreateTime, lastMonthEnd) ); BigDecimal lastProductionOutput = BigDecimal.ZERO; for (ProductionProductOutput output : lastOutputList) { if (output.getQuantity() != null) { lastProductionOutput = lastProductionOutput.add(output.getQuantity()); } } // 计算生产总消耗(当前月) List currentInputList = productionProductInputMapper.selectList( new LambdaQueryWrapper() .ge(ProductionProductInput::getCreateTime, currentMonthStart) .le(ProductionProductInput::getCreateTime, currentMonthEnd) ); BigDecimal currentProductionConsumption = BigDecimal.ZERO; for (ProductionProductInput input : currentInputList) { if (input.getQuantity() != null) { currentProductionConsumption = currentProductionConsumption.add(input.getQuantity()); } } // 计算生产总消耗(上月) List lastInputList = productionProductInputMapper.selectList( new LambdaQueryWrapper() .ge(ProductionProductInput::getCreateTime, lastMonthStart) .le(ProductionProductInput::getCreateTime, lastMonthEnd) ); BigDecimal lastProductionConsumption = BigDecimal.ZERO; for (ProductionProductInput input : lastInputList) { if (input.getQuantity() != null) { lastProductionConsumption = lastProductionConsumption.add(input.getQuantity()); } } // 计算供应商数量(当前月) List currentSuppliers = supplierManageMapper.selectList( new LambdaQueryWrapper() .ge(SupplierManage::getCreateTime, currentMonthStart) .le(SupplierManage::getCreateTime, currentMonthEnd) ); int currentSupplierCount = currentSuppliers != null ? currentSuppliers.size() : 0; // 计算供应商数量(上月) List lastSuppliers = supplierManageMapper.selectList( new LambdaQueryWrapper() .ge(SupplierManage::getCreateTime, lastMonthStart) .le(SupplierManage::getCreateTime, lastMonthEnd) ); int lastSupplierCount = lastSuppliers != null ? lastSuppliers.size() : 0; // 计算趋势 double productionOutputMonthlyChange = 0.0; if (lastProductionOutput.compareTo(BigDecimal.ZERO) > 0) { productionOutputMonthlyChange = (currentProductionOutput.subtract(lastProductionOutput) .divide(lastProductionOutput, 4, BigDecimal.ROUND_HALF_UP).doubleValue()) * 100; } double productionConsumptionMonthlyChange = 0.0; if (lastProductionConsumption.compareTo(BigDecimal.ZERO) > 0) { productionConsumptionMonthlyChange = (currentProductionConsumption.subtract(lastProductionConsumption) .divide(lastProductionConsumption, 4, BigDecimal.ROUND_HALF_UP).doubleValue()) * 100; } double supplierCountMonthlyChange = 0.0; if (lastSupplierCount > 0) { supplierCountMonthlyChange = ((currentSupplierCount - lastSupplierCount) * 100.0) / lastSupplierCount; } result.put("productionOutput", currentProductionOutput.doubleValue()); // 生产总产 result.put("productionConsumption", currentProductionConsumption.doubleValue()); // 生产总消耗 result.put("productionOutputMonthlyChange", productionOutputMonthlyChange); // 生产总产月度变化 result.put("productionConsumptionMonthlyChange", productionConsumptionMonthlyChange); // 生产总消耗月度变化 result.put("supplierCount", currentSupplierCount); // 产品总供应公司 result.put("supplierCountMonthlyChange", supplierCountMonthlyChange); // 供应商数量月度变化 return result; } @Override public List> getProductOutputCategoryPieData() { List> result = new ArrayList<>(); // 按产品大类 // 查询所有报工记录 List outputList = productionProductOutputMapper.selectList(null); // 按产品分组计算产出数量 Map productOutputMap = new HashMap<>(); for (ProductionProductOutput output : outputList) { if (output.getProductModelId() != null && output.getQuantity() != null) { // 根据productModelId查询ProductModel ProductModel productModel = productModelMapper.selectById(output.getProductModelId()); if (productModel != null && productModel.getProductId() != null) { // 根据productId查询Product Product product = productMapper.selectById(productModel.getProductId()); if (product != null) { // 按产品ID分组计算产出数量 productOutputMap.put(product.getId(), productOutputMap.getOrDefault(product.getId(), BigDecimal.ZERO).add(output.getQuantity())); } } } } // 转换为结果格式 for (Map.Entry entry : productOutputMap.entrySet()) { Product product = productMapper.selectById(entry.getKey()); if (product != null) { Map item = new HashMap<>(); item.put("name", product.getProductName()); item.put("value", entry.getValue().intValue()); result.add(item); } } return result; } @Override public List> getDefectReasonAnalysis() { List> result = new ArrayList<>(); // 查询所有质量检验记录 List qualityInspectList = qualityInspectMapper.selectList(null); // 按不良原因分组统计数量 Map reasonCountMap = new HashMap<>(); for (QualityInspect inspect : qualityInspectList) { if (inspect.getDefectiveReason() != null && !inspect.getDefectiveReason().isEmpty()) { String reason = inspect.getDefectiveReason(); reasonCountMap.put(reason, reasonCountMap.getOrDefault(reason, 0) + 1); } } // 转换为结果格式 for (Map.Entry entry : reasonCountMap.entrySet()) { Map item = new HashMap<>(); item.put("name", entry.getKey()); item.put("value", entry.getValue()); result.add(item); } return result; } @Override public List> getProcessDefectRateAnalysis(String startDate, String endDate) { List> result = new ArrayList<>(); // 默认查询近一个月数据 if (startDate == null || endDate == null) { LocalDate now = LocalDate.now(); startDate = now.minusMonths(1).toString(); endDate = now.toString(); } // 解析日期 LocalDate startLocalDate = LocalDate.parse(startDate); LocalDate endLocalDate = LocalDate.parse(endDate); Date start = Date.from(startLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); Date end = Date.from(endLocalDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()); // 查询所有工序 List processList = productProcessMapper.selectList(null); // 收集所有日期 Set dateSet = new TreeSet<>(); LocalDate currentDate = startLocalDate; while (!currentDate.isAfter(endLocalDate)) { dateSet.add(currentDate); currentDate = currentDate.plusDays(1); } // 一次性查询所有日期范围内的质量检验记录 List allQualityInspects = qualityInspectMapper.selectList( new LambdaQueryWrapper() .ge(QualityInspect::getCheckTime, start) .lt(QualityInspect::getCheckTime, end) ); // 按日期和工序分组处理数据 Map> dateProcessMap = new HashMap<>(); for (QualityInspect inspect : allQualityInspects) { if (inspect.getCheckTime() != null && inspect.getProcess() != null) { // 转换检查时间为LocalDate LocalDate inspectDate = inspect.getCheckTime().toInstant() .atZone(ZoneId.systemDefault()).toLocalDate(); // 确保日期在查询范围内 if (dateSet.contains(inspectDate)) { String processName = inspect.getProcess(); // 初始化日期和工序数据 dateProcessMap.computeIfAbsent(inspectDate, k -> new HashMap<>()); BigDecimal[] quantities = dateProcessMap.get(inspectDate) .computeIfAbsent(processName, k -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); // 累加数量 if (inspect.getQuantity() != null) { quantities[0] = quantities[0].add(inspect.getQuantity()); } if (inspect.getDefectiveQuantity() != null) { quantities[1] = quantities[1].add(inspect.getDefectiveQuantity()); } } } } // 构建结果数据 for (LocalDate date : dateSet) { Map item = new HashMap<>(); item.put("date", date.toString()); // 初始化每日总数量和不良数量 BigDecimal dailyTotalQuantity = BigDecimal.ZERO; BigDecimal dailyDefectiveQuantity = BigDecimal.ZERO; // 初始化工序数据列表 List> processesList = new ArrayList<>(); // 获取该日期的工序数据 Map processData = dateProcessMap.getOrDefault(date, new HashMap<>()); for (ProductProcess process : processList) { if (process.getName() != null) { String processName = process.getName(); BigDecimal[] quantities = processData.getOrDefault(processName, new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); BigDecimal processTotalQuantity = quantities[0]; BigDecimal processDefectiveQuantity = quantities[1]; // 累加每日总数量 dailyTotalQuantity = dailyTotalQuantity.add(processTotalQuantity); dailyDefectiveQuantity = dailyDefectiveQuantity.add(processDefectiveQuantity); // 计算该工序的不良率 double processDefectRate = 0.0; if (processTotalQuantity.compareTo(BigDecimal.ZERO) > 0) { // 计算不良率,保留两位小数 BigDecimal defectRateDecimal = processDefectiveQuantity.divide(processTotalQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)); processDefectRate = defectRateDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); } // 构建工序数据对象 Map processMap = new HashMap<>(); processMap.put(process.getName(), processDefectRate); processesList.add(processMap); } } // 计算每日平均不良率 double dailyAverageDefectRate = 0.0; if (dailyTotalQuantity.compareTo(BigDecimal.ZERO) > 0) { // 计算不良率,保留两位小数 BigDecimal defectRateDecimal = dailyDefectiveQuantity.divide(dailyTotalQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)); dailyAverageDefectRate = defectRateDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); } // 添加平均不良率和工序数据到结果项 item.put("averageDefectRate", dailyAverageDefectRate); item.put("processes", processesList); result.add(item); } return result; } }