diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsClaimSyncSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsClaimSyncSupport.java index a74391fd..ea242d5c 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsClaimSyncSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/hcs/HcsClaimSyncSupport.java @@ -33,17 +33,11 @@ import org.springblade.core.tool.utils.StringUtil; import org.springblade.hcs.config.HcsProperties; import org.springblade.hcs.dto.HcsClaimRecordAddDTO; import org.springblade.hcs.dto.HcsCollectionFlowVO; -import org.springblade.hcs.dto.HcsFormSaveVO; import org.springblade.hcs.dto.HcsIdVO; -import org.springblade.hcs.dto.HcsMechanismsDTO; import org.springblade.hcs.dto.HcsPageQueryDTO; import org.springblade.hcs.dto.HcsPageVO; -import org.springblade.hcs.dto.HcsPerfRecordFormDataDTO; -import org.springblade.hcs.dto.HcsPerfRecordPropsDTO; -import org.springblade.hcs.dto.HcsPerfRecordSaveDTO; import org.springblade.hcs.dto.HcsRefVO; import org.springblade.hcs.dto.HcsResult; -import org.springblade.hcs.dto.HcsUserRefVO; import org.springblade.hcs.exception.HcsException; import org.springblade.hcs.feign.IHcsClient; import org.springblade.transport.constant.HcsSyncConstant; @@ -102,6 +96,7 @@ public class HcsClaimSyncSupport { private final ContractManageMapper contractManageMapper; private final IContractExeStageService contractExeStageService; private final HcsExeStageSyncSupport hcsExeStageSyncSupport; + private final HcsPerfRecordAddSupport hcsPerfRecordAddSupport; /** * 金蝶认领推送成功后推送合同合规(C103-9 → C107-1 → C108-1) @@ -213,7 +208,7 @@ public class HcsClaimSyncSupport { } } // ③ C108-1 履约流水:按合同一条(开关 perf-record.sync-enabled,与付款链履约记录同步同开关), - // 须已推送合规且存在已同步收款计划行(fd_plan_id 必填) + // 须已推送合规且存在已同步收款计划行(fd_plan_id 必填);履约日期为收款流水交易日期 if (!hcsProperties.getPerfRecord().isSyncEnabled()) { log.info("HCS履约流水推送跳过:履约记录同步开关未开启 contractNo={}", contractManage.getContractNo()); return; @@ -226,7 +221,7 @@ public class HcsClaimSyncSupport { log.info("HCS履约流水推送跳过:无已同步收款履约计划行 contractNo={}", contractManage.getContractNo()); return; } - pushPerfRecord(flow, contractManage, stageRow, claimedTotal, latestClaimDate(claims)); + pushPerfRecord(flow, contractManage, stageRow, claimedTotal); } /** @@ -279,54 +274,18 @@ public class HcsClaimSyncSupport { } /** - * C108-1 履约流水推送(单合同一条:申请金额=实际金额=该合同累计认领金额) + * C108-1 履约流水推送(单合同一条:申请金额=实际金额=该合同累计认领金额,履约日期=收款流水交易日期) */ private void pushPerfRecord(KingdeeReceiptFlow flow, ContractManage contractManage, - HcsContractExeStage stageRow, BigDecimal claimedTotal, LocalDate planDate) { - // 表单模板ID(配置 perf-record.xform-id,环境值 §9-U9,未配置不传) - String xformId = StringUtil.isBlank(hcsProperties.getPerfRecord().getXformId()) ? null : hcsProperties.getPerfRecord().getXformId(); - HcsPerfRecordPropsDTO props = new HcsPerfRecordPropsDTO(); - // 【必填】申请编号:收款通知单号,兜底明细流水号 - props.setFdApplyNo(firstNonBlank(flow.getReceiptNoticeNo(), flow.getDetailSerialNo())); - // 申请金额 / 实际金额:该合同累计认领金额 - props.setFdApplyAmount(claimedTotal.toPlainString()); - props.setFdFactAmount(claimedTotal.toPlainString()); - // 【必填】履约日期:最近认领日期(毫秒时间戳) - props.setFdPlanDate(toMillis(planDate)); - // 履约类型:收款 - props.setFdPalnType(HcsSyncConstant.PERFORM_TYPE_COLLECTION); - // 履约性质:收款计划行款项性质 - props.setFdProperty(stageRow.getFundNature()); - // 履约计划id / 来源履约计划项ID:收款计划行合规阶段ID(HCS 只认自己的阶段ID) - props.setFdId(stageRow.getHcsStageFdId()); - props.setFdPlanId(stageRow.getHcsStageFdId()); - // 金蝶单据号:A301-3 推送返回的金蝶收款单号 - props.setFdJdDocNo(flow.getKingdeeBillNo()); - // 【必填】合同ID:HCS 合同ID - props.setFdContractId(contractManage.getHcsFdId()); - // 业务ID:TMS 收款流水ID(溯源) - props.setFdBusinessId(String.valueOf(flow.getId())); - props.setFdCreateTime(System.currentTimeMillis()); - props.setFdXformId(xformId); - HcsPerfRecordFormDataDTO formData = new HcsPerfRecordFormDataDTO(); - formData.setFdXformId(xformId); - formData.setDynamicProps(props); - // 机制数据(C108-1 必填):认领附件暂不转传,传空列表 - HcsMechanismsDTO mechanisms = new HcsMechanismsDTO(); - mechanisms.setAttachment(List.of()); - HcsPerfRecordSaveDTO param = new HcsPerfRecordSaveDTO(); - param.setCurUser(HcsUserRefVO.ofLoginName(hcsProperties.getOperatorLoginName())); - param.setFormData(formData); - param.setMechanisms(mechanisms); - log.info("HCS履约流水新建开始 flowId:{},contractNo:{},认领金额 {}", flow.getId(), contractManage.getContractNo(), claimedTotal); - HcsResult result = hcsClient.perfRecordAdd(param); - if (result == null || !result.isSuccess() || result.getData() == null || StringUtil.isBlank(result.getData().getFdId())) { - log.error("HCS履约流水新建失败响应:{},contractNo={}", result == null ? "无响应" : String.format("msg=%s, traceId=%s", result.getMsg(), result.getTraceId()), contractManage.getContractNo()); - throw new HcsException("C108-1 履约流水新建失败:" + (result == null ? "响应为空" : result.getMsg())); - } - // shortcut: 履约流水 fdId 未持久化(认领链无 C108-2 更新场景);需推进实际金额更新时先落库 - log.info("HCS履约流水新建成功 flowId:{},contractNo:{},perfFdId:{}", - flow.getId(), contractManage.getContractNo(), result.getData().getFdId()); + HcsContractExeStage stageRow, BigDecimal claimedTotal) { + // 履约日期:交易日期(需求口径),交易时间为空兜底当天 + LocalDate perfDate = flow.getTransactionTime() != null ? flow.getTransactionTime().toLocalDate() : LocalDate.now(); + String perfFdId = hcsPerfRecordAddSupport.pushPerfRecordAdd(contractManage, stageRow, + firstNonBlank(flow.getReceiptNoticeNo(), flow.getDetailSerialNo()), claimedTotal, toMillis(perfDate), + HcsSyncConstant.PERFORM_TYPE_COLLECTION, flow.getKingdeeBillNo(), flow.getId(), + "收款履约-" + firstNonBlank(flow.getReceiptNoticeNo(), flow.getDetailSerialNo())); + // shortcut: 履约流水 fdId 未持久化(认领链无 C108-2 更新场景,重推会重复);需推进实际金额更新时先落库 + log.info("HCS履约流水新建完成 flowId:{},contractNo:{},perfFdId:{}", flow.getId(), contractManage.getContractNo(), perfFdId); } /** @@ -353,17 +312,6 @@ public class HcsClaimSyncSupport { .findFirst().orElse(null); } - /** - * 最近认领日期(C108-1 履约日期) - */ - private LocalDate latestClaimDate(List claims) { - return claims.stream() - .map(ReceiptClaim::getClaimDate) - .filter(Objects::nonNull) - .max(LocalDate::compareTo) - .orElse(LocalDate.now()); - } - private String firstNonBlank(String... values) { for (String value : values) { if (Func.isNotEmpty(value)) {