fix: - 修复BFI单据保存结果反序列化失败导致错误信息丢失。

- 财务应付单保存A102-2,传业务字段。并保存id
- 付款管理批量同步方法优化
This commit is contained in:
刘泉佳
2026-09-18 10:48:43 +08:00
parent d0c5483d8b
commit 20fddf2c60
13 changed files with 470 additions and 139 deletions
@@ -3,7 +3,7 @@
> 适用系统:TMS(BladeX 微服务平台,服务:blade-transport)
> 对接系统:金蝶云·星瀚(业财融合 BFI,经 iPaaS 网关)
> 关联文档:`doc/docs/TMS业财融合-集成流程图文字版与业务流程梳理.md`、`doc/docs/业财融合系统接口文档.xlsx`、`doc/docs/业务流程/付款申请同步金蝶(星瀚)技术文档.md`(A103-3 预付款路径)
> 最后更新:2026-09-16
> 最后更新:2026-09-18(字段映射与联调默认值按当前代码重新梳理)
---
@@ -63,12 +63,12 @@
| 约定 | 说明 |
| --- | --- |
| 状态校验 | 仅 `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 = synced/paying/paid/closed` 的单据直接返回已存单据号,不重复推送 |
| ①防重键 | 星瀚应付单侧 `awrp_src_code`(=付款申请号_结算明细单据号1_单据号2...,去重拼接)+ `awrp_src_sys`,②失败后重推时①走更新语义,不重复生成应付单 |
| ②防重键 | 付款申请单侧 `awrp_src_code`(=paymentNo)+ `awrp_src_sys`;分录行 `awrp_entry_code`(=paymentNo + "-序号")不得重复 |
| ②关联键 | `awrp_finapbill_entryid` = ①明细的 `awrp_entry_code`(=paymentNo + "-序号"),**不依赖①返回的内部 id** |
| 失败重推 | 任一步失败置 `kingdeeStatus = failed`,可重新勾选同步(①已成功的应付单按防重键走更新语义) |
| 前置校验 | ①推送前校验物料/计量单位常量非空(见 5.2);未关联合同、合同不存在、组织编码为空、结算币种为空时同步失败 |
| 前置校验 | 分录解析前校验:未关联正式结算明细、货物类型未维护档案编码、计量单位为空均报错;未关联合同、组织编码为空、结算币种为空时同步失败 |
---
@@ -95,37 +95,36 @@
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| billtypeid_number | 单据类型.编码 | 是 | 按映射字典转换:`KingdeeBfiConstant.BFI_AP_BILL_BILLTYPE_NAME`(默认"服务采购应付")经 `AP_BILL_BILLTYPE_MAP` 名称→编码 | 路由规则见 5.3;未维护名称报错 |
| org_number | 结算组织.编码 | 是 | **合同所属组织**:`contract.organizationId` → `dept.deptCode`,空回退组织名称(复用 `bfiOrgNumber`) | 缺失报错 |
| 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 | |
| asstacttype | 往来类型 | 是 | **按合同类别路由**(`bfiAsstactType`):`contractCategory = 客户合同` → `bd_customer`,否则 → `bd_supplier` | 与结算类型路由口径一致 |
| asstact_number | 往来户.编码 | 是 | **合同乙方**(`bfiAsstactNumber`):`contract.partyB` → 客商档案按全称/简称匹配取 `customerCode` | 乙方为空或客商档案未维护编码均报错,不回退原值 |
| purmode | 付款方式 | 是 | 常量 `BFI_AP_BILL_PUR_MODE_CASH` | `CASH` 现购(系统自动 100% 推付款) |
| currency_number | 结算币别.货币代码 | 是 | **合同结算币种** `contract.settlementCurrency`(复用 `bfiCurrency`);`RMB` 统一映射为 `CNY` | 缺失报错 |
| payorg_number | 付款组织.编码 | 是 | 同 org_number | 采购组织 purorg_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` | 有合同即传 |
| isincludetax / ispricetotal | 录入含税价 / 录入总价 | 否 | 固定 `true` / `true`;`isintax` 固定 `false` | 录入总价免单价换算 |
| awrp_src_sys | 外部系统编号 | 是 | 配置 `thirdParty.bfi.payApply.srcSys` | 应付单候选键 |
| awrp_src_code | 外部系统来源单据号 | 是 | **`paymentNo + "_" + 结算明细单据号1_单据号2...`**(单据号去重、保持行序,`String.join("_")`) | 应付单候选键 |
| awrp_src_type | 外部单据类型 | 是 | 常量 `BFI_AP_BILL_SRC_TYPE` | 暂按 `TMS财务应付单`,**待金蝶确认** |
未传的可选字段:settlementtype_number(结算方式)、taxrateid_number(税率)、duedate、bookdate、department_number、preentry(预付信息)等。
未传的可选字段(代码注释保留):exratetable_number/exratedate(汇率表/汇率日期)、asstactname(往来单位名称)、remark(备注)、awrp_src_bt(来源单据)、awrp_src_con_no(上游合同号)、settlementtype_number(结算方式)、taxrateid_number(税率)、purorg_number(采购组织)、duedate、bookdate、department_number、preentry(预付信息)等。
### 4.2 A102-2 明细(`BfiApBillSaveEntryDTO`,单条申请固定 1 行)
### 4.2 A102-2 明细(`BfiApBillSaveEntryDTO`,按货物编码+计量单位聚合,多行)
分录数据由 `resolveBfiEntryGroups` 解析:**货物费用行**(`blade_formal_settlement_detail_fee`,每货物一条)优先,无费用行时兜底**结算明细行**;按货物编码+计量单位聚合(一行含多种货物类型时金额数量均分),已移除按申请付款金额分摊逻辑,**金额直接取结算金额**。
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| 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` | |
| material_number | 物料编码.编码 | 是 | **联调临时:常量 `BFI_AP_BILL_MATERIAL_NUMBER_TEST`(`SP0324`)**(调试块 `if(true)` 强制覆盖) | 真实来源:货物类型 → 货物类型档案 `cargoCode`,档案对齐后恢复 |
| measureunit_number | 计量单位.编码 | 是 | **联调临时:常量 `BFI_AP_BILL_MEASUREUNIT_NUMBER_TEST`(`TON`)**(同上) | 真实来源:快照运费计算单位 `quantityUnit`(档案暂无编码字段) |
| quantity | 明细.数量 | 是 | 组内 `transportQuantity` 合计 | ≤0 兜底 1 |
| e_pricetaxtotal | 明细.应付金额 | 是 | 组内 `settlementAmountTax`(结算金额含税)合计 | **必传**,缺失金蝶报"应付金额不能为空" |
| e_amount | 明细.金额(不含税) | 否 | 组内 `settlementAmountNoTax`(结算金额不含税)合计 | |
| project_number | 项目.项目编码 | 是 | **联调临时:常量 `BFI_AP_BILL_PROJECT_NUMBER_TEST`(`999`)** | 真实来源:`projectId` → `ProjectApply.projectCode`,无项目传 `999` |
| awrp_entry_code | 外部系统来源分录标识 | 是 | `paymentNo + "-" + 组序号` | 候选键;②下推时以 `awrp_finapbill_entryid` 关联此行 |
未传:planentity 付款计划(不传由金蝶按明细自动汇总)、e_amount/e_tax、taxrateid_number、awrp_src_con_eno。
未传:planentity 付款计划(不传由金蝶按明细自动汇总)、e_tax、taxrateid_number、e_remark、awrp_src_con_eno。
### 4.3 A103-1 主表(`BfiPayApplyPushDTO`)
@@ -139,20 +138,20 @@
| awrp_textfield1 | 付款渠道 | 否 | 复用 `bfiPaymentMethodLabel`:`paymentMethod` 经字典 `pay_method` 翻译为标签 | |
| creator_name | 申请人 | 否 | `applicantName` | |
### 4.4 A103-1 分录(`BfiPayApplyPushEntryDTO`,固定 1 行)
### 4.4 A103-1 分录(`BfiPayApplyPushEntryDTO`,与应付单明细一一对应多行)
| 接口字段 | 含义 | 必填 | 来源 | 说明 |
| --- | --- | --- | --- | --- |
| e_paymenttype_number | 付款类型.编码 | 是 | 常量 `201` | 正式付款 |
| awrp_finapbill_entryid | 结算单分录id | 是 | `paymentNo + "-1"` | **对应 A102-2 明细 awrp_entry_code** |
| awrp_entry_code | 对方唯一行 id | 是 | `paymentNo + "-1"` | 不得重复 |
| awrp_finapbill_entryid | 结算单分录id | 是 | `paymentNo + "-" + 组序号` | **对应 A102-2 明细 awrp_entry_code** |
| awrp_entry_code | 对方唯一行 id | 是 | `paymentNo + "-" + 组序号` | 不得重复 |
| e_assacct | 往来账户 | 是 | `bankAccount` | 收款账号(页面"收款账户") |
| e_bebank_number | 往来银行.编码 | 是 | `bankName` | **必填编码,当前暂传银行名称,待银行档案编码映射**(与 A103-3 遗留项一致) |
| e_applyamount | 申请金额 | 是 | `appliedAmount`(2 位小数) | |
| e_applyamount | 申请金额 | 是 | 组内 `settlementAmountTax`(结算金额含税) | 与对应应付单分录 `e_pricetaxtotal` 一致 |
| e_expaydate | 期望付款日 | 否 | 同 applydate | |
| project_number | 项目.项目编码 | 是 | 复用 `bfiProjectNumber` | 无项目传 `999` |
| awrp_src_type | 外部单据类型 | 是 | 复用配置 `payApply.srcType` | |
| project_number | 项目.项目编码 | 是 | **联调临时:常量 `BFI_AP_BILL_PROJECT_NUMBER_TEST`(`999`)**(真实取值 `bfiProjectNumber` 代码注释保留) | 无项目传 `999` |
| e_remark | 备注 | 否 | `remark` | |
| awrp_src_type | 外部单据类型 | 是 | 复用配置 `payApply.srcType` | |
未传:e_duedate、e_settlementtype_number、e_costcenter_number、awrp_splb_number。
@@ -170,12 +169,16 @@ A102-2 所需的金蝶侧固定档案编码**不进 Nacos 配置**,统一定
| --- | --- | --- | --- |
| 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 项映射 | 财务应收单类型字典(借贷项调整/其他应收/销售费用应收/服务销售应收/标准销售应收),当前付款链路未启用 | 全量字典 |
| AR_BILL_BILLTYPE_MAP | 5 项映射 | 财务应收单类型字典,当前付款链路未启用 | 全量字典 |
| PAY_APPLY_BILLTYPE_MAP | 2 项映射 | 付款申请单类型字典(采购付款申请/其他付款申请),使用规则待业务确认 | 全量字典 |
| BFI_SUPPLIER_ASSTACT_TYPE | `bd_supplier` | 往来类型-供应商 | 启用 |
| BFI_CUSTOMER_ASSTACT_TYPE | `bd_customer` | 往来类型-客户(合同类别为"客户合同"时使用) | 启用 |
| 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_PUR_MODE_CASH | `CASH` | A102-2 付款方式(现购,自动 100% 推付款) | 启用 |
| BFI_AP_BILL_PUR_MODE_CREDIT | `CREDIT` | A102-2 付款方式(赊购,金蝶侧可调金额) | 备用 |
| BFI_AP_BILL_MATERIAL_NUMBER_TEST | `SP0324` | **联调临时**:明细物料编码,调试块强制覆盖真实取值 | 联调后恢复档案取值 |
| BFI_AP_BILL_MEASUREUNIT_NUMBER_TEST | `TON` | **联调临时**:明细计量单位编码,同上 | 联调后恢复档案取值 |
| BFI_AP_BILL_PROJECT_NUMBER_TEST | `999` | **联调临时**:A102-2/A103-1 项目编码 | 档案对齐后恢复 `bfiProjectNumber` |
| BFI_AP_BILL_SRC_TYPE | `TMS财务应付单` | A102-2 外部单据类型 | 待金蝶确认 |
### 5.3 单据类型路由与映射转换
@@ -195,6 +198,8 @@ A102-2 所需的金蝶侧固定档案编码**不进 Nacos 配置**,统一定
| 结算方式/税率 | settlementtype_number、taxrateid_number 不传 | 金蝶是否强制、编码取值 |
| 预付抵扣 | preentry(y_billtype/y_billid/y_settleamt)不传 | 存在预付款抵扣时是否需传,本期不传、后续迭代 |
| 银行编码 | e_bebank_number 暂传银行名称 | 必填编码,待银行档案编码映射(与 A103-3 遗留项相同) |
| 物料/计量单位/项目编码 | 联调期临时传金蝶测试档案值(SP0324/TON/999,见 4.2/4.4 与 5.2) | 档案对齐后移除 A102-2 明细中的调试块并恢复真实取值 |
| 币种映射 | 合同结算币种 `RMB` 统一映射为 `CNY`(`bfiCurrency`) | 长期保留 |
| 付款申请单/收入确认单类型映射 | 字典已存 `PAY_APPLY_BILLTYPE_MAP`(2 项);收入确认单(ar_revcfmbill_*)字典未入库 | 付款申请单、收入确认单的映射使用规则待业务确认 |
---
@@ -212,7 +217,8 @@ A102-2 所需的金蝶侧固定档案编码**不进 Nacos 配置**,统一定
| 单笔同步 `syncKingdee` | 校验失败/推送失败置 `failed` 并抛 `ServiceException`,前端提示原因(含金蝶 errors 明细) |
| ①成功②失败 | `kingdeeStatus = failed`;重推时①按防重键走更新语义,继续② |
| 批量同步 `syncKingdeeBatch` | 逐单循环,**单条失败不中断批次**;返回结果列表附 `付款申请[id]同步失败:原因` |
| 物料/计量单位常量为空 | 推送前拦截,报错提示待金蝶侧确认补常量 |
| 货物类型未维护档案编码 / 计量单位为空 | 分录解析(`collectEntryGroups`)时拦截,报错提示补充档案 |
| 合同乙方为空 / 客商档案未维护客商编码 | 往来户取值(`bfiAsstactNumber`)时拦截,报错提示合同号与乙方名称 |
| 金蝶接口级失败 | `BfiServiceImpl.commonCall` 抛 `BfiException`,同上处理 |
| 重复点击同步 | 已 `synced` 单据跳过;`failed`/`unsynced` 允许重推 |
@@ -220,7 +226,7 @@ A102-2 所需的金蝶侧固定档案编码**不进 Nacos 配置**,统一定
## 8. 遗留事项
1. **物料/计量单位编码**:A102-2 明细必填,待金蝶侧提供后补充 `BFI_AP_BILL_MATERIAL` / `BFI_AP_BILL_MEASURE_UNIT` 常量,在此之前正式付款同步会主动拦截报错。
1. **物料/计量单位/项目编码(联调临时)**:A102-2 明细当前经调试块固定传金蝶测试档案值(`SP0324`/`TON`,见 `pushBfiApBill` 内 `if(true)` 调试代码),项目编码 A102-2/A103-1 固定传 `999`;金蝶侧档案对齐后需**删除调试块**并恢复真实取值(货物类型档案编码 / 快照计量单位 / `bfiProjectNumber`)。
2. **应付单 id 不落库**:A102-2 仅校验保存成功;后续 A102-4 勾稽、应付单附件、反审核删除等需要 id 的场景,按防重键经 `queryApBill` 二次查询。
3. **银行编码映射**:e_bebank_number 暂传银行名称,待建立银行档案编码映射(与预付款路径遗留项相同)。
4. **预付抵扣 preentry**:正式付款涉及预付款抵扣时是否传预付信息,本期不传、后续迭代。