Browse Source

确认原始记录时,同步去班次实绩更新统计信息

lingpeng.li 5 days ago
parent
commit
424dbecd29

+ 31 - 18
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetHotsendChangeShift/controller/BilletHotsendChangeShiftController.java

@@ -325,6 +325,10 @@ public class BilletHotsendChangeShiftController extends JeecgController<BilletHo
 			}
 		}
 
+		// 自动执行交班任务,如果 changeShiftId 为null,则默认处理交班时间不为空的最近一条记录
+		String changeShiftId = null;
+		billetHotsendChangeShiftService.executeShiftTask(billetHotsendChangeShiftInfo.getCcmNo(),changeShiftId);
+
 		return Result.OK("操作成功!");
 	}
 	
@@ -571,6 +575,15 @@ public class BilletHotsendChangeShiftController extends JeecgController<BilletHo
 		performShiftChange(null);
 		return Result.OK(null);
 	}
+
+	@ApiOperation(value="手动更新班次实绩", notes="手动更新班次实绩")
+	@GetMapping(value = "/updateShift")
+	public Result<String> updateShift(@RequestParam(name="ccmNo", required = false) String ccmNo,
+									  @RequestParam(name="changeShiftId", required = false) String changeShiftId) {
+
+		billetHotsendChangeShiftService.executeShiftTask(ccmNo,changeShiftId);
+		return Result.OK("更新成功");
+	}
 	/**
 	 * 自动化交班
 	 * @author: jeecg-boot
@@ -667,21 +680,21 @@ public class BilletHotsendChangeShiftController extends JeecgController<BilletHo
 		// 每天	00:00:05 执行的任务逻辑
 
 		// 5号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask11();
+//		executeShiftTask11();
 		// 6号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask22();
+//		executeShiftTask22();
 		// 5号机 班次吊运明细维护到交班信息
 		executeShiftTask33();
 		// 6号机 班次吊运明细维护到交班信息
 		executeShiftTask44();
 		// 5号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask55();
+//		executeShiftTask55();
 		// 6号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask66();
+//		executeShiftTask66();
 		// 5号机 轧钢棒一维护到交班信息
-		executeShiftTask77();
+//		executeShiftTask77();
 		// 6号机 轧钢高线维护到交班信息
-		executeShiftTask88();
+//		executeShiftTask88();
 	}
 
 	@Scheduled(cron = "0 15 8 * * ?")
@@ -689,21 +702,21 @@ public class BilletHotsendChangeShiftController extends JeecgController<BilletHo
 		// 08:05:00 执行的任务逻辑
 
 		// 5号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask11();
+//		executeShiftTask11();
 		// 6号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask22();
+//		executeShiftTask22();
 		// 5号机 班次吊运明细维护到交班信息
 		executeShiftTask33();
 		// 6号机 班次吊运明细维护到交班信息
 		executeShiftTask44();
 		// 5号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask55();
+//		executeShiftTask55();
 		// 6号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask66();
+//		executeShiftTask66();
 		// 5号机 轧钢棒一维护到交班信息
-		executeShiftTask77();
+//		executeShiftTask77();
 		// 6号机 轧钢高线维护到交班信息
-		executeShiftTask88();
+//		executeShiftTask88();
 	}
 
 	@Scheduled(cron = "0 15 16 * * ?")
@@ -711,21 +724,21 @@ public class BilletHotsendChangeShiftController extends JeecgController<BilletHo
 		// 16:00:05 执行的任务逻辑
 
 		// 5号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask11();
+//		executeShiftTask11();
 		// 6号机、统计热送、热装、起跺数量维护到交班信息
-		executeShiftTask22();
+//		executeShiftTask22();
 		// 5号机 班次吊运明细维护到交班信息
 		executeShiftTask33();
 		// 6号机 班次吊运明细维护到交班信息
 		executeShiftTask44();
 		// 5号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask55();
+//		executeShiftTask55();
 		// 6号机 统计班次吊运明细、轧钢棒二、轧钢棒三、轧钢上若维护到交班信息
-		executeShiftTask66();
+//		executeShiftTask66();
 		// 5号机 轧钢棒一维护到交班信息
-		executeShiftTask77();
+//		executeShiftTask77();
 		// 6号机 轧钢高线维护到交班信息
-		executeShiftTask88();
+//		executeShiftTask88();
 	}
 
 	/**

+ 2 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetHotsendChangeShift/service/IBilletHotsendChangeShiftService.java

@@ -19,4 +19,6 @@ public interface IBilletHotsendChangeShiftService extends IService<BilletHotsend
     void fiveChangeShiftHandle(BilletHotsendChangeShift billetHotsendChangeShiftVo);
 
     void sixChangeShiftHandle(BilletHotsendChangeShift billetHotsendChangeShiftVo);
+
+    void executeShiftTask(String ccmNo,String changeShiftId);
 }

+ 533 - 9
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetHotsendChangeShift/service/impl/BilletHotsendChangeShiftServiceImpl.java

@@ -5,7 +5,11 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
@@ -14,24 +18,35 @@ import org.jeecg.modules.billet.billetHotsendChangeShift.entity.BilletHotsendCha
 import org.jeecg.modules.billet.billetHotsendChangeShift.mapper.BilletHotsendChangeShiftMapper;
 import org.jeecg.modules.billet.billetHotsendChangeShift.service.IBilletHotsendChangeShiftService;
 import org.jeecg.modules.billet.billetHotsendChangeShift.util.ScheduleUtils;
+import org.jeecg.modules.billet.billetOriginalProductRecord.entity.BilletOriginalProductRecord;
+import org.jeecg.modules.billet.billetOriginalProductRecord.mapper.BilletOriginalProductRecordMapper;
+import org.jeecg.modules.billet.billetOriginalProductRecord.service.IBilletOriginalProductRecordService;
 import org.jeecg.modules.billet.operateLog.service.IOperateLogService;
+import org.jeecg.modules.billet.rollHeight.entity.DestinationStatisticsDetails;
 import org.jeecg.modules.billet.shiftConfiguration.entity.ShiftConfiguration;
 import org.jeecg.modules.billet.shiftConfiguration.service.IShiftConfigurationService;
 import org.jeecg.modules.billet.storageBill.entity.ShiftEnum;
+import org.jeecg.modules.billet.storageBill.entity.StorageBill;
+import org.jeecg.modules.billet.storageBill.entity.StorageBillPrint;
+import org.jeecg.modules.billet.storageBill.mapper.StorageBillMapper;
+import org.jeecg.modules.billet.storageBill.mapper.StorageBillPrintMapper;
 import org.jeecg.modules.connConfig.mapper.ConfigMqttMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @Description: 钢坯交班记录
  * @Author: jeecg-boot
- * @Date:   2024-11-19
+ * @Date: 2024-11-19
  * @Version: V1.0
  */
 @Slf4j
@@ -54,6 +69,12 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
     @Autowired
     private ConfigMqttMapper configMqttMapper;
 
+    @Autowired
+    private BilletOriginalProductRecordMapper billetOriginalProductRecordMapper;
+
+    @Autowired
+    private StorageBillPrintMapper storageBillPrintMapper;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public JSONObject billetHotsendChangeShiftHandle(BilletHotsendChangeShift billetHotsendChangeShiftVo) {
@@ -88,10 +109,10 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
         String currentShiftGroup = oConvertUtils.getString(redisTemplate.opsForValue().get(keyShiftGroup));
         String currentShift = oConvertUtils.getString(redisTemplate.opsForValue().get(keyShift));
 
-        log.info(DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()) + " 交班当前班次信息值:" + currentShift+ ","+ currentShiftGroup);
+        log.info(DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()) + " 交班当前班次信息值:" + currentShift + "," + currentShiftGroup);
 
         // 班别名(白中夜)
-        String nextShiftName  = "";
+        String nextShiftName = "";
         // 验证23:00 到01:00 之间
         if (ScheduleUtils.isBetweenTime(new Date(), "07:40", "08:30")) {
             nextShiftName = "白";
@@ -99,9 +120,9 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
             nextShiftName = "中";
         } else if (ScheduleUtils.isBetweenTime(new Date(), "23:40", "00:30")) {
             nextShiftName = "夜";
-        }else {
+        } else {
             log.info("{}{}", ccmNo + "未在交班范围内,交班失败!,", DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
-            result.put("fail","未在交班时间范围内,交班操作失败!");
+            result.put("fail", "未在交班时间范围内,交班操作失败!");
             return result;
         }
         // 班组值
@@ -110,7 +131,7 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
         String finalNextShiftVal = ShiftEnum.getCodeByName(nextShiftName + "班");
 
         // 设置键并设置过期时间
-        redisTemplate.opsForValue().set(autoChangeShiftLimitKey,"executed", EXPIRE_TIME, EXPIRE_TIME_UNIT);
+        redisTemplate.opsForValue().set(autoChangeShiftLimitKey, "executed", EXPIRE_TIME, EXPIRE_TIME_UNIT);
 
         try {
             // 先更新班组班别缓存
@@ -166,7 +187,7 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
                     .orderByDesc(ShiftConfiguration::getCreateTime)
                     .last("limit 1");
             ShiftConfiguration shiftConfiguration = shiftConfigurationService.getOne(queryWrapper);
-            if (shiftConfiguration != null){
+            if (shiftConfiguration != null) {
                 // 生出储运配置信息
                 ShiftConfiguration newShiftConfiguration = new ShiftConfiguration();
                 newShiftConfiguration.setId(String.valueOf(IdWorker.getId()));
@@ -200,7 +221,7 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
         // 缓存交班索引ID
         String nextshiftIdKey = String.format("class:nextshift:Id:%s", "6");
         List<String> ccmNoList = Arrays.asList("6");
-        for (String ccmNo : ccmNoList){
+        for (String ccmNo : ccmNoList) {
             String keyShiftGroup = String.format("class:shift:group:%s", ccmNo);
             String keyShift = String.format("class:shift:%s", ccmNo);
             // 保存旧的缓存值,用于异常回滚
@@ -278,7 +299,7 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
                         .orderByDesc(ShiftConfiguration::getCreateTime)
                         .last("limit 1");
                 ShiftConfiguration shiftConfiguration = shiftConfigurationService.getOne(queryWrapper);
-                if (shiftConfiguration != null){
+                if (shiftConfiguration != null) {
                     // 生出储运配置信息
                     ShiftConfiguration newShiftConfiguration = new ShiftConfiguration();
                     newShiftConfiguration.setId(String.valueOf(IdWorker.getId()));
@@ -340,8 +361,511 @@ public class BilletHotsendChangeShiftServiceImpl extends ServiceImpl<BilletHotse
         }
     }
 
+    @Override
+    public void executeShiftTask(String ccmNo,String changeShiftId) {
+
+        BilletHotsendChangeShift billetHotsendChangeShift;
+        LambdaQueryWrapper<BilletHotsendChangeShift> queryWrapper = new LambdaQueryWrapper<>();
+
+        if (oConvertUtils.isEmpty(changeShiftId)) {
+
+            queryWrapper.eq(BilletHotsendChangeShift::getCcmNo, ccmNo)
+                    .isNotNull(BilletHotsendChangeShift::getChangeShiftTime)
+                    .orderByDesc(BilletHotsendChangeShift::getChangeShiftTime)
+                    .last("limit 1");
+
+            billetHotsendChangeShift = this.getOne(queryWrapper);
+            if (billetHotsendChangeShift == null) {
+                log.info("{}{}", "当班热送热装数量维护到交班信息失败,交班记录为空!", new Date());
+                return;
+            }
+        } else {
+
+            queryWrapper.eq(BilletHotsendChangeShift::getId, changeShiftId)
+                    .eq(BilletHotsendChangeShift::getCcmNo, ccmNo);
+
+            billetHotsendChangeShift = this.getOne(queryWrapper);
+            if (billetHotsendChangeShift == null) {
+                log.info("{}{}", "当班热送热装数量维护到交班信息失败,交班记录为空!", new Date());
+                return;
+            }
+        }
+        commonShiftUpdate(billetHotsendChangeShift);
+    }
+
+
+    /**
+     * @param billetHotsendChangeShift
+     */
+    private void commonShiftUpdate(BilletHotsendChangeShift billetHotsendChangeShift) {
+
+        // 获取米重数据
+        String meterWeightKey = String.format("ccmno:meter:weight:%s", billetHotsendChangeShift.getCcmNo());
+        String mWeightStr = oConvertUtils.getString(redisTemplate.opsForValue().get(meterWeightKey));
+        BigDecimal meterWeightFactor = StringUtils.isNotEmpty(mWeightStr)
+                ? new BigDecimal(mWeightStr)
+                : new BigDecimal("0.2265"); // 如果没有米重数据,使用 0.2265 作为系数
+
+        // 查询交班期间的钢坯原始记录
+        LambdaQueryWrapper<BilletOriginalProductRecord> queryWrapper1 = new LambdaQueryWrapper<>();
+        queryWrapper1.eq(BilletOriginalProductRecord::getCcmNo, billetHotsendChangeShift.getCcmNo());
+        queryWrapper1.eq(BilletOriginalProductRecord::getShift, billetHotsendChangeShift.getShift());
+        queryWrapper1.eq(BilletOriginalProductRecord::getShiftGroup, billetHotsendChangeShift.getShiftGroup());
+        queryWrapper1.between(BilletOriginalProductRecord::getCreateTime,
+                billetHotsendChangeShift.getCreateTime(), billetHotsendChangeShift.getChangeShiftTime());
+
+        List<BilletOriginalProductRecord> list = billetOriginalProductRecordMapper.selectList(queryWrapper1);
+
+        if (oConvertUtils.listIsNotEmpty(list)) {
+            ObjectMapper objectMapper = new ObjectMapper();
+
+            Map<String, Integer> mergedCount = new HashMap<>();
+            Map<String, BigDecimal> mergedWeight = new HashMap<>();
+
+            Map<String, Integer> mergedCountHotSend = new HashMap<>();
+            Map<String, BigDecimal> mergedWeightHotSend = new HashMap<>();
+
+            Map<String, Integer> mergedCountHotFeign = new HashMap<>();
+            Map<String, BigDecimal> mergedWeightHotFeign = new HashMap<>();
+
+            Map<String, Integer> mergedCountStack = new HashMap<>();
+            Map<String, BigDecimal> mergedWeightStack = new HashMap<>();
+
+
+            // 定义每个目的地的计数和重量汇总映射
+            Map<String, Map<String, Integer>> destinationCountMap = new HashMap<>();
+            Map<String, Map<String, BigDecimal>> destinationWeightMap = new HashMap<>();
+
+            Map<String, DestinationStatisticsDetails> rollClubOneMap = new HashMap<>();
+
+            // 初始化目的地
+            List<String> destinations = Arrays.asList("roll_club_two", "roll_club_three", "roll_out_shipp", "roll_deputy_cross", "roll_old_areas");
+            for (String dest : destinations) {
+                destinationCountMap.put(dest, new HashMap<>());
+                destinationWeightMap.put(dest, new HashMap<>());
+            }
+
+            for (BilletOriginalProductRecord record : list) {
+
+                // 热送统计
+                try {
+                    JsonNode rollDetails = objectMapper.readTree(record.getRollClubOneDetails());
+                    JsonNode lengthGroupCount = rollDetails.path("lengthGroupCount");
+
+                    if (lengthGroupCount.isObject()) {
+                        for (Iterator<Map.Entry<String, JsonNode>> it = lengthGroupCount.fields(); it.hasNext(); ) {
+                            Map.Entry<String, JsonNode> entry = it.next();
+                            String mm = entry.getKey();
+                            int count = entry.getValue().asInt(0);
+
+                            BigDecimal singleWeight = new BigDecimal(mm)
+                                    .divide(new BigDecimal("1000"), 3, RoundingMode.HALF_UP)
+                                    .multiply(meterWeightFactor)
+                                    .setScale(3, RoundingMode.HALF_UP);
+
+                            BigDecimal weight = singleWeight.multiply(BigDecimal.valueOf(count));
+
+                            mergedCountHotSend.merge(mm, count, Integer::sum);
+                            mergedWeightHotSend.merge(mm, weight, BigDecimal::add);
+
+                            mergedCount.merge(mm, count, Integer::sum);
+                            mergedWeight.merge(mm, weight, BigDecimal::add);
+                        }
+                    }
+                } catch (Exception ignored) {
+                }
+
+                // 热装统计
+                try {
+                    JsonNode hotArray = objectMapper.readTree(record.getHotChargeLength());
+                    for (JsonNode node : hotArray) {
+                        String mm = node.path("hotChargeLength").asText();
+                        int count = node.path("totalCount").asInt(0);
+
+                        BigDecimal singleWeight = new BigDecimal(mm)
+                                .divide(new BigDecimal("1000"), 3, RoundingMode.HALF_UP)
+                                .multiply(meterWeightFactor)
+                                .setScale(3, RoundingMode.HALF_UP);
+
+                        BigDecimal weight = singleWeight.multiply(BigDecimal.valueOf(count));
+
+                        mergedCountHotFeign.merge(mm, count, Integer::sum);
+                        mergedWeightHotFeign.merge(mm, weight, BigDecimal::add);
+
+                        mergedCount.merge(mm, count, Integer::sum);
+                        mergedWeight.merge(mm, weight, BigDecimal::add);
+                    }
+                } catch (Exception ignored) {
+                }
+
+                // 堆垛统计
+                try {
+                    JsonNode stackArray = objectMapper.readTree(record.getStackLength());
+                    for (JsonNode node : stackArray) {
+                        String mm = node.path("stackingLength").asText();
+                        int count = node.path("stackingCount").asInt(0);
+
+                        BigDecimal singleWeight = new BigDecimal(mm)
+                                .divide(new BigDecimal("1000"), 3, RoundingMode.HALF_UP)
+                                .multiply(meterWeightFactor)
+                                .setScale(3, RoundingMode.HALF_UP);
+
+                        BigDecimal weight = singleWeight.multiply(BigDecimal.valueOf(count));
+
+                        mergedCountStack.merge(mm, count, Integer::sum);
+                        mergedWeightStack.merge(mm, weight, BigDecimal::add);
+
+                        mergedCount.merge(mm, count, Integer::sum);
+                        mergedWeight.merge(mm, weight, BigDecimal::add);
+                    }
+                } catch (Exception ignored) {
+                }
+
+                try {
+                    JsonNode hotArray = objectMapper.readTree(record.getHotChargeLength());
+                    for (JsonNode node : hotArray) {
+                        String mm = node.path("hotChargeLength").asText(); // 定尺
+                        int count = node.path("totalCount").asInt(0);
+                        String destination = node.path("hotChargeDestination").asText(); // 目的地
+
+                        if (!destinationCountMap.containsKey(destination)) {
+                            continue; // 不属于目标五类,跳过
+                        }
+
+                        // 单重
+                        BigDecimal singleWeight = new BigDecimal(mm)
+                                .divide(new BigDecimal("1000"), 3, RoundingMode.HALF_UP)
+                                .multiply(meterWeightFactor)
+                                .setScale(3, RoundingMode.HALF_UP);
+
+                        // 总重
+                        BigDecimal totalWeightForThis = singleWeight.multiply(BigDecimal.valueOf(count));
+
+                        // 累加支数
+                        Map<String, Integer> countMap = destinationCountMap.get(destination);
+                        countMap.merge(mm, count, Integer::sum);
+
+                        // 累加重量
+                        Map<String, BigDecimal> weightMap = destinationWeightMap.get(destination);
+                        weightMap.merge(mm, totalWeightForThis, BigDecimal::add);
+                    }
+                } catch (Exception ignored) {
+                }
+
+                try {
+                    JsonNode rollClubOneNode = objectMapper.readTree(record.getRollClubOneDetails());
+                    JsonNode lengthGroupNode = rollClubOneNode.path("lengthGroupCount");
+
+                    if (lengthGroupNode.isObject()) {
+                        for (Iterator<Map.Entry<String, JsonNode>> it = lengthGroupNode.fields(); it.hasNext(); ) {
+                            Map.Entry<String, JsonNode> entry = it.next();
+                            String length = entry.getKey();
+                            int count = entry.getValue().asInt(0);
+
+                            BigDecimal singleWeight = new BigDecimal(length)
+                                    .divide(new BigDecimal("1000"), 3, RoundingMode.HALF_UP)
+                                    .multiply(meterWeightFactor)
+                                    .setScale(3, RoundingMode.HALF_UP);
+
+                            BigDecimal totalWeight = singleWeight.multiply(BigDecimal.valueOf(count)).setScale(4, RoundingMode.HALF_UP);
+
+                            DestinationStatisticsDetails stat = rollClubOneMap.get(length);
+                            if (stat == null) {
+                                stat = new DestinationStatisticsDetails();
+                                stat.setSize(length);
+                                stat.setNums(count);
+                                stat.setBlankOutput(totalWeight.doubleValue());
+                                stat.setCcmNo(billetHotsendChangeShift.getCcmNo());
+                                rollClubOneMap.put(length, stat);
+                            } else {
+                                stat.setNums(stat.getNums() + count);
+                                double updatedWeight = BigDecimal.valueOf(stat.getBlankOutput())
+                                        .add(totalWeight)
+                                        .setScale(3, RoundingMode.HALF_UP)
+                                        .doubleValue();
+
+                                stat.setBlankOutput(updatedWeight);
+                            }
+                        }
+                    }
+                } catch (Exception ignored) {
+                }
+
+            }
+
+            // 汇总热送
+            int totalHotSendCount = mergedCountHotSend.values().stream().mapToInt(Integer::intValue).sum();
+            BigDecimal totalHotSendWeight = mergedWeightHotSend.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            // 汇总热装
+            int totalHotFeignCount = mergedCountHotFeign.values().stream().mapToInt(Integer::intValue).sum();
+            BigDecimal totalHotFeignWeight = mergedWeightHotFeign.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            // 汇总堆垛
+            int totalStackCount = mergedCountStack.values().stream().mapToInt(Integer::intValue).sum();
+            BigDecimal totalStackWeight = mergedWeightStack.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            // 汇总当班全部
+            int totalCount = mergedCount.values().stream().mapToInt(Integer::intValue).sum();
+            BigDecimal totalWeight = mergedWeight.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            // 设置到交班记录对象
+            billetHotsendChangeShift.setShiftHotsendAmount(totalHotSendCount);
+            billetHotsendChangeShift.setShiftHotsendWeight(totalHotSendWeight.setScale(3, RoundingMode.HALF_UP).doubleValue());
+
+            billetHotsendChangeShift.setShiftHotfeignAmount(totalHotFeignCount);
+            billetHotsendChangeShift.setShiftHotfeignWeight(totalHotFeignWeight.setScale(3, RoundingMode.HALF_UP).doubleValue());
+
+            billetHotsendChangeShift.setShiftStackAmount(totalStackCount);
+            billetHotsendChangeShift.setShiftStackWeight(totalStackWeight.setScale(3, RoundingMode.HALF_UP).doubleValue());
+
+            billetHotsendChangeShift.setShiftProduct(totalWeight.doubleValue());
+            billetHotsendChangeShift.setShiftSum(totalCount);
+
+            // 构建每种定尺的统计详情列表
+            List<DestinationStatisticsDetails> lengthGroupList = new ArrayList<>();
+
+            for (Map.Entry<String, Integer> entry : mergedCount.entrySet()) {
+                String mm = entry.getKey();
+                Integer count = entry.getValue();
+                BigDecimal weight = mergedWeight.getOrDefault(mm, BigDecimal.ZERO).setScale(3, RoundingMode.HALF_UP);
+
+                DestinationStatisticsDetails detail = new DestinationStatisticsDetails(
+                        mm,                              // 定尺
+                        count,                           // 总支数
+                        weight.doubleValue(),            // 出坯重量(double)
+                        billetHotsendChangeShift.getCcmNo() // 铸机号
+                );
+
+                lengthGroupList.add(detail);
+            }
+
+            // 班次定尺明细
+            billetHotsendChangeShift.setSizeDetailsList(JSON.toJSONString(lengthGroupList));
+
+            List<DestinationStatisticsDetails> rollClubOneDetailsStatisticsList = new ArrayList<>(rollClubOneMap.values());
+
+            String ccmNo = billetHotsendChangeShift.getCcmNo();
+            if ("5".equals(ccmNo)) {
+                billetHotsendChangeShift.setRollClubOneDetails(JSON.toJSONString(rollClubOneDetailsStatisticsList));
+            } else if ("6".equals(ccmNo)) {
+                billetHotsendChangeShift.setRollClubHeightDetails(JSON.toJSONString(rollClubOneDetailsStatisticsList));
+            }
+
+
+            // 定义结果列表
+            List<DestinationStatisticsDetails> statisticsDetailsList1 = new ArrayList<>();
+            List<DestinationStatisticsDetails> statisticsDetailsList2 = new ArrayList<>();
+            List<DestinationStatisticsDetails> statisticsDetailsList3 = new ArrayList<>();
+            List<DestinationStatisticsDetails> statisticsDetailsList4 = new ArrayList<>();
+            List<DestinationStatisticsDetails> statisticsDetailsList5 = new ArrayList<>();
+
+            // 转换Map到List
+            for (String dest : destinations) {
+                Map<String, Integer> countMap = destinationCountMap.get(dest);
+                Map<String, BigDecimal> weightMap = destinationWeightMap.get(dest);
+
+                List<DestinationStatisticsDetails> targetList;
+                switch (dest) {
+                    case "roll_club_two":
+                        targetList = statisticsDetailsList1;
+                        break;
+                    case "roll_club_three":
+                        targetList = statisticsDetailsList2;
+                        break;
+                    case "roll_out_shipp":
+                        targetList = statisticsDetailsList3;
+                        break;
+                    case "roll_deputy_cross":
+                        targetList = statisticsDetailsList4;
+                        break;
+                    case "roll_old_areas":
+                        targetList = statisticsDetailsList5;
+                        break;
+                    default:
+                        continue;
+                }
+
+                for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
+                    String mm = entry.getKey();
+                    Integer count = entry.getValue();
+                    BigDecimal weight = weightMap.getOrDefault(mm, BigDecimal.ZERO).setScale(3, RoundingMode.HALF_UP);
+
+                    DestinationStatisticsDetails detail = new DestinationStatisticsDetails(
+                            mm,
+                            count,
+                            weight.doubleValue(),
+                            billetHotsendChangeShift.getCcmNo()
+                    );
+
+                    targetList.add(detail);
+                }
+
+            }
+
+            // 合并五个列表并根据 size 分组统计
+            List<DestinationStatisticsDetails> mergedList = Stream.of(
+                            statisticsDetailsList1,
+                            statisticsDetailsList2,
+                            statisticsDetailsList3,
+                            statisticsDetailsList4,
+                            statisticsDetailsList5
+                    ).filter(Objects::nonNull) // 过滤可能的 null 列表
+                    .flatMap(List::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(3, 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());
+
+
+            // 班次装运统计  车次总数、总重、总支数  查询当班装运单信息
+            LambdaQueryWrapper<StorageBillPrint> queryWrapper3 = new LambdaQueryWrapper<>();
+            String classes = billetHotsendChangeShift.getShift() + "/" + billetHotsendChangeShift.getShiftGroup();
+            queryWrapper3.eq(StorageBillPrint::getCcmNo, billetHotsendChangeShift.getCcmNo())
+                    .eq(StorageBillPrint::getClasses, classes)
+                    .between(StorageBillPrint::getArrivalTime, billetHotsendChangeShift.getCreateTime(), billetHotsendChangeShift.getChangeShiftTime());
+            List<StorageBillPrint> storageBillPrintList = storageBillPrintMapper.selectList(queryWrapper3);
+            if (oConvertUtils.listIsEmpty(storageBillPrintList)) {
+                log.info("{}{}", "查询班次实绩吊运明细、轧钢棒二、轧钢棒三、轧钢上若,装运信息为空!", billetHotsendChangeShift.getCcmNo());
+                return;
+            }
+            // 过滤 storageBillPrintList 中总支数为0的记录,计算出总条数
+            int allCarNum = (int) storageBillPrintList.stream()
+                    .filter(storageBillPrint -> storageBillPrint.getAmountTotal() != 0)
+                    .count();
+            // 装运总车次
+            billetHotsendChangeShift.setAllCarNum(allCarNum);
+
+            int finalAmountTotal = mergedList.stream().mapToInt(DestinationStatisticsDetails::getNums).sum();
+            billetHotsendChangeShift.setCounts(finalAmountTotal);
+
+            double finalBlankOutputs = mergedList.stream().mapToDouble(DestinationStatisticsDetails::getBlankOutput).sum();
+            BigDecimal bd = BigDecimal.valueOf(finalBlankOutputs).setScale(3, BigDecimal.ROUND_HALF_UP);
+            billetHotsendChangeShift.setBlankOutputs(bd.doubleValue());
+
+            // 轧钢棒二明细
+            // 按照 size 分组,计算 nums 和 blankOutput 的总和,取每组第一条记录的 ccmNo
+            Map<String, DestinationStatisticsDetails> result1 = statisticsDetailsList1.stream()
+                    .collect(Collectors.groupingBy(
+                            DestinationStatisticsDetails::getSize,
+                            Collectors.collectingAndThen(
+                                    Collectors.reducing((first, second) -> {
+                                        DestinationStatisticsDetails combined = new DestinationStatisticsDetails();
+                                        combined.setSize(first.getSize());
+                                        combined.setNums(first.getNums() + second.getNums());
+                                        combined.setBlankOutput(roundToFourDecimals(first.getBlankOutput() + second.getBlankOutput()));
+                                        combined.setCcmNo(first.getCcmNo());
+                                        return combined;
+                                    }),
+                                    Optional::get
+                            )
+                    ));
+            List<DestinationStatisticsDetails> statisticsDetailsGroup1List = new ArrayList<>(result1.values());
+            billetHotsendChangeShift.setRollClubTwoDetails(JSON.toJSONString(statisticsDetailsGroup1List));
+
+            // 轧钢棒三明细
+            // 按照 size 分组,计算 nums 和 blankOutput 的总和,取每组第一条记录的 ccmNo
+            Map<String, DestinationStatisticsDetails> result2 = statisticsDetailsList2.stream()
+                    .collect(Collectors.groupingBy(
+                            DestinationStatisticsDetails::getSize,
+                            Collectors.collectingAndThen(
+                                    Collectors.reducing((first, second) -> {
+                                        DestinationStatisticsDetails combined = new DestinationStatisticsDetails();
+                                        combined.setSize(first.getSize());
+                                        combined.setNums(first.getNums() + second.getNums());
+                                        combined.setBlankOutput(roundToFourDecimals(first.getBlankOutput() + second.getBlankOutput()));
+                                        combined.setCcmNo(first.getCcmNo());
+                                        return combined;
+                                    }),
+                                    Optional::get
+                            )
+                    ));
+            List<DestinationStatisticsDetails> statisticsDetailsGroup2List = new ArrayList<>(result2.values());
+            billetHotsendChangeShift.setRollClubThreeDetails(JSON.toJSONString(statisticsDetailsGroup2List));
+
+            // 轧钢上若明细
+            // 按照 size 分组,计算 nums 和 blankOutput 的总和,取每组第一条记录的 ccmNo
+            Map<String, DestinationStatisticsDetails> result3 = statisticsDetailsList3.stream()
+                    .collect(Collectors.groupingBy(
+                            DestinationStatisticsDetails::getSize,
+                            Collectors.collectingAndThen(
+                                    Collectors.reducing((first, second) -> {
+                                        DestinationStatisticsDetails combined = new DestinationStatisticsDetails();
+                                        combined.setSize(first.getSize());
+                                        combined.setNums(first.getNums() + second.getNums());
+                                        combined.setBlankOutput(roundToFourDecimals(first.getBlankOutput() + second.getBlankOutput()));
+                                        combined.setCcmNo(first.getCcmNo());
+                                        return combined;
+                                    }),
+                                    Optional::get
+                            )
+                    ));
+            List<DestinationStatisticsDetails> statisticsDetailsGroup3List = new ArrayList<>(result3.values());
+            billetHotsendChangeShift.setRollClubShipDetails(JSON.toJSONString(statisticsDetailsGroup3List));
+
+
+            // 轧钢付跨明细
+            // 按照 size 分组,计算 nums 和 blankOutput 的总和,取每组第一条记录的 ccmNo
+            Map<String, DestinationStatisticsDetails> result4 = statisticsDetailsList4.stream()
+                    .collect(Collectors.groupingBy(
+                            DestinationStatisticsDetails::getSize,
+                            Collectors.collectingAndThen(
+                                    Collectors.reducing((first, second) -> {
+                                        DestinationStatisticsDetails combined = new DestinationStatisticsDetails();
+                                        combined.setSize(first.getSize());
+                                        combined.setNums(first.getNums() + second.getNums());
+                                        combined.setBlankOutput(roundToFourDecimals(first.getBlankOutput() + second.getBlankOutput()));
+                                        combined.setCcmNo(first.getCcmNo());
+                                        return combined;
+                                    }),
+                                    Optional::get
+                            )
+                    ));
+            List<DestinationStatisticsDetails> statisticsDetailsGroup4List = new ArrayList<>(result4.values());
+            billetHotsendChangeShift.setRollDeputyCrossDetails(JSON.toJSONString(statisticsDetailsGroup4List));
+
+            // 轧钢老区明细
+            // 按照 size 分组,计算 nums 和 blankOutput 的总和,取每组第一条记录的 ccmNo
+            Map<String, DestinationStatisticsDetails> result5 = statisticsDetailsList5.stream()
+                    .collect(Collectors.groupingBy(
+                            DestinationStatisticsDetails::getSize,
+                            Collectors.collectingAndThen(
+                                    Collectors.reducing((first, second) -> {
+                                        DestinationStatisticsDetails combined = new DestinationStatisticsDetails();
+                                        combined.setSize(first.getSize());
+                                        combined.setNums(first.getNums() + second.getNums());
+                                        combined.setBlankOutput(roundToFourDecimals(first.getBlankOutput() + second.getBlankOutput()));
+                                        combined.setCcmNo(first.getCcmNo());
+                                        return combined;
+                                    }),
+                                    Optional::get
+                            )
+                    ));
+            List<DestinationStatisticsDetails> statisticsDetailsGroup5List = new ArrayList<>(result5.values());
+            billetHotsendChangeShift.setRollOldAreasDetails(JSON.toJSONString(statisticsDetailsGroup5List));
+
+        }
+        this.updateById(billetHotsendChangeShift);
+    }
+
+    private static double roundToFourDecimals(double value) {
+        BigDecimal bd = new BigDecimal(Double.toString(value));
+        bd = bd.setScale(4, RoundingMode.HALF_UP);
+        return bd.doubleValue();
+    }
+
+
     /**
      * 计算余数并提取相应元素
+     *
      * @param billetBasicInfoList
      * @return
      */

+ 1 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/billetOriginalProductRecord/service/impl/BilletOriginalProductRecordServiceImpl.java

@@ -470,7 +470,7 @@ public class BilletOriginalProductRecordServiceImpl extends ServiceImpl<BilletOr
         String mWeightStr = oConvertUtils.getString(redisTemplate.opsForValue().get(meterWeightKey));
         BigDecimal meterWeightFactor = StringUtils.isNotEmpty(mWeightStr)
                 ? new BigDecimal(mWeightStr)
-                : BigDecimal.ONE; // 如果没有米重数据,使用1作为系数
+                : new BigDecimal("0.2265"); // 如果没有米重数据,使用 0.2265 作为系数
 
         // 查询当前班次的原始记录
         LambdaQueryWrapper<SampleCardDeliveryRecord> queryWrapper = new LambdaQueryWrapper<>();