docs: 补充履约计划与履约记录四场景实现与业务说明

This commit is contained in:
刘泉佳
2026-10-29 21:04:42 +08:00
parent fce3f00a1e
commit 1172ee8fb7
2 changed files with 606 additions and 0 deletions
@@ -0,0 +1,289 @@
# 履约计划与履约记录业务说明(付款 / 开票 / 收票 / 收款)
> 适用对象:合同、结算、付款、开票、收票相关业务人员
> 更新日期:2026-10-29
> 用途:说明 TMS 与合同合规系统之间「履约计划」「履约记录」是怎么产生、什么时候产生、先后顺序和注意事项。
---
## 一、先看懂三个概念
| 概念 | 通俗理解 | 举例 |
| --- | --- | --- |
| **合同** | 业务发生的前提 | 与承运商签的运输合同、与客户签的运输服务合同 |
| **履约计划** | 合同约定的**收付款计划台账**(打算收/付多少钱、什么时候收/付) | 合同约定进度款 100 万,分几次结算 |
| **履约记录** | 计划实际执行的**流水**(真正付了、收了、开了票、收了票) | 本次实际付款 30 万、本次认领收款 20 万 |
一句话记住:**计划是“打算”,记录是“实际发生”**。先有计划,才有记录;记录必须挂在某一条计划下面。
---
## 二、总体流程
```
合同审批通过
↓
生成 / 确认履约计划(付款计划、收款计划)
↓
合同与计划推送到合规系统(合规侧生成对应的计划编号)
↓
业务实际发生:付款 / 收款 / 开票 / 收票
↓
系统自动生成履约记录,回传合规系统
```
关键顺序:
1. **合同先推合规**;
2. **履约计划再推合规**;
3. **计划推送成功后,履约记录才能生成**。
如果合同还没推合规,或者计划还没推成功,记录会暂时生成不了,等前面的步骤完成后自动补上(收款场景除外,见第六节)。
---
## 三、履约计划是怎么来的
### 3.1 计划从哪来
| 来源 | 说明 |
| --- | --- |
| 合同里维护「履约规则」 | 业务人员在合同页签里填写付款/收款计划行 |
| 合同审批通过自动生成 | 合同没有维护计划行时,系统自动补一条默认计划:承运商合同生成付款计划,客户合同生成收款计划 |
| 业务发生自动累加 | 付款审批通过、收款认领后,计划金额自动累加 |
### 3.2 计划金额什么时候变
| 业务动作 | 计划金额变化 |
| --- | --- |
| 付款申请**审批通过** | 对应付款计划的金额 += 本次申请金额 |
| 收款流水**认领完成** | 对应收款计划的金额 += 本次认领分摊金额 |
请注意:
- 计划金额是**“已批准 / 已认领”的口径**,不是实际到账/实付口径;
- 实际付了多少、收了多少,看履约记录;
- 付款计划只在款项性质一致时累加(预付款不会加到进度款计划上);
- 同一合同多次付款、多次认领,计划金额会持续累加。
### 3.3 计划的修改
- 合同审批通过后,已推送成功的计划行再修改,系统会自动重新推送合规;
- 删除已推送的计划行,会在合规侧同步删除(不能直接物理删除);
- 新增的计划行随下一次推送一起补到合规。
---
## 四、四个场景的履约记录
### 4.1 付款履约记录
**什么时候产生:金蝶实际付款之后。**
业务过程:
```
付款申请审批通过
→ 只更新计划金额,不产生履约付款记录
→ 推送金蝶付款申请
金蝶完成实际付款
→ 系统回写实付金额
→ 生成履约付款记录
```
业务要点:
| 项目 | 说明 |
| --- | --- |
| 生成条数 | 一张付款申请对应一条;**分次付款不新增,只更新同一条的实际金额** |
| 金额 | 申请金额 + 实际付款金额 |
| 日期 | 付款申请日期 |
| 附件 | 付款场景会把付款附件一并传到合规 |
| 特批 | 需要特批的付款,特批通过后也不会立刻生成记录,仍要等金蝶实际付款 |
> 常见误区:付款审批通过后就去合规找履约付款记录——此时还没有,属于正常现象,金蝶付款后才会出现。
---
### 4.2 收款履约记录
**什么时候产生:收款流水认领完成之后。**
业务过程:
```
收款流水到账并同步到 TMS
→ 业务人员做认领(分摊到应收结算单)
→ 认领提交后,系统自动:
① 更新该合同的收款计划金额
② 推送认领记录到合规
③ 生成收款履约记录
```
业务要点:
| 项目 | 说明 |
| --- | --- |
| 生成条数 | 每完成一次认领,按涉及的合同各生成一条 |
| 金额 | **本次认领分摊到该合同的金额**(不是合同累计认领金额) |
| 日期 | 认领日期 |
| 作废 | 认领作废只会在合规侧把认领记录置为作废,**不会冲回计划金额,也不会冲回已生成的履约记录** |
> 注意:收款链路的推送失败**不会自动重试**,如合规侧没有数据,请联系系统管理员排查。
---
### 4.3 开票履约记录
**什么时候产生:金蝶开票完成、发票回到 TMS 之后。**
业务过程:
```
开票申请审批通过
→ 推送金蝶开票
→ 推送合规开票登记(此时还没有发票日期)
金蝶完成开票
→ 系统回写发票信息(每张发票一条)
→ 按每张发票生成履约开票记录
```
业务要点:
| 项目 | 说明 |
| --- | --- |
| 生成条数 | **每张发票一条**;一张开票申请开多张发票,就会生成多条 |
| 金额 | 发票价税合计 |
| 日期 | 发票的开票日期 |
| 标题 | `开票履约-发票号`,可在合规侧按此检索 |
| 失败处理 | 合同或计划条件不满足时暂不生成,系统自动重试,条件满足后补上 |
---
### 4.4 收票履约记录
**什么时候产生:收票单成功推送合规之后。**
业务过程:
```
收票登记审批通过
→ 推送金蝶收票单
→ 推送合规收票单(C109)
→ 推送成功后,按收票单里的每条结算信息生成履约收票记录
```
业务要点:
| 项目 | 说明 |
| --- | --- |
| 生成条数 | **每条结算信息(分摊行)一条**;一张收票单分摊到多张结算单就会生成多条 |
| 金额 | 分摊到该结算单的收票金额 |
| 日期 | 收票单的发票日期 |
| 标题 | `收票履约-发票号-结算单号` |
| 失败处理 | 收票单还没成功推合规时暂不生成,等收票单推送成功后自动补上 |
---
### 4.5 四场景速查
| 场景 | 什么时候出现 | 生成条数 | 金额口径 | 日期口径 |
| --- | --- | --- | --- | --- |
| 付款 | 金蝶实际付款后 | 一张付款申请一条(分期更新同一条) | 申请金额 / 实付金额 | 申请日期 |
| 收款 | 认领提交后 | 每次认领 × 每个合同一条 | 本次认领分摊金额 | 认领日期 |
| 开票 | 金蝶开票完成后 | 每张发票一条 | 发票价税合计 | 发票开票日期 |
| 收票 | 收票单推合规成功后 | 每条结算分摊行一条 | 分摊收票金额 | 发票日期 |
---
## 五、合规侧怎么核对
在合规系统履约记录列表中,按标题前缀检索最快:
| 场景 | 标题前缀 |
| --- | --- |
| 付款 | `付款履约-` |
| 收款 | `收款履约-` |
| 开票 | `开票履约-` |
| 收票 | `收票履约-` |
核对时重点看四项:**合同是否正确、金额是否正确、日期口径是否符合上表、条数是否与业务动作匹配**。
---
## 六、异常与重试
| 场景 | 推送失败后是否自动重试 | 业务需要做什么 |
| --- | --- | --- |
| 付款 | 是,系统定时自动重试 | 一般无需处理;长期失败联系管理员 |
| 开票 | 是,系统定时自动重试 | 确认金蝶是否已开票完成;长期失败联系管理员 |
| 收票 | 是,系统定时自动重试 | 先确认收票单是否已成功推送合规 |
| 收款 | **否** | 联系系统管理员手动排查处理 |
常见“暂时生成不了”的原因:
1. 合同还没推送合规;
2. 履约计划还没推送成功(没有可关联的计划);
3. 对应单据还没审批通过;
4. 收票单还没成功推送合规;
5. 金蝶还没实际付款 / 还没完成开票。
前四类在条件满足后会自动补推,不需要重复操作单据。
---
## 七、作废、驳回与变更
| 业务动作 | 对合规履约数据的影响 |
| --- | --- |
| 付款审批驳回 | 不产生履约付款记录 |
| 付款需要特批 | 特批期间不产生履约数据;特批通过后也要等金蝶实际付款 |
| 付款申请作废 | 当前**不会冲回**已累加的计划金额,也不会冲回履约付款记录 |
| 收款认领作废 | 合规侧认领记录作废;**计划金额与收款履约记录不冲回** |
| 合同变更审批通过 | 计划行随变更重新推送合规,已生成的履约记录不受影响 |
> 如业务上需要“作废后金额必须回退”,请单独提需求或在合规侧人工调整,不能依赖当前自动链路。
---
## 八、常见问题(FAQ)
**1. 合同刚审批通过,合规为什么没有履约记录?**
正常。此时只有履约计划,记录要等业务实际发生(付款、收款、开票、收票)后才生成。
**2. 付款已经审批通过了,合规为什么没有付款履约记录?**
正常。付款履约记录以**金蝶实际付款**为准,审批通过只更新计划金额。
**3. 同一笔付款分两次支付,合规会出现两条记录吗?**
不会。一张付款申请对应一条记录,第二次付款更新实际金额。
**4. 同一笔收款分多次认领,合规会出现几条?**
每次认领都会生成一条(按涉及合同分别生成),金额为本次分摊金额。
**5. 一张开票申请开了多张发票,合规有几条?**
每张发票一条。
**6. 收票单有多条结算信息,合规有几条?**
每条结算信息一条。
**7. 合规侧一条记录都没有,先查什么?**
按顺序确认:合同是否已推合规 → 履约计划是否已推成功 → 单据是否已审批通过 →(开票)金蝶是否已开票完成 →(收票)收票单是否已推合规。收款链路不会自动重试,需联系管理员。
**8. 计划金额和履约记录金额为什么对不上?**
两者口径不同:计划金额是“已批准/已认领”的累计口径,履约记录是“本次实际发生”的口径。付款场景下,计划看申请金额,记录看实付金额。
**9. 作废后合规金额为什么没变?**
当前作废不回冲计划金额和履约记录,需要在合规侧人工处理或单独提需求。
---
## 附录:业务名称与合规接口对照(供对接同学参考)
| 业务名称 | 合规接口 |
| --- | --- |
| 合同推送 | C103-1 / C103-11 |
| 履约计划推送 | C103-9 |
| 付款履约记录 新建 / 更新 | C108-1 / C108-2 |
| 收款认领记录 新增 / 作废 | C107-1 / C107-3 |
| 开票登记 | C111 |
| 收票单推送 | C109 |
@@ -0,0 +1,317 @@
# 履约计划与履约记录四场景实现逻辑(付款 / 开票 / 收票 / 收款)
> 日期:2026-10-29
> 范围:`tms-api` blade-transport 中 TMS ↔ 合同合规系统(HCS)的「履约计划」(C103-9)与「履约记录」(C108-1/2)。
> 目标:只讲清**逻辑、流程、先后顺序**,不展开代码细节。
---
## 0. 总览
一句话:**履约计划是合同资金的“计划行”,履约记录是这些计划行的“实际发生流水”**。计划先行(先拿到 HCS 阶段ID),记录才能引用它;四个业务场景(付款/收款/开票/收票)各自在“业务真正发生”的时点产生一条或多条履约记录。
### 0.1 全景顺序
```
合同审批通过
└─ 建默认履约计划行 → 推合同 C103-1(拿合同 hcs_fd_id)
└─ 推履约计划 C103-9(拿计划 hcs_exeplan_id + 每行 hcs_stage_fd_id)
├─ 付款:审批通过 → 计划金额累加 → 金蝶实际付款 → C108-1/C108-2
├─ 收款:认领提交 → 计划金额累加 → C107-1 → C108-1
├─ 开票:金蝶开票完成、发票落库 → C111 登记 → 每张发票 C108-1
└─ 收票:收票单推合规 C109 成功 → 每条结算分摊行 C108-1
```
### 0.2 四条链的关键先后关系
| 场景 | 前一条链必须先完成 | 履约记录产生时点 | 记录粒度 |
| --- | --- | --- | --- |
| 付款 | C103-1 拿到 `hcs_fd_id`;C103-9 计划行拿到 `hcs_stage_fd_id` | **金蝶实际付款后**(`paidAmount>0` 且金额推进) | 付款申请单(1 张单 1 条,分期走更新) |
| 收款 | 同上,且收款计划行已同步 | **认领事务提交后** | 认领主单 × 合同(每次认领各 1 条) |
| 开票 | 合同/收款计划行已同步;金蝶 A303-5 发票已落库 | **金蝶开票完成后** | 每张发票 1 条 |
| 收票 | 合同/付款计划行已同步;**C109 收票单已推合规成功** | **C109 推送成功后** | 每条结算分摊行 1 条 |
---
## 1. 两个对象与 ID 链
| 对象 | TMS 落点 | HCS 接口 | 作用 |
| --- | --- | --- | --- |
| 履约计划行 | `blade_contract_exe_stage`(`HcsContractExeStage`) | C103-9 行级 add/update/delete | 合同维度的付款/收款资金计划 |
| 履约记录 | 各业务表上的 `hcs_perf_fd_id` | C108-1 新建 / C108-2 更新 | 计划的实际执行流水 |
必须持久化的 ID 链(后面所有推送都依赖它):
```
blade_contract_manage.hcs_fd_id 合规合同ID(C103-1)
blade_contract_manage.hcs_exeplan_id 合规履约计划ID(C103-9)
blade_contract_exe_stage.hcs_stage_fd_id 合规阶段ID(C103-9 按行回填,= C108 的 fd_plan_id)
blade_payment_application.hcs_perf_fd_id 付款履约记录ID(C108-1 返回)
blade_invoice_application_invoice.hcs_perf_fd_id 开票履约记录ID
blade_invoice_receipt_settlement.hcs_perf_fd_id 收票履约记录ID
blade_receipt_claim_hcs_record.hcs_claim_record_fd_id C107-1 认领记录ID(供 C107-3 作废)
```
`fd_plan_id` 在 C108 接口中**必填**,只能取 HCS 自己返回的 `hcs_stage_fd_id`。因此没有已同步计划行时,履约记录一律推不出去,只能失败重试,等合同链把计划补推成功后自愈。
---
## 2. 履约计划(C103-9)
### 2.1 计划行从哪来
| 入口 | 行为 |
| --- | --- |
| 合同表单「履约规则」页签维护(`ContractExeStageServiceImpl#submitRows/removeRow`) | 新行 → `row_op=add`;已同步行编辑 → `update`;已同步行删除 → 软删 + `delete` 标记(不能物理删,delete 要凭阶段ID 上报) |
| 合同审批通过(`createDefaultRowOnApprove`) | 无任何计划行时自动建默认行:承运商合同=付款/进度款,客户合同=收款/进度款;同时把该合同所有未拿到阶段ID 的行统一置 `add` |
| 付款审批通过(`accumulatePaidAmountOnApprove`) | 按付款类型映射款项性质(正式结算=进度款,其余=预付款),对**精确匹配**该款项性质的已同步付款行,原子累加 `fund_amount += 申请金额`,并置 `update + unsynced` |
| 收款认领(`accumulateClaimedAmountOnPush`) | 取收款/进度款计划行(无进度款则兜底首条已同步收款行),累加本次分摊到该合同的认领金额,置 `update + unsynced` |
要点:
- 金额累加只发生在“审批通过/认领提交”,**不是**在实际收付款时;因此计划金额反映的是“已批准/已认领的计划口径”,履约记录才反映实际发生额。
- 付款累加严格要求款项性质一致,匹配不到就跳过,避免预付款计进进度款;收款累加允许兜底行。
- 已同步行靠 `hcs_stage_fd_id` 重推;未同步行保持 `add`,随合同链首推(首次推送即携带累加后的金额)。
### 2.2 同步逻辑(`HcsExeStageSyncSupport#syncExeStages`)
1. 前置:合同必须有 `hcs_fd_id`。
2. 取该合同所有 `row_op <> 'none'` 的行;删除行已软删,用原生 SQL 绕过逻辑删除才能取到。
3. 整体操作类型:`hcs_exeplan_id` 为空 → `add`(首次),否则 `update`。
4. 行级:`add` 行带 `fdUniqueId=TMS行ID`(重试稳定);`update/delete` 行必须带 `fdId=hcs_stage_fd_id`。
5. 响应回填:回填 `hcs_exeplan_id`、逐行回填 `hcs_stage_fd_id`,清 `row_op`、置 `synced`;`add` 行没匹配到阶段ID → 置 `failed`,下轮重试。
### 2.3 三个触发入口(谁调 C103-9)
| 入口 | 位置 | 门禁 | 说明 |
| --- | --- | --- | --- |
| 合同链 | `HcsContractSyncSupport#pushContract` 第⑤步 | `exe-stage.sync-enabled` | 合同起草/更新成功后、特批挂起前同步计划 |
| 付款链 | `HcsPaymentSyncSupport#pushPayment` 第②步 | `exe-stage.sync-enabled` | 特批门禁通过后,先重推计划,再推履约记录 |
| 收款链 | `HcsClaimSyncSupport#pushOneContract` 第①步 | `exe-stage.sync-enabled` | 先累加并重推计划,再推 C107-1/C108-1 |
> 合同还没推合规时,计划行只做本地标记/累加,不报错,等合同链首推时一并带上。
---
## 3. 履约记录(C108)
### 3.1 公共前置与公共字段
所有场景的 C108-1 都要求:
- 合同已推合规(`hcs_fd_id` 非空);
- 存在已同步计划行(`hcs_stage_fd_id` 非空):付款/收票取**付款**计划行,收款/开票取**收款**计划行;
- `perf-record.sync-enabled` 开启;
- `fd_plan_id`/`fd_id` = 计划行 `hcs_stage_fd_id`,`fd_property` = 计划行款项性质。
四个场景的差异主要在:**触发时点、粒度、金额、履约日期、类型、幂等键**。
### 3.2 付款(`HcsPaymentSyncSupport` + `HcsPerfRecordSyncSupport`)
```
付款申请审批通过
→ hcs_sync_status=unsynced;计划金额 += 申请金额
→ 即时推送/扫描:先 C103-9 重推计划
→ 此时 paidAmount=0 → 跳过履约记录(日志“金蝶未实际付款”),整体仍置 synced
金蝶实际付款 → A103-2 回写(applyPayApplyResult)
→ paidAmount 首次>0 或金额变化 → hcs_sync_status=unsynced
→ 扫描付款任务:
无 hcs_perf_fd_id → C108-1 新建,返回 fdId 立即落库
有 hcs_perf_fd_id → C108-2 更新(分期付款推进实际金额)
```
- 金额:申请金额=`appliedAmount`,实际金额=`paidAmount`。
- 日期:申请日期(`applyDate`)。
- 类型:`付款`。
- 幂等:单据粒度,`hcs_perf_fd_id` 决定新建还是更新;金额不变不会重复触发。
- 附件:仅付款场景保留附件转传(C103-2 → `fd_plan_att`),其余场景传空列表。
- 特批:`need` 发起 C106-3 后挂起;特批通过后**不补推任何履约数据**,只恢复审批并补推金蝶;驳回不产生履约数据。
### 3.3 收款(`HcsClaimSyncSupport`)
```
认领登记(只登记本地,不推金蝶)
→ 事务提交后 afterCommit → pushClaimToHcs(claimId)
① 按“本次分摊到该合同”的金额累加收款计划行 → C103-9 重推
② C107-1 认领记录(认领主单 × 合同一条,金额=本次分摊额)
③ C108-1 履约流水(同一粒度:认领主单 × 合同一条)
```
- 触发点:**认领事务提交后**,不是金蝶回调。
- 前置:`exe-stage.sync-enabled` 为整条链总门禁;C108-1 另受 `perf-record.sync-enabled` 门禁。
- 定位合规流水:C104-2 按明细流水号查出合规收款流水ID;查不到只跳过 C107-1,不影响计划更新。
- 金额:本次认领分摊到该合同的金额(申请金额=实际金额)。
- 日期:认领日期(当前代码 `claim.claimDate`)。
- 类型:当前代码传的是 `collection`(见第 6 节差异说明)。
- 幂等/重试:事件驱动、**无定时重试**;C108-1 返回的 fdId 未落库(无 C108-2 场景),失败只记日志。
- 作废:只推 C107-3 把 C107-1 记录置为已作废;**不回冲计划金额、不回冲履约记录**。
### 3.4 开票(`HcsInvoicePerfSyncSupport`)
```
开票申请审批通过 → 推金蝶 A303-1 → 推合规 C111 开票登记(票据日期为空)
金蝶开票完成 → A303-5 回写:发票逐张落库;申请单置 invoiced + hcs_sync_status=unsynced
扫描开票任务(同一轮):
① C111 推送/回填票据日期
② 履约开票记录:扫描 hcs_perf_fd_id 为空且未超重试上限的发票
申请单须审批通过
合同回溯:开票申请 → 应收结算关联 → 正式结算单 → 合同
每张发票一条 C108-1
```
- 金额:发票价税合计 `invoiceAmount`。
- 日期:发票完成开票日期 `invoiceDate`。
- 类型:`开票`。
- 申请编号:发票号;标题:`开票履约-{发票号}`。
- 幂等:发票粒度,`hcs_perf_fd_id` 非空即跳过;失败 `retry+1` + 原因,下轮补偿,超上限人工处理。
- 合同回溯不到、无已同步收款计划行 → 记失败原因,等条件满足后自愈。
### 3.5 收票(`HcsReceiptPerfSyncSupport`)
```
收票单审批通过 → 推金蝶收票单(A303-2 + A302-6)
扫描收票任务(同一轮):
① C109 收票单推送合规 → 成功置 hcs_sync_status=synced
② 履约收票记录:扫描 hcs_perf_fd_id 为空且未超重试上限的分摊行
所属收票单须审批通过且 hcs_sync_status=synced(C109 必须先成功)
合同回溯:分摊行 → 正式结算单 → 合同
每条结算分摊行一条 C108-1
```
- 金额:分摊收票金额 `allocatedInvoiceAmount`,为空兜底结算金额。
- 日期:收票单发票日期 `invoiceDate`。
- 类型:`收票`;关联**付款**计划行。
- 申请编号:`{发票号}-{结算单号}`;标题:`收票履约-{申请编号}`。
- 幂等:分摊行粒度,`hcs_perf_fd_id` 非空跳过;C109 未成功时记“尚未推送合规”,成功后下轮自动补偿。
### 3.6 四场景对照
| 维度 | 付款 | 收款 | 开票 | 收票 |
| --- | --- | --- | --- | --- |
| 触发时点 | 金蝶实际付款回写后 | 认领事务提交后 | 金蝶开票完成、发票落库后 | C109 推送成功后 |
| 粒度 | 付款申请单 | 认领主单 × 合同 | 每张发票 | 每条结算分摊行 |
| 申请金额 | 申请金额 | 本次分摊金额 | 发票价税合计 | 分摊收票金额 |
| 实际金额 | 实付金额 | 同申请金额 | 同申请金额 | 同申请金额 |
| 履约日期 | 申请日期 | 认领日期 | 发票开票日期 | 发票日期 |
| 类型 | 付款 | collection(现状) | 开票 | 收票 |
| 计划行 | 付款(按款项性质) | 收款(进度款优先) | 收款(进度款优先) | 付款(进度款优先) |
| 幂等键 | `hcs_perf_fd_id`(可更新) | 无(每次认领新建) | `hcs_perf_fd_id` | `hcs_perf_fd_id` |
| 失败重试 | 定时扫描 | 无 | 定时扫描 | 定时扫描 |
| 更新接口 | C108-2 支持 | 不支持 | 不支持 | 不支持 |
---
## 4. 端到端时序(先后顺序)
### 4.1 计划必须先于记录
```mermaid
sequenceDiagram
participant C as 合同
participant H as HCS
participant B as 业务单据(付款/认领/发票/收票)
C->>H: C103-1 合同起草
H-->>C: hcs_fd_id
C->>H: C103-9 履约计划(add)
H-->>C: hcs_exeplan_id + 每行 hcs_stage_fd_id
Note over C,H: 阶段ID 落库后,下面四条链才有 fd_plan_id
B->>H: C108-1 履约记录(fd_plan_id=阶段ID)
```
### 4.2 付款链
```mermaid
sequenceDiagram
participant P as 付款申请
participant H as HCS
participant K as 金蝶
P->>P: 审批通过:计划金额+=申请金额
P->>H: C103-9 重推计划
P->>P: paidAmount=0,跳过 C108
K-->>P: 实际付款回写(paidAmount 变化)
P->>H: C108-1(首次)/ C108-2(分期)
```
### 4.3 收款链
```mermaid
sequenceDiagram
participant U as 认领
participant H as HCS
U->>U: 认领登记(本地)
U->>H: ① C103-9 累加收款计划并重推
U->>H: ② C104-2 定位合规流水 → C107-1 认领记录
U->>H: ③ C108-1 履约流水(本次分摊金额)
```
### 4.4 开票 / 收票(任务内顺序)
```
开票任务:C111 开票登记 → 发票逐张 C108-1(同一轮)
收票任务:C109 收票单 → 分摊行逐条 C108-1(同一轮,C109 必须先成功)
```
---
## 5. 定时任务与开关
| 任务 | 默认 cron | 内容 |
| --- | --- | --- |
| contract | `0 1/5 * * * ?` | C103-1/C103-11 → C103-9 |
| payment | `0 2/5 * * * ?` | C106 特批 → C103-9 → C108-1/2 |
| invoice-application | `0 3/5 * * * ?` | C111 → 履约开票 C108-1 |
| invoice-receipt | `0 4/5 * * * ?` | C109 → 履约收票 C108-1 |
| 收款 | 无独立任务 | 认领事务提交后事件驱动 |
| 配置(`thirdParty.hcs.*`) | 作用 | 默认 |
| --- | --- | --- |
| `exe-stage.sync-enabled` | C103-9 总开关;同时门禁整条收款链 | true |
| `perf-record.sync-enabled` | 四场景履约记录总开关 | false |
| `perf-record.xform-id` | C108 表单模板ID | 空 |
| `push.payment/invoice-application/invoice-receipt.sync-enabled` | 各任务开关 | false |
| `push.max-retry` / `push.batch-size` | 重试上限 / 单轮批量 | 5 / 配置值 |
| `attachment.transfer-enabled` | 付款履约记录附件转传 | true |
手动入口:`POST /hcs/sync/{bizType}` 批量扫描一轮(开票/收票为组合动作,含履约记录);`POST /hcs/sync/{bizType}/{id}` 单条重推(仅主单据,不覆盖发票/分摊行粒度)。
---
## 6. 当前实现与设计文档的差异(重要)
以下为代码实际情况,与《2026-10-27 履约计划与履约记录逻辑与流程梳理》《2026-10-28 C108 履约记录四场景推送改造流程梳理》存在出入,落地时以本节为准:
| 点 | 设计文档口径 | 当前代码 |
| --- | --- | --- |
| 收款触发 | 金蝶认领推送 A301-3 成功后 | **认领事务提交后**(认领只登记本地,不推金蝶) |
| 收款履约日期 | 收款流水交易日期 `transaction_time` | **认领日期 `claimDate`**(提交 `4a76e65b` 回退了该调整) |
| 收款履约类型 | 中文「收款」 | **`collection`**(`PERFORM_TYPE_COLLECTION`,未使用 `PERF_TYPE_COLLECTION`) |
| 收款金额 | 该合同累计认领金额 | **本次认领分摊到该合同的金额** |
| 收款组装 | 复用 `HcsPerfRecordAddSupport` | **仍为 `HcsClaimSyncSupport` 内部独立组装** |
| 付款链 C103-9 门禁 | 不受 `exe-stage` 开关限制 | **受 `exe-stage.sync-enabled` 控制** |
| 收款链 fdId | 需落库以支持后续更新 | **未落库**(无 C108-2 场景) |
| 付款作废 / 认领作废 | — | 均不回冲计划金额与履约记录(认领仅 C107-3 作废) |
建议:若确认收款需按「交易日期 + 中文类型 + 通用组件」口径,应把 `HcsClaimSyncSupport#pushPerfRecord` 切到 `HcsPerfRecordAddSupport`,并同步修正日期与类型常量;否则应同步更新设计文档,避免联调口径不一致。
---
## 7. 代码索引
| 职责 | 类 / 方法 |
| --- | --- |
| 计划行维护、差异标记、金额累加、默认行 | `ContractExeStageServiceImpl`:`submitRows` / `removeRow` / `accumulatePaidAmountOnApprove` / `accumulateClaimedAmountOnPush` / `createDefaultRowOnApprove` / `findPaymentStageRow` / `findCollectionStageRow` |
| C103-9 同步与回填 | `HcsExeStageSyncSupport#syncExeStages` |
| 付款链编排 | `HcsPaymentSyncSupport#pushPayment` |
| 付款履约记录 C108-1/2 | `HcsPerfRecordSyncSupport#pushPerfRecord` |
| 收款链编排 | `HcsClaimSyncSupport#pushClaimToHcs` / `#pushOneContract` / `#pushPerfRecord` / `#voidClaimToHcs` |
| C108-1 通用组件(开票/收票共用) | `HcsPerfRecordAddSupport#pushPerfRecordAdd` |
| 开票履约记录 | `HcsInvoicePerfSyncSupport#pushUnsyncedInvoicePerfRecords` |
| 收票履约记录 | `HcsReceiptPerfSyncSupport#pushUnsyncedReceiptPerfRecords` |
| 定时任务编排 | `HcsPushTask`:`pushHcsPayment` / `syncHcsInvoiceApplications` / `syncHcsInvoiceReceipts` |
| 审批即时推送 | `HcsImmediatePushSupport#pushPaymentAndWait / pushPaymentAfterCommit` |
| 金蝶实付回写触发 | `PaymentApplicationServiceImpl#applyPayApplyResult` |
| 认领事务提交触发 | `ReceiptFlowServiceImpl`(`afterCommit` → `pushClaimToHcs`) |
| 常量与映射 | `HcsSyncConstant`(`PERF_TYPE_*`、`PERFORM_TYPE_*`、`FUND_NATURE_*`、`fundNatureOfPayment`) |