refactor(anneal): 优化炉火实绩明细数据结构和查询逻辑

- 将WmsAnnealPerformanceDetailVo中的coils列表改为单个coil对象
- 新增parentCoilIds字段支持按父卷ID批量查询加工后钢卷
- 实现通过parentCoilId查找split后子卷的映射逻辑
- 添加直接查询未split原卷的备用查询机制
- 重构详情数据扁平化处理,每个计划钢卷创建独立详情记录
- 优化统计信息重新计算逻辑,准确统计过滤后的计划数量
- 移除WmsMaterialCoilVo中不再使用的furnaceLevel字段
This commit is contained in:
2026-07-11 11:05:06 +08:00
parent 2a611bad19
commit 8fcb852d3d
5 changed files with 102 additions and 52 deletions

View File

@@ -443,5 +443,8 @@ public class WmsMaterialCoilBo extends BaseEntity {
*/ */
@TableField(exist = false) @TableField(exist = false)
private Boolean excludeScheduledDetail; private Boolean excludeScheduledDetail;
@TableField(exist = false)
private String parentCoilIds;
} }

View File

@@ -261,10 +261,10 @@ public class WmsMaterialCoilVo extends BaseEntity {
*/ */
private Integer exclusiveStatus; private Integer exclusiveStatus;
/** // /**
* 炉火层级1=一层2=二层3=三层) // * 炉火层级1=一层2=二层3=三层)
*/ // */
private Integer furnaceLevel; // private Integer furnaceLevel;
/** /**
* 是否已被发货单明细绑定true=不可再次绑定) * 是否已被发货单明细绑定true=不可再次绑定)

View File

@@ -5,7 +5,6 @@ import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* 炉火实绩明细视图对象 * 炉火实绩明细视图对象
@@ -42,5 +41,5 @@ public class WmsAnnealPerformanceDetailVo {
private Integer furnaceLevel; private Integer furnaceLevel;
private List<WmsMaterialCoilVo> coils; private WmsMaterialCoilVo coil;
} }

View File

@@ -3,6 +3,7 @@ package com.klp.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.klp.common.core.domain.PageQuery; import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.domain.bo.WmsAnnealPerformanceBo; import com.klp.domain.bo.WmsAnnealPerformanceBo;
import com.klp.domain.bo.WmsMaterialCoilBo; import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsMaterialCoilVo; import com.klp.domain.vo.WmsMaterialCoilVo;
@@ -86,30 +87,61 @@ public class WmsAnnealPerformanceServiceImpl implements IWmsAnnealPerformanceSer
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
// 批量查询钢卷信息 // 批量查询钢卷信息通过parentCoilId查加工后的卷
Map<Long, WmsMaterialCoilVo> coilVoMap = new HashMap<>(); // 加工后钢卷的parentCoilId指向加工前钢卷的coilId需要以此建立映射
Map<Long, WmsMaterialCoilVo> parentIdToCoilMap = new HashMap<>();
if (!allCoilIds.isEmpty()) { if (!allCoilIds.isEmpty()) {
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo(); WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
coilBo.setCoilIds(allCoilIds.stream().map(String::valueOf).collect(Collectors.joining(","))); coilBo.setParentCoilIds(allCoilIds.stream().map(String::valueOf).collect(Collectors.joining("-")));
PageQuery pageQuery = new PageQuery(); PageQuery pageQuery = new PageQuery();
pageQuery.setPageNum(1); pageQuery.setPageNum(1);
pageQuery.setPageSize(Integer.MAX_VALUE); pageQuery.setPageSize(Integer.MAX_VALUE);
TableDataInfo<WmsMaterialCoilVo> coilPage = materialCoilService.queryPageList(coilBo, pageQuery); TableDataInfo<WmsMaterialCoilVo> coilPage = materialCoilService.queryPageList(coilBo, pageQuery);
if (coilPage != null && coilPage.getRows() != null) { if (coilPage != null && coilPage.getRows() != null) {
for (WmsMaterialCoilVo coilVo : coilPage.getRows()) { for (WmsMaterialCoilVo coilVo : coilPage.getRows()) {
if (coilVo.getCoilId() != null) { // 加工后钢卷的parentCoilId存的是加工前coilId
coilVoMap.put(coilVo.getCoilId(), coilVo); String parentCoilIdStr = coilVo.getParentCoilId();
if (StringUtils.isNotBlank(parentCoilIdStr)) {
for (String pid : parentCoilIdStr.split(",")) {
String trimmed = pid.trim();
if (StringUtils.isNotBlank(trimmed)) {
try {
parentIdToCoilMap.put(Long.parseLong(trimmed), coilVo);
} catch (NumberFormatException e) {
// 忽略无效ID
}
}
}
} }
} }
} }
} }
// 用于重新计算统计信息 // 查询2直接通过coilId查未split的钢卷它们本身就是加工后的卷
Map<Long, WmsMaterialCoilVo> directCoilMap = new HashMap<>();
{
WmsMaterialCoilBo directBo = new WmsMaterialCoilBo();
directBo.setCoilIds(allCoilIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
PageQuery pq = new PageQuery();
pq.setPageNum(1);
pq.setPageSize(Integer.MAX_VALUE);
TableDataInfo<WmsMaterialCoilVo> directPage = materialCoilService.queryPageList(directBo, pq);
if (directPage != null && directPage.getRows() != null) {
for (WmsMaterialCoilVo cv : directPage.getRows()) {
if (cv.getCoilId() != null) {
directCoilMap.put(cv.getCoilId(), cv);
}
}
}
}
// 重新构建details每条detail对应一个计划钢卷logicWarehouseId/furnaceLevel从planCoil获取
List<WmsAnnealPerformanceDetailVo> flatDetails = new ArrayList<>();
Long filteredPlanCount = 0L; Long filteredPlanCount = 0L;
Long filteredCoilCount = 0L; Long filteredCoilCount = 0L;
BigDecimal filteredTotalWeight = BigDecimal.ZERO; BigDecimal filteredTotalWeight = BigDecimal.ZERO;
Set<Long> countedPlanIds = new HashSet<>();
// 处理每个计划
for (WmsAnnealPerformanceDetailVo detail : details) { for (WmsAnnealPerformanceDetailVo detail : details) {
Long planId = detail.getPlanId(); Long planId = detail.getPlanId();
List<WmsFurnacePlanCoil> planCoils = planCoilsMap.get(planId); List<WmsFurnacePlanCoil> planCoils = planCoilsMap.get(planId);
@@ -118,34 +150,22 @@ public class WmsAnnealPerformanceServiceImpl implements IWmsAnnealPerformanceSer
continue; continue;
} }
// 设置出炉时的逻辑库区到detail级别取第一个非空的logicWarehouseId
for (WmsFurnacePlanCoil planCoil : planCoils) {
if (planCoil.getLogicWarehouseId() != null) {
detail.setLogicWarehouseId(planCoil.getLogicWarehouseId());
detail.setLogicWarehouseName(logicWarehouseNameMap.get(planCoil.getLogicWarehouseId()));
break;
}
}
// 为每个钢卷设置炉火层级和钢卷信息(不覆盖钢卷本身的逻辑库区)
List<WmsMaterialCoilVo> coilVos = new ArrayList<>();
for (WmsFurnacePlanCoil planCoil : planCoils) { for (WmsFurnacePlanCoil planCoil : planCoils) {
Long coilId = planCoil.getCoilId(); Long coilId = planCoil.getCoilId();
if (coilId == null) { if (coilId == null) {
continue; continue;
} }
WmsMaterialCoilVo coilVo = coilVoMap.get(coilId); // 优先取split后的子卷没有再取原卷未split场景
WmsMaterialCoilVo coilVo = parentIdToCoilMap.get(coilId);
if (coilVo == null) {
coilVo = directCoilMap.get(coilId);
}
if (coilVo == null) { if (coilVo == null) {
coilVo = new WmsMaterialCoilVo(); coilVo = new WmsMaterialCoilVo();
coilVo.setCoilId(coilId); coilVo.setCoilId(coilId);
} }
// 保持钢卷本身的warehouseId/warehouseName不变不覆盖
// 设置炉火层级
coilVo.setFurnaceLevel(planCoil.getFurnaceLevel());
// 如果传入了筛选条件,只保留匹配的钢卷 // 如果传入了筛选条件,只保留匹配的钢卷
if (bo.getEnterCoilNo() != null && !bo.getEnterCoilNo().isEmpty()) { if (bo.getEnterCoilNo() != null && !bo.getEnterCoilNo().isEmpty()) {
if (coilVo.getEnterCoilNo() == null || if (coilVo.getEnterCoilNo() == null ||
@@ -167,35 +187,38 @@ public class WmsAnnealPerformanceServiceImpl implements IWmsAnnealPerformanceSer
} }
} }
coilVos.add(coilVo); // 为每个planCoil创建独立的detail携带自身的logicWarehouseId/furnaceLevel
} WmsAnnealPerformanceDetailVo coilDetail = new WmsAnnealPerformanceDetailVo();
coilDetail.setPlanId(detail.getPlanId());
coilDetail.setPlanNo(detail.getPlanNo());
coilDetail.setTargetFurnaceId(detail.getTargetFurnaceId());
coilDetail.setTargetFurnaceName(detail.getTargetFurnaceName());
coilDetail.setActualStartTime(detail.getActualStartTime());
coilDetail.setEndTime(detail.getEndTime());
coilDetail.setLogicWarehouseId(planCoil.getLogicWarehouseId());
coilDetail.setLogicWarehouseName(planCoil.getLogicWarehouseId() != null
? logicWarehouseNameMap.get(planCoil.getLogicWarehouseId()) : null);
coilDetail.setFurnaceLevel(planCoil.getFurnaceLevel());
coilDetail.setCoil(coilVo);
flatDetails.add(coilDetail);
// 如果过滤后没有钢卷,跳过该计划 filteredCoilCount++;
if (!coilVos.isEmpty()) { if (coilVo.getNetWeight() != null) {
detail.setCoils(coilVos); filteredTotalWeight = filteredTotalWeight.add(coilVo.getNetWeight());
filteredPlanCount++; }
filteredCoilCount += coilVos.size(); countedPlanIds.add(planId);
BigDecimal planWeight = coilVos.stream()
.map(c -> c.getNetWeight() != null ? c.getNetWeight() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
filteredTotalWeight = filteredTotalWeight.add(planWeight);
} }
} }
// 移除没有钢卷的计划 filteredPlanCount = (long) countedPlanIds.size();
details.removeIf(detail -> detail.getCoils() == null || detail.getCoils().isEmpty());
// 如果传入了筛选条件,重新计算统计信息 // 替换details并重新计算统计信息
if ((bo.getEnterCoilNo() != null && !bo.getEnterCoilNo().isEmpty()) details = flatDetails;
|| (bo.getCurrentCoilNo() != null && !bo.getCurrentCoilNo().isEmpty())
|| bo.getWarehouseId() != null
|| bo.getCoilWarehouseId() != null) {
summary.setPlanCount(filteredPlanCount); summary.setPlanCount(filteredPlanCount);
summary.setCoilCount(filteredCoilCount); summary.setCoilCount(filteredCoilCount);
summary.setTotalWeight(filteredTotalWeight); summary.setTotalWeight(filteredTotalWeight);
} }
} }
}
WmsAnnealPerformanceVo vo = new WmsAnnealPerformanceVo(); WmsAnnealPerformanceVo vo = new WmsAnnealPerformanceVo();
vo.setSummary(summary); vo.setSummary(summary);

View File

@@ -1253,6 +1253,31 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
qw.in("mc.coil_id", coilIdList); qw.in("mc.coil_id", coilIdList);
} }
} }
// 根据parentCoilId筛选查询某个原始钢卷的加工后子卷支持逗号分隔多ID
// 注意此处合卷不能用
if (StringUtils.isNotBlank(bo.getParentCoilIds())) {
String[] parentIdArray = bo.getParentCoilIds().split("-");
List<String> findInSetConditions = new ArrayList<>();
for (String pid : parentIdArray) {
String trimmed = pid.trim();
if (StringUtils.isNotBlank(trimmed)) {
try {
Long.parseLong(trimmed);
findInSetConditions.add("FIND_IN_SET('" + trimmed + "', mc.parent_coil_id)");
} catch (NumberFormatException e) {
// 忽略无效ID
}
}
}
if (!findInSetConditions.isEmpty()) {
qw.and(w -> {
for (int i = 0; i < findInSetConditions.size(); i++) {
if (i > 0) w.or();
w.apply(findInSetConditions.get(i));
}
});
}
}
// // 仅查询未发货且未绑定在发货计划里的钢卷 // // 仅查询未发货且未绑定在发货计划里的钢卷
// if (Boolean.TRUE.equals(bo.getOnlyUnshippedAndUnplanned())) { // if (Boolean.TRUE.equals(bo.getOnlyUnshippedAndUnplanned())) {
// // 未发货:排除状态=1已出库/已发货) // // 未发货:排除状态=1已出库/已发货)