创建排单调用组件创建排单报文结构修改

This commit is contained in:
gaoqr
2026-08-04 11:42:26 +08:00
parent bc899eb693
commit ee1010842b
8 changed files with 196 additions and 16 deletions
@@ -59,6 +59,7 @@ import com.cf.imes.module.executor.enums.ErrorCodeConstants;
import com.cf.imes.module.executor.enums.OrderPlanQueryTypeEnum; import com.cf.imes.module.executor.enums.OrderPlanQueryTypeEnum;
import com.cf.imes.module.executor.enums.OrderStatusEnum; import com.cf.imes.module.executor.enums.OrderStatusEnum;
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderClient; import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderClient;
import com.cf.imes.module.executor.service.plan.producing.ProducingPlanOrderMaterialGroup;
import com.cf.imes.module.system.api.auth.AuthApi; import com.cf.imes.module.system.api.auth.AuthApi;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -76,6 +77,7 @@ import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static com.cf.imes.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
@@ -168,6 +170,8 @@ public class PlanServiceImpl implements PlanService {
String processName = createReqVO.getProcessName(); String processName = createReqVO.getProcessName();
List<PlanDO> planDOS = new ArrayList<>(); List<PlanDO> planDOS = new ArrayList<>();
Map<Long, ProducingPlanOrderMaterialGroup> producingMaterialGroupByPlanId =
new HashMap<>();
SavePlanPlateList savePlanPlateList = Optional.ofNullable(createReqVO.getSavePlanPlateList()).orElseThrow(()-> new ServiceException(PLAN_PLATE_DATA_ERROR)); SavePlanPlateList savePlanPlateList = Optional.ofNullable(createReqVO.getSavePlanPlateList()).orElseThrow(()-> new ServiceException(PLAN_PLATE_DATA_ERROR));
@@ -184,7 +188,9 @@ public class PlanServiceImpl implements PlanService {
List<PlanActualGoodsList> planActualGoodsLists = Optional.ofNullable(createReqVO.getPlanActualGoodsListList()).orElse(new ArrayList<>()); List<PlanActualGoodsList> planActualGoodsLists = Optional.ofNullable(createReqVO.getPlanActualGoodsListList()).orElse(new ArrayList<>());
// 混单时判断是否进行板材对应并创建排单 // 混单时判断是否进行板材对应并创建排单
mixConfigPlateCorresponding(planActualGoodsLists, plateItemList, goodsItemList, planDOS, processId, processName, loginUser, mixedType); mixConfigPlateCorresponding(planActualGoodsLists, plateItemList, goodsItemList,
planDOS, producingMaterialGroupByPlanId, processId, processName,
loginUser, mixedType);
} else { } else {
@@ -195,7 +201,9 @@ public class PlanServiceImpl implements PlanService {
// 查找材质和厚度和颜色相同的大板 // 查找材质和厚度和颜色相同的大板
Map<String, List<Long>> grouped = groupByMaterialAndThicknessAndColorAndBrand(goodsItemList); Map<String, List<Long>> grouped = groupByMaterialAndThicknessAndColorAndBrand(goodsItemList);
createPlanAndPlateDataList(grouped, plateItemList, planDOS, processId, processName, loginUser, PlanTypeEnum.ORDERPLAN.getType()); createPlanAndPlateDataList(grouped, plateItemList, goodsItemList, planDOS,
producingMaterialGroupByPlanId, processId, processName, loginUser,
PlanTypeEnum.ORDERPLAN.getType());
} }
// 计算排单的数量和面积 // 计算排单的数量和面积
if (CollUtil.isNotEmpty(planDOS)) { if (CollUtil.isNotEmpty(planDOS)) {
@@ -211,7 +219,7 @@ public class PlanServiceImpl implements PlanService {
} }
// 增加排单 // 增加排单
planMapper.insertBatch(planDOS); planMapper.insertBatch(planDOS);
createProducingPlanOrders(planDOS); createProducingPlanOrders(planDOS, producingMaterialGroupByPlanId);
} }
} }
@@ -1629,6 +1637,7 @@ public class PlanServiceImpl implements PlanService {
List<SavePlanPlateList.PlateItemList> plateItemList, List<SavePlanPlateList.PlateItemList> plateItemList,
List<SavePlanPlateList.GoodsItemList> goodsItemList, List<SavePlanPlateList.GoodsItemList> goodsItemList,
List<PlanDO> planDOS, List<PlanDO> planDOS,
Map<Long, ProducingPlanOrderMaterialGroup> producingMaterialGroupByPlanId,
Long processId, Long processId,
String processName, String processName,
LoginUser loginUser, LoginUser loginUser,
@@ -1640,14 +1649,17 @@ public class PlanServiceImpl implements PlanService {
if(CollUtil.isNotEmpty(planActualGoodsLists)) { if(CollUtil.isNotEmpty(planActualGoodsLists)) {
// 有选实际大板的小板加大板创建排单 // 有选实际大板的小板加大板创建排单
getCreatePlanMultipleGoodsList(planActualGoodsLists, plateItemList, planDOS, processId, processName, loginUser); getCreatePlanMultipleGoodsList(planActualGoodsLists, plateItemList, planDOS,
producingMaterialGroupByPlanId, processId, processName, loginUser);
// 不用混单的材质按goodsCode商品编码分组 // 不用混单的材质按goodsCode商品编码分组
grouped = groupByGoodsCodeEqualToOne(goodsItemList); grouped = groupByGoodsCodeEqualToOne(goodsItemList);
if (CollUtil.isNotEmpty(grouped)) { if (CollUtil.isNotEmpty(grouped)) {
createPlanAndPlateDataList(grouped, plateItemList, planDOS, processId, processName, loginUser, PlanTypeEnum.ORDERPLAN.getType()); createPlanAndPlateDataList(grouped, plateItemList, goodsItemList, planDOS,
producingMaterialGroupByPlanId, processId, processName, loginUser,
PlanTypeEnum.ORDERPLAN.getType());
} }
} else { } else {
@@ -1655,7 +1667,9 @@ public class PlanServiceImpl implements PlanService {
grouped = groupByGoodsCodeEqualToOne(goodsItemList); grouped = groupByGoodsCodeEqualToOne(goodsItemList);
if (CollUtil.isNotEmpty(grouped)) { if (CollUtil.isNotEmpty(grouped)) {
createPlanAndPlateDataList(grouped, plateItemList, planDOS, processId, processName, loginUser, PlanTypeEnum.ORDERPLAN.getType()); createPlanAndPlateDataList(grouped, plateItemList, goodsItemList, planDOS,
producingMaterialGroupByPlanId, processId, processName, loginUser,
PlanTypeEnum.ORDERPLAN.getType());
} }
} }
@@ -1721,6 +1735,7 @@ public class PlanServiceImpl implements PlanService {
private void getCreatePlanMultipleGoodsList(List<PlanActualGoodsList> planActualGoodsLists, private void getCreatePlanMultipleGoodsList(List<PlanActualGoodsList> planActualGoodsLists,
List<SavePlanPlateList.PlateItemList> plateItemList, List<SavePlanPlateList.PlateItemList> plateItemList,
List<PlanDO> planDOS, List<PlanDO> planDOS,
Map<Long, ProducingPlanOrderMaterialGroup> producingMaterialGroupByPlanId,
Long processId, Long processId,
String processName, String processName,
LoginUser loginUser) { LoginUser loginUser) {
@@ -1782,6 +1797,8 @@ public class PlanServiceImpl implements PlanService {
.build(); .build();
planDOS.add(planDO); planDOS.add(planDO);
producingMaterialGroupByPlanId.put(planId,
toProducingMaterialGroup(planId, f.getPlanActualGoodsModelDO()));
} }
// 统计更新order_goods的数量和面积 // 统计更新order_goods的数量和面积
computePlatePlanAndComputeOrderGoodsInfo(allGoodsIds); computePlatePlanAndComputeOrderGoodsInfo(allGoodsIds);
@@ -1794,7 +1811,9 @@ public class PlanServiceImpl implements PlanService {
private void createPlanAndPlateDataList(Map<String, List<Long>> grouped, private void createPlanAndPlateDataList(Map<String, List<Long>> grouped,
List<SavePlanPlateList.PlateItemList> plateItemList, List<SavePlanPlateList.PlateItemList> plateItemList,
List<SavePlanPlateList.GoodsItemList> goodsItemList,
List<PlanDO> planDOS, List<PlanDO> planDOS,
Map<Long, ProducingPlanOrderMaterialGroup> producingMaterialGroupByPlanId,
Long processId, Long processId,
String processName, String processName,
LoginUser loginUser, LoginUser loginUser,
@@ -1855,6 +1874,11 @@ public class PlanServiceImpl implements PlanService {
.build(); .build();
planDOS.add(planDO); planDOS.add(planDO);
goodsItemList.stream()
.filter(goods -> value.contains(goods.getId()))
.findFirst()
.ifPresent(goods -> producingMaterialGroupByPlanId.put(planId,
toProducingMaterialGroup(planId, goods)));
} }
// 统计更新order_goods的数量和面积 // 统计更新order_goods的数量和面积
computePlatePlanAndComputeOrderGoodsInfo(allGoodsIds); computePlatePlanAndComputeOrderGoodsInfo(allGoodsIds);
@@ -1973,7 +1997,9 @@ public class PlanServiceImpl implements PlanService {
/** /**
* 为包含组件来源板件的本地排单创建组件生产排单。 * 为包含组件来源板件的本地排单创建组件生产排单。
*/ */
private void createProducingPlanOrders(List<PlanDO> plans) { private void createProducingPlanOrders(
List<PlanDO> plans,
Map<Long, ProducingPlanOrderMaterialGroup> materialGroupByPlanId) {
String token = null; String token = null;
for (PlanDO plan : plans) { for (PlanDO plan : plans) {
List<String> sourceBlockIds = getSourceBlockIdsByPlanId(plan.getId()); List<String> sourceBlockIds = getSourceBlockIdsByPlanId(plan.getId());
@@ -1984,11 +2010,17 @@ public class PlanServiceImpl implements PlanService {
throw new ServiceException(PRODUCING_PLAN_ORDER_SYNC_FAILED, throw new ServiceException(PRODUCING_PLAN_ORDER_SYNC_FAILED,
"workflowSchemeId is required"); "workflowSchemeId is required");
} }
ProducingPlanOrderMaterialGroup materialGroup =
materialGroupByPlanId.get(plan.getId());
if (materialGroup == null) {
throw new ServiceException(PRODUCING_PLAN_ORDER_SYNC_FAILED,
"customMaterialGroupList is required");
}
if (token == null) { if (token == null) {
token = getProducingToken(); token = getProducingToken();
} }
Long producingPlanOrderId = producingPlanOrderClient.create( Long producingPlanOrderId = producingPlanOrderClient.create(
token, plan.getProcessId(), sourceBlockIds); token, plan.getProcessId(), sourceBlockIds, List.of(materialGroup));
plan.setProducingPlanOrderId(producingPlanOrderId); plan.setProducingPlanOrderId(producingPlanOrderId);
planMapper.update(new LambdaUpdateWrapper<PlanDO>() planMapper.update(new LambdaUpdateWrapper<PlanDO>()
.eq(PlanDO::getId, plan.getId()) .eq(PlanDO::getId, plan.getId())
@@ -1997,6 +2029,62 @@ public class PlanServiceImpl implements PlanService {
} }
} }
/**
* 根据普通排单使用的材质属性构建组件生产系统自定义材质分组。
*/
private ProducingPlanOrderMaterialGroup toProducingMaterialGroup(
Long planId, SavePlanPlateList.GoodsItemList goods) {
return ProducingPlanOrderMaterialGroup.builder()
.id(goods.getGoodsId())
.name(buildProducingMaterialGroupName(
planId, null, goods.getMaterial(), goods.getColor(), goods.getThickness()))
.type(1)
.thickness(goods.getThickness())
.hasWave(goods.getTexture())
.materialIds(Collections.emptyList())
.brand(goods.getBrand())
.material(goods.getMaterial())
.color(goods.getColor())
.build();
}
/**
* 根据混单选择的实际大板属性构建组件生产系统自定义材质分组。
*/
private ProducingPlanOrderMaterialGroup toProducingMaterialGroup(
Long planId, PlanActualGoodsModelDO goods) {
return ProducingPlanOrderMaterialGroup.builder()
.id(goods.getGoodsId())
.name(buildProducingMaterialGroupName(
planId, goods.getGoodsName(), goods.getMaterial(),
goods.getColor(), goods.getThickness()))
.type(1)
.thickness(goods.getThickness())
.materialIds(Collections.emptyList())
.brand(goods.getBrand())
.material(goods.getMaterial())
.color(goods.getColor())
.build();
}
/**
* 生成对方接口必填的材质分组名称。
*/
private String buildProducingMaterialGroupName(
Long planId, String goodsName, String material, String color, BigDecimal thickness) {
if (StringUtils.isNotBlank(goodsName)) {
return goodsName;
}
String generatedName = Stream.of(
material,
color,
thickness == null ? null : thickness.stripTrailingZeros().toPlainString())
.filter(StringUtils::isNotBlank)
.collect(Collectors.joining("-"));
return StringUtils.isNotBlank(generatedName)
? generatedName : String.valueOf(planId);
}
/** /**
* 向已有组件生产排单追加板件。 * 向已有组件生产排单追加板件。
* *
@@ -39,8 +39,12 @@ public class ProducingPlanOrderClient {
.build(); .build();
} }
public Long create(String token, Long workflowSchemeId, List<String> blockIds) { public Long create(String token, Long workflowSchemeId, List<String> blockIds,
CreateRequest request = new CreateRequest(blockIds, workflowSchemeId); List<ProducingPlanOrderMaterialGroup> customMaterialGroupList) {
CreateRequest request = new CreateRequest(
blockIds, workflowSchemeId, customMaterialGroupList);
log.info("Submitting producing plan order customMaterialGroupList={}",
serialize(customMaterialGroupList));
HttpResponse<String> response = send( HttpResponse<String> response = send(
properties.getBaseUrl(), token, "POST", serialize(request), "create"); properties.getBaseUrl(), token, "POST", serialize(request), "create");
try { try {
@@ -175,6 +179,7 @@ public class ProducingPlanOrderClient {
private static class CreateRequest { private static class CreateRequest {
private List<String> blockIds; private List<String> blockIds;
private Long workflowSchemeId; private Long workflowSchemeId;
private List<ProducingPlanOrderMaterialGroup> customMaterialGroupList;
} }
@Data @Data
@@ -0,0 +1,63 @@
package com.cf.imes.module.executor.service.plan.producing;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
/**
* 组件生产系统创建生产排单时使用的自定义材质分组。
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ProducingPlanOrderMaterialGroup {
/** 自定义材质分组 ID。 */
private String id;
/** 物料名称。 */
private String name;
/** 物料类型,1 表示板材。 */
private Integer type;
/** 板材宽度。 */
private BigDecimal width;
/** 板材长度。 */
private BigDecimal length;
/** 板材厚度。 */
private BigDecimal thickness;
/** 是否有纹路。 */
private Boolean hasWave;
/** 分组下的物料 ID 列表,当前按接口约定暂不填充。 */
private List<String> materialIds;
/** 备注。 */
private String remark;
/** 厂家。 */
private String factory;
/** 品牌。 */
private String brand;
/** 规格。 */
private String spec;
/** 材料。 */
private String material;
/** 颜色。 */
private String color;
}
@@ -15,7 +15,7 @@ import java.time.Duration;
public class ProducingPlanOrderProperties { public class ProducingPlanOrderProperties {
private String baseUrl = private String baseUrl =
"http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/plan-order"; "https://chenfeng.tech:38113/api-branch=opt_split_order/api/v1/producing/plan-order";
private Duration connectTimeout = Duration.ofSeconds(5); private Duration connectTimeout = Duration.ofSeconds(5);
@@ -42,7 +42,21 @@ class ProducingPlanOrderClientTest {
@Test @Test
void shouldUseSourceBlockIdsForAllFourOperations() throws Exception { void shouldUseSourceBlockIdsForAllFourOperations() throws Exception {
Long remotePlanId = client.create("mes-token", 36L, List.of("source-1", "source-2")); ProducingPlanOrderMaterialGroup materialGroup =
ProducingPlanOrderMaterialGroup.builder()
.id("goods-1")
.name("颗粒板-白色-18")
.type(1)
.thickness(new java.math.BigDecimal("18"))
.hasWave(true)
.materialIds(List.of())
.brand("测试品牌")
.material("颗粒板")
.color("白色")
.build();
Long remotePlanId = client.create(
"mes-token", 36L, List.of("source-1", "source-2"),
List.of(materialGroup));
client.appendBlocks("mes-token", remotePlanId, List.of("source-3")); client.appendBlocks("mes-token", remotePlanId, List.of("source-3"));
client.deleteBlocks("mes-token", remotePlanId, List.of("source-2")); client.deleteBlocks("mes-token", remotePlanId, List.of("source-2"));
client.delete("mes-token", remotePlanId); client.delete("mes-token", remotePlanId);
@@ -64,6 +78,12 @@ class ProducingPlanOrderClientTest {
assertThat(createBody.get("workflowSchemeId").longValue()).isEqualTo(36L); assertThat(createBody.get("workflowSchemeId").longValue()).isEqualTo(36L);
assertThat(createBody.get("blockIds").toString()) assertThat(createBody.get("blockIds").toString())
.isEqualTo("[\"source-1\",\"source-2\"]"); .isEqualTo("[\"source-1\",\"source-2\"]");
JsonNode materialBody = createBody.get("customMaterialGroupList").get(0);
assertThat(materialBody.get("id").textValue()).isEqualTo("goods-1");
assertThat(materialBody.get("name").textValue()).isEqualTo("颗粒板-白色-18");
assertThat(materialBody.get("materialIds").isArray()).isTrue();
assertThat(materialBody.get("materialIds").isEmpty()).isTrue();
assertThat(materialBody.get("material").textValue()).isEqualTo("颗粒板");
assertThat(objectMapper.readTree(requests.get(1).body()) assertThat(objectMapper.readTree(requests.get(1).body())
.get("appendBlockIds").get(0).textValue()).isEqualTo("source-3"); .get("appendBlockIds").get(0).textValue()).isEqualTo("source-3");
assertThat(objectMapper.readTree(requests.get(2).body()) assertThat(objectMapper.readTree(requests.get(2).body())
@@ -646,9 +646,9 @@ public class ProducingOrderImportFactory {
// 缓存goodCode和orderGoodsId的对应关系 // 缓存goodCode和orderGoodsId的对应关系
materialMap.put(plateGoodsGoodsId, goodsDO); materialMap.put(plateGoodsGoodsId, goodsDO);
} }
if (StringUtils.isNotEmpty(materialReqVO.getSourceMaterialId())) { if (StringUtils.isNotEmpty(plateGoodsGoodsId)) {
externalMaterialMap.putIfAbsent( externalMaterialMap.putIfAbsent(
materialReqVO.getSourceMaterialId(), plateGoodsGoodsId,
toExternalBlockMaterial(materialReqVO)); toExternalBlockMaterial(materialReqVO));
} }
} }
@@ -32,7 +32,9 @@ public class ProducingOrderExtraSyncRequest {
private Map<String, String> parts = new LinkedHashMap<>(); private Map<String, String> parts = new LinkedHashMap<>();
/** /**
* 对方 materials.id 到 iMES 板材库/配件物料对象的映射,仅包含 type=1/2/3。 * iMES 物料标识到板材库/配件物料对象的映射。板材(type=1)使用
* {@code order_goods.goods_id} 作为 key,配件和封边条(type=2/3)使用对方
* {@code materials.id} 作为 key。
*/ */
@Builder.Default @Builder.Default
private Map<String, ProducingExternalMaterial> externalMaterialMapping = private Map<String, ProducingExternalMaterial> externalMaterialMapping =
@@ -29,7 +29,9 @@ public class ProducingOrderItemSerialNoUpdateRequest {
private Map<String, String> parts = new LinkedHashMap<>(); private Map<String, String> parts = new LinkedHashMap<>();
/** /**
* 对方 materials.id 到 iMES 板材库/配件物料对象的映射。 * iMES 物料标识到板材库/配件物料对象的映射。板材(type=1)使用
* {@code order_goods.goods_id} 作为 key,配件和封边条(type=2/3)使用对方
* {@code materials.id} 作为 key。
*/ */
private Map<String, ProducingExternalMaterial> externalMaterialMapping = private Map<String, ProducingExternalMaterial> externalMaterialMapping =
new LinkedHashMap<>(); new LinkedHashMap<>();