Merge branch 'master' into feature/20261103-bfi-warehouse-material

# Conflicts:
#	blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeReceivedInvoiceSyncSupport.java
#	doc/docs/业务流程/2026-10-17-结算调整单操作流程说明(分场景).md
#	doc/sql/transport/lqj/20261102/06_blade_invoice_receipt_supplier_code_menu_20261031.sql
#	doc/sql/transport/lqj/20261102/19_blade_dict_fee_category_warehouse_20261103.sql
This commit is contained in:
刘泉佳
2026-11-04 17:27:58 +08:00
202 changed files with 9266 additions and 1150 deletions
@@ -137,6 +137,7 @@
- 预检为**软提示**,不阻断建单(默认建议);是否升级为硬拦截由业务另行确认。
- **降级**:金蝶查询超时/不可用/接口异常时,预检返回"未校验",**不阻断**建单与回带,由后续审批分流与重推闸门兜底。
- 预检结果**只用于提示**,不作为后续环节的结论缓存:审批(操作 2)、重推(操作 3)各自按**当下**状态重新判定。
- 预检查询结果**顺带回写**正式结算单的冲销状态字段(`kingdee_writeoff_status`,见 §15)供列表展示;异常降级时不回写、保留上次值。
![选单后金蝶冲销预检:该结算单已推送金蝶且旧单尚未冲销时的醒目提示,仅为软提示,不阻断建单](./2026-10-16-结算调整单接入金蝶设计(未推送自动推-已推送冲销后重推新单).assets/03-新增调整单-选单后金蝶冲销预检提示.png)
@@ -171,7 +172,7 @@
`repush(调整单id)` 重写为:
1. **前置校验**:调整单 `approvalStatus = approved`;原单存在。
2. **冲销校验(硬闸门)**:取调整单号 + 原单号,按旧键(`原结算单号_明细单据号`)查 A102-4(应付)/ A302-4(应收);要求存在且 `hadwrittenoff = true`,否则抛出「原应付/应收单尚未在金蝶冲销,禁止重推」。
2. **冲销校验(硬闸门)**:取调整单号 + 原单号,按旧键(`原结算单号_明细单据号`)查 A102-4(应付)/ A302-4(应收);要求存在且 `hadwrittenoff = true`,否则抛出「原应付/应收单尚未在金蝶冲销,禁止重推」。**闸门查询结果无论放行还是拦截均回写**正式结算单冲销状态(§15.3③),拦截后列表即同步为"未冲销"。
3. **克隆新正式结算单**:`cloneFormalSettlement(原单, 调整单)`
- 新号由 `nextNo` 取正式流水(`FJS`/`SJS`+日期+4 位);
- 克隆明细、明细费项、汇总费项、发票、汇率等;
@@ -198,7 +199,7 @@
- 只认 `hadwrittenoff = true`(`BfiApBillVO` 158 / `BfiArBillVO` 138)。部分冲销同样放行。
- `iswrittenoff` 不单独作为放行依据。落地前需用 Apifox 实测 A102-4/A302-4 确实回传 `hadwrittenoff`。
- **两处判定,用途不同**:操作 1 选单预检 = 软提示(第 6.2 节);操作 3 重推 = **硬闸门**(第 8 节)。预检不替代闸门——冲销在金蝶可被撤销,且建单到重推期间状态可能变化。
- **三处判定,用途不同**:操作 1 选单预检 = 软提示(第 6.2 节);操作 3 重推 = **硬闸门**(第 8 节);定时回写 = 列表展示供数(第 15 节)。预检不替代闸门——冲销在金蝶可被撤销,且建单到重推期间状态可能变化;定时回写值**只用于展示**,闸门放行永远以实时查询为准。
### 9.3 克隆新正式结算单
@@ -296,3 +297,49 @@ ALTER TABLE blade_formal_settlement ADD COLUMN adjust_status VARCHAR(32) NULL CO
5. **按钮与菜单**:「推送金蝶」与「重新推送」合并为**单一入口**(按金蝶状态分流:未同步/失败→推原结算单;已同步→冲销后重推新单),统一复用既有菜单 `settlement_adjustment_repush`,不新增菜单。
6. **待实测**:A102-4/A302-4 的 `hadwrittenoff` 实际回传(§13.1);克隆新单对 `PreSettlement` 占用的影响(§13.2)。
---
## 15. 金蝶冲销状态落库与列表展示(2026-10-30 新增)
### 15.1 背景与定位
预检(§6.2)与重推闸门(§8)是**事件触发**的单点实时校验:只有建调整单、点重推时才会查金蝶,覆盖不到结算单列表的全量展示;而列表是高频页面,不能每次刷新/翻页都实时查金蝶(外部依赖与延迟会拖垮列表)。因此把冲销状态**持久化 + 定时回写**(与 `PaymentKingdeeResultTask` 既有回写模式一致);决策时刻(预检提示、闸门放行)仍坚持实时查询。三条链路互补:**接口查询保证决策正确,定时回写保证列表有数**。
### 15.2 数据模型(DDL)
脚本 `doc/sql/transport/lqj/20261102/06_blade_formal_settlement_kingdee_writeoff_20261030.sql`(可重复执行):
```sql
ALTER TABLE blade_formal_settlement ADD COLUMN kingdee_write_off_status VARCHAR(20) NULL COMMENT '金蝶冲销状态:unwrittenoff-未冲销 writtenoff-已冲销(NULL=未推送金蝶或未校验)';
ALTER TABLE blade_formal_settlement ADD COLUMN kingdee_write_off_time datetime NULL COMMENT '金蝶冲销状态确认时间(定时回写/预检回写时间)';
```
> 列名遵循 MyBatis-Plus 驼峰转下划线默认映射(`kingdeeWriteOffStatus` → `kingdee_write_off_status`),实体无需 `@TableField`;脚本对早期误建的旧列名(`kingdee_writeoff_status`)会先重命名再补缺,可重复执行。
实体 `FormalSettlement` 同步加 `kingdeeWriteOffStatus` / `kingdeeWriteOffTime`;`FormalSettlementVO` 继承实体自动带出,无需改 VO。
### 15.3 三条查询/回写链路
| 链路 | 触发 | 行为 |
|---|---|---|
| ① 定时回写(兜底供数) | `PaymentKingdeeResultTask` 子流程④(默认每 10 分钟,single-flight 锁 `kingdee-writeoff-sync`) | 扫 `kingdeeSyncStatus=synced` 的结算单 → 结算明细分批一次查全(消除 N+1)组装防重键 → A102-4/A302-4 整批查询 `hadwrittenoff` → 状态有变化的 `updateBatchById` 批量回写;金蝶异常整轮告警、保持上次值 |
| ② 预检实时回写 | 操作 1 选单预检 | 查询成功即回写该单状态(已冲销/未冲销都存);异常降级"未校验"不回写 |
| ③ 闸门实时回写 | 操作 3 重推硬闸门 | 查询结果无论放行/拦截均回写(拦截=未冲销也存,提示后列表即同步) |
回写统一走 `FormalSettlementServiceImpl.refreshKingdeeWriteOff(id, writtenOff)`:状态未变化不落库,避免预检反复点击重复写库。
### 15.4 列表展示口径
| 场景 | 显示 |
|---|---|
| 未推送金蝶(unsynced/failed) | `-` |
| 已推送,尚未回写过(存量上线初期) | 未校验 |
| 已推送,旧单未冲销 | 未冲销(黄) |
| 已推送,旧单已冲销(含部分冲销) | 已冲销(绿) |
前端:`formalSettlementTable.js` 新增「金蝶冲销状态」列(`formalSettlement.js` COLUMN_EXTRA 标记 `slot`)、`formal-settlement-table-panel.vue` 单元格插槽渲染标签、`utils/kingdee.js` 新增 `kingdeeWriteOffTagType` 颜色映射、`formalSettlementSearch.js` 新增 `kingdeeWriteOffStatusOptions` 文案。
### 15.5 与硬闸门的关系(重要)
定时回写值**只用于展示**,允许滞后一个调度周期(默认 10 分钟);重推放行与否**永远以闸门实时查询为准**(§8.2),不读取定时值——避免拿旧状态放行导致金蝶重复生成应付/应收单。
@@ -136,7 +136,7 @@ A301-1 收款单查询(业务日期窗口取 `thirdParty.bfi.recBillSync.days`
### 3.6 新增表
`blade_receipt_claim_hcs_record`(收款认领合规推送记录,DDL 见 `doc/sql/transport/lqj/20261028/01_blade_receipt_claim_hcs_record_20261028.sql`):
`blade_receipt_claim_hcs_record`(收款认领合规推送记录,DDL 见 `doc/sql/transport/lqj/20261102/01_blade_receipt_claim_hcs_record_20261028.sql`):
| 字段 | 说明 |
| --- | --- |