Browse Source

钢坯装运单列表维护付跨数据,以及装运单修改目的地增加对于付跨目的地的切换

lingpeng.li 1 month ago
parent
commit
1146cfbc5d

+ 26 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollClubOne/controller/RollClubOneDetailsController.java

@@ -11,6 +11,7 @@ import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
 import org.jeecg.modules.billet.rollClubOne.entity.HotSendRollClubOneDetails;
 import org.jeecg.modules.billet.rollClubOne.entity.RollClubOneDetails;
 import org.jeecg.modules.billet.rollClubOne.service.IRollClubOneDetailsService;
@@ -27,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -248,4 +250,28 @@ public class RollClubOneDetailsController extends JeecgController<RollClubOneDet
     }
 
 
+
+    @AutoLog(value = "钢坯浇筑页面-补录钢坯去棒一")
+    @ApiOperation(value="钢坯浇筑页面-补录钢坯去棒一", notes="钢坯浇筑页面-补录钢坯去棒一")
+    @PostMapping(value = "/addBilletBasic")
+    public Result<?> addBilletBasic(@RequestBody BilletBasicInfoAdd billetBasicInfoAdd){
+        // 记录开始时间
+        long startMillis = System.currentTimeMillis();
+        log.info("开始执行时间:{}", new Date(startMillis));
+        try {
+            String result = rollClubOneDetailsService.addBilletBasicHandle(billetBasicInfoAdd);
+            // 记录结束时间并计算耗时
+            long endMillis = System.currentTimeMillis();
+            long durationMillis = endMillis - startMillis;
+            log.info("结束执行时间:{},总耗时:{} 毫秒", new Date(endMillis), durationMillis);
+            return Result.OK(result);
+        } catch (Exception e) {
+            // 记录异常时的执行时间
+            long errorMillis = System.currentTimeMillis();
+            log.error("执行过程中发生异常,异常时间:{},耗时:{} 毫秒", new Date(errorMillis), errorMillis - startMillis);
+            throw new RuntimeException(e);
+        }
+    }
+
+
 }

+ 3 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollClubOne/service/IRollClubOneDetailsService.java

@@ -1,7 +1,7 @@
 package org.jeecg.modules.billet.rollClubOne.service;
 
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
 import org.jeecg.modules.billet.rollClubOne.entity.RollClubOneDetails;
 import org.jeecg.modules.billet.storageBill.dto.RollDetailQueryDTO;
 import org.jeecg.modules.billet.storageBill.vo.RollOnDutyDataVo;
@@ -21,4 +21,6 @@ public interface IRollClubOneDetailsService extends IService<RollClubOneDetails>
     RollSendDetailsVO queryWorkbenchesDetail(RollDetailQueryDTO queryDTO);
 
     RollSendDetailsPageVO rollClubOneWorkbenchesQuery(RollDetailQueryDTO queryDTO);
+
+    String addBilletBasicHandle(BilletBasicInfoAdd billetBasicInfoAdd);
 }

+ 416 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollClubOne/service/impl/RollClubOneDetailsServiceImpl.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.billet.rollClubOne.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.extern.slf4j.Slf4j;
@@ -8,11 +10,26 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletBasicInfoAdd;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.BilletRulerConfig;
+import org.jeecg.modules.actualControl.billetActual.billetActual.entity.RollClubOneInfo;
+import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletBasicInfoService;
+import org.jeecg.modules.actualControl.billetActual.billetActual.service.IBilletRulerConfigService;
+import org.jeecg.modules.actualControl.billetActual.billetAssemblyNumber.entity.BilletAssemblyNumber;
+import org.jeecg.modules.actualControl.billetActual.billetAssemblyNumber.mapper.BilletAssemblyNumberMapper;
+import org.jeecg.modules.actualControl.heatsActuals.entity.HeatsActuals;
+import org.jeecg.modules.actualControl.heatsActuals.service.IHeatsActualsService;
+import org.jeecg.modules.billet.billetHotsend.entity.BilletHotsend;
+import org.jeecg.modules.billet.billetHotsend.mapper.BilletHotsendBaseMapper;
 import org.jeecg.modules.billet.billetHotsendChangeShift.entity.BilletHotsendChangeShift;
 import org.jeecg.modules.billet.billetHotsendChangeShift.service.IBilletHotsendChangeShiftService;
+import org.jeecg.modules.billet.rollClubOne.entity.RollClubOne;
 import org.jeecg.modules.billet.rollClubOne.entity.RollClubOneDetails;
 import org.jeecg.modules.billet.rollClubOne.mapper.RollClubOneDetailsMapper;
+import org.jeecg.modules.billet.rollClubOne.mapper.RollClubOneMapper;
 import org.jeecg.modules.billet.rollClubOne.service.IRollClubOneDetailsService;
+import org.jeecg.modules.billet.rollClubOne.service.IRollClubOneService;
 import org.jeecg.modules.billet.storageBill.dto.RollDetailQueryDTO;
 import org.jeecg.modules.billet.storageBill.mapper.StorageBillMapper;
 import org.jeecg.modules.billet.storageBill.vo.RollOnDutyDataVo;
@@ -28,7 +45,9 @@ import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * @Description: 棒一明细信息
@@ -50,6 +69,25 @@ public class RollClubOneDetailsServiceImpl extends ServiceImpl<RollClubOneDetail
     @Autowired
     private StorageBillMapper storageBillMapper;
 
+    @Autowired
+    private IHeatsActualsService heatsActualsService;
+
+    @Autowired
+    private BilletHotsendBaseMapper billetHotsendBaseMapper;
+
+    @Autowired
+    private IBilletBasicInfoService billetBasicInfoService;
+
+    @Autowired
+    private IBilletRulerConfigService billetRulerConfigService;
+
+    @Autowired
+    private BilletAssemblyNumberMapper billetAssemblyNumberMapper;
+
+    @Autowired
+    private RollClubOneMapper rollClubOneMapper;
+
+
     @Override
     public RollOnDutyDataVo queryOnDutyRecord(String ccmNo) {
         RollOnDutyDataVo rollOnDutyVo = new RollOnDutyDataVo();
@@ -353,6 +391,384 @@ public class RollClubOneDetailsServiceImpl extends ServiceImpl<RollClubOneDetail
     }
 
 
+    @Override
+    public String addBilletBasicHandle(BilletBasicInfoAdd billetBasicInfoAdd) {
+
+        String brandNum = String.format("billet:basic:info:brand:num:%s", billetBasicInfoAdd.getCcmNo()); // 牌号
+        String brandNumStr = !oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)).isEmpty() ? oConvertUtils.getString(redisTemplate.opsForValue().get(brandNum)) : "";
+        String result = "";
+        // 处理整炉补录钢坯逻辑
+        result = completeHeatsHandle(billetBasicInfoAdd, brandNumStr);
+        return result;
+    }
+
+    /**
+     * 整炉添加逻辑处理
+     *
+     * @param billetBasicInfoAdd
+     */
+    private String completeHeatsHandle(BilletBasicInfoAdd billetBasicInfoAdd, String brandNumStr) {
+
+        LambdaQueryWrapper<HeatsActuals> queryWrapper1 = new LambdaQueryWrapper<HeatsActuals>()
+                .eq(HeatsActuals::getHeatsCode, billetBasicInfoAdd.getHeatNo())
+                .orderByDesc(HeatsActuals::getCreateTime).last("limit 1");
+        HeatsActuals actualsCheck = heatsActualsService.getOne(queryWrapper1);
+        if (actualsCheck != null) {
+            return "炉次实绩中炉号重复,补录失败!";
+        }
+
+        // 查询基础信息
+        LambdaQueryWrapper<HeatsActuals> queryWrapper = new LambdaQueryWrapper<HeatsActuals>()
+                .eq(HeatsActuals::getCasterCode, billetBasicInfoAdd.getCcmNo())
+                .orderByDesc(HeatsActuals::getCreateTime).last("limit 1");
+        HeatsActuals actuals = heatsActualsService.getOne(queryWrapper);
+
+        HeatsActuals heatsActuals = new HeatsActuals();
+        BeanUtils.copyProperties(actuals, heatsActuals);
+
+        try {
+            heatsActuals.setId(String.valueOf(IdWorker.getId()));
+            heatsActuals.setHeatsCode(billetBasicInfoAdd.getHeatNo());
+            heatsActuals.setShift(billetBasicInfoAdd.getShift());
+            heatsActuals.setShiftGroup(billetBasicInfoAdd.getShiftGroup());
+            //根据最新一炉的炉次信息计算 空包重量核算
+            if (heatsActuals.getMoltenSteelWeight() > 0 && heatsActuals.getFullLadleWeight() > 0) { // 如果钢水重量存在核算
+                heatsActuals.setEmptyLadleWeight(heatsActuals.getFullLadleWeight() - heatsActuals.getMoltenSteelWeight());
+            }
+            // 整理添加总支数
+            heatsActuals.setBilletSum(0);
+            heatsActuals.setBlankOutput(0.0d);
+            heatsActuals.setCreateTime(new Date());
+            heatsActuals.setUpdateTime(new Date());
+            heatsActualsService.save(heatsActuals);
+        } catch (Exception e) {
+            log.error("整炉补坯保存炉次实绩数据出现异常", e);
+            throw new RuntimeException("整炉补坯保存炉次实绩数据出现失败!", e);
+        }
+        log.info("1炉次实绩插入:" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        //新增炉次传递单
+        BilletHotsend billetHotsend = new BilletHotsend();
+        billetHotsend.setId(String.valueOf(IdWorker.getId()));
+        billetHotsend.setCcmNo(billetBasicInfoAdd.getCcmNo()); // 铸机号
+        billetHotsend.setHeatNo(billetBasicInfoAdd.getHeatNo()); // 炉号
+        billetHotsend.setShiftGroup(billetBasicInfoAdd.getShiftGroup()); // 班组
+        billetHotsend.setShift(billetBasicInfoAdd.getShift()); // 班别
+        billetHotsend.setSteel(heatsActuals.getGrade()); // 钢种
+        billetHotsend.setSpec(heatsActuals.getSpec()); // 规格
+
+        billetHotsend.setBrandNum(brandNumStr);
+        billetHotsend.setAmountTotal(heatsActuals.getBilletSum()); // 支数
+        billetHotsend.setBlankOutput(0.0d); // 出批量
+        billetHotsend.setDecideWeight(0.0d); // 定重
+        billetHotsend.setWasteBlankOutput(0.0);
+        billetHotsend.setCreateTime(new Date());
+        billetHotsend.setUpdateTime(new Date());
+        billetHotsendBaseMapper.insert(billetHotsend);
+        log.info("2炉次传递单插入:" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        LambdaQueryWrapper<BilletBasicInfo> queryWrapperB = new LambdaQueryWrapper<BilletBasicInfo>()
+                .eq(BilletBasicInfo::getCcmNo, billetBasicInfoAdd.getCcmNo())
+                .orderByDesc(BilletBasicInfo::getCreateTime).last("limit 1");
+        BilletBasicInfo billetInfo = billetBasicInfoService.getOne(queryWrapperB);
+
+        BilletBasicInfo billetBasicInfo = new BilletBasicInfo();
+        BeanUtils.copyProperties(billetInfo, billetBasicInfo);
+        // 去棒一数据补录
+
+        int oneStrandRemainSum = 0;
+        int twoStrandRemainSum = 0;
+        int threeStrandRemainSum = 0;
+        int fourStrandRemainSum = 0;
+        int fiveStrandRemainSum = 0;
+        int sixStrandRemainSum = 0;
+
+        // 有去组批的,有去棒一的(混合情况) 1、先处理去棒一的数据 2、在减掉棒一的数量,剩余的进行组批
+        List<BilletBasicInfo> rollClubOneResultList = new ArrayList<>();
+        // 添加棒一明细
+        List<RollClubOneInfo> rollClubOneList = billetBasicInfoAdd.getRollClubOneList();
+
+        // 提取所有需要查询的长度
+        Set<Integer> lengthSet = new HashSet<>();
+        for (RollClubOneInfo item : rollClubOneList) {
+            if (item != null && item.getLength() != null) {
+                lengthSet.add(item.getLength());
+            }
+        }
+
+        // 预查询所有长度对应的定尺规则,避免循环中重复查询
+        Map<Integer, BilletRulerConfig> rulerConfigMap = new HashMap<>();
+        if (!lengthSet.isEmpty()) {
+            LambdaQueryWrapper<BilletRulerConfig> queryWrapperRC = new LambdaQueryWrapper<>();
+            queryWrapperRC.in(BilletRulerConfig::getLength, lengthSet);
+            List<BilletRulerConfig> configList = billetRulerConfigService.list(queryWrapperRC);
+            for (BilletRulerConfig config : configList) {
+                rulerConfigMap.put(config.getLength(), config);
+            }
+        }
+        log.info("开始去棒一数据组装:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        // 遍历 RollClubOneInfo 列表
+        for (RollClubOneInfo item : rollClubOneList) {
+            Integer strandNo = item.getStrandNo();
+            Integer length = item.getLength();
+            Integer addSum = item.getAddSum();
+            if (strandNo == 1 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getOneStrandNoSum())) {
+                oneStrandRemainSum = billetBasicInfoAdd.getOneStrandNoSum() - addSum;
+            } else if (strandNo == 2 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getTwoStrandNoSum())) {
+                twoStrandRemainSum = billetBasicInfoAdd.getTwoStrandNoSum() - addSum;
+            } else if (strandNo == 3 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getThreeStrandNoSum())) {
+                threeStrandRemainSum = billetBasicInfoAdd.getThreeStrandNoSum() - addSum;
+            } else if (strandNo == 4 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFourStrandNoSum())) {
+                fourStrandRemainSum = billetBasicInfoAdd.getFourStrandNoSum() - addSum;
+            } else if (strandNo == 5 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getFiveStrandNoSum())) {
+                fiveStrandRemainSum = billetBasicInfoAdd.getFiveStrandNoSum() - addSum;
+            } else if (strandNo == 6 && oConvertUtils.isNotEmpty(billetBasicInfoAdd.getSixStrandNoSum())) {
+                sixStrandRemainSum = billetBasicInfoAdd.getSixStrandNoSum() - addSum;
+            }
+            // 根据 addSum 生成对应数量的 BilletBasicInfo 对象
+            for (int i = 0; i < addSum; i++) {
+                BilletBasicInfo billet = new BilletBasicInfo();
+                BeanUtils.copyProperties(billetBasicInfo, billet);
+                billet.setStrandNo(strandNo);
+                billet.setLength(length);
+                // 设置其他必要属性
+                billet.setId(String.valueOf(IdWorker.getId()));
+                billet.setHeatNo(billetBasicInfoAdd.getHeatNo());
+                String billetNo = generateUniqueBilletNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+                billet.setBilletNo(billetNo);
+                billet.setCreateTime(new Date());
+                billet.setUpdateTime(new Date());
+                billet.setAssemblyNumber(null);
+                billet.setBelongTable("roll_club_one");
+                billet.setBhtcId("1");
+                // 优化:从预查询的映射表中获取定尺规则,避免重复查询数据库
+                BilletRulerConfig billetRulerConfig = rulerConfigMap.get(length);
+                Double weight = billetRulerConfig != null ? billetRulerConfig.getWeight() : billetBasicInfo.getWeight();
+                billet.setWeight(weight);
+                billet.setBilletWeight(weight);
+                rollClubOneResultList.add(billet);
+            }
+        }
+        log.info("结束去棒一数据组装:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        if (oConvertUtils.listIsNotEmpty(rollClubOneResultList)) {
+            log.info("开始整炉去棒一明细处理:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+            // 去棒一明细处理
+            saveRollClubOneInfo(rollClubOneResultList, billetBasicInfoAdd);
+            log.info("结束整炉去棒一明细处理:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        }
+
+        log.info("开始处理每流剩余:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        List<BilletBasicInfo> result = new ArrayList<>();
+        if (oneStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, oneStrandRemainSum, 1, billetBasicInfoAdd.getOneLength());
+            result.addAll(billetBasicInfoList);
+        }
+        if (twoStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, twoStrandRemainSum, 2, billetBasicInfoAdd.getTwoLength());
+            result.addAll(billetBasicInfoList);
+        }
+        if (threeStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, threeStrandRemainSum, 3, billetBasicInfoAdd.getThreeLength());
+            result.addAll(billetBasicInfoList);
+        }
+        if (fourStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, fourStrandRemainSum, 4, billetBasicInfoAdd.getFourLength());
+            result.addAll(billetBasicInfoList);
+        }
+        if (fiveStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, fiveStrandRemainSum, 5, billetBasicInfoAdd.getFiveLength());
+            result.addAll(billetBasicInfoList);
+        }
+        if (sixStrandRemainSum > 0) {
+            List<BilletBasicInfo> billetBasicInfoList = saveBilletBasicInfoList(billetBasicInfo, billetBasicInfoAdd, sixStrandRemainSum, 6, billetBasicInfoAdd.getSixLength());
+            result.addAll(billetBasicInfoList);
+        }
+        log.info("结束处理每流剩余:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+
+        result.addAll(rollClubOneResultList);
+
+        List<BilletBasicInfo> finalBilletBasicInfoListSort = updateBilletBasicInfoAndSave(result);
+
+        billetBasicInfoService.saveOrUpdateBatch(finalBilletBasicInfoListSort);
+
+        log.info("开始整炉去除棒一组批更新处理:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+
+
+        // 更新炉次传递单中的总数和坯重
+        double totalBilletWeight = finalBilletBasicInfoListSort.stream()
+                .mapToDouble(BilletBasicInfo::getBilletWeight)
+                .sum();
+        billetHotsend.setAmountTotal(finalBilletBasicInfoListSort.size());
+        billetHotsend.setBlankOutput(totalBilletWeight);
+
+        if (oConvertUtils.listIsNotEmpty(rollClubOneResultList) && rollClubOneResultList.size() > 0) {
+            billetHotsend.setRollcluboneNum(rollClubOneResultList.size());
+        }
+        log.info("炉次传递单更新:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        billetHotsendBaseMapper.updateById(billetHotsend);
+
+        // 更新炉次实绩中的总数和坯重
+        heatsActuals.setBlankOutput(totalBilletWeight);
+        heatsActuals.setBilletSum(finalBilletBasicInfoListSort.size());
+        log.info("炉次实绩更新:{}" + DateUtils.date2Str(new Date(), DateUtils.datetimeFormat.get()));
+        heatsActualsService.updateById(heatsActuals);
+
+        return "整炉补录成功!";
+    }
+
+
+    /**
+     * 整炉处理
+     *
+     * @param billetBasicInfo
+     * @param billetBasicInfoAdd
+     * @param addSum
+     * @param strandNo
+     * @param length
+     */
+    private List<BilletBasicInfo> saveBilletBasicInfoList(BilletBasicInfo billetBasicInfo, BilletBasicInfoAdd billetBasicInfoAdd, int addSum, int strandNo, int length) {
+        List<BilletBasicInfo> resultList = new ArrayList<>();
+
+        // 批量查询定尺规则
+        LambdaQueryWrapper<BilletRulerConfig> queryWrapper = new LambdaQueryWrapper<BilletRulerConfig>().eq(BilletRulerConfig::getLength, billetBasicInfo.getLength());
+        List<BilletRulerConfig> billetRulerConfigs = billetRulerConfigService.list(queryWrapper);
+        Map<Integer, BilletRulerConfig> rulerConfigMap = billetRulerConfigs.stream()
+                .collect(Collectors.toMap(BilletRulerConfig::getLength, Function.identity()));
+
+        // 根据 addSum 生成对应数量的 BilletBasicInfo 对象
+        for (int i = 0; i < addSum; i++) {
+            BilletBasicInfo billet = new BilletBasicInfo();
+            BeanUtils.copyProperties(billetBasicInfo, billet);
+            billet.setStrandNo(strandNo);
+            billet.setLength(length);
+            // 设置其他必要属性
+            billet.setId(String.valueOf(IdWorker.getId()));
+            billet.setHeatNo(billetBasicInfoAdd.getHeatNo());
+            String billetNo = generateUniqueBilletNo(Integer.valueOf(billetBasicInfoAdd.getCcmNo()), billetBasicInfoAdd.getHeatNo());
+            billet.setBilletNo(billetNo);
+            billet.setCreateTime(new Date());
+            billet.setUpdateTime(new Date());
+            billet.setAssemblyNumber(null);
+            billet.setBelongTable(null);
+            billet.setBhtcId(null);
+
+            // 获取定尺规则
+            BilletRulerConfig billetRulerConfig = rulerConfigMap.get(billetBasicInfo.getLength());
+            Double weight = Optional.ofNullable(billetRulerConfig)
+                    .map(BilletRulerConfig::getWeight)
+                    .orElse(billetBasicInfo.getWeight());
+
+            billet.setWeight(weight);
+            billet.setBilletWeight(weight);
+            resultList.add(billet);
+        }
+        return resultList;
+    }
+
+
+    /**
+     * 生成唯一的坯号
+     *
+     * @return 坯号
+     */
+    private String generateUniqueBilletNo(Integer ccmNo, String heatNo) {
+        String billetNo;
+        do {
+            billetNo = heatNo + String.format("%04d", (int) (Math.random() * 10000));
+        } while (billetBasicInfoService.exists(new QueryWrapper<BilletBasicInfo>().eq("billet_no", billetNo).eq("ccm_no", ccmNo)));
+        return billetNo;
+    }
+
+
+    /**
+     * 生成唯一的组坯号
+     *
+     * @return 坯号
+     */
+    private String generateUniqueAssemblyNumber(String ccmNo, String heatNo) {
+        String assembly_number;
+        do {
+            assembly_number = heatNo + String.format("%07d", (int) (Math.random() * 10000000));
+        } while (billetAssemblyNumberMapper.exists(
+                new QueryWrapper<BilletAssemblyNumber>()
+                        .eq("assembly_number", assembly_number)
+                        .eq("ccm_no", ccmNo))
+        );
+        return assembly_number;
+    }
+
+    /**
+     * 处理流内顺序号、和炉内顺序号
+     *
+     * @param resultList
+     */
+    public List<BilletBasicInfo> updateBilletBasicInfoAndSave(List<BilletBasicInfo> resultList) {
+        if (oConvertUtils.listIsEmpty(resultList)) {
+            return null;
+        }
+        Map<Integer, List<BilletBasicInfo>> strandNoGroupMap = resultList.stream()
+                .collect(Collectors.groupingBy(BilletBasicInfo::getStrandNo));
+        // 并行处理每个分组(可选优化,适用于多核CPU和大量分组)
+        strandNoGroupMap.values().parallelStream().forEach(groupList -> {
+            for (int i = 0; i < groupList.size(); i++) {
+                groupList.get(i).setStrandnoIndex(i + 1); // 流内顺序号从1开始
+            }
+        });
+        // 设置炉内顺序号(全局顺序)
+        IntStream.range(0, resultList.size()).forEach(i -> resultList.get(i).setHeatnoIndex(i + 1));
+        return resultList;
+    }
+
+    /**
+     * 整理补录,去棒一钢坯,炉内顺序号、流号处理,轧钢棒一、棒一明细保存
+     *
+     * @param billetBasicInfoList
+     * @param billetBasicInfoAdd
+     */
+    private void saveRollClubOneInfo(List<BilletBasicInfo> billetBasicInfoList, BilletBasicInfoAdd billetBasicInfoAdd) {
+        // 对 resultList 中的元素按 Strandno 分组后重新赋值 StrandnoIndex
+        // 更新炉次传递单中的总数和坯重
+        double rollClubOneWeight = billetBasicInfoList.stream()
+                .mapToDouble(BilletBasicInfo::getBilletWeight)
+                .sum();
+
+        RollClubOne rollClubOne = new RollClubOne();
+        rollClubOne.setId(String.valueOf(IdWorker.getId()));
+        rollClubOne.setCcmNo(billetBasicInfoAdd.getCcmNo());
+        rollClubOne.setHeatNo(billetBasicInfoAdd.getHeatNo());
+        rollClubOne.setShiftGroup(billetBasicInfoAdd.getShiftGroup());
+        rollClubOne.setShift(billetBasicInfoAdd.getShift());
+        rollClubOne.setBlankOutput(rollClubOneWeight);
+        rollClubOne.setSize(String.valueOf(billetBasicInfoList.stream().findFirst().orElse(null).getLength())); //定尺
+        rollClubOne.setSteel(String.valueOf(billetBasicInfoList.stream().findFirst().orElse(null).getGrade())); //钢种
+        rollClubOne.setSpec(String.valueOf(billetBasicInfoList.stream().findFirst().orElse(null).getSpec())); //规格
+        rollClubOne.setBlankOutput(billetBasicInfoList.stream().mapToDouble(BilletBasicInfo::getBilletWeight).sum());//出坯量总和
+        rollClubOne.setCreateDate(new Date());
+        rollClubOne.setCreateTime(new Date());
+        rollClubOneMapper.insert(rollClubOne);
+
+        // 保存棒一明细信息
+        List<RollClubOneDetails> rollClubOneDetailsList = new ArrayList<>();
+        billetBasicInfoList.forEach(x -> {
+            RollClubOneDetails rollClubOneDetails = new RollClubOneDetails();
+            BeanUtils.copyProperties(x, rollClubOneDetails);
+            rollClubOneDetails.setId(String.valueOf(IdWorker.getId()));
+            rollClubOneDetails.setCcmNo(billetBasicInfoAdd.getCcmNo());
+            rollClubOneDetails.setShift(billetBasicInfoAdd.getShift());
+            rollClubOneDetails.setStartNum(0);
+            rollClubOneDetails.setEndNum(1);
+            rollClubOneDetails.setShiftGroup(billetBasicInfoAdd.getShiftGroup());
+            rollClubOneDetails.setLicensePlate("辊道");
+            rollClubOneDetails.setSize(String.valueOf(x.getLength()));
+            rollClubOneDetails.setSteel(x.getGrade());
+            rollClubOneDetails.setCreateTime(new Date());
+            rollClubOneDetails.setBlankOutput(x.getBilletWeight());//出坯量
+            rollClubOneDetailsList.add(rollClubOneDetails);
+        });
+
+        for (RollClubOneDetails rollClubOneDetails : rollClubOneDetailsList) {
+            baseMapper.insert(rollClubOneDetails);
+        }
+    }
+
     /**
      * 从Redis中获取班组班别
      *

+ 5 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollDeputyCross/mapper/RollDeputyCrossDetailsMapper.java

@@ -1,7 +1,11 @@
 package org.jeecg.modules.billet.rollDeputyCross.mapper;
 
+import org.apache.ibatis.annotations.Param;
 import org.jeecg.modules.billet.rollDeputyCross.entity.RollDeputyCrossDetails;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.billet.storageBill.vo.HeatNoCount;
+
+import java.util.List;
 
 /**
  * @Description: 付跨明细
@@ -11,4 +15,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface RollDeputyCrossDetailsMapper extends BaseMapper<RollDeputyCrossDetails> {
 
+    List<HeatNoCount> countHeatNoGroupBy(@Param("storageBillIds") List<String> storageBillIds);
 }

+ 18 - 0
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/rollDeputyCross/mapper/xml/RollDeputyCrossDetailsMapper.xml

@@ -2,4 +2,22 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.jeecg.modules.billet.rollDeputyCross.mapper.RollDeputyCrossDetailsMapper">
 
+    <select id="countHeatNoGroupBy" resultType="org.jeecg.modules.billet.storageBill.vo.HeatNoCount">
+        SELECT
+        storage_bill_id AS storageBillId,
+        heat_no AS heatNo,
+        SUM(
+        CASE
+        WHEN stack_addr IS NOT NULL AND TRIM(stack_addr) != '' THEN 4
+        ELSE 1
+        END
+        ) AS count
+        FROM roll_deputy_cross_details
+        WHERE storage_bill_id IN
+        <foreach collection="storageBillIds" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+        GROUP BY storage_bill_id, heat_no
+    </select>
+
 </mapper>

+ 1 - 1
zgztBus/jeecg-module-sbm/src/main/java/org/jeecg/modules/billet/storageBill/entity/BilletHotsendDetails.java

@@ -27,6 +27,6 @@ public class BilletHotsendDetails {
 //
 //    private List<StackingDownLogDetails> stackingDownLogDetailsList;
 
-//    private List<RollDeputyCrossDetails> rollDeputyCrossDetailsList;
+    private List<RollDeputyCrossDetails> rollDeputyCrossDetailsList;
 
 }

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

@@ -49,6 +49,7 @@ import org.jeecg.modules.billet.rollClubTwo.service.IRollClubTwoDetailsService;
 import org.jeecg.modules.billet.rollClubTwo.service.IRollClubTwoService;
 import org.jeecg.modules.billet.rollDeputyCross.entity.RollDeputyCross;
 import org.jeecg.modules.billet.rollDeputyCross.entity.RollDeputyCrossDetails;
+import org.jeecg.modules.billet.rollDeputyCross.mapper.RollDeputyCrossDetailsMapper;
 import org.jeecg.modules.billet.rollDeputyCross.service.IRollDeputyCrossDetailsService;
 import org.jeecg.modules.billet.rollDeputyCross.service.IRollDeputyCrossService;
 import org.jeecg.modules.billet.rollHeight.entity.DestinationStatisticsDetails;
@@ -187,6 +188,9 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
     @Autowired
     private IRollDeputyCrossDetailsService rollDeputyCrossDetailsService;
 
+    @Autowired
+    private RollDeputyCrossDetailsMapper rollDeputyCrossDetailsMapper;
+
 
     @Override
     public void departHandle(BilletHotsendDetailsVo billetHotsendDetailsVo) {
@@ -279,10 +283,10 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         processRollHeightDetails(rollHeightDetails);
         result.setRollHeightDetails(rollHeightDetails);
 
-//        List<RollDeputyCrossDetails> rollDeputyCrossDetailsList = rollDeputyCrossDetailsService.list(new LambdaQueryWrapper<RollDeputyCrossDetails>().in(RollDeputyCrossDetails::getStorageBillId, idList));
-//        processRollDeputyCrossDetails(rollDeputyCrossDetailsList);
-//        result.setRollDeputyCrossDetailsList(rollDeputyCrossDetailsList);
-//
+        List<RollDeputyCrossDetails> rollDeputyCrossDetailsList = rollDeputyCrossDetailsService.list(new LambdaQueryWrapper<RollDeputyCrossDetails>().in(RollDeputyCrossDetails::getStorageBillId, idList));
+        processRollDeputyCrossDetails(rollDeputyCrossDetailsList);
+        result.setRollDeputyCrossDetailsList(rollDeputyCrossDetailsList);
+
         return result;
     }
 
@@ -5630,6 +5634,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             result = switchFromRollClubThree(storageBill, destination);
         } else if ("上若".equals(storageBill.getDestination())) {
             result = switchFromRollOutShipp(storageBill, destination);
+        } else if ("付跨".equals(storageBill.getDestination())) {
+            result = switchFromRollDeputyCross(storageBill, destination);
         }
 
         // 如果切换过程中出现错误,直接返回错误信息
@@ -5657,6 +5663,7 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         allCounts.addAll(rollClubTwoDetailsMapper.countHeatNoGroupBy(storageBillIds));
         allCounts.addAll(rollClubThreeDetailsMapper.countHeatNoGroupBy(storageBillIds));
         allCounts.addAll(rollOutShippDetailsMapper.countHeatNoGroupBy(storageBillIds));
+        allCounts.addAll(rollDeputyCrossDetailsMapper.countHeatNoGroupBy(storageBillIds));
         allCounts.addAll(billetAutoTmpMapper.countHeatNoGroupBy(storageBillIds));
 
         // 聚合到 Map<storageBillId, Map<heatNo, count>>
@@ -5742,6 +5749,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             saveRollOutShippDetails(rollClubTwoList, rollClubTwoDetailsList);
         } else if ("棒三".equals(destination)) {
             saveRollClubThreeDetails(rollClubTwoList, rollClubTwoDetailsList);
+        } else if ("付跨".equals(destination)) {
+            saveRollDeputyCrossDetails(rollClubTwoList, rollClubTwoDetailsList);
         }
 
         // 删除原记录
@@ -5820,6 +5829,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             saveRollOutShippDetails(rollClubThreeList, rollClubThreeDetailsList);
         } else if ("棒二".equals(destination)) {
             saveRollClubTwoDetails(rollClubThreeList, rollClubThreeDetailsList, billetHotsend.getShift());
+        } else if ("付跨".equals(destination)) {
+            saveRollDeputyCrossDetails(rollClubThreeList, rollClubThreeDetailsList);
         }
 
         // 删除原记录
@@ -5897,6 +5908,8 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             saveRollClubTwoDetails(rollOutShippList, rollOutShippDetailsList, null);
         } else if ("棒三".equals(destination)) {
             saveRollClubThreeDetails(rollOutShippList, rollOutShippDetailsList);
+        } else if ("付跨".equals(destination)) {
+            saveRollDeputyCrossDetails(rollOutShippList, rollOutShippDetailsList);
         }
 
         // 删除原记录
@@ -5907,6 +5920,87 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         return updateBilletBasicInfo(billetHotsend.getCcmNo(), billetNos, destination);
     }
 
+
+    /**
+     * 付跨切换到其他目的地的处理逻辑
+     */
+    private String switchFromRollDeputyCross(StorageBill storageBill, String destination) {
+        // 根据铸机号、装运单ID查询付跨明细信息
+        LambdaQueryWrapper<RollDeputyCrossDetails> queryWrapperFk = new LambdaQueryWrapper<>();
+        queryWrapperFk.eq(RollDeputyCrossDetails::getCcmNo, storageBill.getCcmNo())
+                .eq(RollDeputyCrossDetails::getStorageBillId, storageBill.getId());
+        List<RollDeputyCrossDetails> rollDeputyCrossDetailsList = rollDeputyCrossDetailsService.list(queryWrapperFk);
+        if (oConvertUtils.listIsEmpty(rollDeputyCrossDetailsList)) {
+            return "付跨装运明细为空,棒线切换失败!";
+        }
+
+        List<String> billetNos = rollDeputyCrossDetailsList.stream()
+                .map(RollDeputyCrossDetails::getBilletNo)
+                .filter(billetNo -> billetNo != null && !billetNo.isEmpty())
+                .flatMap(billetNo -> Arrays.stream(billetNo.split(",")))
+                .map(String::trim)
+                .filter(trimmedBilletNo -> !trimmedBilletNo.isEmpty())
+                .distinct()
+                .collect(Collectors.toList());
+
+        List<RollClubCommon> rollClubCommonList = createRollClubCommonList(rollDeputyCrossDetailsList);
+        Map<String, List<RollClubCommon>> rollClubCommonLists = groupByShiftAttributes(rollClubCommonList);
+
+        // 维护热送单炉信息
+        BilletHotsend billetHotsend = new BilletHotsend();
+        billetHotsend.setCcmNo(storageBill.getCcmNo());
+
+        for (Map.Entry<String, List<RollClubCommon>> entry : rollClubCommonLists.entrySet()) {
+            String[] parts = entry.getKey().split(",");
+            billetHotsend.setHeatNo(parts[0]);// 炉号
+            billetHotsend.setShiftGroup(parts[1]);// 班组
+            billetHotsend.setShift(parts[2]);// 班别
+
+            LambdaQueryWrapper<BilletHotsend> queryWrapper2 = new LambdaQueryWrapper<>();
+            queryWrapper2.eq(BilletHotsend::getCcmNo, billetHotsend.getCcmNo())
+                    .eq(BilletHotsend::getHeatNo, billetHotsend.getHeatNo())
+                    .eq(BilletHotsend::getShift,  billetHotsend.getShift())
+                    .eq(BilletHotsend::getShiftGroup, billetHotsend.getShiftGroup());
+            BilletHotsend idExistBh = billetHotsendBaseMapper.selectOne(queryWrapper2);
+            if (oConvertUtils.isEmpty(idExistBh)) {
+                log.info("{}{}", "炉次传递单不存在,切换棒线失败!", JSON.toJSON(billetHotsend));
+                // 手动回滚事务
+                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                return "炉次传递单不存在,棒线切换失败!";
+            }
+
+            List<RollClubCommon> groupRollClubCommonList = entry.getValue();
+            updateBilletHotsendForRollDeputyCross(idExistBh, destination, groupRollClubCommonList);
+            billetHotsendBaseMapper.updateById(idExistBh);
+        }
+
+        // 根据炉号、班组、班别查询热送单信息
+        LambdaQueryWrapper<RollDeputyCross> queryWrapper11 = new LambdaQueryWrapper<>();
+        queryWrapper11.eq(RollDeputyCross::getCcmNo, billetHotsend.getCcmNo())
+                .eq(RollDeputyCross::getStorageBillId, storageBill.getId());
+        List<RollDeputyCross> rollDeputyCrossList = rollDeputyCrossService.list(queryWrapper11);
+        if (oConvertUtils.listIsEmpty(rollDeputyCrossList)) {
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            return "轧钢付跨信息不存在,棒线切换失败!";
+        }
+
+        // 根据目标类型保存相应的明细信息
+        if ("上若".equals(destination)) {
+            saveRollOutShippDetails(rollDeputyCrossList, rollDeputyCrossDetailsList);
+        } else if ("棒二".equals(destination)) {
+            saveRollClubTwoDetails(rollDeputyCrossList, rollDeputyCrossDetailsList, billetHotsend.getShift());
+        } else if ("棒三".equals(destination)) {
+            saveRollClubThreeDetails(rollDeputyCrossList, rollDeputyCrossDetailsList);
+        }
+
+        // 删除原记录
+        rollDeputyCrossService.removeBatchByIds(rollDeputyCrossList);
+        rollDeputyCrossDetailsService.removeBatchByIds(rollDeputyCrossDetailsList);
+
+        // 更新钢坯基础信息
+        return updateBilletBasicInfo(billetHotsend.getCcmNo(), billetNos, destination);
+    }
+
     /**
      * 创建 RollClubCommon 列表
      */
@@ -5936,6 +6030,12 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
                 rollClubCommon.setLength(Integer.valueOf(details.getSize()));
                 rollClubCommon.setStorageBillId(details.getStorageBillId());
                 rollClubCommon.setBilletWeight(details.getBlankOutput());
+            } else if (x instanceof RollDeputyCrossDetails) {
+                RollDeputyCrossDetails details = (RollDeputyCrossDetails) x;
+                rollClubCommon.setGrade(details.getSteel());
+                rollClubCommon.setLength(Integer.valueOf(details.getSize()));
+                rollClubCommon.setStorageBillId(details.getStorageBillId());
+                rollClubCommon.setBilletWeight(details.getBlankOutput());
             }
 
             rollClubCommonList.add(rollClubCommon);
@@ -5957,6 +6057,9 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         } else if ("棒三".equals(destination)) {
             hotsend.setRollclubtwoNum(hotsend.getRollclubtwoNum() - effectiveCount);
             hotsend.setRollclubthreeNum(hotsend.getRollclubthreeNum() + effectiveCount);
+        } else if ("付跨".equals(destination)) {
+            hotsend.setRollclubtwoNum(hotsend.getRollclubtwoNum() - effectiveCount);
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() + effectiveCount);
         }
     }
 
@@ -5976,6 +6079,9 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         } else if ("棒二".equals(destination)) {
             hotsend.setRollclubthreeNum(hotsend.getRollclubthreeNum() - effectiveCount);
             hotsend.setRollclubtwoNum(hotsend.getRollclubtwoNum() + effectiveCount);
+        } else if ("付跨".equals(destination)) {
+            hotsend.setRollclubthreeNum(hotsend.getRollclubthreeNum() - effectiveCount);
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() + effectiveCount);
         }
     }
 
@@ -5995,6 +6101,31 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         } else if ("棒三".equals(destination)) {
             hotsend.setRollclubthreeNum(hotsend.getRollclubthreeNum() + effectiveCount);
             hotsend.setRolloutshippNum(hotsend.getRolloutshippNum() - effectiveCount);
+        } else if ("付跨".equals(destination)) {
+            hotsend.setRolloutshippNum(hotsend.getRolloutshippNum() - effectiveCount);
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() + effectiveCount);
+        }
+    }
+
+    /**
+     * 更新热送单信息 - 付跨来源
+     */
+    private void updateBilletHotsendForRollDeputyCross(BilletHotsend hotsend, String destination, List<RollClubCommon> commonList) {
+
+        // 计算有效数量:stackAddr为空的项按1计算,不为空的项按4计算
+        int effectiveCount = commonList.stream()
+                .mapToInt(item -> item.getStackAddr() == null || item.getStackAddr().isEmpty() ? 1 : 4)
+                .sum();
+
+        if ("上若".equals(destination)) {
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() - effectiveCount);
+            hotsend.setRolloutshippNum(hotsend.getRolloutshippNum() + effectiveCount);
+        } else if ("棒二".equals(destination)) {
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() - effectiveCount);
+            hotsend.setRollclubtwoNum(hotsend.getRollclubtwoNum() + effectiveCount);
+        } else if ("棒三".equals(destination)) {
+            hotsend.setRollDeputyCrossNum(hotsend.getRollDeputyCrossNum() - effectiveCount);
+            hotsend.setRollclubthreeNum(hotsend.getRollclubthreeNum() + effectiveCount);
         }
     }
 
@@ -6082,6 +6213,33 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         rollClubThreeDetailsService.saveBatch(rollClubThreeDetailsList);
     }
 
+    /**
+     * 保存付跨明细信息
+     */
+    private void saveRollDeputyCrossDetails(List<? extends Object> parentList, List<? extends Object> detailsList) {
+        // 保存付跨主表信息
+        List<RollDeputyCross> rollDeputyCrossList = new ArrayList<>();
+        parentList.forEach(x -> {
+            RollDeputyCross rollDeputyCross = new RollDeputyCross();
+            BeanUtils.copyProperties(x, rollDeputyCross);
+            rollDeputyCross.setId(String.valueOf(IdWorker.getId()));
+            rollDeputyCross.setUpdateTime(new Date());
+            rollDeputyCrossList.add(rollDeputyCross);
+        });
+        rollDeputyCrossService.saveBatch(rollDeputyCrossList);
+
+        // 保存付跨明细表信息
+        List<RollDeputyCrossDetails> rollDeputyCrossDetailsList = new ArrayList<>();
+        detailsList.forEach(x -> {
+            RollDeputyCrossDetails rollDeputyCrossDetails = new RollDeputyCrossDetails();
+            BeanUtils.copyProperties(x, rollDeputyCrossDetails);
+            rollDeputyCrossDetails.setId(String.valueOf(IdWorker.getId()));
+            rollDeputyCrossDetails.setUpdateTime(new Date());
+            rollDeputyCrossDetailsList.add(rollDeputyCrossDetails);
+        });
+        rollDeputyCrossDetailsService.saveBatch(rollDeputyCrossDetailsList);
+    }
+
     /**
      * 更新钢坯基础信息
      */
@@ -6115,6 +6273,12 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
             } else if ("棒二".equals(destination) && "6".equals(x.getCcmNo().toString())) {
                 x.setBelongTable("roll_club_two");
                 x.setBhtcId("13");
+            } else if ("付跨".equals(destination) && "5".equals(x.getCcmNo().toString())) {
+                x.setBelongTable("roll_deputy_cross");
+                x.setBhtcId("17");
+            } else if ("付跨".equals(destination) && "6".equals(x.getCcmNo().toString())) {
+                x.setBelongTable("roll_deputy_cross");
+                x.setBhtcId("18");
             }
             x.setUpdateTime(new Date());
         });
@@ -7621,6 +7785,70 @@ public class StorageBillServiceImpl extends ServiceImpl<StorageBillMapper, Stora
         }
     }
 
+
+    public void processRollDeputyCrossDetails(List<RollDeputyCrossDetails> rollDeputyCrossDetailsList) {
+        if (CollectionUtils.isEmpty(rollDeputyCrossDetailsList)) {
+            return;
+        }
+
+        // 1. 统一收集所有 billetNo,避免多次查询
+        Set<String> allBilletNos = rollDeputyCrossDetailsList.stream()
+                .map(RollDeputyCrossDetails::getBilletNo)
+                .filter(StringUtils::isNotBlank)
+                .flatMap(billetNo -> Arrays.stream(billetNo.split(",")))
+                .map(String::trim)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toSet());
+
+        // 2. 一次性查询 BilletBasicInfo,避免重复查询数据库
+        Map<String, String> billetToAssemblyMap = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(allBilletNos)) {
+            List<BilletBasicInfo> billetBasicInfoList = billetBasicInfoService.list(
+                    new LambdaQueryWrapper<BilletBasicInfo>().in(BilletBasicInfo::getBilletNo, allBilletNos));
+
+            // 构建 billetNo -> assemblyNumber 映射
+            billetToAssemblyMap = billetBasicInfoList.stream()
+                    .filter(info -> StringUtils.isNotBlank(info.getBilletNo()) && StringUtils.isNotBlank(info.getAssemblyNumber()))
+                    .collect(Collectors.toMap(
+                            BilletBasicInfo::getBilletNo,
+                            BilletBasicInfo::getAssemblyNumber,
+                            (existing, replacement) -> existing // 遇重复保留第一个
+                    ));
+
+        }
+
+        // 3. 遍历 details 并更新 assemblyNumber
+        for (RollDeputyCrossDetails details : rollDeputyCrossDetailsList) {
+            // 解析 billetNo
+            Set<String> billetNoSet = Optional.ofNullable(details.getBilletNo())
+                    .map(billetNo -> Arrays.stream(billetNo.split(","))
+                            .map(String::trim)
+                            .filter(StringUtils::isNotBlank)
+                            .collect(Collectors.toSet()))
+                    .orElse(Collections.emptySet());
+
+            if (billetNoSet.isEmpty()) {
+                continue;
+            }
+
+            // 先加入 details 现有的 assemblyNumber
+            Set<String> assemblySet = new HashSet<>();
+            String existingAssembly = details.getAssemblyNumber();
+            if (StringUtils.isNotBlank(existingAssembly)) {
+                Collections.addAll(assemblySet, existingAssembly.split(","));
+            }
+
+            // 直接从 Map 获取 assemblyNumber,避免重复查询数据库
+            billetNoSet.stream()
+                    .map(billetToAssemblyMap::get)
+                    .filter(StringUtils::isNotBlank)
+                    .forEach(assemblySet::add);
+
+            // 更新 assemblyNumber
+            details.setAssemblyNumber(String.join(",", assemblySet));
+        }
+    }
+
     /**
      * 堆垛数据同步
      * @param billetHotsend