| ¶Ô±ÈÐÂÎļþ | 
 |  |  | 
 |  |  | package com.ruoyi.business.service.impl; | 
 |  |  |  | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
 |  |  | import com.ruoyi.basic.entity.CoalInfo; | 
 |  |  | import com.ruoyi.basic.entity.CoalPlan; | 
 |  |  | import com.ruoyi.basic.entity.CoalValue; | 
 |  |  | import com.ruoyi.basic.entity.Customer; | 
 |  |  | import com.ruoyi.basic.mapper.CoalInfoMapper; | 
 |  |  | import com.ruoyi.basic.mapper.CoalPlanMapper; | 
 |  |  | import com.ruoyi.basic.mapper.CoalValueMapper; | 
 |  |  | import com.ruoyi.basic.mapper.CustomerMapper; | 
 |  |  | import com.ruoyi.business.dto.*; | 
 |  |  | import com.ruoyi.business.entity.*; | 
 |  |  | import com.ruoyi.business.mapper.*; | 
 |  |  | import com.ruoyi.business.service.ProductHomeService; | 
 |  |  | import com.ruoyi.common.core.domain.R; | 
 |  |  | import lombok.extern.slf4j.Slf4j; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import org.springframework.util.CollectionUtils; | 
 |  |  |  | 
 |  |  | import java.math.BigDecimal; | 
 |  |  | import java.math.RoundingMode; | 
 |  |  | import java.time.LocalDate; | 
 |  |  | import java.time.LocalDateTime; | 
 |  |  | import java.time.LocalTime; | 
 |  |  | import java.time.format.DateTimeFormatter; | 
 |  |  | import java.util.*; | 
 |  |  | import java.util.stream.Collectors; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * @author :yys | 
 |  |  |  * @date : 2025/10/13 9:11 | 
 |  |  |  */ | 
 |  |  | @Service | 
 |  |  | @Slf4j | 
 |  |  | public class ProductHomeServiceImpl implements ProductHomeService { | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private ProductionMapper productionMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private ProductionSchedulingMapper productionSchedulingMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private OfficialInventoryMapper officialInventoryMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private SalesRecordMapper salesRecordMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CoalInfoMapper coalInfoMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CustomerMapper customerMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private PurchaseRegistrationMapper purchaseRegistrationMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CoalValueMapper coalValueMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CoalPlanMapper coalPlanMapper; | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<ProductionSchedulingStatisticsDto> productionSchedulingStatistics(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<ProductionScheduling> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(ProductionScheduling::getSchedulingDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         List<ProductionScheduling> schedulingList = productionSchedulingMapper.selectList(wrapper); | 
 |  |  |  | 
 |  |  |         ProductionSchedulingStatisticsDto result = new ProductionSchedulingStatisticsDto(); | 
 |  |  |         BigDecimal totalScheduling = BigDecimal.ZERO; | 
 |  |  |         BigDecimal completedScheduling = BigDecimal.ZERO; | 
 |  |  |         BigDecimal pendingScheduling = BigDecimal.ZERO; | 
 |  |  |  | 
 |  |  |         for (ProductionScheduling scheduling : schedulingList) { | 
 |  |  |             BigDecimal num = scheduling.getSchedulingNum(); | 
 |  |  |             if (num != null) { | 
 |  |  |                 totalScheduling = totalScheduling.add(num); | 
 |  |  |                 if (scheduling.getStatus() == 3) { // å·²æ¥å·¥ | 
 |  |  |                     completedScheduling = completedScheduling.add(num); | 
 |  |  |                 } else if (scheduling.getStatus() == 1) { // å¾
ç产 | 
 |  |  |                     pendingScheduling = pendingScheduling.add(num); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         result.setTotalOutput(totalScheduling); | 
 |  |  |         result.setCompletedScheduling(completedScheduling); | 
 |  |  |         result.setPendingScheduling(pendingScheduling); | 
 |  |  |  | 
 |  |  |         return R.ok(result); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ProductionScheduling>> productionSchedulingStatisticsList(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<ProductionScheduling> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(ProductionScheduling::getSchedulingDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         List<ProductionScheduling> schedulingList = productionSchedulingMapper.selectList(wrapper); | 
 |  |  |         // éè¿ç
¤ç§idè·åç
¤ç§åç§° | 
 |  |  |         schedulingList.forEach(scheduling -> { | 
 |  |  |             CoalInfo coalInfo = coalInfoMapper.selectById(scheduling.getCoalId()); | 
 |  |  |             scheduling.setCoalName(coalInfo.getCoal()); | 
 |  |  |         }); | 
 |  |  |         return R.ok(schedulingList); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<OfficialInventory>> productionSchedulingInventoryList(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<OfficialInventory> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         List<OfficialInventory> schedulingList = officialInventoryMapper.selectList(wrapper); | 
 |  |  |         schedulingList.forEach(scheduling -> { | 
 |  |  |             CoalInfo coalInfo = coalInfoMapper.selectById(scheduling.getCoalId()); | 
 |  |  |             scheduling.setCoalName(coalInfo.getCoal()); | 
 |  |  |         }); | 
 |  |  |         return R.ok(schedulingList); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<MaterialStatisticsDto> materialStatistics(DateQueryDto dto) { | 
 |  |  |         MaterialStatisticsDto result = new MaterialStatisticsDto(); | 
 |  |  |         // è·å仿¥å¼å§æ¶é´ï¼ç»ææ¶é´ | 
 |  |  |         LocalDateTime todayStart = LocalDateTime.of( | 
 |  |  |                 LocalDateTime.now().toLocalDate(), | 
 |  |  |                 LocalTime.MIN | 
 |  |  |         ); | 
 |  |  |         LocalDateTime todayEnd = LocalDateTime.of( | 
 |  |  |                 LocalDateTime.now().toLocalDate(), | 
 |  |  |                 LocalTime.MAX | 
 |  |  |         ); | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<OfficialInventory> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |         wrapper.between(OfficialInventory::getRegistrationDate, todayStart, todayEnd); | 
 |  |  |         // è·å仿¥å
¥åºæ»é | 
 |  |  |         List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(wrapper); | 
 |  |  |         if (!CollectionUtils.isEmpty(officialInventories)) { | 
 |  |  |             BigDecimal todayInboundTotal = officialInventories.stream() | 
 |  |  |                     .map(OfficialInventory::getInventoryQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |             result.setTodayInboundTotal(todayInboundTotal); | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |         // è·åå½ååºåæ»é | 
 |  |  |         R<List<OfficialInventory>> listR = productionSchedulingInventoryList(dto); | 
 |  |  |         if (R.isSuccess(listR)) { | 
 |  |  |             List<OfficialInventory> officialInventoriesList = listR.getData(); | 
 |  |  |             if (!CollectionUtils.isEmpty(officialInventoriesList)) { | 
 |  |  |                 BigDecimal todayOutboundTotal = officialInventoriesList.stream() | 
 |  |  |                         .map(OfficialInventory::getInventoryQuantity) | 
 |  |  |                         .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |                 result.setTodayOutboundTotal(todayOutboundTotal); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         // è·å仿¥åºåºæ»é | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<SalesRecord> wrapperSalesRecord = new LambdaQueryWrapper<>(); | 
 |  |  |         wrapperSalesRecord.between(SalesRecord::getSaleDate, todayStart, todayEnd); | 
 |  |  |         // è·å仿¥å
¥åºæ»é | 
 |  |  |         List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapperSalesRecord); | 
 |  |  |         if (!CollectionUtils.isEmpty(salesRecords)) { | 
 |  |  |             BigDecimal todayInboundTotal = salesRecords.stream() | 
 |  |  |                     .map(SalesRecord::getInventoryQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |             result.setTodayOutboundTotal(todayInboundTotal); | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |         return R.ok(result); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> coalTypeDistribution(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |         // è·åç
¤ç§å表 | 
 |  |  |         List<CoalInfo> coalInfoList = coalInfoMapper.selectList(null); | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<SalesRecord> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(SalesRecord::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapper); | 
 |  |  |         // æ ¹æ®ç
¤ç§è¿è¡åç»ï¼å¹¶è®¡ç®å æ¯ | 
 |  |  |         Map<Long, List<SalesRecord>> coalTypeMap = salesRecords.stream() | 
 |  |  |                 .collect(Collectors.groupingBy(SalesRecord::getCoalId)); | 
 |  |  |  | 
 |  |  |         List<ItemListDto> itemListDtos = coalInfoList.stream().map(coalInfo -> { | 
 |  |  |             ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |             itemListDto.setName(coalInfo.getCoal()); | 
 |  |  |  | 
 |  |  |             // è®¡ç®è¯¥ç
¤ç§çéå®è®°å½æ»æ°é | 
 |  |  |             List<SalesRecord> records = coalTypeMap.getOrDefault(coalInfo.getId(), Collections.emptyList()); | 
 |  |  |             BigDecimal totalQuantity = records.stream() | 
 |  |  |                     .map(SalesRecord::getInventoryQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |  | 
 |  |  |             itemListDto.setValue(totalQuantity); | 
 |  |  |             return itemListDto; | 
 |  |  |         }).collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |         // è®¡ç®ææç
¤ç§çé宿»é | 
 |  |  |         BigDecimal totalAll = itemListDtos.stream() | 
 |  |  |                 .map(ItemListDto::getValue) | 
 |  |  |                 .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |  | 
 |  |  |         // è®¾ç½®å æ¯ | 
 |  |  |         for (ItemListDto item : itemListDtos) { | 
 |  |  |             if (totalAll.compareTo(BigDecimal.ZERO) > 0) { | 
 |  |  |                 BigDecimal percentage = item.getValue().multiply(BigDecimal.valueOf(100)) | 
 |  |  |                         .divide(totalAll, 2, RoundingMode.HALF_UP); | 
 |  |  |                 item.setPercent(percentage); | 
 |  |  |             } else { | 
 |  |  |                 item.setPercent(BigDecimal.ZERO); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> originDistribution(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |         // è·å客æ·å表 | 
 |  |  |         List<Customer> coalInfoList = customerMapper.selectList(null); | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<SalesRecord> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(SalesRecord::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<SalesRecord> salesRecords = salesRecordMapper.selectList(wrapper); | 
 |  |  |         // æ ¹æ®ç
¤ç§è¿è¡åç»ï¼å¹¶è®¡ç®å æ¯ | 
 |  |  |         Map<Long, List<SalesRecord>> coalTypeMap = salesRecords.stream() | 
 |  |  |                 .collect(Collectors.groupingBy(SalesRecord::getCustomerId)); | 
 |  |  |  | 
 |  |  |         List<ItemListDto> itemListDtos = coalInfoList.stream().map(coalInfo -> { | 
 |  |  |             ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |             itemListDto.setName(coalInfo.getCustomerName()); | 
 |  |  |  | 
 |  |  |             // è®¡ç®è¯¥ç
¤ç§çéå®è®°å½æ»æ°é | 
 |  |  |             List<SalesRecord> records = coalTypeMap.getOrDefault(coalInfo.getId(), Collections.emptyList()); | 
 |  |  |             BigDecimal totalQuantity = records.stream() | 
 |  |  |                     .map(SalesRecord::getInventoryQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |  | 
 |  |  |             itemListDto.setValue(totalQuantity); | 
 |  |  |             return itemListDto; | 
 |  |  |         }).collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |         // è®¡ç®ææç
¤ç§çé宿»é | 
 |  |  |         BigDecimal totalAll = itemListDtos.stream() | 
 |  |  |                 .map(ItemListDto::getValue) | 
 |  |  |                 .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |  | 
 |  |  |         // è®¾ç½®å æ¯ | 
 |  |  |         for (ItemListDto item : itemListDtos) { | 
 |  |  |             if (totalAll.compareTo(BigDecimal.ZERO) > 0) { | 
 |  |  |                 BigDecimal percentage = item.getValue().multiply(BigDecimal.valueOf(100)) | 
 |  |  |                         .divide(totalAll, 2, RoundingMode.HALF_UP); | 
 |  |  |                 item.setPercent(percentage); | 
 |  |  |             } else { | 
 |  |  |                 item.setPercent(BigDecimal.ZERO); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<CarDto>> carCodeDistribution(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<PurchaseRegistration> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(PurchaseRegistration::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(wrapper); | 
 |  |  |         // éè¿è½¦çå·åç»è·å次æ°ï¼è®¡ç®æ»é | 
 |  |  |         Map<String, List<PurchaseRegistration>> carMap = purchaseRegistrations.stream() | 
 |  |  |                 .collect(Collectors.groupingBy(PurchaseRegistration::getLicensePlate)); | 
 |  |  |         List<CarDto> carDtos = carMap.entrySet().stream().map(entry -> { | 
 |  |  |             CarDto carDto = new CarDto(); | 
 |  |  |             carDto.setCode(entry.getKey()); | 
 |  |  |             carDto.setCount(entry.getValue().size()); | 
 |  |  |             carDto.setTotal(entry.getValue().stream() | 
 |  |  |                     .map(PurchaseRegistration::getPurchaseQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add)); | 
 |  |  |             return carDto; | 
 |  |  |         }).collect(Collectors.toList()); | 
 |  |  |         return R.ok(carDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<PurchaseRegistration>> recentTransaction(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |  | 
 |  |  |         // ä½¿ç¨ LambdaQueryWrapper æå»ºæ¥è¯¢æ¡ä»¶ | 
 |  |  |         LambdaQueryWrapper<PurchaseRegistration> wrapper = new LambdaQueryWrapper<>(); | 
 |  |  |  | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             wrapper.between(PurchaseRegistration::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(wrapper); | 
 |  |  |         purchaseRegistrations.forEach(purchaseRegistration -> { | 
 |  |  |             purchaseRegistration.setCoalName(coalInfoMapper.selectById(purchaseRegistration.getCoalId()).getCoal()); | 
 |  |  |         }); | 
 |  |  |         return R.ok(purchaseRegistrations); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> heatValueDistribution(DateQueryDto dto) { | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |         LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             officialInventoryLambdaQueryWrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper); | 
 |  |  |         Map<String, BigDecimal> heatValueMap = new HashMap<>(); | 
 |  |  |         BigDecimal totalQuantity = BigDecimal.ZERO; | 
 |  |  |         for (OfficialInventory officialInventory : officialInventories) { | 
 |  |  |             List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>() | 
 |  |  |                     .eq(CoalValue::getPlanId, officialInventory.getId()) | 
 |  |  |                     .eq(CoalValue::getFieldName, "åçé")); | 
 |  |  |             if (coalValues != null && !coalValues.isEmpty()) { | 
 |  |  |                 // æ ¹æ®åçéå¼è¿è¡åç±»ç»è®¡ | 
 |  |  |  | 
 |  |  |                 heatValueMap.put("4000以ä¸", BigDecimal.ZERO); | 
 |  |  |                 heatValueMap.put("4000-4500", BigDecimal.ZERO); | 
 |  |  |                 heatValueMap.put("4500-5000", BigDecimal.ZERO); | 
 |  |  |                 heatValueMap.put("5000-5500", BigDecimal.ZERO); | 
 |  |  |                 heatValueMap.put("5500-6000", BigDecimal.ZERO); | 
 |  |  |                 heatValueMap.put("6000+", BigDecimal.ZERO); | 
 |  |  |  | 
 |  |  |                 for (CoalValue coalValue : coalValues) { | 
 |  |  |                     BigDecimal heatValue = BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())); | 
 |  |  |                     if (heatValue == null) continue; | 
 |  |  |  | 
 |  |  |                     if (heatValue.compareTo(BigDecimal.valueOf(4000)) < 0) { | 
 |  |  |                         heatValueMap.put("4000以ä¸", heatValueMap.get("4000以ä¸").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } else if (heatValue.compareTo(BigDecimal.valueOf(4000)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(4500)) < 0) { | 
 |  |  |                         heatValueMap.put("4000-4500", heatValueMap.get("4000-4500").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } else if (heatValue.compareTo(BigDecimal.valueOf(4500)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(5000)) < 0) { | 
 |  |  |                         heatValueMap.put("4500-5000", heatValueMap.get("4500-5000").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } else if (heatValue.compareTo(BigDecimal.valueOf(5000)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(5500)) < 0) { | 
 |  |  |                         heatValueMap.put("5000-5500", heatValueMap.get("5000-5500").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } else if (heatValue.compareTo(BigDecimal.valueOf(5500)) >= 0 && heatValue.compareTo(BigDecimal.valueOf(6000)) < 0) { | 
 |  |  |                         heatValueMap.put("5500-6000", heatValueMap.get("5500-6000").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } else { | 
 |  |  |                         heatValueMap.put("6000+", heatValueMap.get("6000+").add(officialInventory.getInventoryQuantity())); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         // è®¡ç®æ»é | 
 |  |  |         totalQuantity = heatValueMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |         // å°ç»æè½¬æ¢ä¸º ItemListDto å表 | 
 |  |  |         BigDecimal finalTotalQuantity = totalQuantity; | 
 |  |  |         List<ItemListDto> itemListDtos = heatValueMap.entrySet().stream() | 
 |  |  |                 .map(entry -> { | 
 |  |  |                     ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |                     itemListDto.setName(entry.getKey()); | 
 |  |  |                     itemListDto.setValue(entry.getValue()); | 
 |  |  |                     if (finalTotalQuantity.compareTo(BigDecimal.ZERO) > 0) { | 
 |  |  |                         BigDecimal percentage = entry.getValue().multiply(BigDecimal.valueOf(100)) | 
 |  |  |                                 .divide(finalTotalQuantity, 2, RoundingMode.HALF_UP); | 
 |  |  |                         itemListDto.setPercent(percentage); | 
 |  |  |                     } | 
 |  |  |                     return itemListDto; | 
 |  |  |                 }) | 
 |  |  |                 .collect(Collectors.toList()); | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<ReportStatisticsDto> reportStatistics(DateQueryDto dto) { | 
 |  |  |         ReportStatisticsDto reportStatisticsDto = new ReportStatisticsDto(); | 
 |  |  |         String start = dto.getEntryDateStart(); | 
 |  |  |         String end = dto.getEntryDateEnd(); | 
 |  |  |         LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |         if (start != null && !start.isEmpty() && end != null && !end.isEmpty()) { | 
 |  |  |             officialInventoryLambdaQueryWrapper.between(OfficialInventory::getRegistrationDate, LocalDate.parse(start, DateTimeFormatter.ISO_LOCAL_DATE), LocalDate.parse(end, DateTimeFormatter.ISO_LOCAL_DATE)); | 
 |  |  |         } | 
 |  |  |         List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper); | 
 |  |  |         if(!CollectionUtils.isEmpty(officialInventories)){ | 
 |  |  |             BigDecimal reduce = officialInventories.stream() | 
 |  |  |                     .map(OfficialInventory::getInventoryQuantity) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |             List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>() | 
 |  |  |                     .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList())) | 
 |  |  |                     .eq(CoalValue::getFieldName, "åçé")); | 
 |  |  |             BigDecimal totalQuantity = coalValues.stream() | 
 |  |  |                     .map(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue()))) | 
 |  |  |                     .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             long count = coalValues.stream() | 
 |  |  |                     .filter(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())).compareTo(BigDecimal.valueOf(5000)) >= 0) | 
 |  |  |                     .count(); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |             if (!coalValues.isEmpty()){ | 
 |  |  |                 // åä½çå¼èç
¤é = reduce * 1000 / totalQuantity | 
 |  |  |                 BigDecimal heatValue = reduce.multiply(BigDecimal.valueOf(1000)).divide(totalQuantity, 2, RoundingMode.HALF_UP); | 
 |  |  |                 reportStatisticsDto.setUnitHeatValue(heatValue); | 
 |  |  |                 // å¹³ååçé | 
 |  |  |                 reportStatisticsDto.setAverageFuel(totalQuantity.divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP)); | 
 |  |  |                 // æ´ä½è¾¾æ ç(åçéâ¥5000大å¡) | 
 |  |  |                 BigDecimal wholeStandardRate = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); | 
 |  |  |                 reportStatisticsDto.setWholeStandardRate(wholeStandardRate); | 
 |  |  |             }else{ | 
 |  |  |                 reportStatisticsDto.setAverageFuel(BigDecimal.ZERO); | 
 |  |  |                 reportStatisticsDto.setWholeStandardRate(BigDecimal.ZERO); | 
 |  |  |                 reportStatisticsDto.setUnitHeatValue(BigDecimal.ZERO); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return R.ok(reportStatisticsDto); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> reportTrend(DateQueryDto dto) { | 
 |  |  |         List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery(); | 
 |  |  |         List<ItemListDto> itemListDtos = new ArrayList<>(); | 
 |  |  |         for (LocalDate s : lastFiveDaysQuery) { | 
 |  |  |             ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |             itemListDto.setName(s.toString()); | 
 |  |  |             LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |             // å¨så颿¼ä¸00:00:00 | 
 |  |  |             officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s); | 
 |  |  |             List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper); | 
 |  |  |             if(!CollectionUtils.isEmpty(officialInventories)){ | 
 |  |  |                 List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>() | 
 |  |  |                         .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList())) | 
 |  |  |                         .eq(CoalValue::getFieldName, "åçé")); | 
 |  |  |                 // æ´ä½è¾¾æ ç(åçéâ¥5000大å¡) | 
 |  |  |                 long count = coalValues.stream() | 
 |  |  |                         .filter(coalValue -> BigDecimal.valueOf(Long.parseLong(coalValue.getCoalValue())).compareTo(BigDecimal.valueOf(5000)) >= 0) | 
 |  |  |                         .count(); | 
 |  |  |                 // å¤æé¤æ°ä¸è½ä¸ºé¶çæ
åµ | 
 |  |  |                 if (!coalValues.isEmpty()) { | 
 |  |  |                     BigDecimal wholeStandardRate = BigDecimal.valueOf(count).divide(BigDecimal.valueOf(coalValues.size()), 2, RoundingMode.HALF_UP); | 
 |  |  |                     itemListDto.setValue(wholeStandardRate); | 
 |  |  |                 }else{ | 
 |  |  |                     itemListDto.setValue(BigDecimal.ZERO); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |             itemListDtos.add(itemListDto); | 
 |  |  |         } | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> coalTypeHeatValueComparison(DateQueryDto dto) { | 
 |  |  |         List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery(); | 
 |  |  |         List<ItemListDto> itemListDtos = new ArrayList<>(); | 
 |  |  |         for (LocalDate s : lastFiveDaysQuery) { | 
 |  |  |             ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |             itemListDto.setName(s.toString()); | 
 |  |  |             LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |             // å¨så颿¼ä¸00:00:00 | 
 |  |  |             officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s); | 
 |  |  |             List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper); | 
 |  |  |             if(!CollectionUtils.isEmpty(officialInventories)){ | 
 |  |  |                 List<CoalValue> coalValues = coalValueMapper.selectList(new LambdaQueryWrapper<CoalValue>() | 
 |  |  |                         .in(CoalValue::getPlanId, officialInventories.stream().map(OfficialInventory::getId).collect(Collectors.toList())) | 
 |  |  |                         .eq(CoalValue::getFieldName, "åçé")); | 
 |  |  |                 // åçé(æ±å) | 
 |  |  |                 long count = coalValues.stream() | 
 |  |  |                         .mapToLong(coalValue -> Long.parseLong(coalValue.getCoalValue())) | 
 |  |  |                         .sum(); | 
 |  |  |                 itemListDto.setValue(BigDecimal.valueOf(count)); | 
 |  |  |             } | 
 |  |  |             itemListDtos.add(itemListDto); | 
 |  |  |         } | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> processingRateAnalysis(DateQueryDto dto) { | 
 |  |  |         List<LocalDate> lastFiveDaysQuery = getLastFiveDaysQuery(); | 
 |  |  |         List<ItemListDto> itemListDtos = new ArrayList<>(); | 
 |  |  |         for (LocalDate s : lastFiveDaysQuery) { | 
 |  |  |             ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |             itemListDto.setName(s.toString()); | 
 |  |  |             // è·åéè´æ°é | 
 |  |  |             LambdaQueryWrapper<PurchaseRegistration> purchaseRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |             // å¨så颿¼ä¸00:00:00 | 
 |  |  |             purchaseRegistrationLambdaQueryWrapper.eq(PurchaseRegistration::getRegistrationDate, s); | 
 |  |  |             List<PurchaseRegistration> purchaseRegistrations = purchaseRegistrationMapper.selectList(purchaseRegistrationLambdaQueryWrapper); | 
 |  |  |             if(!CollectionUtils.isEmpty(purchaseRegistrations)){ | 
 |  |  |                 BigDecimal totalQuantity = purchaseRegistrations.stream() | 
 |  |  |                         .map(PurchaseRegistration::getPurchaseQuantity) | 
 |  |  |                         .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |                 // è·åæ£å¼åºåæ°é | 
 |  |  |                 LambdaQueryWrapper<OfficialInventory> officialInventoryLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |                 // å¨så颿¼ä¸00:00:00 | 
 |  |  |                 officialInventoryLambdaQueryWrapper.eq(OfficialInventory::getRegistrationDate, s); | 
 |  |  |                 List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(officialInventoryLambdaQueryWrapper); | 
 |  |  |                 if(!CollectionUtils.isEmpty(officialInventories)){ | 
 |  |  |                     BigDecimal officialInventoryQuantity = officialInventories.stream() | 
 |  |  |                             .map(OfficialInventory::getInventoryQuantity) | 
 |  |  |                             .reduce(BigDecimal.ZERO, BigDecimal::add); | 
 |  |  |                     // å å·¥å¾ç = æ£å¼åºåæ°é/éè´æ°é | 
 |  |  |                     if(!totalQuantity.equals(BigDecimal.ZERO)){ | 
 |  |  |                         itemListDto.setValue(officialInventoryQuantity.divide(totalQuantity, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100))); | 
 |  |  |                     }else{ | 
 |  |  |                         itemListDto.setValue(BigDecimal.ZERO); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             itemListDtos.add(itemListDto); | 
 |  |  |         } | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public R<List<ItemListDto>> costStructure(DateQueryDto dto) { | 
 |  |  |         List<ItemListDto> itemListDtos = new ArrayList<>(); | 
 |  |  |         LocalDate now = LocalDate.now(); | 
 |  |  |         LocalDate startDate = now.minusDays(4); | 
 |  |  |         LambdaQueryWrapper<Production> productionLambdaQueryWrapper = new LambdaQueryWrapper<>(); | 
 |  |  |         productionLambdaQueryWrapper.between(Production::getCreateTime, startDate, now); | 
 |  |  |         List<Production> productions = productionMapper.selectList(productionLambdaQueryWrapper); | 
 |  |  |         ItemListDto itemListDto = new ItemListDto(); | 
 |  |  |         itemListDto.setName("äººå·¥ææ¬"); | 
 |  |  |         itemListDto.setValue(productions.stream() | 
 |  |  |                 .map(Production::getLaborCost) | 
 |  |  |                 .reduce(BigDecimal.ZERO, BigDecimal::add)); | 
 |  |  |         itemListDtos.add(itemListDto); | 
 |  |  |         ItemListDto itemListDtoOne = new ItemListDto(); | 
 |  |  |         itemListDtoOne.setName("è½èææ¬"); | 
 |  |  |         itemListDtoOne.setValue(productions.stream() | 
 |  |  |                 .map(Production::getEnergyConsumptionCost) | 
 |  |  |                 .reduce(BigDecimal.ZERO, BigDecimal::add)); | 
 |  |  |         itemListDtos.add(itemListDtoOne); | 
 |  |  |         return R.ok(itemListDtos); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * è·åæè¿äºå¤©çæ¶é´éå | 
 |  |  |      */ | 
 |  |  |     private List<LocalDate> getLastFiveDaysQuery() { | 
 |  |  |         LocalDate now = LocalDate.now(); | 
 |  |  |         LocalDate startDate = now.minusDays(4); | 
 |  |  |         List<LocalDate> dates = new ArrayList<>(); | 
 |  |  |         for (int i = 0; i < 5; i++) { | 
 |  |  |             LocalDate date = startDate.plusDays(i); | 
 |  |  |             dates.add(date); | 
 |  |  |         } | 
 |  |  |         return dates; | 
 |  |  |     } | 
 |  |  | } |