Kaynağa Gözat

钢坯项目添加钢坯热装实绩-分页列表查询、钢坯热装单-班统计查询接口

lingpeng.li 3 ay önce
ebeveyn
işleme
659510dfb2

+ 8 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/stackingAndLoadingVehicles/controller/StackingAndLoadingVehiclesController.java

@@ -15,6 +15,7 @@ import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.entity.StackingAndLoadingVehicles;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.entity.UpdateBatchParams;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.service.IStackingAndLoadingVehiclesService;
+import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.ClipLayerVo;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.LoadingParams;
 import org.jeecg.modules.billet.storageBill.entity.StorageBill;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -211,4 +212,11 @@ public class StackingAndLoadingVehiclesController extends JeecgController<Stacki
 		 String result = stackingAndLoadingVehiclesService.judgeDiscardHandle(loadingParams);
 		 return Result.OK(result);
 	 }
+
+	 @ApiOperation(value="垛位装车公共容器总夹数层数显示", notes="垛位装车公共容器总夹数层数显示")
+	 @PostMapping(value = "/clipNumAndLayerNum")
+	 public Result<?> clipNumAndLayerNum(){
+		 List<ClipLayerVo> clipLayerVos = stackingAndLoadingVehiclesService.clipNumAndLayerNum();
+		 return Result.OK(clipLayerVos);
+	 }
 }

+ 3 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/stackingAndLoadingVehicles/service/IStackingAndLoadingVehiclesService.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.billet.stackingAndLoadingVehicles.service;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.entity.StackingAndLoadingVehicles;
+import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.ClipLayerVo;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.LoadingParams;
 
 import java.util.List;
@@ -24,4 +25,6 @@ public interface IStackingAndLoadingVehiclesService extends IService<StackingAnd
     JSONObject addStackInfo(LoadingParams loadingParams);
 
     String judgeDiscardHandle(LoadingParams loadingParams);
+
+    List<ClipLayerVo> clipNumAndLayerNum();
 }

+ 44 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/stackingAndLoadingVehicles/service/impl/StackingAndLoadingVehiclesServiceImpl.java

@@ -43,6 +43,7 @@ import org.jeecg.modules.billet.stackingAndLoadingVehicles.mapper.StackingAndLoa
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.service.IStackingAndLoadingVehiclesService;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.service.IStackingDownLogService;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.service.IStackingUpLogService;
+import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.ClipLayerVo;
 import org.jeecg.modules.billet.stackingAndLoadingVehicles.vo.LoadingParams;
 import org.jeecg.modules.billet.storageBill.entity.ShiftEnum;
 import org.jeecg.modules.billet.storageBill.entity.ShiftGroupEnum;
@@ -922,6 +923,49 @@ public class StackingAndLoadingVehiclesServiceImpl extends ServiceImpl<StackingA
         return "钢坯叛废成功!";
     }
 
+    @Override
+    public List<ClipLayerVo> clipNumAndLayerNum() {
+
+        LambdaQueryWrapper<StackingAndLoadingVehicles> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+
+        List<StackingAndLoadingVehicles> stackingAndLoadingVehicles = stackingAndLoadingVehiclesMapper.selectList(lambdaQueryWrapper);
+
+        // 按 stackAddr 分组处理
+        List<ClipLayerVo> result = stackingAndLoadingVehicles.stream()
+                .collect(Collectors.groupingBy(StackingAndLoadingVehicles::getStackAddr)) // 按 stackAddr 分组
+                .entrySet().stream()
+                .map(entry -> {
+                    String stackAddr = entry.getKey();
+                    List<StackingAndLoadingVehicles> groupList = entry.getValue();
+
+                    // 过滤 heatNo 不为空或 null 的数据,计算条数
+                    long clipNum = groupList.stream()
+                            .filter(item -> item.getHeatNo() != null && !item.getHeatNo().isEmpty())
+                            .count();
+
+                    // 过滤 heatNo 不为空或 null 的数据,找出 layer 的最大值
+                    int maxLayerNum = groupList.stream()
+                            .filter(item -> item.getHeatNo() != null && !item.getHeatNo().isEmpty())
+                            .map(StackingAndLoadingVehicles::getLayer) // 获取 layer 字符串
+                            .filter(Objects::nonNull) // 过滤 null
+                            .map(layer -> {
+                                try {
+                                    return Integer.parseInt(layer); // 转换成 Integer
+                                } catch (NumberFormatException e) {
+                                    return 0; // 解析失败默认 0
+                                }
+                            })
+                            .max(Integer::compareTo) // 找出最大值
+                            .orElse(0); // 如果没有值,则默认 0
+
+                    // 组装 ClipLayerVo 对象
+                    return new ClipLayerVo(stackAddr, (int) clipNum, maxLayerNum);
+                })
+                .collect(Collectors.toList());
+
+        return result;
+    }
+
     /**
      *  初始化堆垛公共容器
      * @param stackingAndLoadingVehiclesList

+ 28 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/stackingAndLoadingVehicles/vo/ClipLayerVo.java

@@ -0,0 +1,28 @@
+package org.jeecg.modules.billet.stackingAndLoadingVehicles.vo;
+
+import lombok.Data;
+
+@Data
+public class ClipLayerVo {
+
+    /**
+     * 垛位
+     */
+    private String stackAddr;
+
+    /**
+     * 总夹数
+     */
+    private Integer clipNum;
+
+    /**
+     * 总层数
+     */
+    private Integer layerNum;
+
+    public ClipLayerVo(String stackAddr, Integer clipNum, Integer layerNum) {
+        this.stackAddr = stackAddr;
+        this.clipNum = clipNum;
+        this.layerNum = layerNum;
+    }
+}

+ 109 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/controller/StorageBillController.java

@@ -186,6 +186,13 @@ public class StorageBillController extends JeecgController<StorageBill, IStorage
 		return Result.OK(pageList);
 	}
 
+	@ApiOperation(value="钢坯热装明细信息-分页列表查询", notes="钢坯热装明细信息-分页列表查询")
+	@GetMapping(value = "/hotChargingDetails")
+	public Result<BilletHotsendDetails> queryPageHotDetailsList(StorageBill storageBill) {
+		BilletHotsendDetails pageList = storageBillService.findBilletHotChargingDetails(storageBill);
+		return Result.OK(pageList);
+	}
+
 	@ApiOperation(value="钢坯热送单-班统计查询", notes="钢坯热送单-班统计查询")
 	@GetMapping(value = "/onduty/statistics")
 	public Result<OnDutyStatistics> queryOndutyStatistics(@RequestParam(name="ccmNo") String ccmNo) {
@@ -479,6 +486,108 @@ public class StorageBillController extends JeecgController<StorageBill, IStorage
 		return Result.OK((String) jsonObject.get("success"));
 	}
 
+    @ApiOperation(value = "钢坯热装单-班统计查询", notes = "钢坯热装单-班统计查询")
+    @GetMapping(value = "/hotCharging/statistics")
+    public Result<OnDutyStatistics> queryHotChargingStatistics(@RequestParam(name = "ccmNo") String ccmNo) {
+        // 获取当前班组班次信息
+        OnDutyStatistics onDutyStatistics = storageBillService.queryHotChargingStatistics(ccmNo);
+        return Result.OK(onDutyStatistics);
+    }
+
+
+    @ApiOperation(value = "钢坯热装实绩-分页列表查询", notes = "钢坯热装实绩-分页列表查询")
+    @GetMapping(value = "/listHotChargingSJ")
+    public Result<IPage<StorageBill>> queryHotChargingPageSJList(StorageBill storageBill,
+                                                                 @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+                                                                 @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
+                                                                 HttpServletRequest req) {
+        QueryWrapper<StorageBill> queryWrapper = QueryGenerator.initQueryWrapper(storageBill, req.getParameterMap());
+        queryWrapper.notIn("license_plate", Arrays.asList("堆垛辊道", "辊道"));
+        queryWrapper.isNotNull("heat_no");
+        // 添加分组条件
+        queryWrapper.groupBy("heat_no");
+        // 如果需要统计每组的 amount_total 总和,可以添加聚合函数
+        queryWrapper.select("GROUP_CONCAT( DISTINCT id ) AS id", "GROUP_CONCAT( DISTINCT ccm_no ) AS ccmNo",
+                "GROUP_CONCAT( DISTINCT shift_group ) AS shiftGroup", "GROUP_CONCAT( DISTINCT shift ) AS shift",
+                "heat_no", "GROUP_CONCAT( DISTINCT steel ) AS steel", "GROUP_CONCAT( DISTINCT spec ) AS spec",
+                "GROUP_CONCAT( DISTINCT size ) AS size", "GROUP_CONCAT( DISTINCT license_plate ) AS licensePlate",
+                "GROUP_CONCAT( DISTINCT btype ) AS btype", "GROUP_CONCAT( DISTINCT destination ) AS destination",
+                "GROUP_CONCAT( DISTINCT type_config_id ) AS typeConfigId", "GROUP_CONCAT( DISTINCT unique_code ) AS uniqueCode",
+                "SUM(amount_total) as amountTotal", "GROUP_CONCAT( DISTINCT assembly_number ) AS assemblyNumber", "MAX(create_time) as createTime");
+        Page<StorageBill> page = new Page<>(pageNo, pageSize);
+        IPage<StorageBill> pageList = storageBillService.page(page, queryWrapper);
+
+        for (StorageBill bill : pageList.getRecords()) {
+            List<String> storageBillIds = Arrays.stream(bill.getId().split(",")).collect(Collectors.toList());
+            String totalBlankOutputStr = "";
+            // 根据装运单ID查询对应的明细,统计总的出坯量
+            if ("棒二".equals(bill.getDestination()) && oConvertUtils.listIsNotEmpty(storageBillIds)) {
+                LambdaQueryWrapper<RollClubOneDetails> queryWrapper1 = new LambdaQueryWrapper<>();
+                queryWrapper1.eq(RollClubOneDetails::getHeatNo, bill.getHeatNo());
+                queryWrapper1.in(RollClubOneDetails::getStorageBillId, storageBillIds);
+                List<RollClubOneDetails> rollClubOneDetailsList = rollClubOneDetailsService.list(queryWrapper1);
+                // 使用 Stream API 统计 blankOutput 字段的总和
+                OptionalDouble totalBlankOutputOptional = rollClubOneDetailsList != null ?
+                        OptionalDouble.of(rollClubOneDetailsList.stream()
+                                .mapToDouble(details -> details.getBlankOutput() != null ? details.getBlankOutput() : 0)
+                                .sum()) : OptionalDouble.empty();
+                // 将总和转换为字符串,保留两位小时,四舍五入原则
+                if (totalBlankOutputOptional.isPresent()) {
+                    // 使用 BigDecimal 进行精确计算和格式化
+                    BigDecimal total = BigDecimal.valueOf(totalBlankOutputOptional.getAsDouble());
+                    // 保留两位小数
+                    total = total.setScale(3, BigDecimal.ROUND_HALF_UP);
+                    totalBlankOutputStr = total.toString();
+                } else {
+                    totalBlankOutputStr = "0";
+                }
+
+            } else if ("棒三".equals(bill.getDestination()) && oConvertUtils.listIsNotEmpty(storageBillIds)) {
+                LambdaQueryWrapper<RollHeightDetails> queryWrapper2 = new LambdaQueryWrapper<>();
+                queryWrapper2.eq(RollHeightDetails::getHeatNo, bill.getHeatNo());
+                queryWrapper2.in(RollHeightDetails::getStorageBillId, storageBillIds);
+                List<RollHeightDetails> rollHeightDetailsList = rollHeightDetailsService.list(queryWrapper2);
+                // 使用 Stream API 统计 blankOutput 字段的总和
+                OptionalDouble totalBlankOutputOptional = rollHeightDetailsList != null ?
+                        OptionalDouble.of(rollHeightDetailsList.stream()
+                                .mapToDouble(details -> details.getBlankOutput() != null ? details.getBlankOutput() : 0)
+                                .sum()) : OptionalDouble.empty();
+                // 将总和转换为字符串,保留两位小时,四舍五入原则
+                if (totalBlankOutputOptional.isPresent()) {
+                    // 使用 BigDecimal 进行精确计算和格式化
+                    BigDecimal total = BigDecimal.valueOf(totalBlankOutputOptional.getAsDouble());
+                    // 保留两位小数
+                    total = total.setScale(3, BigDecimal.ROUND_HALF_UP);
+                    totalBlankOutputStr = total.toString();
+                } else {
+                    totalBlankOutputStr = "0";
+                }
+            } else if ("上若".equals(bill.getDestination()) && oConvertUtils.listIsNotEmpty(storageBillIds)) {
+                LambdaQueryWrapper<RollHeightDetails> queryWrapper2 = new LambdaQueryWrapper<>();
+                queryWrapper2.eq(RollHeightDetails::getHeatNo, bill.getHeatNo());
+                queryWrapper2.in(RollHeightDetails::getStorageBillId, storageBillIds);
+                List<RollHeightDetails> rollHeightDetailsList = rollHeightDetailsService.list(queryWrapper2);
+                // 使用 Stream API 统计 blankOutput 字段的总和
+                OptionalDouble totalBlankOutputOptional = rollHeightDetailsList != null ?
+                        OptionalDouble.of(rollHeightDetailsList.stream()
+                                .mapToDouble(details -> details.getBlankOutput() != null ? details.getBlankOutput() : 0)
+                                .sum()) : OptionalDouble.empty();
+                // 将总和转换为字符串,保留两位小时,四舍五入原则
+                if (totalBlankOutputOptional.isPresent()) {
+                    // 使用 BigDecimal 进行精确计算和格式化
+                    BigDecimal total = BigDecimal.valueOf(totalBlankOutputOptional.getAsDouble());
+                    // 保留两位小数
+                    total = total.setScale(3, BigDecimal.ROUND_HALF_UP);
+                    totalBlankOutputStr = total.toString();
+                } else {
+                    totalBlankOutputStr = "0";
+                }
+            }
+            bill.setRemarks(totalBlankOutputStr);
+        }
+        return Result.OK(pageList);
+    }
+
 	@ApiOperation(value="当班信息汇总-班次实绩", notes="当班信息汇总-班次实绩")
 	@GetMapping(value = "/queryOnDutyInfo")
 	public Result<OnDutyInfo> queryOnDutyInfoHandle(@RequestParam(name="ccmNo") String ccmNo) {

+ 4 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/service/IStorageBillService.java

@@ -20,6 +20,8 @@ public interface IStorageBillService extends IService<StorageBill> {
 
     BilletHotsendDetails findBilletHotsendDetails(StorageBill storageBill);
 
+    BilletHotsendDetails findBilletHotChargingDetails(StorageBill storageBill);
+
     List<StorageBill> findCar(String ccmNo, String destination);
 
     JSONObject storageBillSave(StorageBill storageBill);
@@ -34,6 +36,8 @@ public interface IStorageBillService extends IService<StorageBill> {
 
     OnDutyStatistics queryOndutyStatistics(String ccmNo);
 
+    OnDutyStatistics queryHotChargingStatistics(String ccmNo);
+
     JSONObject ondutyStatisticsExport(String ccmNo, String ondutyDate);
 
     OnDutyInfo queryOnDutyInfoHandle(String ccmNo);

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

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Maps;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
@@ -238,6 +239,61 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         return result;
     }
 
+    @Override
+    public BilletHotsendDetails findBilletHotChargingDetails(StorageBill storageBill) {
+        BilletHotsendDetails result = new BilletHotsendDetails();
+
+        List<String> idList = Arrays.stream(storageBill.getId().split(","))
+                .collect(Collectors.toList());
+        if (oConvertUtils.listIsEmpty(idList)){
+            log.info("{}{}", "装运单ID为空,装运明细查询失败", JSON.toJSON(storageBill));
+            return null;
+        }
+
+        List<String> typeConfigIds = Arrays.stream(storageBill.getTypeConfigId().split(","))
+                .collect(Collectors.toList());
+        if (oConvertUtils.listIsEmpty(typeConfigIds)){
+            log.info("{}{}", "钢坯配置类型ID为空,装运明细查询失败", JSON.toJSON(storageBill));
+            return null;
+        }
+
+        //根据部门orgCode查询部门,需要将职位id进行传递
+        List<BilletHotsendTypeConfig> billetHotsendTypeConfigs = billetHotsendTypeConfigService.listByIds(typeConfigIds);
+        if (CollectionUtils.isEmpty(billetHotsendTypeConfigs)){
+            log.info("{}{}", "钢坯类型配置信息查询为空,装运明细查询失败", JSON.toJSON(storageBill));
+            return null;
+        }
+        for (BilletHotsendTypeConfig billetHotsendTypeConfig : billetHotsendTypeConfigs) {
+            if ("billet_auto_tmp".equals(billetHotsendTypeConfig.getBelongTable())){
+                List<BilletAutoTmp> billetAutoTmpList = billetAutoTmpService.list(new LambdaQueryWrapper<BilletAutoTmp>().in(BilletAutoTmp::getStorageBillId, idList));
+                if (oConvertUtils.listIsNotEmpty(billetAutoTmpList)){
+                    List<RollClubTwoDetails> rollClubTwoDetailsList = new ArrayList<>();
+                    billetAutoTmpList.forEach(x ->{
+                        RollClubTwoDetails rollClubTwoDetails = new RollClubTwoDetails();
+                        BeanUtils.copyProperties(x, rollClubTwoDetails);
+                        rollClubTwoDetailsList.add(rollClubTwoDetails);
+                    });
+                    result.setRollClubTwoDetailsList(rollClubTwoDetailsList);
+                    return result;
+                }
+                return result;
+            }
+        }
+
+        List<RollClubOneDetails> rollClubOneDetailsList = rollClubOneDetailsService.list(new LambdaQueryWrapper<RollClubOneDetails>().in(RollClubOneDetails::getStorageBillId, idList));
+        result.setRollClubOneDetailsList(rollClubOneDetailsList);
+        List<RollClubTwoDetails> rollClubTwoDetailsList = rollClubTwoDetailsService.list(new LambdaQueryWrapper<RollClubTwoDetails>().in(RollClubTwoDetails::getStorageBillId, idList));
+        result.setRollClubTwoDetailsList(rollClubTwoDetailsList);
+        List<RollClubThreeDetails> rollClubThreeDetailsList = rollClubThreeDetailsService.list(new LambdaQueryWrapper<RollClubThreeDetails>().in(RollClubThreeDetails::getStorageBillId, idList));
+        result.setRollClubThreeDetailsList(rollClubThreeDetailsList);
+        List<RollOutShippDetails> rollOutShippDetailsList = rollOutShippDetailsService.list(new LambdaQueryWrapper<RollOutShippDetails>().in(RollOutShippDetails::getStorageBillId, idList));
+        result.setRollOutShippDetailsList(rollOutShippDetailsList);
+        List<RollHeightDetails> rollHeightDetails = rollHeightDetailsService.list(new LambdaQueryWrapper<RollHeightDetails>().in(RollHeightDetails::getStorageBillId, idList));
+        result.setRollHeightDetails(rollHeightDetails);
+
+        return result;
+    }
+
     @Override
     public List<StorageBill> findCar(String ccmNo, String destination) {
         return storageBillMapper.findCar(ccmNo, destination);
@@ -683,6 +739,156 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         return onDutyStatistics;
     }
 
+    @Override
+    public OnDutyStatistics queryHotChargingStatistics(String ccmNo) {
+        OnDutyStatistics onDutyStatistics = new OnDutyStatistics();
+
+        // 获取当前班组班次信息
+        String keyShiftGroup = String.format("class:shift:group:%s", ccmNo);
+        String keyShift = String.format("class:shift:%s", ccmNo);
+        String shiftGroup = oConvertUtils.getString(redisTemplate.opsForValue().get(keyShiftGroup));
+        String shift = oConvertUtils.getString(redisTemplate.opsForValue().get(keyShift));
+        if (oConvertUtils.isEmpty(shiftGroup) || oConvertUtils.isEmpty(shift)){
+            log.info("{}{}", "B端热装单统计当班热装查询失败!", "未查询到当班信息!");
+            return onDutyStatistics;
+        }
+        // 根据铸机号、班组班别查询对应的热送单信息
+        BilletHotsendChangeShift billetHotsendChangeShiftList = billetHotsendChangeShiftService.getOne(new LambdaQueryWrapper<BilletHotsendChangeShift>()
+                .eq(BilletHotsendChangeShift::getCcmNo, ccmNo).eq(BilletHotsendChangeShift::getShiftGroup, shiftGroup).eq(BilletHotsendChangeShift::getShift, shift)
+                .orderByDesc(BilletHotsendChangeShift::getCreateTime).last("limit 1"));
+        // 查询热装信息(棒二明细、棒三明细、上若明细)统计热装总支数、热装总重量<出坯量>
+        List<DestinationStatisticsDetails> statisticsDetailsList1 = new ArrayList<>();
+        List<DestinationStatisticsDetails> statisticsDetailsList2 = new ArrayList<>();
+        List<DestinationStatisticsDetails> statisticsDetailsList3 = new ArrayList<>();
+        // 统计总数
+        int totalNumsAll = 0;
+        BigDecimal totalBlankOutputsAll = BigDecimal.ZERO;
+        LambdaQueryWrapper<RollClubTwoDetails> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(RollClubTwoDetails::getCcmNo, ccmNo);
+        queryWrapper.eq(RollClubTwoDetails::getShiftGroup, shiftGroup);
+        queryWrapper.eq(RollClubTwoDetails::getShift, shift);
+        // 添加大于 billetHotsendChangeShiftList 的 createTime 条件
+        if (billetHotsendChangeShiftList != null && billetHotsendChangeShiftList.getCreateTime() != null) {
+            queryWrapper.gt(RollClubTwoDetails::getCreateTime, billetHotsendChangeShiftList.getCreateTime());
+        }
+        List<RollClubTwoDetails> rollClubTwoDetailsList = rollClubTwoDetailsService.list(queryWrapper);
+        if (oConvertUtils.listIsNotEmpty(rollClubTwoDetailsList)){
+            statisticsDetailsList1 = rollClubTwoDetailsList.stream()
+                    .collect(Collectors.groupingBy(RollClubTwoDetails::getSize, Collectors.toList()))
+                    .entrySet().stream()
+                    .map(entry -> {
+                        String size = entry.getKey();
+                        List<RollClubTwoDetails> group = entry.getValue();
+                        Integer nums = group.size();
+                        Double totalBlankOutput = group.stream().mapToDouble(RollClubTwoDetails::getBlankOutput).sum();
+                        BigDecimal bd = BigDecimal.valueOf(totalBlankOutput).setScale(4, BigDecimal.ROUND_HALF_UP);
+                        double finalBlankOutput = bd.doubleValue();
+                        String ccmNos = group.isEmpty() ? null : group.get(0).getCcmNo();
+                        return new DestinationStatisticsDetails(size, nums, finalBlankOutput, ccmNos);
+                    }).collect(Collectors.toList());
+            int totalNums = statisticsDetailsList1.stream()
+                    .mapToInt(DestinationStatisticsDetails::getNums)
+                    .sum();
+
+            double totalBlankOutputs = rollClubTwoDetailsList.stream().mapToDouble(RollClubTwoDetails::getBlankOutput).sum();
+            BigDecimal bd = BigDecimal.valueOf(totalBlankOutputs).setScale(4, BigDecimal.ROUND_HALF_UP);
+            totalNumsAll += totalNums;
+            totalBlankOutputsAll = totalBlankOutputsAll.add(bd);
+        }
+
+        LambdaQueryWrapper<RollClubThreeDetails> queryWrapper1 = new LambdaQueryWrapper<>();
+        queryWrapper1.eq(RollClubThreeDetails::getCcmNo, ccmNo);
+        queryWrapper1.eq(RollClubThreeDetails::getShiftGroup, shiftGroup);
+        queryWrapper1.eq(RollClubThreeDetails::getShift, shift);
+        // 添加大于 billetHotsendChangeShiftList 的 createTime 条件
+        if (billetHotsendChangeShiftList != null && billetHotsendChangeShiftList.getCreateTime() != null) {
+            queryWrapper1.gt(RollClubThreeDetails::getCreateTime, billetHotsendChangeShiftList.getCreateTime());
+        }
+        List<RollClubThreeDetails> rollClubThreeDetailsList = rollClubThreeDetailsService.list(queryWrapper1);
+        if (oConvertUtils.listIsNotEmpty(rollClubThreeDetailsList)){
+            statisticsDetailsList2 = rollClubThreeDetailsList.stream()
+                    .collect(Collectors.groupingBy(RollClubThreeDetails::getSize, Collectors.toList()))
+                    .entrySet().stream()
+                    .map(entry -> {
+                        String size = entry.getKey();
+                        List<RollClubThreeDetails> group = entry.getValue();
+                        Integer nums = group.size();
+                        Double totalBlankOutput = group.stream().mapToDouble(RollClubThreeDetails::getBlankOutput).sum();
+                        BigDecimal bd = BigDecimal.valueOf(totalBlankOutput).setScale(4, BigDecimal.ROUND_HALF_UP);
+                        double finalBlankOutput = bd.doubleValue();
+                        String ccmNos = group.isEmpty() ? null : group.get(0).getCcmNo();
+                        return new DestinationStatisticsDetails(size, nums, finalBlankOutput, ccmNos);
+                    }).collect(Collectors.toList());
+            int totalNums = statisticsDetailsList2.stream()
+                    .mapToInt(DestinationStatisticsDetails::getNums)
+                    .sum();
+
+            double totalBlankOutputs = rollClubThreeDetailsList.stream().mapToDouble(RollClubThreeDetails::getBlankOutput).sum();
+            BigDecimal bd = BigDecimal.valueOf(totalBlankOutputs).setScale(4, BigDecimal.ROUND_HALF_UP);
+
+            totalNumsAll += totalNums;
+            totalBlankOutputsAll = totalBlankOutputsAll.add(bd);
+        }
+
+        LambdaQueryWrapper<RollOutShippDetails> queryWrapper2 = new LambdaQueryWrapper<>();
+        queryWrapper2.eq(RollOutShippDetails::getCcmNo, ccmNo);
+        queryWrapper2.eq(RollOutShippDetails::getShiftGroup, shiftGroup);
+        queryWrapper2.eq(RollOutShippDetails::getShift, shift);
+        // 添加大于 billetHotsendChangeShiftList 的 createTime 条件
+        if (billetHotsendChangeShiftList != null && billetHotsendChangeShiftList.getCreateTime() != null) {
+            queryWrapper2.gt(RollOutShippDetails::getCreateTime, billetHotsendChangeShiftList.getCreateTime());
+        }
+        List<RollOutShippDetails> rollOutShippDetailsList = rollOutShippDetailsService.list(queryWrapper2);
+        if (oConvertUtils.listIsNotEmpty(rollOutShippDetailsList)){
+            statisticsDetailsList3 = rollOutShippDetailsList.stream()
+                    .collect(Collectors.groupingBy(RollOutShippDetails::getSize, Collectors.toList()))
+                    .entrySet().stream()
+                    .map(entry -> {
+                        String size = entry.getKey();
+                        List<RollOutShippDetails> group = entry.getValue();
+                        Integer nums = group.size();
+                        Double totalBlankOutput = group.stream().mapToDouble(RollOutShippDetails::getBlankOutput).sum();
+                        BigDecimal bd = BigDecimal.valueOf(totalBlankOutput).setScale(4, BigDecimal.ROUND_HALF_UP);
+                        double finalBlankOutput = bd.doubleValue();
+                        String ccmNos = group.isEmpty() ? null : group.get(0).getCcmNo();
+                        return new DestinationStatisticsDetails(size, nums, finalBlankOutput, ccmNos);
+                    }).collect(Collectors.toList());
+            int totalNums = statisticsDetailsList3.stream()
+                    .mapToInt(DestinationStatisticsDetails::getNums)
+                    .sum();
+
+            double totalBlankOutputs = rollOutShippDetailsList.stream().mapToDouble(RollOutShippDetails::getBlankOutput).sum();
+            BigDecimal bd = BigDecimal.valueOf(totalBlankOutputs).setScale(4, BigDecimal.ROUND_HALF_UP);
+
+            totalNumsAll += totalNums;
+            totalBlankOutputsAll = totalBlankOutputsAll.add(bd);
+        }
+
+        // 合并三个列表并根据 size 分组统计
+        List<DestinationStatisticsDetails> mergedList = Stream.of(statisticsDetailsList1, statisticsDetailsList2, statisticsDetailsList3)
+                .flatMap(Collection::stream) // 将所有列表合并成一个流
+                .collect(Collectors.groupingBy(DestinationStatisticsDetails::getSize))
+                .entrySet().stream()
+                .map(entry -> {
+                    String size = entry.getKey();
+                    List<DestinationStatisticsDetails> group = entry.getValue();
+                    int totalNums = group.stream().mapToInt(DestinationStatisticsDetails::getNums).sum();
+                    double totalBlankOutput = group.stream().mapToDouble(DestinationStatisticsDetails::getBlankOutput).sum();
+                    BigDecimal bd = BigDecimal.valueOf(totalBlankOutput).setScale(4, BigDecimal.ROUND_HALF_UP);
+                    double finalBlankOutput = bd.doubleValue();
+                    String ccmNoForGroup = group.isEmpty() ? null : group.get(0).getCcmNo();
+                    return new DestinationStatisticsDetails(size, totalNums, finalBlankOutput, ccmNoForGroup);
+                }).collect(Collectors.toList());
+
+        log.info("{}{}", "钢坯热装单班统计查询结果:", JSON.toJSON(mergedList));
+        onDutyStatistics.setCounts(totalNumsAll);
+        onDutyStatistics.setBlankOutputs(totalBlankOutputsAll);
+        onDutyStatistics.setStatisticsDetailsList(mergedList);
+        onDutyStatistics.setShiftGroup(ShiftGroupEnum.fromCode(shiftGroup).name());
+        onDutyStatistics.setShift(ShiftEnum.fromCode(shift).name());
+        return onDutyStatistics;
+    }
+
     @Override
     public JSONObject ondutyStatisticsExport(String ccmNo, String ondutyDate) {
         JSONObject result = new JSONObject();