From debac10b906bab141342d8bf2e86cfa196b37691 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Thu, 30 Jul 2026 14:41:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=90=8C=E6=AD=A5=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E8=AE=A2=E5=8D=95=E3=80=81=E5=90=8C=E6=AD=A5=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=9D=BF=E4=BB=B6/=E9=85=8D=E4=BB=B6=E8=83=BD?= =?UTF-8?q?=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/dataobject/orderItem/OrderItemDO.java | 7 +- .../module/plan/enums/ErrorCodeConstants.java | 1 + .../dal/dataobject/orderItem/OrderItemDO.java | 7 +- .../ProducingOrderImportServiceImpl.java | 8 +- ...ducingOrderImportTransactionalService.java | 105 +++++++++++++- .../factory/ProducingOrderImportFactory.java | 33 ++++- .../producing/ProducingOrderClient.java | 132 +++++++++++++++++- .../producing/ProducingOrderConverter.java | 1 + .../producing/dto/ProducingImportPart.java | 5 + .../dto/ProducingOrderApiResult.java | 32 +++++ .../dto/ProducingOrderExtraUpdateRequest.java | 124 ++++++++++++++++ ...oducingOrderItemSerialNoUpdateRequest.java | 30 ++++ ...ducingOrderItemSerialNoUpdateResponse.java | 89 ++++++++++++ .../ProducingOrderImportProperties.java | 20 ++- .../src/main/resources/application-dev.yaml | 3 + .../src/main/resources/application-local.yaml | 3 + .../message_errorcode_cht.properties | 1 + .../resources/message_errorcode_en.properties | 1 + .../resources/message_errorcode_zh.properties | 1 + 19 files changed, 587 insertions(+), 16 deletions(-) create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderApiResult.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderExtraUpdateRequest.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderItemSerialNoUpdateRequest.java create mode 100644 cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderItemSerialNoUpdateResponse.java diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderItem/OrderItemDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderItem/OrderItemDO.java index 9b2014c46..bcaa9740a 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderItem/OrderItemDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/orderItem/OrderItemDO.java @@ -88,6 +88,11 @@ public class OrderItemDO { */ private Integer cadViewId; + /** + * 对方配件实例 {@code partsItems[].id}。 + */ + private String sourcePartsItemId; + /** * 分堆状态 */ @@ -97,4 +102,4 @@ public class OrderItemDO { * 源item id */ private Long sourceId; -} \ No newline at end of file +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java index cda7904a7..b1981432c 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java +++ b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java @@ -34,4 +34,5 @@ public class ErrorCodeConstants { public static final ErrorCode PRODUCING_ORDER_CAD_OBJECT_INVALID = new ErrorCode(1_005_000_024, "producing.order.cad_object.invalid"); public static final ErrorCode PRODUCING_ORDER_ENUM_INVALID = new ErrorCode(1_005_000_025, "producing.order.enum.invalid"); public static final ErrorCode PRODUCING_ORDER_IMPORT_FAILED = new ErrorCode(1_005_000_026, "producing.order.import.failed"); + public static final ErrorCode PRODUCING_ORDER_SYNC_FAILED = new ErrorCode(1_005_000_027, "producing.order.sync.failed"); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderItem/OrderItemDO.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderItem/OrderItemDO.java index 0794b3502..085794922 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderItem/OrderItemDO.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/dal/dataobject/orderItem/OrderItemDO.java @@ -83,4 +83,9 @@ public class OrderItemDO { * cad视图id */ private Integer cadViewId; -} \ No newline at end of file + + /** + * 对方配件实例 {@code partsItems[].id}。 + */ + private String sourcePartsItemId; +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportServiceImpl.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportServiceImpl.java index 8a63775d3..55d913983 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportServiceImpl.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportServiceImpl.java @@ -22,8 +22,8 @@ import static com.cf.imes.module.plan.enums.ErrorCodeConstants.PRODUCING_ORDER_I import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORGANID_EMPTY_ERROR; /** - * 编排组件生产单导入的事务外步骤:生成内部调用令牌、拉取并校验报文、登记图纸外链、 - * 获取组织级导入锁,再进入数据库事务。 + * 编排组件生产单导入:在事务外生成内部调用令牌、拉取并校验报文、登记图纸外链、 + * 获取组织级导入锁,再进入数据库事务完成写库和反向同步。 * *
图纸文件记录必须先创建;后续失败时仅做尽力补偿,补偿失败不覆盖原始导入异常。
*/ @@ -52,7 +52,7 @@ public class ProducingOrderImportServiceImpl implements ProducingOrderImportServ * {@inheritDoc} * *数据库事务开始前完成远程报文拉取、完整校验和图纸地址登记, - * 避免把网络等待纳入订单写库事务。
+ * 订单写库完成后在同一事务内反向同步组件系统;反向同步失败时回滚本次导入。 */ @Override public boolean importOrder(ProducingOrderImportReqVO request) { @@ -97,7 +97,7 @@ public class ProducingOrderImportServiceImpl implements ProducingOrderImportServ } stageStartedAt = System.nanoTime(); - transactionalService.importOrder(response, request, organId, fileId); + transactionalService.importOrder(response, request, organId, fileId, token); logStage(request, "transaction", stageStartedAt); log.info("[producing-import] sourceOrderId={} targetOrderId={} stage=total elapsedMs={}", request.getSourceOrderId(), request.getTargetOrderId(), diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportTransactionalService.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportTransactionalService.java index f4c40dd63..426f9d5dc 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportTransactionalService.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/ProducingOrderImportTransactionalService.java @@ -20,7 +20,11 @@ import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper; import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper; import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService; import com.cf.imes.module.plan.service.orderImport.factory.ProducingOrderImportFactory; +import com.cf.imes.module.plan.service.orderImport.producing.ProducingOrderClient; import com.cf.imes.module.plan.service.orderImport.producing.ProducingOrderConverter; +import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingOrderExtraUpdateRequest; +import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingOrderItemSerialNoUpdateRequest; +import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingOrderItemSerialNoUpdateResponse; import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingOrderResponse; import com.cf.imes.module.plan.service.orderImport.property.ProducingOrderImportProperties; import com.cf.imes.module.system.api.assemblyconfig.AssemblyConfigApi; @@ -31,18 +35,22 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.PRODUCING_ORDER_SYNC_FAILED; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ORDER_PLATENUM_REACH_THRESHOLD_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_NOT_EXISTS_ERROR; /** * 组件生产单的写库事务边界。 * - *目标订单校验、报文转换、订单状态更新以及板件/配件/加工组/部件组入库任一步失败, - * 都会回滚本次数据库变更。
+ *目标订单校验、报文转换、订单状态更新、板件/配件/加工组/部件组入库, + * 以及事务末尾的组件系统反向同步任一步失败,都会回滚本次数据库变更。
*/ @Service @Slf4j @@ -72,6 +80,8 @@ public class ProducingOrderImportTransactionalService { private JdbcTemplate jdbcTemplate; @Resource private ProducingOrderConverter producingOrderConverter; + @Resource + private ProducingOrderClient producingOrderClient; /** * 在一个事务内完成目标订单状态更新及全部拆单业务数据写入。 @@ -80,12 +90,14 @@ public class ProducingOrderImportTransactionalService { * @param request 本次导入请求 * @param organId 当前组织 ID * @param cadViewFileId 事务外预先生成的图纸文件 ID + * @param token MES JWT,不包含 {@code Bearer } 前缀 */ @Transactional(rollbackFor = Exception.class) public void importOrder(ProducingOrderResponse response, ProducingOrderImportReqVO request, Long organId, - Long cadViewFileId) { + Long cadViewFileId, + String token) { long totalStartedAt = System.nanoTime(); long stageStartedAt = System.nanoTime(); OrderDO order = getTargetOrder(request.getTargetOrderId(), organId); @@ -111,13 +123,98 @@ public class ProducingOrderImportTransactionalService { assemblyConfigApi, producingOrderImportProperties.getPlateNumThreshold(), jdbcTemplate); stageStartedAt = System.nanoTime(); - factory.analyzeTempData(producingImportData); + ProducingOrderItemSerialNoUpdateRequest serialNoRequest = + factory.analyzeTempData(producingImportData); logStage(request, "factory", stageStartedAt); + + // 反向同步放在本地事务末尾:任一接口失败都会触发本地导入回滚。 + stageStartedAt = System.nanoTime(); + producingOrderClient.updateOrderExtra( + request.getSourceOrderId(), token, + buildOrderExtraRequest(order, request.getSourceOrderId())); + logStage(request, "sync-order-extra", stageStartedAt); + + stageStartedAt = System.nanoTime(); + ProducingOrderItemSerialNoUpdateResponse serialNoResponse = + producingOrderClient.updateItemSerialNos(token, serialNoRequest); + logStage(request, "sync-item-serial-no", stageStartedAt); + log.info("[producing-import-sync] sourceOrderId={} targetOrderId={} " + + "blocksSubmitted={} partsSubmitted={} blocksUpdated={} partsUpdated={}", + request.getSourceOrderId(), request.getTargetOrderId(), + serialNoRequest.getBlocks().size(), serialNoRequest.getParts().size(), + serialNoResponse.getBlocksUpdated(), serialNoResponse.getPartsUpdated()); + log.info("[producing-import-transaction] sourceOrderId={} targetOrderId={} stage=total elapsedMs={}", request.getSourceOrderId(), request.getTargetOrderId(), elapsedMillis(totalStartedAt)); } + /** + * 将 iMES 订单字段转换为对方完整订单单头。 + * + *{@code customSerialNo} 严格使用 {@code orders.custom_order_no}; + * iMES 当前没有客户、经销商和人员业务 ID,因此嵌套对象 ID 传空字符串。
+ */ + private ProducingOrderExtraUpdateRequest buildOrderExtraRequest( + OrderDO order, String sourceOrderId) { + ProducingOrderExtraUpdateRequest.Contact distributor = + ProducingOrderExtraUpdateRequest.Contact.builder() + .id("") + .name(empty(order.getDealer())) + .address("") + .phone(empty(order.getDealerPhoneNumber())) + .build(); + ProducingOrderExtraUpdateRequest.Contact customer = + ProducingOrderExtraUpdateRequest.Contact.builder() + .id("") + .name(empty(order.getCustomer())) + .address(empty(order.getAddress())) + .phone(empty(order.getPhoneNumber())) + .build(); + ProducingOrderExtraUpdateRequest.User createPerson = + ProducingOrderExtraUpdateRequest.User.builder() + .id("") + .name(empty(order.getCreator())) + .build(); + ProducingOrderExtraUpdateRequest.User salePerson = + ProducingOrderExtraUpdateRequest.User.builder() + .id("") + .name(empty(order.getSalesman())) + .build(); + return ProducingOrderExtraUpdateRequest.builder() + .id(sourceOrderId) + .remark(empty(order.getRemark())) + .customSerialNo(empty(order.getCustomOrderNo())) + .type(order.getOrderType()) + .distributor(distributor) + .customer(customer) + .createPerson(createPerson) + .salePerson(salePerson) + .creationTime(toIsoTime(order.getCreateTime(), "create_time")) + .saleTime(toIsoTime(order.getOrderDate(), "order_date")) + .shippingTime(toIsoTime(order.getDeliveryDate(), "delivery_date")) + .build(); + } + + /** + * 将 iMES 本地时间转换为带东八区偏移的 ISO 8601 字符串。 + */ + private String toIsoTime(LocalDateTime value, String fieldName) { + if (value == null) { + throw new ServiceException(PRODUCING_ORDER_SYNC_FAILED, + "orders." + fieldName + " is null"); + } + return value.atOffset(ZoneOffset.ofHours(8)) + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + /** + * 将可空订单文本转换为对方必填对象可接受的空字符串。 + */ + private String empty(String value) { + return value == null ? "" : value; + } + /** * 输出事务内各处理阶段耗时。 */ diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/ProducingOrderImportFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/ProducingOrderImportFactory.java index d2b4048b6..a4ebf9e33 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/ProducingOrderImportFactory.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/ProducingOrderImportFactory.java @@ -32,6 +32,7 @@ import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingImport import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingImportPart; import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingImportProcessGroup; import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingImportData; +import com.cf.imes.module.plan.service.orderImport.producing.dto.ProducingOrderItemSerialNoUpdateRequest; import com.cf.imes.module.plan.dal.dataobject.goods.GoodsDO; import com.cf.imes.module.plan.dal.dataobject.ordecomponent.OrderComponentDO; import com.cf.imes.module.plan.dal.dataobject.order.OrderDO; @@ -79,6 +80,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -165,6 +167,12 @@ public class ProducingOrderImportFactory { // 部件缓存:{cad groupId:imes部件id} private Map仅网络 I/O 异常按配置重试;HTTP 错误、业务错误和无法解析的报文直接失败, - * 防止无意义的重复请求拉长同步导入事务外耗时。
+ *查询订单以及回写订单单头、生产项外部序列号均使用后端生成的 MES JWT。 + * 仅网络 I/O 异常按配置重试;HTTP 和业务错误直接失败。
*/ @Component @Slf4j @@ -99,4 +105,124 @@ public class ProducingOrderClient { String message = lastNetworkError == null ? "network error" : lastNetworkError.getMessage(); throw new ServiceException(PRODUCING_ORDER_PULL_FAILED, message); } + + /** + * 用 iMES 订单信息完整替换对方订单单头。 + * + * @param orderId 对方组件生产系统订单 ID + * @param token MES JWT,不包含 {@code Bearer } 前缀 + * @param request iMES 订单单头 + */ + public void updateOrderExtra(String orderId, + String token, + ProducingOrderExtraUpdateRequest request) { + String encodedOrderId = URLEncoder.encode(orderId, StandardCharsets.UTF_8); + URI uri = URI.create(properties.getOrderExtraUrl().replace("{id}", encodedOrderId)); + HttpResponse接口返回的实际更新数量仅用于日志,不参与事务成功判断。
+ * + * @param token MES JWT,不包含 {@code Bearer } 前缀 + * @param request 对方生产项 ID 与 iMES 编号的映射 + * @return 对方返回的实际更新数量;响应体无法解析时返回空计数对象 + */ + public ProducingOrderItemSerialNoUpdateResponse updateItemSerialNos( + String token, + ProducingOrderItemSerialNoUpdateRequest request) { + URI uri = URI.create(properties.getItemSerialNoUrl()); + HttpResponsePUT 接口具有覆盖语义,网络异常时重复发送同一请求不会生成重复业务数据。
+ */ + private HttpResponse对方接口采用完整替换语义,因此即使 iMES 没有对应的业务主键, + * 联系人和用户对象也需要保留,并将其 ID 写为空字符串。
+ */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProducingOrderExtraUpdateRequest { + + /** + * 对方组件生产系统订单 ID。 + */ + private String id; + + /** + * iMES 订单备注。 + */ + private String remark; + + /** + * iMES 自定义订单号。 + */ + private String customSerialNo; + + /** + * iMES 订单类型。 + */ + private Integer type; + + /** + * 经销商信息。 + */ + private Contact distributor; + + /** + * 客户信息。 + */ + private Contact customer; + + /** + * 订单创建人。 + */ + private User createPerson; + + /** + * 销售业务员。 + */ + private User salePerson; + + /** + * iMES 订单创建时间,使用 ISO 8601 时间字符串。 + */ + private String creationTime; + + /** + * iMES 下单日期,使用 ISO 8601 时间字符串。 + */ + private String saleTime; + + /** + * iMES 交付日期,使用 ISO 8601 时间字符串。 + */ + private String shippingTime; + + /** + * 对方订单单头使用的联系人结构。 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Contact { + + /** + * iMES 暂无对应联系人业务 ID,按接口约定传空字符串。 + */ + private String id; + + /** + * 联系人名称。 + */ + private String name; + + /** + * 联系地址。 + */ + private String address; + + /** + * 联系电话。 + */ + private String phone; + } + + /** + * 对方订单单头使用的用户结构。 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class User { + + /** + * iMES 暂无对应人员业务 ID,按接口约定传空字符串。 + */ + private String id; + + /** + * 人员名称。 + */ + private String name; + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderItemSerialNoUpdateRequest.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderItemSerialNoUpdateRequest.java new file mode 100644 index 000000000..43cddb745 --- /dev/null +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/producing/dto/ProducingOrderItemSerialNoUpdateRequest.java @@ -0,0 +1,30 @@ +package com.cf.imes.module.plan.service.orderImport.producing.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 批量更新组件生产项外部序列号的请求。 + * + *键为对方 {@code blockItems.id}/{@code partsItems.id}, + * 值分别为 iMES 板件编号和基础配件 {@code order_item.id}。
+ */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ProducingOrderItemSerialNoUpdateRequest { + + /** + * 对方板件实例 ID 到 iMES {@code order_plate.plate_no} 的映射。 + */ + private Map实际接口使用通用响应外壳,将更新数量放在 {@code data} 中; + * 同时保留对文档所示顶层更新数量字段的兼容。更新数量仅用于日志观测, + * 不作为本地事务提交条件。
+ */ +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProducingOrderItemSerialNoUpdateResponse { + + /** + * 业务码;实际接口允许返回数字或数字字符串。 + */ + private JsonNode code; + + /** + * 业务提示。 + */ + private String message; + + /** + * 实际接口返回的更新数量对象。 + */ + private UpdateCounts data; + + /** + * 兼容文档中直接放在响应顶层的板件更新数量。 + */ + private Integer blocksUpdated; + + /** + * 兼容文档中直接放在响应顶层的配件更新数量。 + */ + private Integer partsUpdated; + + /** + * 判断已解析响应是否返回成功业务码。 + * + *未返回 {@code code} 时按文档中的无外壳结构处理为成功。
+ * + * @return {@code code} 缺失或等于 0 时返回 {@code true} + */ + public boolean isSuccess() { + return code == null || code.asInt(Integer.MIN_VALUE) == 0; + } + + /** + * 获取对方实际更新的板件数量。 + * + * @return 优先返回 {@code data.blocksUpdated},否则返回兼容的顶层字段 + */ + public Integer getBlocksUpdated() { + return data == null ? blocksUpdated : data.getBlocksUpdated(); + } + + /** + * 获取对方实际更新的配件数量。 + * + * @return 优先返回 {@code data.partsUpdated},否则返回兼容的顶层字段 + */ + public Integer getPartsUpdated() { + return data == null ? partsUpdated : data.getPartsUpdated(); + } + + /** + * 批量更新数量。 + */ + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class UpdateCounts { + + /** + * 对方实际更新的板件索引数量。 + */ + private Integer blocksUpdated; + + /** + * 对方实际更新的配件索引数量。 + */ + private Integer partsUpdated; + } +} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/property/ProducingOrderImportProperties.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/property/ProducingOrderImportProperties.java index 30bba5bee..ca97e0e80 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/property/ProducingOrderImportProperties.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/property/ProducingOrderImportProperties.java @@ -9,7 +9,8 @@ import java.time.Duration; /** * 组件生产单拉取及导入配置。 * - *统一管理对方订单接口地址、HTTP 超时和重试策略,以及单订单板件数量上限。
+ *统一管理对方订单查询、单头回写、生产项编号回写接口, + * HTTP 超时和重试策略,以及单订单板件数量上限。
*/ @Data @Configuration @@ -22,6 +23,18 @@ public class ProducingOrderImportProperties { private String orderUrl = "http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id}"; + /** + * 组件生产单订单单头更新地址,其中 {@code {id}} 会替换为来源订单 ID。 + */ + private String orderExtraUrl = + "http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id}/extra"; + + /** + * 批量更新板件、配件外部序列号的接口地址。 + */ + private String itemSerialNoUrl = + "http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/items/serial-no"; + /** * 建立 HTTP 连接的超时时间。 */ @@ -32,6 +45,11 @@ public class ProducingOrderImportProperties { */ private Duration readTimeout = Duration.ofSeconds(60); + /** + * 事务内反向同步接口的读取超时时间。 + */ + private Duration syncReadTimeout = Duration.ofSeconds(10); + /** * 网络 I/O 失败后的重试次数;HTTP 或业务错误不重试。 */ diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-dev.yaml b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-dev.yaml index 6283dcafa..d2261ab98 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-dev.yaml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-dev.yaml @@ -166,8 +166,11 @@ chenfeng: plan: producing-order: order-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id} + order-extra-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id}/extra + item-serial-no-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/items/serial-no connect-timeout: 5s read-timeout: 60s + sync-read-timeout: 10s network-retry-times: 1 plate-num-threshold: 20000 webcad: diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml index 2deee14d9..f1c058334 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/application-local.yaml @@ -194,8 +194,11 @@ chenfeng: plan: producing-order: order-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id} + order-extra-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/{id}/extra + item-serial-no-url: http://proc.mes.cf/api-branch=opt_split_order/api/v1/producing/order/items/serial-no connect-timeout: 5s read-timeout: 60s + sync-read-timeout: 10s network-retry-times: 1 plate-num-threshold: 20000 webcad: diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_cht.properties b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_cht.properties index 6decf31b9..19d9d5df3 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_cht.properties +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_cht.properties @@ -40,3 +40,4 @@ producing.order.cad_view_path.empty=組件生產單缺少 CAD 圖紙地址 producing.order.cad_object.invalid=組件生產單 CAD 物件映射無效:{0} producing.order.enum.invalid=組件生產單枚舉值無效:{0} producing.order.import.failed=組件生產單匯入失敗 +producing.order.sync.failed=反向同步組件生產單失敗:{0} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_en.properties b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_en.properties index 435aa69de..ec8db6c3e 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_en.properties +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_en.properties @@ -40,3 +40,4 @@ producing.order.cad_view_path.empty=The producing order has no CAD view path producing.order.cad_object.invalid=Invalid CAD object mapping: {0} producing.order.enum.invalid=Invalid producing order enum value: {0} producing.order.import.failed=Failed to import producing order +producing.order.sync.failed=Failed to synchronize the producing order back: {0} diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_zh.properties b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_zh.properties index 33a0fcf49..28f8aae42 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_zh.properties +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/resources/message_errorcode_zh.properties @@ -40,3 +40,4 @@ producing.order.cad_view_path.empty=组件生产单缺少 CAD 图纸地址 producing.order.cad_object.invalid=组件生产单 CAD 对象映射无效:{0} producing.order.enum.invalid=组件生产单枚举值无效:{0} producing.order.import.failed=组件生产单导入失败 +producing.order.sync.failed=反向同步组件生产单失败:{0}