From 576847396e3aa5fe6dc0710243e88822fab82a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Fri, 16 Oct 2026 15:27:10 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E6=B5=81=E6=B0=B4=E5=A4=9A=E6=AC=A1=E8=AE=A4=E9=A2=86=E4=B8=8E?= =?UTF-8?q?=E4=BD=9C=E5=BA=9F=E5=8F=A3=E5=BE=84=E6=A2=B3=E7=90=86=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-10-16-收款流水多次认领与作废口径梳理.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 doc/docs/业务流程/2026-10-16-收款流水多次认领与作废口径梳理.md diff --git a/doc/docs/业务流程/2026-10-16-收款流水多次认领与作废口径梳理.md b/doc/docs/业务流程/2026-10-16-收款流水多次认领与作废口径梳理.md new file mode 100644 index 00000000..e0bb492c --- /dev/null +++ b/doc/docs/业务流程/2026-10-16-收款流水多次认领与作废口径梳理.md @@ -0,0 +1,130 @@ +# 收款流水(认领通知单)多次认领与作废口径梳理 + +> 日期:2026-10-16 +> 范围:`tms-api` blade-transport 收款流水认领、认领记录模块;`tms-erp-web` 认领记录页面 + +--- + +## 一、结论速览 + +| 问题 | 结论 | +| --- | --- | +| 一个通知单能被多次认领,每次认领生成一条还是多条认领记录? | **每次认领操作生成一条认领主单**(`blade_receipt_claim`),多次认领即多条主单;每次认领同时按所选拆分生成 N 条结算单分摊明细(`blade_receipt_claim_settlement`) | +| 认领记录页面是一条一条显示还是只显示一条? | **一条认领主单一行,逐条显示**,不按通知单合并;同一通知单认领 3 次就显示 3 行,每行"认领金额"只是该次认领的金额 | +| 作废是逐条作废归还金额,还是整个通知单全部作废? | **逐条作废、按条归还金额**:作废入口在单条认领记录上,回退金额 = 该条认领主单的 `claim_amount`,流水已认领金额只减这一条;其余认领记录不受影响 | + +--- + +## 二、数据模型 + +``` +blade_kingdee_receipt_flow(收款流水 / 认领通知单,1) + │ receipt_flow_id + ├─< blade_receipt_claim(认领主单,N) ← 每次认领一条 + │ claim_amount 本次认领总金额 + │ claimer_id 认领人(记录页面按本人过滤) + │ claim_status claimed / voided + │ voided_by / voided_time 作废人 / 作废时间 + │ + └─< blade_receipt_claim_settlement(分摊明细,N × M) ← 每次认领按结算单拆行 + receipt_claim_id 归属哪次认领 + formal_settlement_id/no 关联应收正式结算单 + allocated_receipt_amount 本次分摊金额 + claimed_receipt_amount 认领前该结算单已认领金额 + status 1 有效 / 0 无效(作废置 0,不物理删除) +``` + +关键点:**认领主单的粒度是"一次认领操作"**,不是通知单。通知单维度只有累计金额(`claimed_amount`)和状态(`claim_status`:unclaimed / partial / claimed),由每次认领/作废累加回退得出。 + +--- + +## 三、认领:一次操作生成一条主单 + N 条分摊 + +代码:`ReceiptFlowServiceImpl#claim(ReceiptClaimRequest)` + +1. 锁定流水(通知单)与所选结算单。 +2. 校验两条累计上限: + - 每张结算单:已有累计认领 + 本次分摊 ≤ 结算总应收含税金额; + - 流水:已有累计认领(`flowClaimedAmount`,只算未作废记录)+ 本次总额 ≤ 公告未认领金额(`unclaimed_amount`,A301-2 口径)。 +3. **插入一条** `ReceiptClaim` 主单:`claim_amount` = 本次分摊总额,`claim_status = claimed`。 +4. 按所选结算单逐张**插入 N 条** `ReceiptClaimSettlement` 分摊明细。 +5. 累加流水 `claimed_amount`,按累计值重算流水状态(< 未认领金额 → partial,= → claimed)。 +6. 只登记本地,不推送金蝶;推送由定时任务/手动按钮触发。 + +所以:**同一通知单第二次认领是再插一条新主单**,不存在"找已有主单合并金额"的逻辑;校验全部按"未作废记录累计"实时计算,天然支持多次认领。 + +### 认领按钮的显示条件(为什么有些行没有"认领") + +收款流水列表操作列(`receipt-flow.vue` → `canClaim(row)`): + +```js +canClaim(row) { + return this.hasPermission('receipt_flow_claim') && Number(row.remainingAmount || 0) > 0; +} +``` + +两个条件同时满足才显示"认领"按钮: + +1. **按钮权限**:当前用户拥有 `receipt_flow_claim` 按钮权限(admin 直接放行,普通用户取决于菜单按钮配置); +2. **剩余可认领金额 > 0**:`remainingAmount` 由后端 `ReceiptFlowWrapper` 统一计算: + + ``` + remainingAmount = max(公告未认领金额 unclaimed_amount − 累计认领金额 claimed_amount, 0) + ``` + +按认领状态换算: + +| 流水认领状态 | remainingAmount | 认领按钮 | +| --- | --- | --- | +| unclaimed 未认领(公告金额 > 0) | = 公告未认领金额 > 0 | 显示 | +| partial 部分认领 | > 0 | 显示 | +| claimed 认领完成 | = 0(累计 ≥ 公告金额) | **不显示** | +| 公告未认领金额为 0 的流水 | = 0 | **不显示** | +| 无 `receipt_flow_claim` 权限 | — | **不显示** | + +即:**按钮显隐只看金额余额与权限,不看认领状态字段本身**;`claimed` 状态的行因为剩余额度为 0 自然不显示按钮。按钮不显示且不满足"推送金蝶"条件时,操作列显示"-"。 + +注意:顶部"批量认领"按钮只判断权限与是否勾选行(`receipt_flow_claim` + `selectedRows.length`),**不按行剩余金额过滤**;对无剩余额度的流水发起批量认领时,进入批量页面后由提交校验/后端 `claim()` 兜底拦截。 + +--- + +## 四、认领记录页面:逐条显示 + +后端:`ReceiptClaimMapper.xml#selectClaimRecordPage` → `FROM blade_receipt_claim c JOIN blade_kingdee_receipt_flow f`,固定条件 `c.claimer_id = 当前用户`。 + +- **列表一行 = 一条认领主单**,无按流水/通知单的 GROUP BY 合并; +- 同一通知单多次认领 → 多行,各行的认领金额、认领日期、金蝶单号都是当次认领自己的; +- 关联结算单列用 `GROUP_CONCAT(分摊明细.结算单号)` 拼成一串展示(只展示,不参与合并); +- 详情页(`selectClaimRecordDetail` + 分摊明细列表)展示的也是**该次认领**的分摊明细,明细里的"认领前已认领金额"记录的是认领那一刻结算单的累计值,可还原多次认领的先后关系; +- 前端 `receipt-claim-record.vue` 列表 + 行级"作废"按钮(`api.voidClaim(row.id)`),确认文案为"作废后将回退本次认领金额"——与逐条口径一致。 + +另:收款流水列表的详情弹窗里有一个"认领记录"区块,展示的是该流水的**操作日志**(`blade_receipt_flow_record`,action_type = claim/push),按时间线展示每次认领/推送动作,同样不是合并视图。 + +--- + +## 五、作废:逐条作废、按条归还金额 + +代码:`ReceiptClaimRecordServiceImpl#voidClaim(Long id)`,入参就是**单条认领主单 id**。 + +流程(单事务): + +1. 锁定该条认领主单,校验:本人记录、`claim_status = claimed`(已作废不可再作废)。 +2. 锁定关联流水,校验:**未推送金蝶**——已推送的不允许作废,提示"请在金蝶侧人工处置"。 +3. 取该主单名下有效分摊明细(status=1),全部置 `status = 0`(保留审计,不删行)。 +4. 批量刷新相关结算单收款汇总(`refreshPaymentSummaries`)。 +5. **流水 `claimed_amount` 只减去本条主单的 `claim_amount`**(下限 0),并按减后累计重算流水认领状态(0 → unclaimed,< 未认领金额 → partial,≥ → claimed)。 +6. 主单置 `voided`,记录作废人、作废时间;写 `void_claim` 操作日志(金额 = 本次回退金额)。 +7. **不生成金蝶认领冲单**:金蝶单号/状态保留原值,金蝶侧冲销/红红由人工处置;冲单逻辑代码已注释保留(`buildKingdeeBillNo`),后续迭代可放开。 + +边界与影响: + +- 作废某一条,只归还这一条的金额,**同一通知单的其他认领记录不受影响**,仍正常显示、仍可单独作废; +- 作废后该条记录仍在列表中(状态"已作废"),不允许再改附件、不可重复作废; +- 归还后的金额空间立即可被再次认领(认领校验按未作废累计实时计算); +- 附件/操作日志/分摊明细均保留,金额回退可追溯。 + +--- + +## 六、一句话总结 + +通知单(收款流水)是"累计额度"维度,认领记录是"每次操作"维度:**认领一次记一条、页面逐条展示、作废按条回退金额**;整单性质的只有流水上的累计已认领金额与认领状态,由各条记录的认领/作废实时推导,没有任何"按通知单整体作废"的入口。