diff --git a/doc/docs/业务流程/付款申请同步金蝶(星瀚)技术文档.md b/doc/docs/业务流程/付款申请同步金蝶(星瀚)技术文档.md new file mode 100644 index 00000000..42e69d17 --- /dev/null +++ b/doc/docs/业务流程/付款申请同步金蝶(星瀚)技术文档.md @@ -0,0 +1,257 @@ +# 付款申请同步金蝶(星瀚)技术文档 + +> 适用系统:TMS(BladeX 微服务平台,服务:blade-transport) +> 对接系统:金蝶云·星瀚(业财融合 BFI,经 iPaaS 网关) +> 关联文档:`doc/docs/TMS业财融合-集成流程图文字版与业务流程梳理.md`、`doc/docs/TMS业财融合方案.docx`、`doc/docs/业财融合系统接口文档.xlsx` +> 最后更新:2026-09-16 + +--- + +## 1. 背景与范围 + +付款申请审核通过后,需将单据推送至金蝶云·星瀚生成付款申请单,并把星瀚返回的**单据内部主键(id)**记录到 `blade_payment_application.kingdee_bill_no`,供后续附件上传、状态查询、付款结果回写使用。 + +- 触发入口:付款申请页面(前端 `tms-erp-web/src/views/payment/payment-application.vue`)"批量同步"按钮,权限码 `payment_application_sync` +- 对接接口:**A103-3 付款申请保存** `POST /ierp/kapi/v2/awrp/ap/ap/ap_payapply/save` +- 覆盖路径:**预付款**(project_advance / progress_advance)与**正式付款**(settlement_payment)本次均走该接口;正式付款按方案文档原规划走 `ap_finapbill/push`(A103-1 应付下推),待后续切换 +- 调用方式:前端 → TMS 后端转发 → 星瀚(OAuth2 凭证仅存后端配置,前端不持有) + +--- + +## 2. 业务流程 + +### 2.1 业财融合整体链路(SC-04 对公付款) + +``` +TMS 付款申请审核通过 + → 批量同步(本文档):推送金蝶生成付款申请单(A103-3) + → 金蝶财务共享审批(黑盒,机器人处理) + → 金蝶付款处理 + → TMS 定时查询回写付款结果(A103-2 付款申请单查询 / A103-4 付款处理查询,待建设) + → 附件推送(A902,凭付款申请单 id)与合同系统履约同步(C106-2,待建设) +``` + +### 2.2 TMS 付款申请状态流转 + +| 阶段 | approvalStatus | 说明 | +| --- | --- | --- | +| 草稿 | `draft` | 可编辑、可删除 | +| 审批中 | `reviewing` | 提交后进入财务审核 | +| 审批通过 | `approved` | **仅此状态允许同步金蝶**;可作废(voided) | +| 已驳回 | `returned` | 驳回后可编辑重新提交 | +| 已作废 | `voided` | 终态,不可同步 | + +### 2.3 批量同步时序 + +``` +前端 payment-application.vue blade-transport 后端 星瀚(BFI) + │ 勾选 approved 记录 │ │ + │ POST /payment-application/ │ │ + │ sync-kingdee-batch [id...] │ │ + │──────────────────────────────────────>│ 逐单循环(单条失败不中断批次) │ + │ │ FOR UPDATE 锁单 + 状态校验 │ + │ │ 组装 BfiPayApplySaveDTO │ + │ │ POST /ierp/kapi/v2/awrp/ap/ │ + │ │ ap/ap_payapply/save ───────>│ + │ │ <── result[]{billStatus,id,...} ─│ + │ │ kingdeeBillNo = id │ + │ │ kingdeeStatus = synced │ + │ │ 下游台账联动(预付/结算付款记录) │ + │ <── R>(逐单结果)────────│ │ +``` + +### 2.4 前置条件与幂等约定 + +| 约定 | 说明 | +| --- | --- | +| 状态校验 | 仅 `approvalStatus = approved` 允许同步 | +| 幂等跳过 | `kingdeeStatus = synced` 的单据直接返回已存单据号,不重复推送 | +| 防重键 | 星瀚侧 `awrp_src_code`(=paymentNo)+ `awrp_src_sys` 组成候选键,重复推送走更新语义;分录行 `awrp_entry_code`(=paymentNo + "-1")不得重复 | +| 失败重推 | 同步失败置 `kingdeeStatus = failed`,可重新勾选同步 | +| 锁单 | 推送成功后金蝶侧锁定,推送字段不允许修改;如需调整须金蝶反审核+删除后重推(B901 LOCK/UNLOCK) | + +--- + +## 3. 接口定义(A103-3 付款申请保存) + +### 3.1 鉴权 + +`access_token` 通过 `POST /ierp/kapi/oauth2/getToken` 获取(参数 clientId / clientSecret / username / accountId / nonce / timestamp),有效期 2 小时,由 `BfiServiceImpl` 自动获取与缓存,业务代码无需关心。 + +### 3.2 请求 + +- URL:`{thirdParty.bfi.baseUrl}/ierp/kapi/v2/awrp/ap/ap/ap_payapply/save` +- Method:`POST`,请求体 `{"data": [ {主表字段, "entry":[分录]} ]}` + +### 3.3 返回结构(示例) + +```json +{ + "data": { + "failCount": "0", + "result": [ + { + "billIndex": 0, + "billStatus": true, + "errors": [], + "id": "2395327167211785216", + "keys": { + "awrp_src_code": "00225", + "awrp_src_sys": "测试系统" + }, + "number": "FKSQ-00000147", + "type": "Add" + } + ], + "successCount": "1" + }, + "errorCode": "0", + "message": null, + "status": true +} +``` + +| 字段 | 含义 | TMS 处理 | +| --- | --- | --- | +| data.successCount / failCount | 成功/失败数量(字符串数字) | `BfiBillSaveResultVO`,辅助 `isAllSuccess()` | +| result[].billIndex | 对应请求 data 数组下标 | 逐单调用恒为 0 | +| result[].billStatus | 单据级成败 | false 时以 errors 抛出业务异常 | +| result[].id | **星瀚付款申请单内部主键** | **写入 `kingdee_bill_no`** | +| result[].number | 星瀚单据编号(FKSQ-xxxx) | 暂不落库,可经 A103-2 查询勾稽 | +| result[].type | Add 新增 / Push 下推 | 仅记录 | +| errorCode / message / status | 接口级状态 | `commonCall` 统一校验,失败抛 `BfiException` | + +--- + +## 4. 字段映射关系 + +### 4.1 主表(`BfiPayApplySaveDTO` ← `PaymentApplication` 实体 / 配置) + +| 接口字段 | 含义 | 来源 | 说明 | +| --- | --- | --- | --- | +| awrp_src_code | 来源单据号(防重键) | `paymentNo` | 付款申请单号 | +| awrp_src_sys | 外部系统编号(防重键) | 配置 `payApply.srcSys` | 默认 `TMS` | +| settleorg_number / applyorg_number / payorg_number / purorg_number | 结算/申请/付款/采购组织编码 | 配置 `payApply.orgNumber` | 金蝶公司编码,必填 | +| billtype_number | 单据类型编码 | 配置 `payApply.billtype` | 默认 `ap_payapply_BT_S` 采购付款申请 | +| applydate | 申请日期 | `applyDate` | yyyy-MM-dd,空取当天 | +| applycause | 请款事由 | paymentType 映射 | 见 5.1 | +| paycurrency_number / settlecurrency_number | 付款/结算币种 | 配置 `payApply.currency` | 默认 `CNY` | +| awrp_src_type | 外部单据类型 | 配置 `payApply.srcType` | 默认 `TMS付款申请` | +| exratetable_number | 汇率表编码 | 配置 `payApply.exratetable` | 默认 `01` | +| exratedate | 汇率日期 | 同 applydate | yyyy-MM-dd | +| awrp_textfield1 | 付款渠道 | `paymentMethod` 字典标签 | 见 5.4 | +| awrp_src_bt | 来源单据类型 | 有合同传 `awrp_contract_info` | 可选 | +| awrp_src_con_no | 上游合同号 | `contractNo` | 可选,随 awrp_src_bt 一起传 | + +### 4.2 分录(`BfiPayApplySaveEntryDTO`,单条申请固定 1 行) + +| 接口字段 | 含义 | 来源 | 说明 | +| --- | --- | --- | --- | +| e_paymenttype_number | 付款类型编码 | paymentType 映射 | `201` 正式付款 / `202` 预付款,见 5.1 | +| e_asstacttype | 往来类型 | 固定 `bd_supplier` | 供应商 | +| e_asstact_number | 往来户编码 | payeeName → 客商档案 `customerCode` | 按 fullName/shortName 匹配,未匹配回退 payeeName | +| e_assacct | 往来账户 | `bankAccount` | 收款账号 | +| e_bebank_number | 往来银行编码 | `bankName` | 暂传名称,待银行编码映射 | +| e_applyamount / e_payamount | 申请/应付金额 | `appliedAmount` | 2 位小数 | +| e_expaydate | 期望付款日 | 同 applydate | — | +| project_number | 项目编码 | projectId → `ProjectApply.projectCode` | 无项目传 `999` | +| awrp_entry_code | 对方唯一行 id(防重) | `paymentNo + "-1"` | 不得重复 | +| e_remark | 备注 | `remark` | 可选 | + +未传的可选字段:purdept_number、awrp_department_number、e_duedate、e_settlementtype_number、e_costcenter_number、awrp_src_con_eno、awrp_splb_number。 + +--- + +## 5. 字典与枚举对应关系 + +### 5.1 付款类型 paymentType → 接口编码 + +| paymentType(TMS) | 中文含义 | e_paymenttype_number | applycause 请款事由 | +| --- | --- | --- | --- | +| `project_advance` | 项目预付 | `202` | 项目预付款申请 | +| `progress_advance` | 进度预付 | `202` | 进度预付款申请 | +| `settlement_payment` | 结算付款(正式付款) | `201` | 结算付款申请 | + +### 5.2 审批状态 approvalStatus + +`draft` → `reviewing` → `approved` / `returned`;`approved` → `voided`。仅 `approved` 可同步。 + +### 5.3 金蝶同步状态 kingdeeStatus + +| 值 | 含义 | 触发 | +| --- | --- | --- | +| `unsynced` | 未生成 | 新建单据默认 | +| `synced` | 已生成 | 推送成功,`kingdee_bill_no` = 星瀚单据 id | +| `failed` | 生成失败 | 推送异常/金蝶返回 billStatus=false,可重推 | + +### 5.4 付款渠道 awrp_textfield1 + +`paymentMethod` 存业务字典 `pay_method`(DictBiz)的 key/value,推送时经 `DictBizCache.getList("pay_method")` 翻译为字典标签(如电汇、汇票);未命中字典时原样传递。汇票类付款(标签含"汇票")在 TMS 侧另有台账占用逻辑,与推送无关。 + +### 5.5 其他固定值 + +| 常量 | 值 | 用途 | +| --- | --- | --- | +| 往来类型 | `bd_supplier` | e_asstacttype | +| 上游合同类型 | `awrp_contract_info` | awrp_src_bt | +| 无项目编码 | `999` | project_number | + +--- + +## 6. 配置项(Nacos:`thirdParty.bfi.*`) + +模板见 `doc/nacos/blade-dev.yaml`、`blade-prod.yaml`、`third-party-api.yaml`,支持环境变量覆盖: + +| 配置键 | 环境变量 | 默认值 | 说明 | +| --- | --- | --- | --- | +| thirdParty.bfi.baseUrl | BFI_BASE_URL | — | 星瀚网关地址(已有) | +| thirdParty.bfi.clientId / clientSecret / username / accountId | BFI_* | — | OAuth2 凭证(已有) | +| thirdParty.bfi.payApply.srcSys | BFI_PAY_APPLY_SRC_SYS | TMS | 外部系统编号(防重键) | +| thirdParty.bfi.payApply.billtype | BFI_PAY_APPLY_BILLTYPE | ap_payapply_BT_S | 单据类型编码 | +| thirdParty.bfi.payApply.orgNumber | BFI_PAY_APPLY_ORG_NUMBER | 空(**必配**) | 金蝶公司编码,未配置同步报错 | +| thirdParty.bfi.payApply.currency | BFI_PAY_APPLY_CURRENCY | CNY | 币种编码 | +| thirdParty.bfi.payApply.exratetable | BFI_PAY_APPLY_EXRATE_TABLE | 01 | 汇率表编码 | +| thirdParty.bfi.payApply.srcType | BFI_PAY_APPLY_SRC_TYPE | TMS付款申请 | 外部单据类型 | + +--- + +## 7. 异常处理与批量语义 + +| 场景 | 行为 | +| --- | --- | +| 单笔同步 `syncKingdee` | 校验失败/推送失败置 `failed` 并抛 `ServiceException`,前端提示原因(含金蝶 errors 明细) | +| 批量同步 `syncKingdeeBatch` | 逐单循环,**单条失败不中断批次**;失败单标记 `failed` 后继续下一单;返回结果列表中附 `付款申请[id]同步失败:原因` | +| 金蝶接口级失败(status=false / errorCode≠0) | `BfiServiceImpl.commonCall` 抛 `BfiException`,同上处理 | +| 金蝶单据级失败(billStatus=false) | 以 `errors` 拼接抛出 | +| 重复点击同步 | 已 `synced` 单据跳过;`failed`/`unsynced` 允许重推(防重键保证金蝶侧幂等) | + +--- + +## 8. result.id 的后续使用(待建设环节) + +| 环节 | 接口 | id 用法 | +| --- | --- | --- | +| 付款申请附件上传 | A902 `/frame/attachment/uploadFile` | `attachmentUploadFileArgs.billPkId` = 该 id | +| 付款申请单状态查询 | A103-2 `ap_payapply/query` | 按 awrp_src_code+awrp_src_sys 查询,返回体含 id/billno/billstatus(A暂存/B已提交/C已审核/D已关闭)/paystatus(未付/部分付/已付),与本地 id 勾稽 | +| 付款处理查询 | A103-4 `cas_paybill/query` | 返回 sourcebillid/sourcebillnumber,与 id/编号核对付款结果 | + +## 9. 遗留事项 + +1. **付款完成模拟待拆除**:同步成功后仍保留 `paidAmount = 申请金额`、`mockPaymentRecords()` 模拟付款记录(单号前缀 `MOCK-PAY-`)、下游预付/结算付款记录直接置 `paid`。真实流程应由 A103-2/A103-4 定时回写驱动,待回写任务建设时移除。 +2. **正式付款路径切换**:按方案文档正式付款应走 A103-1 `ap_finapbill/push`(应付下推,分录需 `awrp_finapbill_entryid` 关联应付行),当前与预付款共用 A103-3。 +3. **银行编码映射**:e_bebank_number 暂传银行名称,待建立银行档案编码映射。 +4. **单据编号 number**(FKSQ-xxxx)暂未落库,如需展示可经 A103-2 查询或后续增加字段。 + +--- + +## 10. 涉及代码位置 + +| 内容 | 位置 | +| --- | --- | +| 同步入口/字段映射 | `blade-service/blade-transport/.../service/impl/PaymentApplicationServiceImpl.java`(syncKingdee / syncKingdeeBatch / pushBfiPayApply) | +| Controller | `blade-service/blade-transport/.../controller/PaymentApplicationController.java`(/sync-kingdee、/sync-kingdee-batch) | +| BFI 客户端 | `blade-third-party-api/blade-bfi-api/.../feign/IBfiClient.java`(PRE_PAY_APPLY_SAVE_URL) | +| BFI 服务封装 | `blade-third-party-api/blade-bfi-api/.../service/impl/BfiServiceImpl.java`(savePrePayApply / commonCall / getToken) | +| 请求/返回模型 | `blade-bfi-api/.../pojo/dto/BfiPayApplySaveDTO.java`、`BfiPayApplySaveEntryDTO.java`;`pojo/vo/BfiBillSaveResultVO.java`、`BfiBillSaveResultItemVO.java` | +| 前端页面 | `tms-erp-web/src/views/payment/payment-application.vue`(handleSync);`src/api/payment/paymentApplication.js`(syncKingdeeBatch) | +| Nacos 配置模板 | `doc/nacos/blade-dev.yaml`、`blade-prod.yaml`、`third-party-api.yaml`(thirdParty.bfi.payApply.*) |