mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
组件业务数据拉取增加成倍数量记录、部分算法优化
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ public class ProducingOrderImportReqVO {
|
|||||||
private Long targetOrderId;
|
private Long targetOrderId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对方板材 ID 与 iMES 板材库 plate.id 的一对一映射。
|
* 对方板材 ID 与 iMES 板材库 plate.id 的映射;多个对方板材可复用同一 iMES 板材。
|
||||||
*/
|
*/
|
||||||
@Schema(description = "组件系统板材与 iMES 板材映射", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "组件系统板材与 iMES 板材映射", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@Valid
|
@Valid
|
||||||
|
|||||||
+8
-27
@@ -938,17 +938,14 @@ public class ProducingOrderImportFactory {
|
|||||||
// 获取自定义板编号配置
|
// 获取自定义板编号配置
|
||||||
plateNoGenerateConfigVO = customPlateNoGenerateService.getPlateNoGenerateConfig(orderId);
|
plateNoGenerateConfigVO = customPlateNoGenerateService.getPlateNoGenerateConfig(orderId);
|
||||||
|
|
||||||
// 所有房间名
|
// 一次性查询目标订单的全部已有房间,供板件和配件导入共同复用。
|
||||||
List<String> roomNames = douleRoomTree.stream().map(ProducingImportRoomTree::getName).collect(Collectors.toList());
|
// 配件可能位于本次板件数据未包含的房间,因此这里不能只按本次报文房间名查询。
|
||||||
|
|
||||||
// 查询当前订单的所有房间
|
|
||||||
existRoomIdMap = orderBodyMapper.selectMaps(
|
existRoomIdMap = orderBodyMapper.selectMaps(
|
||||||
new QueryWrapper<OrderBodyDO>()
|
new QueryWrapper<OrderBodyDO>()
|
||||||
.select("room_name,MIN(room_id) as room_id")
|
.select("room_name,MIN(room_id) as room_id")
|
||||||
.eq(ORDER_ID_FIELD, orderId)
|
.eq(ORDER_ID_FIELD, orderId)
|
||||||
.eq(ORGAN_ID_FIELD, organId)
|
.eq(ORGAN_ID_FIELD, organId)
|
||||||
.eq(DELETED_FIELD, false)
|
.eq(DELETED_FIELD, false)
|
||||||
.in(ROOM_NAME_FIELD, roomNames)
|
|
||||||
.groupBy(ROOM_NAME_FIELD)).stream()
|
.groupBy(ROOM_NAME_FIELD)).stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
m -> String.valueOf(m.get(ROOM_NAME_FIELD)),
|
m -> String.valueOf(m.get(ROOM_NAME_FIELD)),
|
||||||
@@ -1005,7 +1002,11 @@ public class ProducingOrderImportFactory {
|
|||||||
OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId)
|
OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId)
|
||||||
.roomId(roomId).roomName(roomName).name(boxName)
|
.roomId(roomId).roomName(roomName).name(boxName)
|
||||||
.width(getZeroDouble(box.getWidth())).height(getZeroDouble(box.getHeight()))
|
.width(getZeroDouble(box.getWidth())).height(getZeroDouble(box.getHeight()))
|
||||||
.depth(0.0).multiNum(count).multiSort(i + 1).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build();
|
.depth(0.0)
|
||||||
|
.multiNum(box.getMultiNum() == null ? count : box.getMultiNum())
|
||||||
|
.multiSort(box.getMultiSort() == null ? i + 1 : box.getMultiSort())
|
||||||
|
.plateNum(0).unregularNum(0).filename("无").remark("无")
|
||||||
|
.deleted(false).build();
|
||||||
orderBodyDO.setCreator(operatorName);
|
orderBodyDO.setCreator(operatorName);
|
||||||
orderBodyDO.setDepth(getZeroDouble(box.getDepth()));
|
orderBodyDO.setDepth(getZeroDouble(box.getDepth()));
|
||||||
orderBodyDO.setUpdater(operatorName);
|
orderBodyDO.setUpdater(operatorName);
|
||||||
@@ -1757,30 +1758,10 @@ public class ProducingOrderImportFactory {
|
|||||||
if (ObjectUtil.isNotNull(existRoomId)) {
|
if (ObjectUtil.isNotNull(existRoomId)) {
|
||||||
roomId = existRoomId;
|
roomId = existRoomId;
|
||||||
} else {
|
} else {
|
||||||
// 可能有配件房间柜体不在板件的情况,再查一次
|
// 目标订单的已有房间已在板件解析开始时一次性加载;未命中即为新房间。
|
||||||
// 查询当前订单的所有房间
|
|
||||||
List<String> roomNames = parts.stream().map(ProducingImportRoomTree::getName).collect(Collectors.toList());
|
|
||||||
|
|
||||||
Map<String, Long> existPartsRoomIdMap = orderBodyMapper.selectMaps(
|
|
||||||
new QueryWrapper<OrderBodyDO>()
|
|
||||||
.select("room_name,MIN(room_id) as room_id")
|
|
||||||
.eq(ORDER_ID_FIELD, orderId)
|
|
||||||
.eq(ORGAN_ID_FIELD, organId)
|
|
||||||
.eq(DELETED_FIELD, false)
|
|
||||||
.in(ROOM_NAME_FIELD, roomNames)
|
|
||||||
.groupBy(ROOM_NAME_FIELD)).stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
m -> String.valueOf(m.get(ROOM_NAME_FIELD)),
|
|
||||||
m -> ((Number) m.get("room_id")).longValue()
|
|
||||||
));
|
|
||||||
Long existPartRoomId = existPartsRoomIdMap.get(roomName);
|
|
||||||
if (ObjectUtil.isNotNull(existPartRoomId)) {
|
|
||||||
roomId = existPartRoomId;
|
|
||||||
} else {
|
|
||||||
roomId = (Long) snowFlakeGenerator.nextId(null);
|
roomId = (Long) snowFlakeGenerator.nextId(null);
|
||||||
existRoomIdMap.put(roomName, roomId);
|
existRoomIdMap.put(roomName, roomId);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 柜体列表
|
// 柜体列表
|
||||||
List<ProducingImportRoomTree.ChildrenDTO> roomBoxs = room.getChildren();
|
List<ProducingImportRoomTree.ChildrenDTO> roomBoxs = room.getChildren();
|
||||||
|
|||||||
+83
-14
@@ -142,6 +142,9 @@ public class ProducingOrderConverter {
|
|||||||
context.groupTypes = filterModules(order, 3);
|
context.groupTypes = filterModules(order, 3);
|
||||||
context.groups = filterModules(order, 4);
|
context.groups = filterModules(order, 4);
|
||||||
context.components = filterModules(order, 5);
|
context.components = filterModules(order, 5);
|
||||||
|
context.bodiesByRoomId = indexModulesByParentId(context.bodies);
|
||||||
|
context.componentsByParentId = indexModulesByParentId(context.components);
|
||||||
|
context.bodyMultiplicities = resolveBodyMultiplicities(context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,21 +180,31 @@ public class ProducingOrderConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验板材映射为双方一对一关系,且来源物料必须是 type=1 板材。
|
* 按父节点 ID 建立模块子节点索引,避免按房间或部件组递归处理时重复扫描全部模块。
|
||||||
|
* 子节点列表沿用对方报文顺序,不改变柜体或部件组落库顺序。
|
||||||
|
*/
|
||||||
|
private Map<String, List<ProducingOrderResponse.Module>> indexModulesByParentId(
|
||||||
|
Map<String, ProducingOrderResponse.Module> modules) {
|
||||||
|
Map<String, List<ProducingOrderResponse.Module>> result = new LinkedHashMap<>();
|
||||||
|
for (ProducingOrderResponse.Module module : modules.values()) {
|
||||||
|
result.computeIfAbsent(module.getParentId(), key -> new ArrayList<>())
|
||||||
|
.add(module);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验每个对方板材只提交一次且来源物料必须是 type=1 板材。
|
||||||
|
* 多个对方板材允许映射到同一个 iMES 板材。
|
||||||
*/
|
*/
|
||||||
private void validateMappings(List<ProducingOrderImportReqVO.MaterialMapping> mappings,
|
private void validateMappings(List<ProducingOrderImportReqVO.MaterialMapping> mappings,
|
||||||
Map<String, ProducingOrderResponse.Material> materials) {
|
Map<String, ProducingOrderResponse.Material> materials) {
|
||||||
Set<String> sourceIds = new HashSet<>();
|
Set<String> sourceIds = new HashSet<>();
|
||||||
Set<Long> localIds = new HashSet<>();
|
|
||||||
for (ProducingOrderImportReqVO.MaterialMapping mapping : mappings) {
|
for (ProducingOrderImportReqVO.MaterialMapping mapping : mappings) {
|
||||||
if (!sourceIds.add(mapping.getSourceMaterialId())) {
|
if (!sourceIds.add(mapping.getSourceMaterialId())) {
|
||||||
throw new ServiceException(PRODUCING_ORDER_MATERIAL_MAPPING_INVALID,
|
throw new ServiceException(PRODUCING_ORDER_MATERIAL_MAPPING_INVALID,
|
||||||
"duplicate source material " + mapping.getSourceMaterialId());
|
"duplicate source material " + mapping.getSourceMaterialId());
|
||||||
}
|
}
|
||||||
if (!localIds.add(mapping.getPlateId())) {
|
|
||||||
throw new ServiceException(PRODUCING_ORDER_MATERIAL_MAPPING_INVALID,
|
|
||||||
"duplicate iMES plate " + mapping.getPlateId());
|
|
||||||
}
|
|
||||||
ProducingOrderResponse.Material material = materials.get(mapping.getSourceMaterialId());
|
ProducingOrderResponse.Material material = materials.get(mapping.getSourceMaterialId());
|
||||||
if (material == null || !Objects.equals(material.getType(), 1)) {
|
if (material == null || !Objects.equals(material.getType(), 1)) {
|
||||||
throw new ServiceException(PRODUCING_ORDER_MATERIAL_MAPPING_INVALID,
|
throw new ServiceException(PRODUCING_ORDER_MATERIAL_MAPPING_INVALID,
|
||||||
@@ -500,10 +513,9 @@ public class ProducingOrderConverter {
|
|||||||
size.setDepth(zero(sourceSize == null ? null : sourceSize.getDepth()));
|
size.setDepth(zero(sourceSize == null ? null : sourceSize.getDepth()));
|
||||||
target.setBoxSize(size);
|
target.setBoxSize(size);
|
||||||
List<ProducingImportComponentGroup> children = new ArrayList<>();
|
List<ProducingImportComponentGroup> children = new ArrayList<>();
|
||||||
for (ProducingOrderResponse.Module candidate : context.components.values()) {
|
for (ProducingOrderResponse.Module child : context.componentsByParentId
|
||||||
if (Objects.equals(candidate.getParentId(), source.getId())) {
|
.getOrDefault(source.getId(), Collections.emptyList())) {
|
||||||
children.add(toComponent(candidate, context));
|
children.add(toComponent(child, context));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
target.setChildren(children);
|
target.setChildren(children);
|
||||||
return target;
|
return target;
|
||||||
@@ -1012,14 +1024,17 @@ public class ProducingOrderConverter {
|
|||||||
targetRoom.setName(room.getName());
|
targetRoom.setName(room.getName());
|
||||||
targetRoom.setCount(1);
|
targetRoom.setCount(1);
|
||||||
List<ProducingImportRoomTree.ChildrenDTO> children = new ArrayList<>();
|
List<ProducingImportRoomTree.ChildrenDTO> children = new ArrayList<>();
|
||||||
for (ProducingOrderResponse.Module body : context.bodies.values()) {
|
for (ProducingOrderResponse.Module body : context.bodiesByRoomId
|
||||||
if (!Objects.equals(body.getParentId(), room.getId())) {
|
.getOrDefault(room.getId(), Collections.emptyList())) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ProducingImportRoomTree.ChildrenDTO child =
|
ProducingImportRoomTree.ChildrenDTO child =
|
||||||
new ProducingImportRoomTree.ChildrenDTO();
|
new ProducingImportRoomTree.ChildrenDTO();
|
||||||
child.setName(body.getName());
|
child.setName(body.getName());
|
||||||
child.setIdentityKey("producing:" + body.getId());
|
child.setIdentityKey("producing:" + body.getId());
|
||||||
|
BodyMultiplicity multiplicity =
|
||||||
|
context.bodyMultiplicities.get(body.getId());
|
||||||
|
child.setMultiNum(multiplicity.multiNum());
|
||||||
|
child.setMultiSort(multiplicity.multiSort());
|
||||||
|
// 对方已按成倍数量展开柜体及生产项,工厂不得再次复制。
|
||||||
child.setCount(1);
|
child.setCount(1);
|
||||||
ProducingOrderResponse.Size3D bodySize =
|
ProducingOrderResponse.Size3D bodySize =
|
||||||
body.getExtra() == null ? null : body.getExtra().getSize();
|
body.getExtra() == null ? null : body.getExtra().getSize();
|
||||||
@@ -1038,6 +1053,48 @@ public class ProducingOrderConverter {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析对方已展开的成倍柜体,并为每个柜体计算成倍总数及组内顺序。
|
||||||
|
*
|
||||||
|
* <p>{@code multipleNum} 只出现在成倍组的首个 type=2 柜体上;随后
|
||||||
|
* {@code multipleNum - 1} 个同房间、同名柜体是其余实体。各柜体下的
|
||||||
|
* {@code blockItems}/{@code partsItems} 已具有独立 ID,因此这里只生成
|
||||||
|
* 展示和统计元数据,不再放大生产项数量。</p>
|
||||||
|
*/
|
||||||
|
private Map<String, BodyMultiplicity> resolveBodyMultiplicities(Context context) {
|
||||||
|
Map<String, BodyMultiplicity> result = new HashMap<>();
|
||||||
|
for (ProducingOrderResponse.Module room : context.rooms.values()) {
|
||||||
|
List<ProducingOrderResponse.Module> roomBodies = context.bodiesByRoomId
|
||||||
|
.getOrDefault(room.getId(), Collections.emptyList());
|
||||||
|
for (int index = 0; index < roomBodies.size();) {
|
||||||
|
ProducingOrderResponse.Module first = roomBodies.get(index);
|
||||||
|
Integer declaredMultiple = first.getExtra() == null
|
||||||
|
? null : first.getExtra().getMultipleNum();
|
||||||
|
int multiNum = declaredMultiple == null ? 1 : declaredMultiple;
|
||||||
|
if (multiNum < 1 || index + multiNum > roomBodies.size()) {
|
||||||
|
throw new ServiceException(PRODUCING_ORDER_RESPONSE_INVALID,
|
||||||
|
"module " + first.getId()
|
||||||
|
+ " has invalid multipleNum=" + declaredMultiple);
|
||||||
|
}
|
||||||
|
for (int offset = 0; offset < multiNum; offset++) {
|
||||||
|
ProducingOrderResponse.Module member = roomBodies.get(index + offset);
|
||||||
|
Integer memberMultiple = member.getExtra() == null
|
||||||
|
? null : member.getExtra().getMultipleNum();
|
||||||
|
if (!Objects.equals(first.getName(), member.getName())
|
||||||
|
|| (offset > 0 && memberMultiple != null)) {
|
||||||
|
throw new ServiceException(PRODUCING_ORDER_RESPONSE_INVALID,
|
||||||
|
"module " + first.getId()
|
||||||
|
+ " multiple group is not contiguous");
|
||||||
|
}
|
||||||
|
result.put(member.getId(),
|
||||||
|
new BodyMultiplicity(multiNum, offset + 1));
|
||||||
|
}
|
||||||
|
index += multiNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将实例级键值备注转换为板件备注二维列表。
|
* 将实例级键值备注转换为板件备注二维列表。
|
||||||
*/
|
*/
|
||||||
@@ -1411,5 +1468,17 @@ public class ProducingOrderConverter {
|
|||||||
private Map<String, ProducingOrderResponse.Module> groupTypes;
|
private Map<String, ProducingOrderResponse.Module> groupTypes;
|
||||||
private Map<String, ProducingOrderResponse.Module> groups;
|
private Map<String, ProducingOrderResponse.Module> groups;
|
||||||
private Map<String, ProducingOrderResponse.Module> components;
|
private Map<String, ProducingOrderResponse.Module> components;
|
||||||
|
private Map<String, List<ProducingOrderResponse.Module>> bodiesByRoomId;
|
||||||
|
private Map<String, List<ProducingOrderResponse.Module>> componentsByParentId;
|
||||||
|
private Map<String, BodyMultiplicity> bodyMultiplicities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已展开柜体的成倍元数据。
|
||||||
|
*
|
||||||
|
* @param multiNum 成倍组总数量
|
||||||
|
* @param multiSort 当前柜体在组内的顺序
|
||||||
|
*/
|
||||||
|
private record BodyMultiplicity(int multiNum, int multiSort) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -42,6 +42,18 @@ public class ProducingImportRoomTree {
|
|||||||
|
|
||||||
private Double depth;
|
private Double depth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已展开柜体所属成倍组的总数量。
|
||||||
|
*
|
||||||
|
* <p>该字段只控制 {@code order_body.multi_num},不会再次复制物理生产项。</p>
|
||||||
|
*/
|
||||||
|
private Integer multiNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前已展开柜体在成倍组内的顺序,从 1 开始。
|
||||||
|
*/
|
||||||
|
private Integer multiSort;
|
||||||
|
|
||||||
@NotNull(message = "拆单倍数不能为空")
|
@NotNull(message = "拆单倍数不能为空")
|
||||||
@Max(value = 5000, message = "拆单倍数不能超过5000")
|
@Max(value = 5000, message = "拆单倍数不能超过5000")
|
||||||
@Min(value = 1, message = "拆单倍数最小值为1")
|
@Min(value = 1, message = "拆单倍数最小值为1")
|
||||||
|
|||||||
+5
@@ -86,6 +86,11 @@ public class ProducingOrderResponse {
|
|||||||
public static class ModuleExtra {
|
public static class ModuleExtra {
|
||||||
private Size3D size;
|
private Size3D size;
|
||||||
private Boolean isComposite;
|
private Boolean isComposite;
|
||||||
|
/**
|
||||||
|
* 柜体成倍数量。对方已经按倍数展开柜体模块及物理生产项,
|
||||||
|
* 该字段仅用于还原同组成倍柜体的总数和顺序。
|
||||||
|
*/
|
||||||
|
private Integer multipleNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
Reference in New Issue
Block a user