From e5c251b1ef48f5a96ccad23df3cf458f77b1558b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Tue, 27 Oct 2026 15:32:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B1=A5=E7=BA=A6=E8=AE=A1=E5=88=92ID?= =?UTF-8?q?=E5=9B=9E=E5=A1=AB=E7=AE=80=E5=8C=96=E4=B8=BA=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E8=A1=8C=E9=A6=96=E4=B8=AA=E9=9D=9E=E7=A9=BAfdId=E5=B9=B6?= =?UTF-8?q?=E8=A6=86=E7=9B=96fdAddStages=E9=A6=96=E6=AC=A1=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../support/hcs/HcsExeStageSyncSupport.java | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsExeStageSyncSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsExeStageSyncSupport.java index 89bed20c..9cc2a52d 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsExeStageSyncSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsExeStageSyncSupport.java @@ -46,19 +46,19 @@ import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Stream; /** * HCS 履约规则同步支撑组件(C103-9 新版行级同步,设计文档 §5.3,ADR-0002) *

- * 随合同推送链路执行(合同须已同步、hcs_fd_id 存在):聚合 row_op 非 none 的规则行 - * (add 行不带 fdId,update/delete 行必须带合规阶段ID),整体 fdEopExeplanOperateType - * 首次为 add、后续为 update;返回的 fdExeplanId 回填 blade_contract_manage.hcs_exeplan_id, - * 变更阶段 fdId 按行回填 hcs_stage_fd_id(合规返回的 fdId 必须持久化,后续行更新/删除全靠它)。 + * 随合同推送链路执行(合同须已同步、hcs_fd_id 存在):聚合 row_op 非 none 的规则行, + * 整体 fdEopExeplanOperateType 首次为 add、后续为 update;请求行必送 fdUniqueId(取 TMS 行ID,重试稳定),响应行回 fdId; + * 履约计划ID 取返回 fdChangeStages 行的 fdId 回填 blade_contract_manage.hcs_exeplan_id(实际响应无顶层 fdExeplanId), + * 各行 fdId 按行回填 hcs_stage_fd_id(必须持久化,供履约记录等接口引用)。 * * @author Chill */ @@ -123,10 +123,8 @@ public class HcsExeStageSyncSupport { List stages = new ArrayList<>(); for (HcsContractExeStage row : pendingRows) { HcsExeplanStageDTO stage = new HcsExeplanStageDTO(); - // 阶段项ID:行级 update/delete 必传(取 hcs_stage_fd_id),add 行不带 - if (!"add".equals(row.getRowOp())) { - stage.setFdId(row.getHcsStageFdId()); - } + // 阶段唯一标识:所有行必传(取 TMS 行ID,重试重发保持不变,合规按此匹配行;add 行 hcs_stage_fd_id 为空不能作值) + stage.setFdUniqueId(String.valueOf(row.getId())); // 【必填】行级操作:add / update / delete stage.setFdEopExeplanOperateType(row.getRowOp()); // 【必填】履约类型:payment=付款 / collection=收款 @@ -154,19 +152,25 @@ public class HcsExeStageSyncSupport { } /** - * 回填:fdExeplanId → 合同 hcs_exeplan_id;变更阶段 fdId 按行回填 hcs_stage_fd_id 并清除行级操作标记 + * 回填:响应行 fdId 即履约计划ID → 合同 hcs_exeplan_id(fdAddStages/fdChangeStages 取首个非空);各行 fdId 按行回填 hcs_stage_fd_id 并清除行级操作标记 *

- * TODO 待联调确认:fdChangeStages 与请求行的对应关系 v4 未明确,优先按请求行序对应(首次全 add 场景), - * 行数不一致时按业务属性组合键匹配,仍匹配不到的 add 行保持待同步(下轮重试)。 + * 新增行阶段在 fdAddStages 返回(实测不含业务属性,按 add 行出现顺序对应),变更行在 fdChangeStages 返回; + * fdChangeStages 按请求行序对应,行数不一致时按业务属性组合键匹配,仍匹配不到的 add 行保持待同步(下轮重试)。 */ private void backfill(ContractManage contractManage, List pendingRows, List requestStages, HcsExeplanVO exeplan) { - // 履约计划ID 回填(后续行更新/删除依赖,必须持久化) - if (StringUtil.isNotBlank(exeplan.getFdExeplanId()) - && !exeplan.getFdExeplanId().equals(contractManage.getHcsExeplanId())) { - contractManage.setHcsExeplanId(exeplan.getFdExeplanId()); + // 履约计划ID 回填:响应行 fdId 即履约计划ID(首次同步行在 fdAddStages、变更行在 fdChangeStages,取首个非空回填) + String fdExeplanId = Stream.of(exeplan.getFdChangeStages(), exeplan.getFdAddStages()) + .filter(Objects::nonNull) + .flatMap(List::stream) + .map(HcsExeplanStageVO::getFdId) + .filter(StringUtil::isNotBlank) + .findFirst().orElse(null); + if (StringUtil.isNotBlank(fdExeplanId)) { + contractManage.setHcsExeplanId(fdExeplanId); } backfillExeplanId(contractManage); + List addStages = exeplan.getFdAddStages() == null ? List.of() : exeplan.getFdAddStages(); List changeStages = exeplan.getFdChangeStages() == null ? List.of() : exeplan.getFdChangeStages(); // 行数一致时按请求行序一一对应;不一致时按业务属性组合键匹配 boolean positional = changeStages.size() == requestStages.size(); @@ -177,9 +181,12 @@ public class HcsExeStageSyncSupport { HcsContractExeStage row = pendingRows.get(index); String stageFdId = row.getHcsStageFdId(); if ("add".equals(row.getRowOp())) { - addRowCount++; - HcsExeplanStageVO matched = positional ? changeStages.get(index) : byAttribute.get(attributeKey(requestStages.get(index))); + HcsExeplanStageVO matched = addRowCount < addStages.size() ? addStages.get(addRowCount) : null; + if (matched == null) { + matched = positional ? changeStages.get(index) : byAttribute.get(attributeKey(requestStages.get(index))); + } stageFdId = matched == null ? null : matched.getFdId(); + addRowCount++; if (StringUtil.isBlank(stageFdId)) { unmatchedCount++; }