| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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<ProductWorkOrder>() |
| | | .apply("complete_quantity < plan_quantity and complete_quantity > 0") |
| | | ); |
| | | dto.setInProgressCount(inProgressCount); |
| | | |
| | | // æ¥è¯¢å·²å®æå·¥åï¼å®ææ°é大äºçäºéæ±æ°éï¼ |
| | | Long completedCount = productWorkOrderMapper.selectCount( |
| | | new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .apply("complete_quantity >= plan_quantity and complete_quantity > 0") |
| | | ); |
| | | dto.setCompletedCount(completedCount); |
| | | |
| | | // æ¥è¯¢å¾
宿工åï¼å®ææ°é为0ï¼ |
| | | Long pendingCount = productWorkOrderMapper.selectCount( |
| | | new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .eq(ProductWorkOrder::getCompleteQuantity, 0) |
| | | ); |
| | | dto.setPendingCount(pendingCount); |
| | | |
| | | return dto; |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> getQualityStatistics() { |
| | | Map<String, Object> result = new HashMap<>(); |
| | | |
| | | // æ¥è¯¢æææ¥å·¥è®°å½ |
| | | List<ProductionProductOutput> 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<QualityInspect> qualityInspects = qualityInspectMapper.selectList( |
| | | new LambdaQueryWrapper<QualityInspect>() |
| | | .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<String, Object> getProductionStatistics() { |
| | | Map<String, Object> 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<ProductionProductOutput> currentOutputList = productionProductOutputMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductOutput>() |
| | | .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<ProductionProductOutput> lastOutputList = productionProductOutputMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductOutput>() |
| | | .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<ProductionProductInput> currentInputList = productionProductInputMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductInput>() |
| | | .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<ProductionProductInput> lastInputList = productionProductInputMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductInput>() |
| | | .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<SupplierManage> currentSuppliers = supplierManageMapper.selectList( |
| | | new LambdaQueryWrapper<SupplierManage>() |
| | | .ge(SupplierManage::getCreateTime, currentMonthStart) |
| | | .le(SupplierManage::getCreateTime, currentMonthEnd) |
| | | ); |
| | | int currentSupplierCount = currentSuppliers != null ? currentSuppliers.size() : 0; |
| | | |
| | | // 计ç®ä¾åºåæ°éï¼ä¸æï¼ |
| | | List<SupplierManage> lastSuppliers = supplierManageMapper.selectList( |
| | | new LambdaQueryWrapper<SupplierManage>() |
| | | .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<Map<String, Object>> getProductOutputCategoryPieData() { |
| | | List<Map<String, Object>> result = new ArrayList<>(); |
| | | // æäº§å大类 |
| | | // æ¥è¯¢æææ¥å·¥è®°å½ |
| | | List<ProductionProductOutput> outputList = productionProductOutputMapper.selectList(null); |
| | | |
| | | // æäº§ååç»è®¡ç®äº§åºæ°é |
| | | Map<Long, BigDecimal> 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<Long, BigDecimal> entry : productOutputMap.entrySet()) { |
| | | Product product = productMapper.selectById(entry.getKey()); |
| | | if (product != null) { |
| | | Map<String, Object> item = new HashMap<>(); |
| | | item.put("name", product.getProductName()); |
| | | item.put("value", entry.getValue().intValue()); |
| | | result.add(item); |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<Map<String, Object>> getDefectReasonAnalysis() { |
| | | List<Map<String, Object>> result = new ArrayList<>(); |
| | | |
| | | // æ¥è¯¢ææè´¨éæ£éªè®°å½ |
| | | List<QualityInspect> qualityInspectList = qualityInspectMapper.selectList(null); |
| | | |
| | | // æä¸è¯åå åç»ç»è®¡æ°é |
| | | Map<String, Integer> 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<String, Integer> entry : reasonCountMap.entrySet()) { |
| | | Map<String, Object> item = new HashMap<>(); |
| | | item.put("name", entry.getKey()); |
| | | item.put("value", entry.getValue()); |
| | | result.add(item); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<Map<String, Object>> getProcessDefectRateAnalysis(String startDate, String endDate) { |
| | | List<Map<String, Object>> 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); |
| | | |
| | | // æ¥è¯¢ææå·¥åº |
| | | List<ProductProcess> processList = productProcessMapper.selectList(null); |
| | | |
| | | // æ¶éæææ¥æ |
| | | Set<LocalDate> dateSet = new TreeSet<>(); |
| | | LocalDate currentDate = startLocalDate; |
| | | while (!currentDate.isAfter(endLocalDate)) { |
| | | dateSet.add(currentDate); |
| | | currentDate = currentDate.plusDays(1); |
| | | } |
| | | |
| | | // æå»ºç»ææ°æ® |
| | | for (LocalDate date : dateSet) { |
| | | Map<String, Object> item = new HashMap<>(); |
| | | item.put("date", date.toString()); |
| | | |
| | | // åå§åæ¯æ¥æ»æ°éåä¸è¯æ°é |
| | | BigDecimal dailyTotalQuantity = BigDecimal.ZERO; |
| | | BigDecimal dailyDefectiveQuantity = BigDecimal.ZERO; |
| | | |
| | | // åå§åå·¥åºæ°æ®å表 |
| | | List<Map<String, Object>> processesList = new ArrayList<>(); |
| | | |
| | | for (ProductProcess process : processList) { |
| | | if (process.getName() != null) { |
| | | // æ¥è¯¢è¯¥å·¥åºå¨æå®æ¥æçè´¨éæ£éªè®°å½ |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList( |
| | | new LambdaQueryWrapper<QualityInspect>() |
| | | .eq(QualityInspect::getProcess, process.getName()) |
| | | .ge(QualityInspect::getCheckTime, Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant())) |
| | | .lt(QualityInspect::getCheckTime, Date.from(date.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant())) |
| | | ); |
| | | |
| | | // 计ç®è¯¥å·¥åºçæ»æ£éªæ°éåä¸è¯æ°é |
| | | BigDecimal processTotalQuantity = BigDecimal.ZERO; |
| | | BigDecimal processDefectiveQuantity = BigDecimal.ZERO; |
| | | |
| | | for (QualityInspect inspect : qualityInspects) { |
| | | if (inspect.getQuantity() != null) { |
| | | processTotalQuantity = processTotalQuantity.add(inspect.getQuantity()); |
| | | dailyTotalQuantity = dailyTotalQuantity.add(inspect.getQuantity()); |
| | | } |
| | | if (inspect.getDefectiveQuantity() != null) { |
| | | processDefectiveQuantity = processDefectiveQuantity.add(inspect.getDefectiveQuantity()); |
| | | dailyDefectiveQuantity = dailyDefectiveQuantity.add(inspect.getDefectiveQuantity()); |
| | | } |
| | | } |
| | | |
| | | // 计ç®è¯¥å·¥åºçä¸è¯ç |
| | | 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<String, Object> 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; |
| | | } |
| | | } |