ソースを参照

完善储运中心导出根据定尺分组

lingpeng.li 4 週間 前
コミット
d02c9dd3fc

+ 25 - 15
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/service/impl/StorageBillServiceImpl.java

@@ -61,6 +61,7 @@ import org.jeecg.modules.billet.storageBill.service.IStorageBillService;
 import org.jeecg.modules.billet.storageBill.vo.*;
 import org.jeecg.modules.billet.storageCarLog.entity.StorageCarLog;
 import org.jeecg.modules.billet.storageCarLog.service.IStorageCarLogService;
+import org.jeecg.modules.carUnit.service.ICarUnitService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -152,6 +153,9 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
     @Autowired
     private IHeatsActualsService heatsActualsService;
 
+    @Autowired
+    private ICarUnitService iCarUnitService;
+
     @Autowired
     private StackingAndLoadingVehiclesMapper stackingAndLoadingVehiclesMapper;
     @Override
@@ -4162,6 +4166,7 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         return resultPage;
     }
 
+
     @Override
     public List<StorageCenterInvoicingVO> storageCenterInvoicingInfoList(StorageCenterQueryDTO queryDTO) {
 
@@ -4181,7 +4186,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         Date beginDate = queryDTO.getStorageTimeBegin();
         Date endDate = queryDTO.getStorageTimeEnd();
         if (beginDate != null) {
-            billQueryWrapper.ge(HeatsActuals::getCreateTime, DateUtils.getStartOfDayByDate(beginDate));
+            Date adjustedBeginDate = DateUtils.addDays(beginDate, -5);
+            billQueryWrapper.ge(HeatsActuals::getCreateTime, DateUtils.getStartOfDayByDate(adjustedBeginDate));
         }
         if (endDate != null) {
             billQueryWrapper.le(HeatsActuals::getCreateTime, DateUtils.getEndOfDayByDate(endDate));
@@ -4217,20 +4223,23 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
                     String shift = heat.getShift();
                     String shiftGroup = heat.getShiftGroup();
                     Date createTime = heat.getCreateTime();
+                    Date updateTime = heat.getUpdateTime();
                     List<BilletBasicInfo> billets = groupedByHeatNo.getOrDefault(heatNo, Collections.emptyList());
 
-                    // 汇总重量
-                    BigDecimal totalWeight = billets.stream()
-                            .map(BilletBasicInfo::getBilletWeight)
-                            .filter(Objects::nonNull)
-                            .map(BigDecimal::valueOf)
-                            .reduce(BigDecimal.ZERO, BigDecimal::add);
-
                     Integer ccmNo = Optional.ofNullable(heat.getCasterCode()).map(Integer::valueOf).orElse(0);
 
                     StorageCenterInvoicingVO.HeatNoDetail heatNoDetail = new StorageCenterInvoicingVO.HeatNoDetail();
 
-                    StorageCenterHeatNoInvoicingVO storageCenterHeatNoInvoicingVO = storageCenterInvoicingByHeatNo(heatNo);
+                    StorageCenterQueryDTO storageCenterQueryDTO = new StorageCenterQueryDTO();
+                    storageCenterQueryDTO.setHeatsCode(heatNo);
+                    if (queryDTO.getStorageTimeBegin() != null) {
+                        storageCenterQueryDTO.setStorageTimeBegin(queryDTO.getStorageTimeBegin());
+                    }
+                    if (queryDTO.getStorageTimeEnd() != null) {
+                        storageCenterQueryDTO.setStorageTimeEnd(queryDTO.getStorageTimeEnd());
+                    }
+
+                    StorageCenterHeatNoInvoicingVO storageCenterHeatNoInvoicingVO = iCarUnitService.storageCenterInvoicingByQueryDTO(storageCenterQueryDTO);
 
                     BigDecimal sumWeight = BigDecimal.ZERO;
                     int sumAmount = 0;
@@ -4263,7 +4272,7 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
                         Predicate<StorageCenterHeatNoInvoicingVO.RollChargeDetail> timeFilter = detail -> {
                             Date createTime1 = detail.getCreateTime();
                             if (createTime1 == null) {
-                                return false; // 没有 createTime 的记录直接过滤掉
+                                return false; // 没有 updateTime 的记录直接过滤掉
                             }
 
                             if (storageTimeBegin != null && storageTimeEnd != null) {
@@ -4278,17 +4287,17 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
                         };
 
                         Predicate<StorageCenterHeatNoInvoicingVO.RollSendDetail> timeFilterOther = detail -> {
-                            Date createTime1 = detail.getCreateTime();
-                            if (createTime1 == null) {
+                            Date updateTime1 = detail.getUpdateTime();
+                            if (updateTime1 == null) {
                                 return false; // 没有 createTime 的记录直接过滤掉
                             }
 
                             if (storageTimeBegin != null && storageTimeEnd != null) {
-                                return !createTime1.before(DateUtils.getStartOfDayByDate(storageTimeBegin)) && !createTime1.after(DateUtils.getEndOfDayByDate(storageTimeEnd));
+                                return !updateTime1.before(DateUtils.getStartOfDayByDate(storageTimeBegin)) && !updateTime1.after(DateUtils.getEndOfDayByDate(storageTimeEnd));
                             } else if (storageTimeBegin != null) {
-                                return !createTime1.before(DateUtils.getStartOfDayByDate(storageTimeBegin));
+                                return !updateTime1.before(DateUtils.getStartOfDayByDate(storageTimeBegin));
                             } else if (storageTimeEnd != null) {
-                                return !createTime1.after(DateUtils.getEndOfDayByDate(storageTimeEnd));
+                                return !updateTime1.after(DateUtils.getEndOfDayByDate(storageTimeEnd));
                             } else {
                                 return true; // 时间条件都为空,则不过滤
                             }
@@ -4357,6 +4366,7 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
                     heatNoDetail.setHeatNoWeight(sumWeight);
                     heatNoDetail.setHeatNoAmount(sumAmount);
                     heatNoDetail.setCreateTime(createTime);
+                    heatNoDetail.setUpdateTime(updateTime);
                     heatNoDetail.setShift(shift);
                     heatNoDetail.setShiftGroup(shiftGroup);
                     heatNoDetail.setCreateTime(createTime);

+ 10 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/vo/StorageCenterHeatNoInvoicingVO.java

@@ -164,6 +164,11 @@ public class StorageCenterHeatNoInvoicingVO {
         @ApiModelProperty(value = "创建日期")
         private Date createTime;
 
+        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+        @DateTimeFormat(pattern = "yyyy-MM-dd")
+        @ApiModelProperty(value = "修改日期")
+        private Date updateTime;
+
     }
 
 
@@ -202,6 +207,11 @@ public class StorageCenterHeatNoInvoicingVO {
         @ApiModelProperty(value = "创建日期")
         private Date createTime;
 
+        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "修改日期")
+        private Date updateTime;
+
     }
 
 

+ 5 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/vo/StorageCenterInvoicingVO.java

@@ -62,6 +62,11 @@ public class StorageCenterInvoicingVO {
         @ApiModelProperty(value = "创建时间")
         private Date createTime;
 
+        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "修改时间")
+        private Date updateTime;
+
         @ApiModelProperty(value = "班组")
         private String shiftGroup;
 

+ 5 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/carUnit/service/ICarUnitService.java

@@ -1,7 +1,9 @@
 package org.jeecg.modules.carUnit.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.billet.storageBill.dto.StorageCenterQueryDTO;
 import org.jeecg.modules.billet.storageBill.vo.StorageCenterExportRow;
+import org.jeecg.modules.billet.storageBill.vo.StorageCenterHeatNoInvoicingVO;
 import org.jeecg.modules.billet.storageBill.vo.StorageCenterInvoicingVO;
 import org.jeecg.modules.carUnit.entity.CarUnit;
 
@@ -18,4 +20,7 @@ public interface ICarUnitService extends IService<CarUnit> {
 
     List<StorageCenterExportRow> buildExportData(List<StorageCenterInvoicingVO> records);
 
+
+    StorageCenterHeatNoInvoicingVO storageCenterInvoicingByQueryDTO(StorageCenterQueryDTO queryDTO);
+
 }

+ 608 - 9
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/carUnit/service/impl/CarUnitServiceImpl.java

@@ -4,9 +4,24 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
+import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.SpringContextUtils;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletBasicInfoService;
+import org.jeecg.modules.billet.rollClubOne.service.IRollClubOneDetailsService;
+import org.jeecg.modules.billet.rollClubThree.entity.RollClubThreeDetails;
+import org.jeecg.modules.billet.rollClubThree.service.IRollClubThreeDetailsService;
+import org.jeecg.modules.billet.rollClubTwo.entity.RollClubTwoDetails;
+import org.jeecg.modules.billet.rollClubTwo.service.IRollClubTwoDetailsService;
+import org.jeecg.modules.billet.rollHeight.service.IRollHeightDetailsService;
+import org.jeecg.modules.billet.rollOutShipp.entity.RollOutShippDetails;
+import org.jeecg.modules.billet.rollOutShipp.service.IRollOutShippDetailsService;
 import org.jeecg.modules.billet.shiftConfiguration.entity.ShiftConfiguration;
 import org.jeecg.modules.billet.shiftConfiguration.mapper.ShiftConfigurationMapper;
+import org.jeecg.modules.billet.storageBill.dto.StorageCenterQueryDTO;
+import org.jeecg.modules.billet.storageBill.entity.StorageBill;
+import org.jeecg.modules.billet.storageBill.mapper.StorageBillMapper;
 import org.jeecg.modules.billet.storageBill.vo.StorageCenterExportRow;
 import org.jeecg.modules.billet.storageBill.vo.StorageCenterHeatNoInvoicingVO;
 import org.jeecg.modules.billet.storageBill.vo.StorageCenterInvoicingVO;
@@ -18,14 +33,16 @@ import org.jeecg.modules.carUnit.service.ICarUnitService;
 import org.jeecg.modules.carUnit.service.ISysDictItemService;
 import org.jeecg.modules.carUnit.service.ISysDictService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * @Description: 车辆单位管理
@@ -46,11 +63,35 @@ public class CarUnitServiceImpl extends ServiceImpl<CarUnitMapper, CarUnit> impl
     @Autowired
     private ISysDictService sysDictService;
 
+
+    @Resource
+    private StorageBillMapper storageBillMapper;
+
+    @Autowired
+    private IRollClubOneDetailsService rollClubOneDetailsService;
+
+    @Autowired
+    private IRollClubTwoDetailsService rollClubTwoDetailsService;
+
+    @Autowired
+    private IRollClubThreeDetailsService rollClubThreeDetailsService;
+
+    @Autowired
+    private IRollOutShippDetailsService rollOutShippDetailsService;
+
+    @Autowired
+    private IRollHeightDetailsService rollHeightDetailsService;
+
+    @Autowired
+    private IBilletBasicInfoService billetBasicInfoService;
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+
     @Override
     public List<StorageCenterExportRow> buildExportData(List<StorageCenterInvoicingVO> records) {
         List<StorageCenterExportRow> rows = new ArrayList<>();
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
 
         for (StorageCenterInvoicingVO vo : records) {
             Integer ccmNo = Optional.ofNullable(vo.getHeatNoDetails())
@@ -176,6 +217,564 @@ public class CarUnitServiceImpl extends ServiceImpl<CarUnitMapper, CarUnit> impl
         return rows;
     }
 
+    @Override
+    public StorageCenterHeatNoInvoicingVO storageCenterInvoicingByQueryDTO(StorageCenterQueryDTO queryDTO) {
+
+        String heatNo = queryDTO.getHeatsCode();
+        Date storageTimeBegin = queryDTO.getStorageTimeBegin();
+        Date storageTimeEnd = queryDTO.getStorageTimeEnd();
+        StorageCenterHeatNoInvoicingVO storageCenterHeatNoInvoicingVO = new StorageCenterHeatNoInvoicingVO();
+
+        StorageCenterHeatNoInvoicingVO.RollOneHeatNo rollOneHeatNo = new StorageCenterHeatNoInvoicingVO.RollOneHeatNo();
+        StorageCenterHeatNoInvoicingVO.RollTwoHeatNo rollTwoHeatNo = new StorageCenterHeatNoInvoicingVO.RollTwoHeatNo();
+        StorageCenterHeatNoInvoicingVO.RollThreeHeatNo rollThreeHeatNo = new StorageCenterHeatNoInvoicingVO.RollThreeHeatNo();
+        StorageCenterHeatNoInvoicingVO.RollHeightHeatNo rollHeightHeatNo = new StorageCenterHeatNoInvoicingVO.RollHeightHeatNo();
+        StorageCenterHeatNoInvoicingVO.RollOutHeatNo rollOutHeatNo = new StorageCenterHeatNoInvoicingVO.RollOutHeatNo();
+
+        // 查询 BilletBasicInfo 数据
+        LambdaQueryWrapper<BilletBasicInfo> basicInfoQueryWrapper = new LambdaQueryWrapper<>();
+        basicInfoQueryWrapper.eq(BilletBasicInfo::getHeatNo, heatNo);
+
+        List<BilletBasicInfo> list = billetBasicInfoService.list(basicInfoQueryWrapper);
+        if (oConvertUtils.listIsEmpty(list)) {
+            return storageCenterHeatNoInvoicingVO;
+        }
+
+
+        Map<String, Map<Integer, List<BilletBasicInfo>>> groupedByBelongTableAndLength = list.stream()
+                .collect(Collectors.groupingBy(
+                        b -> Optional.ofNullable(b.getBelongTable()).orElse("unknown"), // 外层:按 belongTable 分组
+                        Collectors.groupingBy(
+                                BilletBasicInfo::getLength // 内层:按 length 分组
+                        )
+                ));
+
+
+        if (groupedByBelongTableAndLength.containsKey("roll_club_one")) {
+            Map<Integer, List<BilletBasicInfo>> lengthGrouped = groupedByBelongTableAndLength.get("roll_club_one");
+
+            List<StorageCenterHeatNoInvoicingVO.SizeDetail> sizeDetailsList = new ArrayList<>();
+            List<StorageCenterHeatNoInvoicingVO.RollSendDetail> rollSendDetailList = new ArrayList<>();
+
+            int totalAmount = 0;
+            BigDecimal totalWeight = BigDecimal.ZERO;
+
+            for (Map.Entry<Integer, List<BilletBasicInfo>> entry : lengthGrouped.entrySet()) {
+                Integer length = entry.getKey();
+                List<BilletBasicInfo> billets = entry.getValue();
+
+                int amount = billets.size();
+                BigDecimal weight = billets.stream()
+                        .map(BilletBasicInfo::getBilletWeight)
+                        .filter(Objects::nonNull)
+                        .map(BigDecimal::valueOf)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                totalAmount += amount;
+                totalWeight = totalWeight.add(weight);
+
+                String spec = Optional.ofNullable(billets.get(0).getSpec()).orElse("Unknown");
+                Date latestUpdateTime = billets.stream()
+                        .map(BilletBasicInfo::getUpdateTime)
+                        .filter(Objects::nonNull)
+                        .max(Date::compareTo)
+                        .orElse(null);
+
+                // 构造 SizeDetail
+                StorageCenterHeatNoInvoicingVO.SizeDetail sizeDetail = new StorageCenterHeatNoInvoicingVO.SizeDetail();
+                sizeDetail.setSize(length);
+                sizeDetail.setSizeAmount(amount);
+                sizeDetail.setSizeWeight(weight);
+                sizeDetailsList.add(sizeDetail);
+
+                // 构造 RollSendDetail
+                StorageCenterHeatNoInvoicingVO.RollSendDetail rollSendDetail = new StorageCenterHeatNoInvoicingVO.RollSendDetail();
+                rollSendDetail.setSize(length);
+                rollSendDetail.setWeight(weight);
+                rollSendDetail.setAmount(amount);
+                rollSendDetail.setSpec(spec);
+                rollSendDetail.setUpdateTime(latestUpdateTime);
+
+                rollSendDetailList.add(rollSendDetail);
+            }
+
+            // 按照时间过滤
+            if (storageTimeBegin != null && storageTimeEnd != null) {
+                Date beginOfDay = DateUtils.getStartOfDayByDate(storageTimeBegin);
+                Date endOfDay = DateUtils.getEndOfDayByDate(storageTimeEnd);
+
+                rollSendDetailList = rollSendDetailList.stream()
+                        .filter(detail -> {
+                            Date updateTimeFilter = detail.getUpdateTime();
+                            return updateTimeFilter != null &&
+                                    !updateTimeFilter.before(beginOfDay) &&
+                                    !updateTimeFilter.after(endOfDay);
+                        })
+                        .collect(Collectors.toList());
+            }
+
+            // 排序
+            rollSendDetailList.sort(Comparator.comparing(StorageCenterHeatNoInvoicingVO.RollSendDetail::getSize));
+
+            // 最终赋值
+            rollOneHeatNo.setTotalAmount(totalAmount);
+            rollOneHeatNo.setTotalWeight(totalWeight);
+            rollOneHeatNo.setSizeDetails(sizeDetailsList);
+            rollOneHeatNo.setRollSendDetails(rollSendDetailList);
+
+            storageCenterHeatNoInvoicingVO.setRollClubOneDetails(rollOneHeatNo);
+        }
+
+
+        if (groupedByBelongTableAndLength.containsKey("roll_height")) {
+            Map<Integer, List<BilletBasicInfo>> lengthGrouped = groupedByBelongTableAndLength.get("roll_height");
+
+            List<StorageCenterHeatNoInvoicingVO.SizeDetail> sizeDetailsList = new ArrayList<>();
+            List<StorageCenterHeatNoInvoicingVO.RollSendDetail> rollSendDetailList = new ArrayList<>();
+
+            int totalAmount = 0;
+            BigDecimal totalWeight = BigDecimal.ZERO;
+
+            for (Map.Entry<Integer, List<BilletBasicInfo>> entry : lengthGrouped.entrySet()) {
+                Integer length = entry.getKey();
+                List<BilletBasicInfo> billets = entry.getValue();
+
+                int amount = billets.size();
+                BigDecimal weight = billets.stream()
+                        .map(BilletBasicInfo::getBilletWeight)
+                        .filter(Objects::nonNull)
+                        .map(BigDecimal::valueOf)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                totalAmount += amount;
+                totalWeight = totalWeight.add(weight);
+
+                String spec = Optional.ofNullable(billets.get(0).getSpec()).orElse("Unknown");
+                Date latestUpdateTime = billets.stream()
+                        .map(BilletBasicInfo::getUpdateTime)
+                        .filter(Objects::nonNull)
+                        .max(Date::compareTo)
+                        .orElse(null);
+
+                // 构造 SizeDetail
+                StorageCenterHeatNoInvoicingVO.SizeDetail sizeDetail = new StorageCenterHeatNoInvoicingVO.SizeDetail();
+                sizeDetail.setSize(length);
+                sizeDetail.setSizeAmount(amount);
+                sizeDetail.setSizeWeight(weight);
+                sizeDetailsList.add(sizeDetail);
+
+                // 构造 RollSendDetail
+                StorageCenterHeatNoInvoicingVO.RollSendDetail rollSendDetail = new StorageCenterHeatNoInvoicingVO.RollSendDetail();
+                rollSendDetail.setSize(length);
+                rollSendDetail.setWeight(weight);
+                rollSendDetail.setAmount(amount);
+                rollSendDetail.setSpec(spec);
+                rollSendDetail.setUpdateTime(latestUpdateTime);
+
+                rollSendDetailList.add(rollSendDetail);
+            }
+
+            // 按照时间过滤
+            if (storageTimeBegin != null && storageTimeEnd != null) {
+                Date beginOfDay = DateUtils.getStartOfDayByDate(storageTimeBegin);
+                Date endOfDay = DateUtils.getEndOfDayByDate(storageTimeEnd);
+
+                rollSendDetailList = rollSendDetailList.stream()
+                        .filter(detail -> {
+                            Date updateTimeFilter = detail.getUpdateTime();
+                            return updateTimeFilter != null &&
+                                    !updateTimeFilter.before(beginOfDay) &&
+                                    !updateTimeFilter.after(endOfDay);
+                        })
+                        .collect(Collectors.toList());
+            }
+
+            // 排序
+            rollSendDetailList.sort(Comparator.comparing(StorageCenterHeatNoInvoicingVO.RollSendDetail::getSize));
+
+            // 最终赋值
+            rollHeightHeatNo.setTotalAmount(totalAmount);
+            rollHeightHeatNo.setTotalWeight(totalWeight);
+            rollHeightHeatNo.setSizeDetails(sizeDetailsList);
+            rollHeightHeatNo.setRollSendDetails(rollSendDetailList);
+
+            storageCenterHeatNoInvoicingVO.setRollHeightDetails(rollHeightHeatNo);
+        }
+
+
+        if (groupedByBelongTableAndLength.containsKey("roll_club_two")) {
+            Map<Integer, List<BilletBasicInfo>> lengthMap = groupedByBelongTableAndLength.get("roll_club_two");
+
+            List<StorageCenterHeatNoInvoicingVO.SizeDetail> sizeDetails = new ArrayList<>();
+            List<StorageCenterHeatNoInvoicingVO.RollChargeDetail> rollChargeDetails = new ArrayList<>();
+
+            int totalAmount = 0;
+            BigDecimal totalWeight = BigDecimal.ZERO;
+
+            for (Map.Entry<Integer, List<BilletBasicInfo>> entry : lengthMap.entrySet()) {
+                Integer length = entry.getKey();
+                List<BilletBasicInfo> billets = entry.getValue();
+
+                int amount = billets.size();
+                BigDecimal weight = billets.stream()
+                        .map(BilletBasicInfo::getBilletWeight)
+                        .filter(Objects::nonNull)
+                        .map(BigDecimal::valueOf)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                totalAmount += amount;
+                totalWeight = totalWeight.add(weight);
+
+                // SizeDetail 构造
+                StorageCenterHeatNoInvoicingVO.SizeDetail sizeDetail = new StorageCenterHeatNoInvoicingVO.SizeDetail();
+                sizeDetail.setSize(length);
+                sizeDetail.setSizeAmount(amount);
+                sizeDetail.setSizeWeight(weight);
+                sizeDetails.add(sizeDetail);
+
+                // 查询 RollClubThreeDetails
+                LambdaQueryWrapper<RollClubTwoDetails> twoDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                twoDetailsLambdaQueryWrapper.eq(RollClubTwoDetails::getHeatNo, heatNo)
+                        .eq(RollClubTwoDetails::getSize, length);
+
+                List<RollClubTwoDetails> twoDetailsList = rollClubTwoDetailsService.list(twoDetailsLambdaQueryWrapper);
+
+                if (oConvertUtils.isNotEmpty(twoDetailsList)) {
+                    // 按 storageBillId 分组
+                    Map<String, List<RollClubTwoDetails>> groupedByStorageBillId = twoDetailsList.stream()
+                            .filter(e -> oConvertUtils.isNotEmpty(e.getStorageBillId()))
+                            .collect(Collectors.groupingBy(RollClubTwoDetails::getStorageBillId));
+
+                    // 查询所有 StorageBill
+                    Set<String> storageBillIds = groupedByStorageBillId.keySet();
+                    Map<String, StorageBill> storageBillMap = new HashMap<>();
+                    if (!storageBillIds.isEmpty()) {
+                        LambdaQueryWrapper<StorageBill> storageBillLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                        storageBillLambdaQueryWrapper.in(StorageBill::getId, storageBillIds);
+                        List<StorageBill> matchedStorageBills = storageBillMapper.selectList(storageBillLambdaQueryWrapper);
+                        storageBillMap = matchedStorageBills.stream()
+                                .collect(Collectors.toMap(StorageBill::getId, Function.identity()));
+                    }
+
+                    // 遍历每个分组
+                    for (Map.Entry<String, List<RollClubTwoDetails>> groupEntry : groupedByStorageBillId.entrySet()) {
+                        String storageBillId = groupEntry.getKey();
+                        List<RollClubTwoDetails> detailList = groupEntry.getValue();
+
+                        int groupAmount = detailList.stream()
+                                .mapToInt(d -> StringUtils.isNotBlank(d.getStackAddr()) ? 4 : 1)
+                                .sum();
+
+                        BigDecimal groupWeight = detailList.stream()
+                                .map(RollClubTwoDetails::getBlankOutput)
+                                .filter(Objects::nonNull)
+                                .map(BigDecimal::valueOf) // 关键转换
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                        StorageBill storageBill = storageBillMap.get(storageBillId);
+                        String spec = billets.stream().map(BilletBasicInfo::getSpec).filter(Objects::nonNull).findFirst().orElse("");
+                        String licensePlate = storageBill != null ? Optional.ofNullable(storageBill.getLicensePlate()).orElse("未知车牌") : "未知车牌";
+                        String btype = storageBill != null ? Optional.ofNullable(storageBill.getBtype()).orElse("未知类型") : "未知类型";
+                        String brandNum = storageBill != null ? Optional.ofNullable(storageBill.getBrandNum()).orElse("") : "";
+                        Integer carNum = storageBill != null ? Optional.ofNullable(storageBill.getCarNum()).orElse(1) : 1;
+                        Date createTime = storageBill != null ? Optional.ofNullable(storageBill.getCreateTime()).orElse(new Date()) : new Date();
+                        Date updateTime = storageBill != null ? Optional.ofNullable(storageBill.getUpdateTime()).orElse(new Date()) : new Date();
+
+                        StorageCenterHeatNoInvoicingVO.RollChargeDetail rollChargeDetail = new StorageCenterHeatNoInvoicingVO.RollChargeDetail();
+                        rollChargeDetail.setSize(length);
+                        rollChargeDetail.setSpec(spec);
+                        rollChargeDetail.setAmount(groupAmount);
+                        rollChargeDetail.setWeight(groupWeight);
+                        rollChargeDetail.setHeatNo(heatNo);
+                        rollChargeDetail.setLicensePlate(licensePlate);
+                        rollChargeDetail.setBtype(btype);
+                        rollChargeDetail.setBrandNum(brandNum);
+                        rollChargeDetail.setCarNum(carNum);
+                        rollChargeDetail.setCreateTime(createTime);
+                        rollChargeDetail.setUpdateTime(updateTime);
+
+                        rollChargeDetails.add(rollChargeDetail);
+                    }
+                }
+            }
+
+            // 时间过滤逻辑
+            if (storageTimeBegin != null && storageTimeEnd != null) {
+                Date beginOfDay = DateUtils.getStartOfDayByDate(storageTimeBegin);
+                Date endOfDay = DateUtils.getEndOfDayByDate(storageTimeEnd);
+
+                rollChargeDetails = rollChargeDetails.stream()
+                        .filter(detail -> {
+                            Date createTimeFilter = detail.getCreateTime();
+                            return createTimeFilter != null &&
+                                    !createTimeFilter.before(beginOfDay) &&
+                                    !createTimeFilter.after(endOfDay);
+                        })
+                        .collect(Collectors.toList());
+            }
+
+            // 排序(按车号)
+            rollChargeDetails.sort(Comparator.comparing(StorageCenterHeatNoInvoicingVO.RollChargeDetail::getCarNum));
+
+            // 赋值到 VO
+            rollTwoHeatNo.setTotalAmount(totalAmount);
+            rollTwoHeatNo.setTotalWeight(totalWeight);
+            rollTwoHeatNo.setSizeDetails(sizeDetails);
+            rollTwoHeatNo.setRollChargeDetails(rollChargeDetails);
+            storageCenterHeatNoInvoicingVO.setRollClubTwoDetails(rollTwoHeatNo);
+        }
+
+
+
+        if (groupedByBelongTableAndLength.containsKey("roll_club_three")) {
+            Map<Integer, List<BilletBasicInfo>> lengthMap = groupedByBelongTableAndLength.get("roll_club_three");
+
+            List<StorageCenterHeatNoInvoicingVO.SizeDetail> sizeDetails = new ArrayList<>();
+            List<StorageCenterHeatNoInvoicingVO.RollChargeDetail> rollChargeDetails = new ArrayList<>();
+
+            int totalAmount = 0;
+            BigDecimal totalWeight = BigDecimal.ZERO;
+
+            for (Map.Entry<Integer, List<BilletBasicInfo>> entry : lengthMap.entrySet()) {
+                Integer length = entry.getKey();
+                List<BilletBasicInfo> billets = entry.getValue();
+
+                int amount = billets.size();
+                BigDecimal weight = billets.stream()
+                        .map(BilletBasicInfo::getBilletWeight)
+                        .filter(Objects::nonNull)
+                        .map(BigDecimal::valueOf)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                totalAmount += amount;
+                totalWeight = totalWeight.add(weight);
+
+                // SizeDetail 构造
+                StorageCenterHeatNoInvoicingVO.SizeDetail sizeDetail = new StorageCenterHeatNoInvoicingVO.SizeDetail();
+                sizeDetail.setSize(length);
+                sizeDetail.setSizeAmount(amount);
+                sizeDetail.setSizeWeight(weight);
+                sizeDetails.add(sizeDetail);
+
+                // 查询 RollClubThreeDetails
+                LambdaQueryWrapper<RollClubThreeDetails> threeDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                threeDetailsLambdaQueryWrapper.eq(RollClubThreeDetails::getHeatNo, heatNo)
+                        .eq(RollClubThreeDetails::getSize, length);
+
+                List<RollClubThreeDetails> threeDetailsList = rollClubThreeDetailsService.list(threeDetailsLambdaQueryWrapper);
+
+                if (oConvertUtils.isNotEmpty(threeDetailsList)) {
+                    // 按 storageBillId 分组
+                    Map<String, List<RollClubThreeDetails>> groupedByStorageBillId = threeDetailsList.stream()
+                            .filter(e -> oConvertUtils.isNotEmpty(e.getStorageBillId()))
+                            .collect(Collectors.groupingBy(RollClubThreeDetails::getStorageBillId));
+
+                    // 查询所有 StorageBill
+                    Set<String> storageBillIds = groupedByStorageBillId.keySet();
+                    Map<String, StorageBill> storageBillMap = new HashMap<>();
+                    if (!storageBillIds.isEmpty()) {
+                        LambdaQueryWrapper<StorageBill> storageBillLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                        storageBillLambdaQueryWrapper.in(StorageBill::getId, storageBillIds);
+                        List<StorageBill> matchedStorageBills = storageBillMapper.selectList(storageBillLambdaQueryWrapper);
+                        storageBillMap = matchedStorageBills.stream()
+                                .collect(Collectors.toMap(StorageBill::getId, Function.identity()));
+                    }
+
+                    // 遍历每个分组
+                    for (Map.Entry<String, List<RollClubThreeDetails>> groupEntry : groupedByStorageBillId.entrySet()) {
+                        String storageBillId = groupEntry.getKey();
+                        List<RollClubThreeDetails> detailList = groupEntry.getValue();
+
+                        int groupAmount = detailList.stream()
+                                .mapToInt(d -> StringUtils.isNotBlank(d.getStackAddr()) ? 4 : 1)
+                                .sum();
+
+                        BigDecimal groupWeight = detailList.stream()
+                                .map(RollClubThreeDetails::getBlankOutput)
+                                .filter(Objects::nonNull)
+                                .map(BigDecimal::valueOf) // 关键转换
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                        StorageBill storageBill = storageBillMap.get(storageBillId);
+                        String spec = billets.stream().map(BilletBasicInfo::getSpec).filter(Objects::nonNull).findFirst().orElse("");
+                        String licensePlate = storageBill != null ? Optional.ofNullable(storageBill.getLicensePlate()).orElse("未知车牌") : "未知车牌";
+                        String btype = storageBill != null ? Optional.ofNullable(storageBill.getBtype()).orElse("未知类型") : "未知类型";
+                        String brandNum = storageBill != null ? Optional.ofNullable(storageBill.getBrandNum()).orElse("") : "";
+                        Integer carNum = storageBill != null ? Optional.ofNullable(storageBill.getCarNum()).orElse(1) : 1;
+                        Date createTime = storageBill != null ? Optional.ofNullable(storageBill.getCreateTime()).orElse(new Date()) : new Date();
+                        Date updateTime = storageBill != null ? Optional.ofNullable(storageBill.getUpdateTime()).orElse(new Date()) : new Date();
+
+                        StorageCenterHeatNoInvoicingVO.RollChargeDetail rollChargeDetail = new StorageCenterHeatNoInvoicingVO.RollChargeDetail();
+                        rollChargeDetail.setSize(length);
+                        rollChargeDetail.setSpec(spec);
+                        rollChargeDetail.setAmount(groupAmount);
+                        rollChargeDetail.setWeight(groupWeight);
+                        rollChargeDetail.setHeatNo(heatNo);
+                        rollChargeDetail.setLicensePlate(licensePlate);
+                        rollChargeDetail.setBtype(btype);
+                        rollChargeDetail.setBrandNum(brandNum);
+                        rollChargeDetail.setCarNum(carNum);
+                        rollChargeDetail.setCreateTime(createTime);
+                        rollChargeDetail.setUpdateTime(updateTime);
+
+                        rollChargeDetails.add(rollChargeDetail);
+                    }
+                }
+            }
+
+            // 时间过滤逻辑
+            if (storageTimeBegin != null && storageTimeEnd != null) {
+                Date beginOfDay = DateUtils.getStartOfDayByDate(storageTimeBegin);
+                Date endOfDay = DateUtils.getEndOfDayByDate(storageTimeEnd);
+
+                rollChargeDetails = rollChargeDetails.stream()
+                        .filter(detail -> {
+                            Date createTimeFilter = detail.getCreateTime();
+                            return createTimeFilter != null &&
+                                    !createTimeFilter.before(beginOfDay) &&
+                                    !createTimeFilter.after(endOfDay);
+                        })
+                        .collect(Collectors.toList());
+            }
+
+            // 排序(按车号)
+            rollChargeDetails.sort(Comparator.comparing(StorageCenterHeatNoInvoicingVO.RollChargeDetail::getCarNum));
+
+            // 赋值到 VO
+            rollThreeHeatNo.setTotalAmount(totalAmount);
+            rollThreeHeatNo.setTotalWeight(totalWeight);
+            rollThreeHeatNo.setSizeDetails(sizeDetails);
+            rollThreeHeatNo.setRollChargeDetails(rollChargeDetails);
+            storageCenterHeatNoInvoicingVO.setRollClubThreeDetails(rollThreeHeatNo);
+        }
+
+
+        if (groupedByBelongTableAndLength.containsKey("roll_out_shipp")) {
+            Map<Integer, List<BilletBasicInfo>> lengthMap = groupedByBelongTableAndLength.get("roll_out_shipp");
+
+            List<StorageCenterHeatNoInvoicingVO.SizeDetail> sizeDetails = new ArrayList<>();
+            List<StorageCenterHeatNoInvoicingVO.RollChargeDetail> rollChargeDetails = new ArrayList<>();
+
+            int totalAmount = 0;
+            BigDecimal totalWeight = BigDecimal.ZERO;
+
+            for (Map.Entry<Integer, List<BilletBasicInfo>> entry : lengthMap.entrySet()) {
+                Integer length = entry.getKey();
+                List<BilletBasicInfo> billets = entry.getValue();
+
+                int amount = billets.size();
+                BigDecimal weight = billets.stream()
+                        .map(BilletBasicInfo::getBilletWeight)
+                        .filter(Objects::nonNull)
+                        .map(BigDecimal::valueOf)
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                totalAmount += amount;
+                totalWeight = totalWeight.add(weight);
+
+                // SizeDetail 构造
+                StorageCenterHeatNoInvoicingVO.SizeDetail sizeDetail = new StorageCenterHeatNoInvoicingVO.SizeDetail();
+                sizeDetail.setSize(length);
+                sizeDetail.setSizeAmount(amount);
+                sizeDetail.setSizeWeight(weight);
+                sizeDetails.add(sizeDetail);
+
+                // 查询 RollClubThreeDetails
+                LambdaQueryWrapper<RollOutShippDetails> outDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                outDetailsLambdaQueryWrapper.eq(RollOutShippDetails::getHeatNo, heatNo)
+                        .eq(RollOutShippDetails::getSize, length);
+
+                List<RollOutShippDetails> outDetailsList = rollOutShippDetailsService.list(outDetailsLambdaQueryWrapper);
+
+                if (oConvertUtils.isNotEmpty(outDetailsList)) {
+                    // 按 storageBillId 分组
+                    Map<String, List<RollOutShippDetails>> groupedByStorageBillId = outDetailsList.stream()
+                            .filter(e -> oConvertUtils.isNotEmpty(e.getStorageBillId()))
+                            .collect(Collectors.groupingBy(RollOutShippDetails::getStorageBillId));
+
+                    // 查询所有 StorageBill
+                    Set<String> storageBillIds = groupedByStorageBillId.keySet();
+                    Map<String, StorageBill> storageBillMap = new HashMap<>();
+                    if (!storageBillIds.isEmpty()) {
+                        LambdaQueryWrapper<StorageBill> storageBillLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                        storageBillLambdaQueryWrapper.in(StorageBill::getId, storageBillIds);
+                        List<StorageBill> matchedStorageBills = storageBillMapper.selectList(storageBillLambdaQueryWrapper);
+                        storageBillMap = matchedStorageBills.stream()
+                                .collect(Collectors.toMap(StorageBill::getId, Function.identity()));
+                    }
+
+                    // 遍历每个分组
+                    for (Map.Entry<String, List<RollOutShippDetails>> groupEntry : groupedByStorageBillId.entrySet()) {
+                        String storageBillId = groupEntry.getKey();
+                        List<RollOutShippDetails> detailList = groupEntry.getValue();
+
+                        int groupAmount = detailList.stream()
+                                .mapToInt(d -> StringUtils.isNotBlank(d.getStackAddr()) ? 4 : 1)
+                                .sum();
+
+                        BigDecimal groupWeight = detailList.stream()
+                                .map(RollOutShippDetails::getBlankOutput)
+                                .filter(Objects::nonNull)
+                                .map(BigDecimal::valueOf) // 关键转换
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+                        StorageBill storageBill = storageBillMap.get(storageBillId);
+                        String spec = billets.stream().map(BilletBasicInfo::getSpec).filter(Objects::nonNull).findFirst().orElse("");
+                        String licensePlate = storageBill != null ? Optional.ofNullable(storageBill.getLicensePlate()).orElse("未知车牌") : "未知车牌";
+                        String btype = storageBill != null ? Optional.ofNullable(storageBill.getBtype()).orElse("未知类型") : "未知类型";
+                        String brandNum = storageBill != null ? Optional.ofNullable(storageBill.getBrandNum()).orElse("") : "";
+                        Integer carNum = storageBill != null ? Optional.ofNullable(storageBill.getCarNum()).orElse(1) : 1;
+                        Date createTime = storageBill != null ? Optional.ofNullable(storageBill.getCreateTime()).orElse(new Date()) : new Date();
+                        Date updateTime = storageBill != null ? Optional.ofNullable(storageBill.getUpdateTime()).orElse(new Date()) : new Date();
+
+                        StorageCenterHeatNoInvoicingVO.RollChargeDetail rollChargeDetail = new StorageCenterHeatNoInvoicingVO.RollChargeDetail();
+                        rollChargeDetail.setSize(length);
+                        rollChargeDetail.setSpec(spec);
+                        rollChargeDetail.setAmount(groupAmount);
+                        rollChargeDetail.setWeight(groupWeight);
+                        rollChargeDetail.setHeatNo(heatNo);
+                        rollChargeDetail.setLicensePlate(licensePlate);
+                        rollChargeDetail.setBtype(btype);
+                        rollChargeDetail.setBrandNum(brandNum);
+                        rollChargeDetail.setCarNum(carNum);
+                        rollChargeDetail.setCreateTime(createTime);
+                        rollChargeDetail.setUpdateTime(updateTime);
+
+                        rollChargeDetails.add(rollChargeDetail);
+                    }
+                }
+            }
+
+            // 时间过滤逻辑
+            if (storageTimeBegin != null && storageTimeEnd != null) {
+                Date beginOfDay = DateUtils.getStartOfDayByDate(storageTimeBegin);
+                Date endOfDay = DateUtils.getEndOfDayByDate(storageTimeEnd);
+
+                rollChargeDetails = rollChargeDetails.stream()
+                        .filter(detail -> {
+                            Date createTimeFilter = detail.getCreateTime();
+                            return createTimeFilter != null &&
+                                    !createTimeFilter.before(beginOfDay) &&
+                                    !createTimeFilter.after(endOfDay);
+                        })
+                        .collect(Collectors.toList());
+            }
+
+            // 排序(按车号)
+            rollChargeDetails.sort(Comparator.comparing(StorageCenterHeatNoInvoicingVO.RollChargeDetail::getCarNum));
+
+            // 赋值到 VO
+            rollOutHeatNo.setTotalAmount(totalAmount);
+            rollOutHeatNo.setTotalWeight(totalWeight);
+            rollOutHeatNo.setSizeDetails(sizeDetails);
+            rollOutHeatNo.setRollChargeDetails(rollChargeDetails);
+            storageCenterHeatNoInvoicingVO.setRollOutShippDetails(rollOutHeatNo);
+        }
+
+
+        return storageCenterHeatNoInvoicingVO;
+    }
+
 
     public static String getTransportUnitNameByCarNumber(String carNumber) {
         if (StringUtils.isBlank(carNumber)) return "";
@@ -233,7 +832,7 @@ public class CarUnitServiceImpl extends ServiceImpl<CarUnitMapper, CarUnit> impl
     private static StorageCenterExportRow convert(StorageCenterHeatNoInvoicingVO.RollChargeDetail detail, Integer ccmNo, String endpoint) {
         StorageCenterExportRow row = new StorageCenterExportRow();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        String dateString = sdf.format(detail.getCreateTime());
+        String dateString = sdf.format(detail.getUpdateTime());
         row.setFactoryDate(dateString);
         row.setEndPoint(endpoint);
         row.setLicensePlate(detail.getLicensePlate());
@@ -271,9 +870,9 @@ public class CarUnitServiceImpl extends ServiceImpl<CarUnitMapper, CarUnit> impl
             row.setSize("170*170*" + result.toPlainString());
         }
         row.setSpec(detail.getSpec());
-        if (detail != null && detail.getCreateTime() != null) {
+        if (detail != null && detail.getUpdateTime() != null) {
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-            row.setFactoryDate(sdf.format(detail.getCreateTime()));
+            row.setFactoryDate(sdf.format(detail.getUpdateTime()));
         } else {
             row.setFactoryDate("");
         }
@@ -283,7 +882,7 @@ public class CarUnitServiceImpl extends ServiceImpl<CarUnitMapper, CarUnit> impl
 
     private static BigDecimal calcWeightPerPiece(BigDecimal total, Integer amount) {
         if (total == null || amount == null || amount == 0) return BigDecimal.ZERO;
-        return total.divide(BigDecimal.valueOf(amount), 3, RoundingMode.HALF_UP);
+        return total.divide(BigDecimal.valueOf(amount), 4, RoundingMode.HALF_UP);
     }
 
     private static String getDictId(String dictCode) {