📝 新增付款管理正式付款同步金蝶技术文档

This commit is contained in:
刘泉佳
2026-09-17 10:39:08 +08:00
parent 7af68bd4f6
commit e18c7dcfda
@@ -0,0 +1,244 @@
# 正式付款同步金蝶(星瀚)技术文档:财务应付单 + 付款申请下推
> 适用系统:TMS(BladeX 微服务平台,服务:blade-transport)
> 对接系统:金蝶云·星瀚(业财融合 BFI,经 iPaaS 网关)
> 关联文档:`doc/docs/TMS业财融合-集成流程图文字版与业务流程梳理.md`、`doc/docs/业财融合系统接口文档.xlsx`、`doc/docs/业务流程/付款申请同步金蝶(星瀚)技术文档.md`(A103-3 预付款路径)
> 最后更新:2026-09-16
---
## 1. 背景与范围
正式结算单发起付款申请后,付款管理(`blade_payment_application`,`paymentType = settlement_payment`)生成一条记录;审批通过后勾选点"批量同步",需**先推送财务应付单(A102-2),再由应付下推付款申请(A103-1)**,两步完成后才视为同步成功。
- 触发入口:付款管理页面(前端 `tms-erp-web/src/views/payment/payment-application.vue`)"批量同步"按钮,权限码 `payment_application_sync`
- 对接接口:
- **A102-2 财务应付单保存** `POST /ierp/kapi/v2/awrp/ap/ap/ap_finapbill/save`
- **A103-1 付款申请保存(应付下推)** `POST /ierp/kapi/v2/awrp/ap/ap/ap_finapbill/push`
- 路径划分:**正式付款**(settlement_payment)走本文档 A102-2 → A103-1 两步链路;**预付款**(project_advance / progress_advance)维持原 A103-3 直推付款申请单,见《付款申请同步金蝶(星瀚)技术文档》
- 调用方式:前端 → TMS 后端转发 → 星瀚(OAuth2 凭证仅存后端,前端不持有)
- 落库结果:A103-1 返回的付款申请单 id 写入 `kingdee_bill_no`(既有字段);**A102-2 返回的应付单 id 不落库**,仅校验保存成功,后续如需可经 A102-4 按防重键(`awrp_src_sys` + `awrp_src_code`)查询(`BfiServiceImpl.queryApBill` 已封装),本次无表结构变更
---
## 2. 业务流程
### 2.1 整体链路(对应需求文档 4.3 步骤 4)
```
正式结算单发起付款申请 → 付款管理生成记录 → 审批通过(approved)
→ 批量同步(本文档)
① A102-2 财务应付单保存(防重键幂等)
② A103-1 应付下推付款申请(分录关联①的 awrp_entry_code)
→ 金蝶财务共享审批(黑盒) → 付款处理 → 付款完成
→ 后续(待建设):A103-2/A103-4 定时回写、A902 附件、B901 锁单
```
### 2.2 批量同步时序
```
前端 payment-application.vue blade-transport 后端 星瀚(BFI)
│ 勾选 approved 记录 │ │
│ POST /payment-application/ │ │
│ sync-kingdee-batch [id...] │ │
│──────────────────────────────────────>│ 逐单循环(单条失败不中断批次) │
│ │ FOR UPDATE 锁单 + approved 校验 │
│ │ ① 组装 BfiApBillSaveDTO │
│ │ POST ap_finapbill/save ──────────────>│
│ │ <── result[]{id,...} ─────────────────│
│ │ 仅校验保存成功(应付单id不落库) │
│ │ ② 组装 BfiPayApplyPushDTO │
│ │ entry.awrp_finapbill_entryid │
│ │ = paymentNo + "-1" │
│ │ POST ap_finapbill/push ──────────────>│
│ │ <── result[]{id,...} ─────────────────│
│ │ kingdeeBillNo = 付款申请单id │
│ │ kingdeeStatus = synced │
│ │ 下游台账联动(结算付款记录/预付台账) │
│ <── R<List<String>>(逐单结果)────────│ │
```
### 2.3 前置条件与幂等约定
| 约定 | 说明 |
| --- | --- |
| 状态校验 | 仅 `approvalStatus = approved` 允许同步 |
| 幂等跳过 | `kingdeeStatus = synced` 的单据直接返回已存单据号,不重复推送 |
| ①防重键 | 星瀚应付单侧 `awrp_src_code`(=paymentNo)+ `awrp_src_sys`,②失败后重推时①走更新语义,不重复生成应付单 |
| ②防重键 | 付款申请单侧 `awrp_src_code`(=paymentNo)+ `awrp_src_sys`;分录行 `awrp_entry_code`(=paymentNo + "-1")不得重复 |
| ②关联键 | `awrp_finapbill_entryid` = ①明细的 `awrp_entry_code`(=paymentNo + "-1"),**不依赖①返回的内部 id** |
| 失败重推 | 任一步失败置 `kingdeeStatus = failed`,可重新勾选同步(①已成功的应付单按防重键走更新语义) |
| 前置校验 | ①推送前校验物料/计量单位常量非空(见 5.2);未关联合同、合同不存在、组织编码为空、结算币种为空时同步失败 |
---
## 3. 接口定义
### 3.1 A102-2 财务应付单保存
- URL:`{thirdParty.bfi.baseUrl}/ierp/kapi/v2/awrp/ap/ap/ap_finapbill/save`
- Method:`POST`,请求体 `{"data": [ {主表字段, "detailentry":[明细]} ]}`
- 返回结构与 A103-3 一致:`data.result[].id` 为星瀚应付单内部主键,`billStatus=false` 时以 `errors` 抛出业务异常,`errorCode/message/status` 由 `BfiServiceImpl.commonCall` 统一校验。
### 3.2 A103-1 付款申请保存(应付下推)
- URL:`{thirdParty.bfi.baseUrl}/ierp/kapi/v2/awrp/ap/ap/ap_finapbill/push`
- Method:`POST`,请求体 `{"data": [ {主表字段, "entry":[分录]} ]}`
- 返回 `result[].id` 为星瀚付款申请单内部主键(写入 `kingdee_bill_no`),`result[].number` 为星瀚单据编号(FKSQ-xxxx,暂不落库),`result[].type = Push`。
---
## 4. 字段映射关系
### 4.1 A102-2 主表(`BfiApBillSaveDTO` ← 付款申请实体 + 合同 + 常量)
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| billtypeid_number | 单据类型.编码 | 是 | 按映射字典转换:`KingdeeBfiConstant.BFI_AP_BILL_BILLTYPE_NAME`(默认"服务采购应付")经 `AP_BILL_BILLTYPE_MAP` 名称→编码 | 路由规则见 5.3;未维护名称报错 |
| org_number | 结算组织.编码 | 是 | **合同所属组织**:`contract.organizationId` → `dept.deptCode`,空回退组织名称(复用 `bfiOrgNumber`) | 缺失报错 |
| bizdate | 单据日期 | 是 | `applyDate`(空取当天) | 沿用 yyyyMMdd,**待确认是否需 yyyy-MM-dd** |
| asstacttype | 往来类型 | 是 | 常量 `bd_supplier` | 供应商 |
| asstact_number | 往来户.编码 | 是 | 复用 `bfiSupplierCode`:payeeName 匹配客商档案 `customerCode`,未命中回退 payeeName | |
| purmode | 付款方式 | 是 | 常量 `BFI_AP_BILL_PUR_MODE` | `CREDIT` 赊购(金蝶侧可调金额);`CASH` 会自动 100% 推付款 |
| currency_number | 结算币别.货币代码 | 是 | **合同结算币种** `contract.settlementCurrency`(复用 `bfiCurrency`) | 缺失报错 |
| payorg_number / purorg_number | 付款/采购组织.编码 | 是/否 | 同 org_number | |
| payproperty_number | 款项性质.编码 | 是 | 常量 `BFI_AP_BILL_PAY_PROPERTY` | 暂按 `2001`,**待金蝶确认** |
| isincludetax / ispricetotal | 录入含税价 / 录入总价 | 否 | `true` / `true` | 录入总价免单价数量换算 |
| exratetable_number / exratedate | 汇率表/汇率日期 | 否 | 复用配置 `thirdParty.bfi.payApply.exratetable`(默认 01)/ 同 bizdate | |
| asstactname | 往来单位名称 | 否 | `payeeName` | |
| remark | 备注 | 否 | `paymentNo + " " + settlementNo` | |
| awrp_src_sys / awrp_src_code | 外部系统编号/来源单据号 | 是 | 配置 `thirdParty.bfi.payApply.srcSys` / `paymentNo` | 应付单候选键 |
| awrp_src_bt / awrp_src_con_no | 来源单据/上游合同号 | 否 | `awrp_contract_info` / `contractNo` | 有合同即传 |
| awrp_src_type | 外部单据类型 | 是 | 常量 `BFI_AP_BILL_SRC_TYPE` | 暂按 `TMS财务应付单`,**待金蝶确认** |
未传的可选字段:settlementtype_number(结算方式)、taxrateid_number(税率)、duedate、bookdate、department_number、preentry(预付信息)等。
### 4.2 A102-2 明细(`BfiApBillSaveEntryDTO`,单条申请固定 1 行)
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| material_number | 物料编码.编码 | 是 | 常量 `BFI_AP_BILL_MATERIAL` | **TMS 无物料档案,当前为空串,推送前校验拦截;待金蝶提供运输服务物料编码** |
| measureunit_number | 计量单位.编码 | 是 | 常量 `BFI_AP_BILL_MEASURE_UNIT` | **同上,待金蝶确认(如"吨")** |
| quantity | 明细.数量 | 是 | 固定 `1` | 结算单无吨位数据,配合 ispricetotal=true 录入总价 |
| e_pricetaxtotal | 明细.应付金额 | 是 | `appliedAmount`(2 位小数) | 含税应付金额 = 申请付款金额 |
| project_number | 项目.项目编码 | 是 | 复用 `bfiProjectNumber`:`projectId` → `ProjectApply.projectCode`,无项目传 `999` | |
| awrp_entry_code | 外部系统来源分录标识 | 是 | `paymentNo + "-1"` | 候选键;②下推时以 `awrp_finapbill_entryid` 关联此行 |
| e_remark | 明细.备注 | 否 | `remark` | |
未传:planentity 付款计划(不传由金蝶按明细自动汇总)、e_amount/e_tax、taxrateid_number、awrp_src_con_eno。
### 4.3 A103-1 主表(`BfiPayApplyPushDTO`)
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| awrp_src_code / awrp_src_sys | 来源单据号/外部系统编号 | 是 | `paymentNo` / 配置 `payApply.srcSys` | 付款申请单候选键 |
| applydate | 申请日期 | 是 | `applyDate`(空取当天) | 同 bizdate 格式 |
| applycause | 请款事由 | 否 | 复用 `bfiApplyCause` | 结算付款 → `结算付款申请` |
| payorg_number / purorg_number | 付款/采购组织.编码 | 否 | 同 A102-2 合同组织编码 | 传值更稳,不传金蝶按应付单自动带出 |
| exratetable_number / exratedate | 汇率表/汇率日期 | 否 | 配置复用 / 同 applydate | 不传金蝶自动带出 |
| awrp_textfield1 | 付款渠道 | 否 | 复用 `bfiPaymentMethodLabel`:`paymentMethod` 经字典 `pay_method` 翻译为标签 | |
| creator_name | 申请人 | 否 | `applicantName` | |
### 4.4 A103-1 分录(`BfiPayApplyPushEntryDTO`,固定 1 行)
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| e_paymenttype_number | 付款类型.编码 | 是 | 常量 `201` | 正式付款 |
| awrp_finapbill_entryid | 结算单分录id | 是 | `paymentNo + "-1"` | **对应 A102-2 明细 awrp_entry_code** |
| awrp_entry_code | 对方唯一行 id | 是 | `paymentNo + "-1"` | 不得重复 |
| e_assacct | 往来账户 | 是 | `bankAccount` | 收款账号(页面"收款账户") |
| e_bebank_number | 往来银行.编码 | 是 | `bankName` | **必填编码,当前暂传银行名称,待银行档案编码映射**(与 A103-3 遗留项一致) |
| e_applyamount | 申请金额 | 是 | `appliedAmount`(2 位小数) | |
| e_expaydate | 期望付款日 | 否 | 同 applydate | |
| project_number | 项目.项目编码 | 是 | 复用 `bfiProjectNumber` | 无项目传 `999` |
| awrp_src_type | 外部单据类型 | 是 | 复用配置 `payApply.srcType` | |
| e_remark | 备注 | 否 | `remark` | |
未传:e_duedate、e_settlementtype_number、e_costcenter_number、awrp_splb_number。
---
## 5. 常量与待确认清单
### 5.1 设计约定
A102-2 所需的金蝶侧固定档案编码**不进 Nacos 配置**,统一定义在常量类 `org.springblade.transport.constant.KingdeeBfiConstant`;金蝶侧确认取值后**直接改常量重新发包**即可。
### 5.2 常量清单(`org.springblade.transport.constant.KingdeeBfiConstant`)
| 常量 | 当前值 | 用途 | 状态 |
| --- | --- | --- | --- |
| BFI_AP_BILL_BILLTYPE_NAME | `服务采购应付` | A102-2 单据类型默认名称,经 `AP_BILL_BILLTYPE_MAP` 转换为编码(`ApFin_service_BT_S`) | 待金蝶确认 |
| AP_BILL_BILLTYPE_MAP | 9 项映射 | 财务应付单类型字典(借贷项调整/费用采购应付/其他应付/产品委外应付/标准采购应付/采购费用应付/销售费用应付/服务采购应付/资产采购应付) | 全量字典 |
| AR_BILL_BILLTYPE_MAP | 5 项映射 | 财务应收单类型字典(借贷项调整/其他应收/销售费用应收/服务销售应收/标准销售应收),当前付款链路未启用 | 全量字典 |
| PAY_APPLY_BILLTYPE_MAP | 2 项映射 | 付款申请单类型字典(采购付款申请/其他付款申请),使用规则待业务确认 | 全量字典 |
| BFI_AP_BILL_PAY_PROPERTY | `2001` | A102-2 款项性质 | 待金蝶确认 |
| BFI_AP_BILL_PUR_MODE | `CREDIT` | A102-2 付款方式(赊购) | 待业务确认(CASH=现购自动推付款) |
| BFI_AP_BILL_MATERIAL | 空串 | A102-2 明细物料编码 | **待金蝶提供,为空时推送前拦截报错** |
| BFI_AP_BILL_MEASURE_UNIT | 空串 | A102-2 明细计量单位 | **待金蝶确认,为空时推送前拦截报错** |
| BFI_AP_BILL_SRC_TYPE | `TMS财务应付单` | A102-2 外部单据类型 | 待金蝶确认 |
### 5.3 单据类型路由与映射转换
| 正式结算单结算类型 | 对应金蝶单据 | 单据类型字典 | 当前状态 |
| --- | --- | --- | --- |
| 应付(payable) | 财务应付单(A102-2 `/ap_finapbill/save`) | `AP_BILL_BILLTYPE_MAP`(9 项) | **已启用**,默认"服务采购应付" |
| 应收(receivable) | 财务应收单(A302-2 `/ar_finarbill/save`) | `AR_BILL_BILLTYPE_MAP`(5 项) | 未启用,同步时拦截报错,推送规则待业务确认 |
转换流程:同步时按 `settlementId` 查正式结算单 `settlementType` 路由;应付走 A102-2,billtype 由默认名称"服务采购应付"经映射字典转编码;查不到结算单(聚合多结算单场景)暂按应付处理。
### 5.4 其他待确认项(代码内以 TODO 注释标注)
| 项 | 现状 | 待确认内容 |
| --- | --- | --- |
| 日期格式 | bizdate/applydate 沿用 A103-3 的 `yyyyMMdd` | 金蝶若校验 `yyyy-MM-dd` 需统一调整 |
| 结算方式/税率 | settlementtype_number、taxrateid_number 不传 | 金蝶是否强制、编码取值 |
| 预付抵扣 | preentry(y_billtype/y_billid/y_settleamt)不传 | 存在预付款抵扣时是否需传,本期不传、后续迭代 |
| 银行编码 | e_bebank_number 暂传银行名称 | 必填编码,待银行档案编码映射(与 A103-3 遗留项相同) |
| 付款申请单/收入确认单类型映射 | 字典已存 `PAY_APPLY_BILLTYPE_MAP`(2 项);收入确认单(ar_revcfmbill_*)字典未入库 | 付款申请单、收入确认单的映射使用规则待业务确认 |
---
## 6. 数据库变更
**本次无表结构变更。** A103-1 返回的付款申请单 id 仍落既有字段 `blade_payment_application.kingdee_bill_no`;A102-2 返回的应付单 id 不落库(下推关联、幂等重推均不依赖该 id),后续 A102-4 勾稽、应付单附件上传、反审核删除等场景需要时,按防重键 `awrp_src_sys + awrp_src_code(=paymentNo)` 经 `queryApBill` 查询即可。前端列表也无新增列。
---
## 7. 异常处理与批量语义
| 场景 | 行为 |
| --- | --- |
| 单笔同步 `syncKingdee` | 校验失败/推送失败置 `failed` 并抛 `ServiceException`,前端提示原因(含金蝶 errors 明细) |
| ①成功②失败 | `kingdeeStatus = failed`;重推时①按防重键走更新语义,继续② |
| 批量同步 `syncKingdeeBatch` | 逐单循环,**单条失败不中断批次**;返回结果列表附 `付款申请[id]同步失败:原因` |
| 物料/计量单位常量为空 | 推送前拦截,报错提示待金蝶侧确认补常量 |
| 金蝶接口级失败 | `BfiServiceImpl.commonCall` 抛 `BfiException`,同上处理 |
| 重复点击同步 | 已 `synced` 单据跳过;`failed`/`unsynced` 允许重推 |
---
## 8. 遗留事项
1. **物料/计量单位编码**:A102-2 明细必填,待金蝶侧提供后补充 `BFI_AP_BILL_MATERIAL` / `BFI_AP_BILL_MEASURE_UNIT` 常量,在此之前正式付款同步会主动拦截报错。
2. **应付单 id 不落库**:A102-2 仅校验保存成功;后续 A102-4 勾稽、应付单附件、反审核删除等需要 id 的场景,按防重键经 `queryApBill` 二次查询。
3. **银行编码映射**:e_bebank_number 暂传银行名称,待建立银行档案编码映射(与预付款路径遗留项相同)。
4. **预付抵扣 preentry**:正式付款涉及预付款抵扣时是否传预付信息,本期不传、后续迭代。
5. **付款完成模拟待拆除**:同步成功后仍保留 `paidAmount = 申请金额`、`mockPaymentRecords()` 模拟付款记录(单号前缀 `MOCK-PAY-`),真实流程应由 A103-2/A103-4 定时回写驱动,与预付款路径共用该遗留项。
6. **正式结算单同步金蝶仍为 mock**:`FormalSettlementServiceImpl.syncKingdee` 当前仅生成 `K3AP+时间戳` 假单号,与本文档的应付单推送(A102-2)无关联,后续如需结算单直推应付单需另行设计。
7. **单据编号 number**(AP/FKSQ-xxxx)暂未落库,如需展示可经 A102-4/A103-2 查询。
8. **单据类型映射规则待确认**:付款申请单(采购/其他)、收入确认单(ar_revcfmbill_*)的类型使用规则待业务确认;应收结算单对应财务应收单(A302-2)的推送链路未启用,当前同步时拦截报错。
---
## 9. 涉及代码位置
| 内容 | 位置 |
| --- | --- |
| 同步入口/分支 | `blade-service/blade-transport/.../service/impl/PaymentApplicationServiceImpl.java`(syncKingdee / syncKingdeeBatch / pushBfiApBill / pushBfiPayApplyPush / pushBfiPayApply / requireBfiSaveSuccess / requireBfiBillId) |
| A102-2 常量 | `blade-service/blade-transport/.../constant/KingdeeBfiConstant.java` |
| Controller | `blade-service/blade-transport/.../controller/PaymentApplicationController.java`(/sync-kingdee、/sync-kingdee-batch,本次无改动) |
| BFI 客户端 | `blade-third-party-api/blade-bfi-api/.../feign/IBfiClient.java`(AP_BILL_SAVE_URL / PAY_APPLY_PUSH_URL) |
| BFI 服务封装 | `blade-third-party-api/blade-bfi-api/.../service/impl/BfiServiceImpl.java`(saveApBill / pushPayApply,本次无改动) |
| 请求/返回模型 | `blade-bfi-api/.../pojo/dto/BfiApBillSaveDTO.java`、`BfiApBillSaveEntryDTO.java`、`BfiPayApplyPushDTO.java`、`BfiPayApplyPushEntryDTO.java` |
| 前端页面 | `tms-erp-web/src/views/payment/payment-application.vue`(无逻辑改动);`src/option/payment/paymentApplication.js`(无改动) |