feat(consignment): 确认加好友后现货作废不回池,撤销履约押金可选并结算打手押金

现货口径(严):已确认加好友 = 买家好友已加上、货随时可能送出去,回池会被下一个工单
再次占用(等于二次出货)。收口在 releaseConsignmentInventoryBindingForWorkOrderWithClient:
解绑前读工单 acceptance_mode/friend_added_at,命中则 archived + allow_matching=FALSE + 留痕,
否则仍回池。所有解绑路径自动继承,发单系统接口未动。

撤销寄售履约(寄卖专属入口)支持两笔押金各自可选,默认按规则自动:
- 打手履约押金:auto / refund / forfeit
- 卖家发布押金:auto / keep_frozen / forfeit
策略抽成 domain/consignment-deposit-policy.ts 纯函数;覆盖时原因照旧必填,选项与金额写进
工单事件便于对账。

顺带修掉两个 bug:
1. 撤销寄售履约从不结算打手履约押金——只清 assigned_worker_id、只处理卖家押金,
   worker_deposit 单撤销后打手押金永久冻结。现按选项结算(退还/没收)。
2. detachConsignmentMaterialFromWorkOrderWithClient 里 $1 既作 $1::text(detachedAt)
   又赋值给 updated_at,Postgres 整体推断成 text → 42804。凡解绑现货摘寄售标记的路径
   (取消指派/撤单/退单/售后/撤销履约/人工回库)在真实库上必然 500,假 client 单测抓不到。
   已显式 ::timestamptz,并补类级静态护栏扫同类写法。

验证:真实库(全回滚)——已确认加好友解绑 → archived/allow_matching=false;
未确认 → 仍 in_stock;打手押金冻结 3000 → 退还 3000(重复结算 0)→ 再冻 2500 → 没收 2500
(可用余额不变、冻结归零、流水 deposit_deduction)。后端 432 例(新增 5 例)全绿。
This commit is contained in:
yml2213
2026-09-17 10:21:38 +08:00
parent a47c243421
commit d158cc91bc
12 changed files with 577 additions and 29 deletions
+30
View File
@@ -21,6 +21,7 @@
| `632dddc4` | 上一轮:H5 渠道整体下线 + 凭据字段修复 + 状态机封闭(撤销守卫 / 库存绑定唯一性 / 生命周期解绑)+ 押金归属取台账 | 迁移 `079`、`consignment-*` 五个文件、`work-order-*` 三个仓库、两个前端面板 |
| `5d11bf20` | 批次 C+D:指派部分成功补偿、凭证核销如实反馈、空规格不放行 + 履约/指派服务端规格复检 | `consignment-fulfillment-service.ts`、`consignment-matching-service.ts`、`consignment-repo.ts`、履约路由、`WorkOrdersPanel.tsx` |
| `d6f6219f` | 批次 F1:内部现货履约停在「待加好友」,客服确认后才进赠送冷却 + 备注快捷项 | `work-order-gift-repo.ts`、履约服务、`WorkOrdersPanel.tsx`、`utils/gift-phase.ts` |
| 本批提交(批次 G,同一提交内含本文档,故不写自身 hash) | 批次 G:确认加好友后现货作废不回池 + 撤销寄售履约押金可选(含修打手押金永久冻结、真实库 42804 500) | `consignment-repo.ts`、`consignment-deposit-policy.ts`、`work-order-deposit-repo.ts`、撤销履约服务与路由、`WorkOrdersPanel.tsx` |
| 本批提交(批次 F2,同一提交内含本文档,故不写自身 hash) | 批次 F2:确认加好友后卖家发布押金不退(`deposit_deduction` 落地)+ 二次冻结护栏 | `consignment-deposit-repo.ts`、取消/退单仓库、撤销履约服务 |
| 本批提交(批次 E,同一提交内含本文档,故不写自身 hash) | 前端四权限门控收口、`allocation_status` 约束与权限文案修正、面板错误态/防双提交/真实待审计数 | `admin-auth.ts`、两个寄卖面板、`AdminWorkerPlatformPage.tsx`、迁移 `080` |
@@ -276,6 +277,35 @@
前端在"部分匹配"候选上先 `modal.confirm` 危险确认,再带 `allowPartial: true` 重试,高配充低配的合法玩法保留但不可误触。
3. ⏳ 匹配下推 SQL + 批量匹配接口 + 工单列表角标(P2-8)未做:当前仍是"取全量在库 → 内存比对"。
### 批次 G · 现货作废口径 + 押金处置可选(本轮)
1. ✅ **确认加好友后现货一律作废下架,不再回池**(严口径):
`确认加好友` 意味着买家好友已加上、货随时可能送出去,回池会被下一个工单再次占用
(等于同一件货二次出货)。这条口径收口在寄卖自己的
`releaseConsignmentInventoryBindingForWorkOrderWithClient` 里:解绑前先读工单的
`acceptance_mode / friend_added_at`,命中则 `status='archived'` + `allow_matching=FALSE`
+ 备注留痕,否则仍按原逻辑 `in_stock` 回池。所有解绑路径(取消指派/撤单/退回大厅/退单/
售后/撤销寄售履约)自动继承,不需要各自判断,发单系统的接口一行没动。
2. ✅ **撤销寄售履约弹窗支持两笔押金各自可选**(只加在寄卖专属入口
`POST /consignment/revoke` 上):
- 打手履约押金:`auto`(已确认加好友则扣除,否则全额退还)/ `refund` / `forfeit`
- 卖家发布押金:`auto`(已确认加好友则没收;否则作废退还、回库保持冻结)/ `keep_frozen` / `forfeit`
默认全部 `auto` = 原行为;覆盖后原因照旧必填,并把选项与金额写进工单事件
(`workerDeposit` / `consignmentDeposit` / `inventoryArchived`)便于对账追责。
策略判定抽成纯函数 `domain/consignment-deposit-policy.ts`,可单测。
3. ✅ **修掉一个资金漏洞:撤销寄售履约从不结算打手履约押金**。
它以前只清 `assigned_worker_id`、只处理卖家发布押金,打手的履约押金没有任何出口,
`worker_deposit`(指派打手)单撤销后押金会**一直冻在钱包里**。现在撤销时按上面的
选项调用 `settleWorkOrderDepositWithClient` 结算(退还或没收,金额取冻结台账与钱包冻结额的较小值)。
4. ✅ **修掉一个真实库必炸的 500(42804)**:`detachConsignmentMaterialFromWorkOrderWithClient`
里 `$1` 既作 `$1::text`(写进 jsonb 的 `detachedAt`)又赋值给 `updated_at`,Postgres 把它
整体推断成 text,赋值给 timestamptz 列直接报错。凡解绑现货时摘寄售标记的路径
(取消指派/撤单/退单/售后/撤销履约/人工回库)在真实库上全都会炸,而假 client 的单测不跑
真 SQL,一直没暴露。已显式 `$1::timestamptz`,并补了一道类级静态护栏
(`sql-param-type-safety.test.ts`)扫描同类"占位符既当 text 又当时间戳"的写法。
5. ⏳ 待你拍板:`撤销寄售履约` 的状态白名单仍含 `pending_acceptance`(打手已提交赠送凭证)。
未确认加好友的单子在这一步撤销仍会回池——如果这类单也可能已经交付,需要一并收紧。
### 批次 F · 待加好友流程与押金不退(本轮)
1. ✅ **内部现货履约不再自动进冷却**:新增 `parkWorkOrderWaitingFriendAddWithClient`,占库落地时把工单停在