docs: 新增金蝶票池选票统一查镜像业务流程文档
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# 金蝶票池选票统一查镜像(收票登记 + 结算单认领 + 按票号补查 + 统一组件)业务流程
|
||||
|
||||
> 适用系统:TMS(BladeX 微服务平台,服务:blade-transport;前端:tms-erp-web)
|
||||
> 对接系统:金蝶发票云旗舰版·票易通(piaozone)全票池 A801-1,经业财融合 BFI 网关(rim 契约)透传
|
||||
> 关联文档:`2026-09-20-收票管理同步金蝶全票池发票(A801-1查询+批量同步+定时绑定关联)业务流程.md`(镜像同步与定时绑定链路,本文档不改变其行为)、`2026-09-20-piaozone-invoice-pool-claim`(结算单认领实时透传初版,本文档将其推翻并本地化)
|
||||
> 最后更新:2026-09-22(实现完成于工作树,提交时机待定)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与决策
|
||||
|
||||
结算单认领查询曾是 A801-1 **实时透传**:接口不返回总数,后端用"多取 1 条探测 hasMore + 合成 total"实现下一页式翻页,前端分页器显示的是假总数(可跳空页);收票登记新增则查本地镜像表(`limit 200` 无分页、前端本地切页)。两处口径不一、且实时链路每次开弹窗都打远程。
|
||||
|
||||
**定稿口径(2026-09-22 逐步确认)**:两处选票**统一查本地镜像表 `blade_kingdee_invoice_pool`,数据库真分页**。镜像本地化后"金蝶接口无分页"问题直接消失,前端回归标准分页弹窗;防重不依赖金蝶 `expenseStatus`(A801-1 响应根本不回传该字段),改用本地事实 `claimed/registered` 标记;缺口由"按发票号码精确补查"兜底。
|
||||
|
||||
| 变更点 | 改造前 | 改造后 |
|
||||
| --- | --- | --- |
|
||||
| 结算单认领查询 | A801-1 实时透传 + 合成 total(假分页)+ expenseStatus 条件 | 查镜像真分页,条件集与收票统一,expenseStatus 删除 |
|
||||
| 收票登记选票 | 镜像 `limit 200`、关键字模糊、前端本地切页、编辑态走 Mock | 查镜像真分页,统一组件;Mock 全删 |
|
||||
| 防重依据 | 无(两处均可重复选) | 每行 `claimed`(存在有效结算单发票行)/`registered`(存在非作废收票登记)标记 + 三态筛选 |
|
||||
| 票不在镜像里 | 无法处理 | 弹窗内"按发票号码补查":精确单查金蝶→过同一套白名单→upsert 入镜像 |
|
||||
| 时效兜底 | 无 | 收票侧弹窗"立即同步"按钮(复用既有手动全票池同步端点,per-request 超时 300s) |
|
||||
|
||||
## 2. 接口契约(后端)
|
||||
|
||||
两个门面端点分挂各自菜单(类级 `@PreAuth` 按菜单隔离,刻意不做跨菜单合并),**同一服务方法落点**:
|
||||
|
||||
| 端点 | 说明 |
|
||||
| --- | --- |
|
||||
| `GET /invoice-receipt/invoice-pool`、`GET /formal-settlement/invoice-pool` | 统一分页查询,收参 `KingdeeInvoicePoolQueryDTO`,返回 `R<IPage<KingdeeInvoicePoolVO>>` |
|
||||
| `POST /invoice-receipt/invoice-pool/fetch?invoiceNo=`、`POST /formal-settlement/invoice-pool/fetch?invoiceNo=` | 按票号精确补查,返回单张 `R<KingdeeInvoicePoolVO>`,校验不过报业务异常 |
|
||||
| `POST /invoice-receipt/sync-invoice-pool` | 既有全票池手动同步(本文档仅新增前端调用方,含 300s 超时覆盖) |
|
||||
|
||||
**A801-1 统一查询口径**:所有出站查询(定时同步窗口分页 `queryPoolPage`、按票号窄查 `queryPoolByInvoiceNo`——补查/批量同步/漏绑补偿共用)一律携带 `invoiceStatus = "0"`(票易通字典:正常),作废/异常票不再进入镜像、也不可被补查命中。注意:仅约束**查询侧**,历史镜像中已存在的非正常票不受影响(如需剔除既有非正常镜像,另立清理口径)。
|
||||
|
||||
**查询条件**(`KingdeeInvoicePoolQueryDTO`):`current/size`(size 钳位 1~100)、`invoiceNo` 模糊、`invoiceDateStart/End`(服务端强校验 yyyy-MM-dd)、`salerName/buyerName` 模糊(镜像列 issuer_name/receiver_name)、`invoiceType` 名称模糊、`salerTaxNo/buyerTaxNo` 精确、`claimed/registered`(true/false/null 三态)。
|
||||
|
||||
**统一视图**(`KingdeeInvoicePoolVO`,字段名与镜像实体一致以复用收票回填):镜像票面全字段 + `availableInvoiceAmount = matchedAmount = invoiceAmount`(价税合计,认领口径不变)+ `claimed/registered`;`id` 为镜像主键(ToStringSerializer),收票登记保存仍绑 `kingdeeInvoicePoolId`。
|
||||
|
||||
## 3. 查询链路(`KingdeeInvoicePoolMapper.xml`)
|
||||
|
||||
复杂查询入 XML(AGENTS 规范),自定义 SQL 不吃 MP 租户/逻辑删除插件,**手工带 `tenant_id` + `is_deleted = 0`**:
|
||||
|
||||
```
|
||||
主查询:blade_kingdee_invoice_pool p(status=1、租户、动态条件、
|
||||
ORDER BY source_updated_time DESC, create_time DESC,MP 分页插件真 count)
|
||||
claimed 标记/过滤:EXISTS blade_formal_settlement_invoice c
|
||||
(c 租户+未删,且嵌套 EXISTS 主单 blade_formal_settlement s 未删且 approval_status != 'voided'
|
||||
——作废结算单不占坑,票据自动释回"未认领")
|
||||
registered 标记/过滤:EXISTS blade_invoice_receipt r
|
||||
(r 租户+未删且 approval_status != 'voided')
|
||||
```
|
||||
|
||||
三张表同为 TenantEntity,EXISTS 片段经 `<sql>` 复用于 SELECT 列(打标记)与 WHERE(做过滤),单一事实源。
|
||||
|
||||
## 4. 补查链路(`InvoiceReceiptServiceImpl.fetchKingdeeInvoiceByNo`)
|
||||
|
||||
```
|
||||
① 镜像优先回读(selectInvoicePoolVO,租户+status=1)
|
||||
│ 命中 → 直接返回。不打远程:编辑态"同步"按钮不受金蝶可用性影响;
|
||||
│ 口径:白名单只约束"入镜像",回读既有镜像不受限
|
||||
② 未命中 → A801-1 按票号窄查(复用 queryPoolByInvoiceNo,pageSize=500)
|
||||
│ 返回行按票号 trim 全等匹配才取(防接口模糊语义假命中);无 → 报"金蝶票池未查询到"
|
||||
③ 白名单校验(与定时同步同一套代码,非复制实现,顺序一致):
|
||||
│ filterByInvoiceTypes(票种白名单)→ 不过:报"票种不在同步白名单内"
|
||||
│ filterByArchiveTaxNos(customerTaxNoSet())(购、销双税号 AND 命中客商档案)
|
||||
│ → 不过:报"请先在客商档案维护统一社会信用代码"
|
||||
④ batchUpsertInvoicePool 入镜像(自带票面指纹比对,幂等,重复点击安全)
|
||||
⑤ selectInvoicePoolVO 回读统一视图返回(含 claimed/registered)
|
||||
```
|
||||
|
||||
**与定时任务的关系(刻意设计)**:同步、镜像 upsert、定时绑定(receiptMap 回填 `kingdeeInvoicePoolId`)、漏绑补偿链路一行未动;补查只是 batchUpsert 的新调用方,不触发绑定回填——补查进来的票若已有登记未绑,由下一轮补偿链路自然收敛。窗口故障自愈性:瞬时失败下轮滑动窗口重拉;票滑出 30 天窗口造成的永久缺口由补查兜底(补查不受时间窗口约束)。
|
||||
|
||||
## 5. 前端统一组件(`src/components/kingdee-invoice-pool-dialog/main.vue`)
|
||||
|
||||
- Props:`modelValue / title / confirmText / multiple / initialInvoiceNo / queryApi / fetchApi / syncApi(可空)`;事件 `confirm(rows)`(单选 `[row]`、多选选中数组)。打开时重置查询、按 `initialInvoiceNo` 预填、清勾选、回第 1 页加载。
|
||||
- 查询表单:发票号码、开票日期区间、开票单位、受票单位、发票类型(可搜索下拉,选项与后端 `BfiConstant.INVOICE_TYPE_NAMES` 中文名对齐)、认领状态、登记状态(布尔下拉清空后传空串,Spring 绑定为 null,"不限"语义正确)。
|
||||
- 表格:票面列 + 三个显式状态列——**认领状态**(已认领红/未认领灰)、**登记状态**(已登记橙/未登记灰)、**金蝶同步**(未同步/已同步/同步失败,镜像 `kingdee_status`);单选模式操作列"选择"+ 双击直选,多选模式复选列 `reserve-selection`;底部左"按票号补查"输入区、右标准分页。
|
||||
- 接线:收票登记表单(`multiple=false`,注入 query/fetch/sync 三个 api,`confirmInvoice(row)` 回填零改动,页面 Mock 与本地切页全删;编辑态"同步"按钮改走补查);结算单编辑器(`multiple=true`、`confirm-text="确认认领"`、不传 syncApi——结算菜单无全量同步端点;`handleInvoiceClaimConfirm` 中转时把复数 `attachmentsJson` 归一为认领契约的单数 `attachmentJson`,`confirmInvoiceClaims` 本体零改动)。
|
||||
- 同步等待体验:服务端全量同步为分钟级接口(前端 per-request 超时 300s),点击"立即同步"展示全屏 ElLoading("预计 1~3 分钟,请勿关闭窗口"),期间锁定弹窗关闭按钮/esc/遮罩点击,完成后自动刷新列表。
|
||||
|
||||
## 6. 业务口径与已知限制
|
||||
|
||||
- **认领场景收紧**:镜像入池受"票种白名单 + 购销双税号 AND 命中客商档案"约束(见 2026-09-20 文档口径),本地化后认领可选集合从裸票池收紧为该白名单集合——**供应商未建档/未维护统一社会信用代码,其进项票在两个弹窗都选不到**,客商档案维护是前置条件。
|
||||
- `claimed` 语义 = 被任一**有效**正式结算单认领过;不做跨单认领金额校验的变更(后端仍只查本单金额上限),"已认领"票默认仍可见(claimed 过滤默认不限,拆分认领等场景需要)。
|
||||
- 金蝶侧已删除的票(delete=1)补查会以 `kingdee_status=failed` 入镜像并可见(与既有 syncKingdee 存量同模式)。
|
||||
- `invoice_no` 在 `blade_formal_settlement_invoice` 无独立索引,claimed 过滤现阶段数据量无感;后续量大建议按幂等模板补 `(tenant_id, invoice_no)` 索引。
|
||||
- 无表结构、无 Nacos、无菜单 SQL 变更。
|
||||
|
||||
## 7. 验证状态
|
||||
|
||||
- 后端:`mvn clean compile -DskipTests -pl blade-service/blade-transport -am` 通过;前端 `pnpm run build` 通过;死符号(`getInvoicePool/invoicePoolQuery/FormalSettlementInvoicePool*/Mock 函数/expenseStatusOptions`)两仓库 grep 归零。
|
||||
- 手工回归清单(9 条):`docs/superpowers/plans/2026-09-22-invoice-pool-mirror-unified-picker.md` Task 8 Step 4,含作废释放、金蝶不可用兜底、立即同步 300s 超时三个新增场景。
|
||||
- 过程与评审记录:`.superpowers/sdd/2026-09-22-invoice-pool-mirror-unified-picker/`(台账 progress.md、各任务简报/报告/评审包)。
|
||||
Reference in New Issue
Block a user