docs: 新增收款认领金蝶对接全链路业务流程文档(A301-2公告同步/A301-3认领推送/A301-1收款单回写)
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
# 收款认领金蝶全链路业务流程(A301-2 认领公告同步 → A301-3 认领结果推送 → A301-1 收款单查询回写)
|
||||
|
||||
> 适用系统:TMS(BladeX 微服务平台,服务:blade-transport)
|
||||
> 对接系统:金蝶云·星瀚(业财融合 BFI,经 iPaaS 网关 `/gwzh/BFI` 直连,不经过合同合规系统)
|
||||
> 覆盖接口:A301-2 收款认领公告查询、A301-3 收款认领结果推送、A301-1 收款单查询(收款处理查询)
|
||||
> 关联文档:`TMS业财融合-集成流程图文字版与业务流程梳理.md` 第 7 节(图06 回款认领)、`2026-09-17-BFI分页查询通用翻页工具(BfiUtil-queryAllPages)技术文档.md`、`2026-09-23-金蝶(星瀚)BFI接口调用全链路梳理(按业务域汇总).md`
|
||||
> 最后更新:2026-09-24(按当前代码梳理;接口契约在 BFI 客户端已编码,本期完成业务侧接线与联调准备)
|
||||
|
||||
---
|
||||
|
||||
## 1. 整体业务链路
|
||||
|
||||
图06「收款查询及认领(回款认领)」采用**业务先行认领(场景二)**:金蝶司库收到银行流水并完成**第一轮自动认领(到客户维度)**,TMS 认领到合同/结算单维度后回推金蝶生成收款单。分三段:
|
||||
|
||||
```
|
||||
阶段一:认领公告同步(TMS 手动触发,POST /receipt-flow/sync)
|
||||
A301-2 收款认领公告查询(claimusers=当前登录用户真实姓名)
|
||||
→ BfiUtil.queryAllPages 全量翻页 → 按 detail_serial_no 幂等 upsert 收款流水表 blade_kingdee_receipt_flow
|
||||
→ 前端"手动同步流水"按钮直接调用(不再传本地 mock 行)
|
||||
|
||||
阶段二:二次认领(页面认领,POST /receipt-flow/claim)
|
||||
用户在收款流水详情/批量认领页选择审批通过的应收正式结算单并按比例分摊
|
||||
→ 本地生成认领主单 blade_receipt_claim + 分摊表 blade_receipt_claim_settlement + 流水金额状态更新
|
||||
→ A301-3 收款认领结果推送(billid=公告id、分录=结算单分摊行)
|
||||
→ 推送成功回写金蝶收款单号 + kingdee_bill_status=pushed;失败则抛异常整体回滚
|
||||
|
||||
阶段三:收款单查询回写(手动触发,POST /receipt-claim-record/query-kingdee-result)
|
||||
A301-1 收款单查询(近 1 个月窗口全量翻页)
|
||||
→ 按 sourcebillnumber=awrp_src_code 本地匹配已推送认领
|
||||
→ 回写金蝶收款单号与单据状态(A暂存/B已提交/C已审核/D已收款)
|
||||
```
|
||||
|
||||
核心设计原则(与付款/应收/收票链路一致):
|
||||
|
||||
1. **公告为准**:收款流水统一由 A301-2 认领公告落库,前端不再自造流水数据;按 `detail_serial_no` 幂等 upsert。
|
||||
2. **推送先于结果**:认领保存与 A301-3 推送在同一事务内,推送失败整体回滚,避免金蝶与本地认领不一致。
|
||||
3. **认领公告 id 必填**:A301-3 按 `billid` 定位公告,同步阶段必须落库公告 id(`bill_id`),缺失拦截。
|
||||
4. **以金蝶侧实际生成为准**:A301-3 推送成功回写金蝶收款单号;A301-1 回写仅推进 `kingdee_bill_status`,不改本地认领金额。
|
||||
5. **异常回收人工处置**:本期认领作废不推金蝶(本地生成 KDCX 冲单号),金蝶侧退票/红冲由人工处置后重推,后续迭代接入。
|
||||
|
||||
---
|
||||
|
||||
## 2. 三个接口在链路中的角色
|
||||
|
||||
| 接口 | 名称 | 方向 | 触发环节 | 业务用途 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| A301-2 | 收款认领公告查询 | TMS → 金蝶(查询) | 阶段一(手动同步) | 按参与认领用户拉取金蝶认领公告,落库存收款流水表供页面认领 |
|
||||
| A301-3 | 收款认领结果推送 | TMS → 金蝶 | 阶段二(页面认领) | 将二次认领结果(认领至结算单,即应收单)推给金蝶生成收款单 |
|
||||
| A301-1 | 收款单查询 | TMS → 金蝶(查询) | 阶段三(手动回写) | 查询金蝶收款单(收款处理)状态,按来源单据编码回写认领结果 |
|
||||
|
||||
查询类接口时间窗约束:A301-1 **业务日期范围 ≤ 1 个月**;A301-2 无时间窗参数,仅按用户与分页。
|
||||
|
||||
---
|
||||
|
||||
## 3. 阶段一:A301-2 认领公告同步
|
||||
|
||||
代码入口:`ReceiptFlowController.sync`(`POST /receipt-flow/sync`,菜单权限 `receipt_flow`,按钮权限 `receipt_flow_sync`)→ `ReceiptFlowServiceImpl.sync()`。
|
||||
|
||||
### 3.1 编排
|
||||
|
||||
1. **确定参与认领用户**:`UserCache.getUserRealName(AuthUtil.getUserId())`,为空拦截「当前用户无姓名,无法同步认领公告」。
|
||||
2. **全量翻页**:`BfiUtil.queryAllPages(pageNo -> bfiService.queryClaimAnnounce(claimusers, pageNo, 200))`,受 `BfiUtil.DEFAULT_MAX_PAGES`(50 页)保护。
|
||||
3. **幂等落库**:按 `detail_serial_no`(取 `detailid`,缺省回退 `tradedetailno`/`bankdetailno`)`FOR UPDATE` 查重后 insert/update 收款流水表;重复明细流水号抛「明细流水号重复」拦截。
|
||||
4. **操作留痕**:`blade_receipt_flow_record` 记 `sync` 操作(新增/更新逐行记录,operator=当前用户)。
|
||||
|
||||
### 3.2 A301-2 返回 → 收款流水表字段映射
|
||||
|
||||
`blade_kingdee_receipt_flow`(新增列见 §7 SQL):
|
||||
|
||||
| A301-2 返回(BfiClaimAnnounceVO) | 收款流水表字段 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| id | `bill_id` | **认领公告 id,A301-3 推送必填**,本期新增 |
|
||||
| billno | `receipt_notice_no` | 认领通知单 |
|
||||
| recviewpayer | `payer_name` | 付款人展示名 |
|
||||
| reamount | `receipt_amount` | 收款金额 |
|
||||
| oppunit | `counterparty_name` | 对方户名 |
|
||||
| oppbanknumber | `counterparty_account` | 对方账号 |
|
||||
| oppbank | `counterparty_bank` | 对方开户行 |
|
||||
| description | `summary` | 摘要 |
|
||||
| tradetime | `transaction_time` | 交易时间 |
|
||||
| detailid(缺省回退 tradedetailno/bankdetailno) | `detail_serial_no` | 明细流水号,**幂等键(tenant_id, detail_serial_no 唯一索引)** |
|
||||
| unclaimamount | `unclaimed_amount` | 未认领金额,本期新增 |
|
||||
| fee | `fee` | 手续费,本期新增 |
|
||||
| recpayee | `payee_name` | 收款人,本期新增 |
|
||||
| claimstatus | `kingdee_claim_status` | 公告认领状态(0未认领/1已认领),本期新增 |
|
||||
| claimme | `claim_me` | 我已认领,本期新增 |
|
||||
| claimedamount | —(不落库) | 本地 `claimed_amount` 只记录 TMS 认领金额,与公告已认领金额语义区分 |
|
||||
|
||||
> **口径说明**:`claimed_amount`/`claim_status` 为**本地认领金额/认领状态**(由 claim/作废驱动),与金蝶公告的 `claimstatus`/`claimedamount` 互不覆盖;公告侧状态单独存 `kingdee_claim_status` / `unclaimed_amount`。
|
||||
|
||||
### 3.3 前端
|
||||
|
||||
`receipt-flow.vue`「手动同步流水」按钮不再生成 mock 行,直接 `POST /receipt-flow/sync`(无请求体),后端返回同步条数后刷新列表。
|
||||
|
||||
---
|
||||
|
||||
## 4. 阶段二:A301-3 认领结果推送
|
||||
|
||||
代码入口:`ReceiptFlowController.claim`(`POST /receipt-flow/claim`)→ `ReceiptFlowServiceImpl.claim(ReceiptClaimRequest)`。
|
||||
|
||||
### 4.1 编排
|
||||
|
||||
1. **本地校验**(沿用现有逻辑):流水锁行、结算单锁行、分摊金额上限校验(累计认领不超结算金额、不超流水剩余可认领金额)、关联结算单同一项目/组织/收付款方。
|
||||
2. **本地落库**:插入 `blade_receipt_claim`(claim_status=claimed、kingdee_bill_status=none、awrp_src_code=生成的来源单据编码)+ 分摊表 `blade_receipt_claim_settlement` + 刷新结算单收款汇总 + 更新流水的 `claimed_amount/claim_status` + 认领留痕。
|
||||
3. **生成来源单据编码**:`awrp_src_code = SKCL + yyyyMMddHHmmss + 认领id尾号6位`(参照冲单号生成,同文件 `buildKingdeeBillNo` 风格),落库 `blade_receipt_claim.awrp_src_code`(本期新增),作为 A301-1 回写匹配键。
|
||||
4. **A301-3 推送**:`bfiService.pushClaimResult(dto)`(网关 body 单笔包装)。推送成功(`BfiBillSaveResultVO` 全项成功)→ 回写 `kingdee_bill_no`(`result[0].number` 金蝶收款单号)+ `kingdee_bill_status=pushed`;失败 → 抛 `ServiceException`(汇总行错误文本)**整体回滚**。
|
||||
|
||||
> **幂等说明**:`awrp_src_sys + awrp_src_code` 为金蝶候选键;推送成功但本地回滚(网络/DB 抖动)后重推会**重新生成 awrp_src_code** 产生新单,联调期以推送失败回滚为主路径规避;后续如遇需要可改为推送前置生码 + 成功补偿落库。
|
||||
|
||||
### 4.2 A301-3 报文取数
|
||||
|
||||
| DTO 字段 | 取数 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| billid | 流水 `bill_id` | **必填**,缺失拦截「认领公告id缺失,请先同步金蝶收款流水」 |
|
||||
| awrp_src_sys | `thirdParty.bfi.srcSys`(默认 WLTMS) | 与付款/收票链路同源 |
|
||||
| awrp_src_code | `SKCL+时间戳+认领id尾号` | 见 4.1 |
|
||||
| recpaytype_number | `KingdeeBfiConstant.BFI_CLAIM_REC_PAY_TYPE`(**待确认**,示例 101) | 收款类型编码 |
|
||||
| paymenttype | `KingdeeBfiConstant.BFI_CLAIM_PAYMENT_TYPE`(**待确认**,默认 bd_customer) | 付款人类型 |
|
||||
| recviewpayer | 流水 `payer_name` | 付款人名称 |
|
||||
| recpayer | 流水 `payer_id`(同步时暂不落库) | **待确认**:金蝶付款人 master id,DTO 标记必填;联调若金蝶强校验则需按付款人名称反查 A902-1 客户/供应商档案 id 补齐 |
|
||||
| entryentity[] | 各结算单分摊行 | 见 4.3 |
|
||||
|
||||
### 4.3 A301-3 分录取数
|
||||
|
||||
| entryentity 字段 | 取数 |
|
||||
| --- | --- |
|
||||
| e_receivableamt | 分摊金额 `allocated_receipt_amount` |
|
||||
| e_corebilltype | `ar_finarbill`(财务应收单,复用 `KingdeeBfiConstant.BFI_AR_BILL_SRC_BT`),有金蝶应收单号时携带 |
|
||||
| e_corebillno | 分摊结算单 `formal_settlement.kingdee_bill_no`(A302-2 同步回写,缺失时不传,`@JsonInclude(NON_NULL)` 省略) |
|
||||
| seq | 分摊行序号(1 起) |
|
||||
| e_receivingtype_number | 同 `recpaytype_number`(**待确认**,示例仅含 e_receivableamt,其余非必填按需放开) |
|
||||
|
||||
### 4.4 金额流转
|
||||
|
||||
认领分摊后收款流水本地状态:
|
||||
|
||||
```
|
||||
claim_amount(认领主单) = Σ 分摊金额
|
||||
flow.claimed_amount = Σ 该流水所有有效认领分摊(local)
|
||||
flow.claim_status = 0 → unclaimed;<receipt_amount → partial;≥ → claimed
|
||||
结算单 claimed/remaining = refreshPaymentSummary(沿用现有)
|
||||
```
|
||||
|
||||
**重要**:A301-3 推送的是认领结果(资金去向),**不修改**流水的收款金额本身;`unclaimed_amount` 为金蝶公告侧口径,仅展示、不参与本地计算。
|
||||
|
||||
---
|
||||
|
||||
## 5. 阶段三:A301-1 收款单查询回写
|
||||
|
||||
代码入口:`ReceiptClaimRecordController.queryKingdeeResult`(`POST /receipt-claim-record/query-kingdee-result`,菜单权限 `receipt_claim_record`)→ `ReceiptClaimRecordServiceImpl.refreshKingdeeResult()`。
|
||||
|
||||
### 5.1 编排
|
||||
|
||||
1. **轮询对象**:`claim_status=claimed` 且 `awrp_src_code` 非空且 `kingdee_bill_status IN (pushed, approved)` 的认领记录。
|
||||
2. **A301-1 查询**:业务日期默认**今天回溯 30 天**(≤1 个月),`BfiUtil.queryAllPages` 全量翻页(pageSize 200)。
|
||||
3. **本地匹配**:金蝶收款单 `sourcebillnumber == 认领.awrp_src_code` → 命中。
|
||||
4. **回写**:`kingdee_bill_no = 收款单 billno`(第一条命中,随后仅推进状态);`kingdee_bill_status` 按单据状态映射:
|
||||
|
||||
| 金蝶 billstatus | 本地 kingdee_bill_status | 展示 |
|
||||
| --- | --- | --- |
|
||||
| A 暂存 / B 已提交 | pushed | 已推送 |
|
||||
| C 已审核 | approved | 审核通过 |
|
||||
| D 已收款 | received | 已收款 |
|
||||
| 其他/G 退单 | failed | 处理失败 |
|
||||
|
||||
> 定时回写开关(复用 `PaymentKingdeeResultTask` 编排风格)本期预留,未接入定时调度;后续按认证领记录量接入独立子流程(开关 `thirdParty.bfi.receiptClaimResult.*`)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 状态机与防重体系
|
||||
|
||||
### 6.1 收款流水本地认领状态
|
||||
|
||||
```
|
||||
unclaimed ──认领分摊──▶ partial/claimed ──(全部作废)──▶ unclaimed
|
||||
▲ │
|
||||
└────同步公告幂等 upsert 不覆盖(公告已认领金额不落 claimed_amount)
|
||||
```
|
||||
|
||||
### 6.2 认领记录金蝶状态
|
||||
|
||||
```
|
||||
none(认领落库默认)──A301-3推送成功──▶ pushed ──A301-1回写D──▶ received(终态)
|
||||
│ │ └──C──▶ approved──┐
|
||||
└────推送失败(抛异常回滚,无残留) └──A/B/garker──▶ failed ──┘
|
||||
作废(本期不推金蝶):→ voided + KDCX 冲单号(本地)
|
||||
```
|
||||
|
||||
### 6.3 防重键与幂等汇总
|
||||
|
||||
| 对象 | 防重键/幂等依据 | 使用接口 |
|
||||
| --- | --- | --- |
|
||||
| 收款流水 | 唯一索引(tenant_id, detail_serial_no) | A301-2 sync upsert |
|
||||
| 金蝶收款单 | awrp_src_sys + awrp_src_code | A301-3(候选键)/ A301-1(回写按 sourcebillnumber 匹配) |
|
||||
| 认领记录 | 本地主键 + awrp_src_code(回写匹配键) | claim / A301-1 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据前提与上线操作
|
||||
|
||||
| # | 事项 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 变更 SQL | `doc/sql/transport/blade_receipt_flow_claim_20260924.sql`(幂等可重复执行):收款流水表新增 `bill_id/payer_id/kingdee_claim_status/claim_me/unclaimed_amount/fee/payee_name`,认领主单新增 `awrp_src_code`。**执行后方可启动服务** |
|
||||
| 2 | Nacos 配置 | 无新增必配项;A301-1 回写窗口(31 天)本周期内为代码常量,后续抽配置 |
|
||||
| 3 | claimusers 前提 | 金蝶认领公告的 `claimusers` 字段须与 TMS 用户真实姓名匹配,否则手动同步查不到公告;联调时需金蝶侧在公告维护认领人 |
|
||||
| 4 | A301-3 待确认字段 | `recpaytype_number`(示例 101)、`paymenttype`(默认 bd_customer)、`recpayer`(金蝶付款人 master id 来源)、分录 `e_corebilltype/e_corebillno/e_receivingtype_number` 是否必传——以金蝶接口文档为准,常量收敛于 `KingdeeBfiConstant.BFI_CLAIM_*` |
|
||||
| 5 | 结算单前提 | 认领分摊的应收正式结算单须审批通过、未作废,且已完成付款侧/应收侧金蝶同步(`formal_settlement.kingdee_bill_no` 有值)以便分录携带财务应收单号 |
|
||||
| 6 | 联调顺序 | 执行 SQL → 金蝶维护认领公告及认领人 → 页面「手动同步流水」→ 收款流水列表/详情认领(选择结算单分摊)→ 推送若失败按金蝶报错调整常量 → 认领记录页「查询金蝶认领结果」验证回写 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 关键代码索引
|
||||
|
||||
| 环节 | 代码位置 |
|
||||
| --- | --- |
|
||||
| 认领公告同步 | `controller/ReceiptFlowController.sync`(`POST /receipt-flow/sync`)→ `service/impl/ReceiptFlowServiceImpl.sync()` |
|
||||
| 认领推送 | `controller/ReceiptFlowController.claim`(`POST /receipt-flow/claim`)→ `service/impl/ReceiptFlowServiceImpl.claim()/pushClaimResultByBfi()` |
|
||||
| 收款单回写 | `controller/ReceiptClaimRecordController.queryKingdeeResult`(`POST /receipt-claim-record/query-kingdee-result`)→ `service/impl/ReceiptClaimRecordServiceImpl.refreshKingdeeResult()` |
|
||||
| BFI 客户端契约 | `blade-third-party-api/blade-bfi-api`:`IBfiService.queryClaimAnnounce/pushClaimResult/queryRecBill`、`BfiClaimAnnounceVO`、`BfiClaimPushDTO/EntryDTO`、`BfiRecBillVO`、`BfiClaimAnnounceQueryDTO/BfiRecBillQueryDTO` |
|
||||
| 常量/配置 | `constant/KingdeeBfiConstant`(BFI_CLAIM_REC_PAY_TYPE、BFI_CLAIM_PAYMENT_TYPE、KINGDEE_STATUS_PUSHED/RECEIVED)、`config/BfiProperties`(srcSys) |
|
||||
| 展示 | `ReceiptFlowVO.kingdeeClaimStatusName` + `ReceiptFlowWrapper` 翻译;`ReceiptClaimRecordVO.kingdeeBillStatusName`(含 pushed/received) |
|
||||
| 前端 | `tms-erp-web:views/payment/receipt-flow.vue`(手动同步去 mock)、`views/payment/receipt-claim-record.vue`(查询金蝶认领结果按钮)、`api/payment/receiptFlow.js、receiptClaimRecord.js` |
|
||||
Reference in New Issue
Block a user