fix: A301-3 报文取数按契约修正——awrp_src_code=分摊结算单号拼接,seq/e_corebillno=结算单id
This commit is contained in:
+1
-1
@@ -137,7 +137,7 @@ public class KingdeeReceiptFlow extends TenantEntity {
|
||||
*/
|
||||
private LocalDateTime pushedTime;
|
||||
/**
|
||||
* 金蝶推送来源单据编码(SKCL+时间戳+流水id尾号6位,按流水生成、重试复用,A301-1 回写匹配键)
|
||||
* 金蝶推送来源单据编码(分摊结算单号下划线拼接,推送时生成落库;分摊不变则重试编码不变,A301-1 回写匹配键)
|
||||
*/
|
||||
private String awrpSrcCode;
|
||||
/**
|
||||
|
||||
+14
-20
@@ -792,10 +792,6 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
return ReceiptClaimPushResult.fail("累计认领金额(" + claimedTotal + ")与公告未认领金额("
|
||||
+ money(flow.getUnclaimedAmount()) + ")不一致,不满足推送条件");
|
||||
}
|
||||
// 推送来源编码:首次生成落库,重试复用(金蝶按 awrp_src_sys + awrp_src_code 幂等,防重试双单)
|
||||
if (Func.isEmpty(flow.getAwrpSrcCode())) {
|
||||
flow.setAwrpSrcCode(buildAwrpSrcCode(flow.getId()));
|
||||
}
|
||||
// 分录取该流水全部有效分摊行(结算单id升序,跨认领主单归集)
|
||||
List<ReceiptClaimSettlement> allocations = claimSettlementMapper.selectList(
|
||||
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||
@@ -814,6 +810,14 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
: formalSettlementMapper.selectList(Wrappers.<FormalSettlement>lambdaQuery()
|
||||
.in(FormalSettlement::getId, settlementIds)).stream()
|
||||
.collect(Collectors.toMap(FormalSettlement::getId, Function.identity(), (first, second) -> first));
|
||||
// 推送来源编码:分摊结算单号下划线拼接(A301-3 契约口径;分摊不变则重试编码不变,
|
||||
// 金蝶按 awrp_src_sys + awrp_src_code 幂等防重试双单)
|
||||
String awrpSrcCode = allocations.stream()
|
||||
.map(ReceiptClaimSettlement::getFormalSettlementNo)
|
||||
.filter(Func::isNotEmpty)
|
||||
.distinct()
|
||||
.collect(Collectors.joining("_"));
|
||||
flow.setAwrpSrcCode(awrpSrcCode);
|
||||
|
||||
BfiClaimPushDTO param = buildClaimPushDTO(flow, allocations, settlements);
|
||||
log.info("调用BFI接口 收款认领结果推送开始 flowId:{},billId:{},awrpSrcCode:{},分摊明细 {} 行,认领金额 {}",
|
||||
@@ -836,7 +840,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
param.setBillid(flow.getBillId());
|
||||
// 【必填】来源系统编码
|
||||
param.setAwrpSrcSys(bfiProperties.getSrcSys());
|
||||
// 【必填】来源系统单据编码(按流水生成,重试复用)
|
||||
// 【必填】来源系统单据编码(分摊结算单号下划线拼接)
|
||||
param.setAwrpSrcCode(flow.getAwrpSrcCode());
|
||||
// 【必填】收款类型.编码
|
||||
param.setRecpaytypeNumber(KingdeeBfiConstant.BFI_CLAIM_REC_PAY_TYPE);
|
||||
@@ -847,20 +851,19 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
// 【必填】付款人id
|
||||
param.setRecpayer(flow.getPayerId());
|
||||
List<BfiClaimPushEntryDTO> entries = new ArrayList<>();
|
||||
int seq = 1;
|
||||
for (ReceiptClaimSettlement allocation : allocations) {
|
||||
BfiClaimPushEntryDTO entry = new BfiClaimPushEntryDTO();
|
||||
// 【必填】应收金额(分摊金额)
|
||||
entry.setEReceivableamt(money(allocation.getAllocatedReceiptAmount()));
|
||||
// 分录行序号
|
||||
entry.setSeq((long) seq++);
|
||||
// 分录行序号(结算单id)
|
||||
entry.setSeq(allocation.getFormalSettlementId());
|
||||
FormalSettlement settlement = settlements.get(allocation.getFormalSettlementId());
|
||||
if (settlement != null && Func.isNotEmpty(settlement.getKingdeeBillNo())) {
|
||||
// 结算单已同步金蝶应收单时携带核心单据引用,金蝶按应收单号核销认领金额
|
||||
// 结算单已同步金蝶应收单时携带核心单据引用,金蝶按结算单id核销认领金额
|
||||
// 核心单据类型
|
||||
// entry.setECorebilltype(KingdeeBfiConstant.BFI_CLAIM_CORE_BILL_TYPE);
|
||||
// 核心单据编号
|
||||
entry.setECorebillno(settlement.getKingdeeBillNo());
|
||||
// 核心单据编号(结算单id)
|
||||
entry.setECorebillno(String.valueOf(settlement.getId()));
|
||||
}
|
||||
entries.add(entry);
|
||||
}
|
||||
@@ -939,15 +942,6 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
||||
return ReceiptClaimPushResult.fail("金蝶认领结果推送失败:" + reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送来源编码:SKCL + 时间戳 + 流水id尾号6位(按流水生成,重试复用)
|
||||
*/
|
||||
private String buildAwrpSrcCode(Long flowId) {
|
||||
String time = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
|
||||
String suffix = String.valueOf(flowId);
|
||||
return "SKCL" + time + suffix.substring(Math.max(0, suffix.length() - 6));
|
||||
}
|
||||
|
||||
/**
|
||||
* A301-2 收款认领公告查询:按认领人姓名全量翻页,时间窗口取 Nacos 配置(默认近半年)。
|
||||
* 认领公告同步、手动推送对账与定时任务对账共用。
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
新增两条核心规则(本次重构的业务闸门):
|
||||
|
||||
- **认领完成 = 累计有效认领金额 == 公告未认领金额**(`unclaimed_amount`,即 A301-2 的 `unclaimamount`;作废分摊不计入累计)。只有认领完成的流水才满足推送条件——**不认领完就不推**。
|
||||
- **推送单元 = 收款流水**:一条流水只产生一张金蝶收款单,分录取该流水下全部有效分摊行(可能跨多次认领主单),`awrp_src_code` 按流水生成、重试复用。
|
||||
- **推送单元 = 收款流水**:一条流水只产生一张金蝶收款单,分录取该流水下全部有效分摊行(可能跨多次认领主单);`awrp_src_code` 按分摊结算单号下划线拼接(A301-3 契约口径),一条流水只推送一次,编码不会撞码。
|
||||
|
||||
## 3. 领域模型与职责划分
|
||||
|
||||
@@ -60,7 +60,7 @@ blade_receipt_claim_settlement(分摊行) ← 累计认领的权威来
|
||||
| `push_status` | varchar(20) | 推送状态:`none` 未推送(默认)/ `pushed` 已推送 / `failed` 推送失败 |
|
||||
| `push_fail_reason` | varchar(1000) | 最近一次推送失败原因(成功后清空) |
|
||||
| `pushed_time` | datetime | 首次推送成功时间 |
|
||||
| `awrp_src_code` | varchar(64) | 推送来源编码 `SKCL+yyyyMMddHHmmss+流水id尾号6位`;**首次推送尝试时生成并落库,重试复用同一编码**(依赖金蝶候选键 `awrp_src_sys+awrp_src_code` 幂等,防重试双单) |
|
||||
| `awrp_src_code` | varchar(64) | 推送来源编码 = **分摊结算单号下划线拼接**(A301-3 契约口径);推送时生成并落库,分摊不变则重试编码不变(依赖金蝶候选键 `awrp_src_sys+awrp_src_code` 幂等,防重试双单) |
|
||||
|
||||
认领状态 `claim_status` **口径变更**(字段沿用,含义改):
|
||||
|
||||
@@ -116,10 +116,10 @@ claimed 累计有效认领 == unclaimed_amount(且 > 0) ← 「认领
|
||||
- 公告查不到 → 失败:「金蝶公告不存在或已不在认领范围,请重新同步」
|
||||
- 重验:累计有效认领 == 最新 unclaimed_amount,不等 → 失败并提示两侧金额差额
|
||||
(不等说明金蝶侧有人认领过或金额有变,需人工核对后作废/补认领)
|
||||
④ awrp_src_code:已有则复用;无则生成并落库(SKCL+时间戳+流水id尾号6位)
|
||||
④ awrp_src_code:按分摊结算单号下划线拼接生成并落库(分摊不变则重试编码不变)
|
||||
⑤ 组装 A301-3:billid=流水.bill_id,entries = 该流水全部有效分摊行
|
||||
(分摊行 join 结算单,按结算单 id 升序;金额=allocated_receipt_amount;
|
||||
结算单有 kingdee_bill_no 时携带 e_corebillno,沿用现有取数)
|
||||
seq=结算单id;结算单有 kingdee_bill_no 时携带 e_corebillno=结算单id,沿用契约取数)
|
||||
⑥ 调 pushClaimResult:
|
||||
成功 → push_status=pushed、push_fail_reason 清空、pushed_time=now、
|
||||
kingdee_bill_no=响应 number、kingdee_bill_status=pushed;
|
||||
@@ -183,14 +183,14 @@ claimed 累计有效认领 == unclaimed_amount(且 > 0) ← 「认领
|
||||
| 场景 | 行为 |
|
||||
| --- | --- |
|
||||
| 定时任务与手动按钮并发推同一流水 | 流水行锁串行化 + `push_status != pushed` 静态闸门,不会双推 |
|
||||
| 推送超时但金蝶实际已生成收款单 | 本地记 failed;重试复用同一 `awrp_src_code`,金蝶候选键幂等,不产生重复收款单 |
|
||||
| 推送超时但金蝶实际已生成收款单 | 本地记 failed;重试时分摊不变则 `awrp_src_code` 不变,金蝶候选键幂等,不产生重复收款单 |
|
||||
| 推送成功后作废一笔认领、再补认领到等式满足 | 终态闸门拦截,不二次推送;金蝶侧冲销人工处置 |
|
||||
| 公告侧 unclaimed_amount 变小(他人在金蝶认领) | 推送前实时对账发现差额 → 拦截并提示差额,人工作废多余本地认领后重推 |
|
||||
| 公告侧 unclaimed_amount 变大 | 用户补认领到等式满足后推送(认领上限随新值放开) |
|
||||
| unclaimamount = 0 的公告 | 认领上限为 0,不可认领;累计认领 > 0 的推送前置条件天然排除空推 |
|
||||
| 手动推送者不在公告认领范围 | A301-2 按其姓名查不到公告 → 拦截提示,改由认领人操作 |
|
||||
|
||||
防重键沿用旧文档 §6.3,变更点:`awrp_src_code` 由「认领主单、结算单号拼接」改为「流水、按流水生成、重试复用」,A301-1 匹配键随之移到流水上。
|
||||
防重键沿用旧文档 §6.3,变更点:`awrp_src_code` 由「认领主单、每次认领各自拼接」改为「流水、按该流水全部分摊结算单号拼接、仅推送一次」,A301-1 匹配键随之移到流水上。
|
||||
|
||||
## 6. 前端改动汇总(tms-erp-web)
|
||||
|
||||
@@ -231,7 +231,7 @@ claimed 累计有效认领 == unclaimed_amount(且 > 0) ← 「认领
|
||||
| 推送触发 | 每次认领动作 | 定时任务(`receiptClaimPush.*` 开关)+ 手动按钮,双入口同一服务方法 |
|
||||
| 推送条件 | 无(认领即推) | 累计有效认领 == 公告未认领金额(推送前重查 A301-2 实时对账) |
|
||||
| 推送粒度 | 每次认领一张金蝶收款单 | 一条流水一张金蝶收款单(分摊行归集) |
|
||||
| awrp_src_code | 认领主单上,结算单号拼接(可撞码) | 流水上,SKCL+时间戳+流水尾号,重试复用 |
|
||||
| awrp_src_code | 认领主单上,每次认领各自按结算单号拼接(多流水分摊到同一批结算单时撞码) | 流水上,按该流水全部分摊结算单号拼接,一条流水仅推送一次,不再撞码 |
|
||||
| 认领上限/认领完成口径 | receipt_amount | unclaimed_amount |
|
||||
| 推送状态/失败原因 | 无(失败即回滚无痕) | 流水上 push_status / push_fail_reason / pushed_time,失败可重试可追溯 |
|
||||
| A301-1 轮询对象 | 认领主单 | 流水(级联刷新认领主单冗余字段) |
|
||||
@@ -244,7 +244,7 @@ claimed 累计有效认领 == unclaimed_amount(且 > 0) ← 「认领
|
||||
| 认领 | `ReceiptFlowServiceImpl.claim()` | 上限口径改公告未认领金额(缺失/为0拦截);删除同步推送调用,事务内只落本地 |
|
||||
| 推送 | `IReceiptFlowService.pushClaimToKingdee(flowId)` / `pushClaimByTask()` | 新增。共用 `pushClaimLocked`(`TransactionTemplate` 编程式事务,流水行锁覆盖闸门→对账→推送→落库,防并发双推);失败不抛异常跨事务边界,以 `ReceiptClaimPushResult` 返回 |
|
||||
| 定时任务 | `task/ReceiptClaimPushTask.java`(新增) | Nacos 开关 `thirdParty.bfi.receiptClaimPush.syncEnabled/cron`(默认关闭、每10分钟);候选=认领完成且 push_status ∈ (none, failed),按认领人姓名去重逐人重查 A301-2 |
|
||||
| 推送报文 | `buildClaimPushDTO` | billid=流水.bill_id;分录=该流水全部有效分摊行(结算单升序,seq 1起);e_corebillno=结算单金蝶应收单号;awrp_src_code 按流水生成(SKCL+时间戳+尾号6位)、重试复用 |
|
||||
| 推送报文 | `buildClaimPushDTO` | billid=流水.bill_id;分录=该流水全部有效分摊行(结算单升序);seq=结算单id;e_corebillno=结算单id(结算单已同步金蝶应收时携带);awrp_src_code=分摊结算单号下划线拼接 |
|
||||
| 手动接口 | `ReceiptFlowController.pushKingdee`(`POST /receipt-flow/push-kingdee`) | 成功返回金蝶收款单号,失败 R.fail(原因);按钮权限 `receipt_flow_push` |
|
||||
| 回写 | `ReceiptClaimRecordServiceImpl.refreshKingdeeResult()` | 轮询对象改流水(push_status=pushed 且回写状态 pushed/approved),按流水 awrp_src_code 匹配,级联刷新认领主单冗余字段 |
|
||||
| 作废 | `ReceiptClaimRecordServiceImpl.voidClaim()` | claim_status 重算口径改对照公告未认领金额(其余不变,作废不触发推送) |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- 支持重复执行,兼容 20260924 脚本已执行/未执行的环境,与该脚本无执行顺序要求
|
||||
-- 变更点:
|
||||
-- 1. 收款流水表新增推送域字段(推送状态/失败原因/推送时间/推送编码/金蝶收款单号/回写状态)
|
||||
-- 2. 认领主单移除 awrp_src_code 及其索引(推送编码上移至流水:按流水生成、重试复用)
|
||||
-- 2. 认领主单移除 awrp_src_code 及其索引(推送编码上移至流水:分摊结算单号拼接)
|
||||
-- 3. 收款流水表新增定时任务扫描索引与 A301-1 回写匹配索引
|
||||
|
||||
-- 1. 收款流水表:推送状态
|
||||
@@ -41,10 +41,10 @@ PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 4. 收款流水表:推送来源单据编码(A301-3 awrp_src_code,A301-1 回写匹配键,重试复用)
|
||||
-- 4. 收款流水表:推送来源单据编码(A301-3 awrp_src_code,分摊结算单号拼接,A301-1 回写匹配键)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `awrp_src_code` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ''金蝶推送来源单据编码(SKCL+时间戳+流水id尾号6位,按流水生成重试复用)''',
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `awrp_src_code` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ''金蝶推送来源单据编码(分摊结算单号下划线拼接,A301-1回写匹配键)''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'awrp_src_code'
|
||||
|
||||
Reference in New Issue
Block a user