feat(consignment): 客服手动指定现货匹配的界面入口
后端批次已提供判定/差异/强制留痕与双向读取接口,这里补界面,让客服真的能用上。 - 新增共享弹窗 ConsignmentManualMatchModal:订单侧(匹配弹窗「手动指定现货匹配」)与 库存侧(寄售仓库行内「手动匹配订单」)共用同一套交互与落地逻辑,避免两套 UI 漂移 - 交互:搜索 → 选中(精确/非精确/规格冲突三档标签 + 字段级差异说明)→ 选交付方式 (内部现货履约 / 指派供货打手)→ 非精确需勾选确认、冲突需勾选「确认规格不一致」并必填原因 → 落地;并在落地前提示"现货立刻被占用、点错需撤销寄售履约" - 判定规则收敛成纯函数 consignment-manual-match.ts(需不需要确认/填原因、能否提交、 关键词过滤、标签文案)并加 4 例单测 - 服务与类型补齐:fetchWorkOrderConsignmentMatchOptions / fetchInventoryMatchableOrders, fulfill/assign 入参增加 allowSpecMismatch 与 matchNote - 凭证核销失败的提示沿用既有规则(核销失败不能报成功) 验证:前端 typecheck/lint/format/44 例测试/build 全过;两个新接口未登录访问均 401 (路由已挂载、权限位生效)。
This commit is contained in:
@@ -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` |
|
||||
| 本批提交(批次 S,同一提交内含本文档,故不写自身 hash) | 批次 S:手动指定现货匹配(判定/差异/强制留痕 + 双向入口 + 共享弹窗) | `consignment-matching-service.ts`、`consignment-fulfillment-service.ts`、`ConsignmentManualMatchModal.tsx` |
|
||||
| 本批提交(批次 R,同一提交内含本文档,故不写自身 hash) | 批次 R:售后立案回落到供货卖家;抽共享"从工单找供货卖家"查询 | `consignment-supplier-repo.ts`、`after-sales-repo.ts`、`consignment-deposit-repo.ts` |
|
||||
| 本批提交(批次 Q,同一提交内含本文档,故不写自身 hash) | 批次 Q:验收结算补寄卖货款给供货卖家;修指派打手线报酬 100 倍单位错 | `consignment-deposit-repo.ts`、`work-order-settlement-repo.ts`、`consignment-fulfillment-service.ts` |
|
||||
| 本批提交(批次 P,同一提交内含本文档,故不写自身 hash) | 批次 P:确认加好友/上传赠送截图恢复为卖家操作,客服兜底 | `consignment-item-stage.ts`、`consignment-worker-service.ts`、`worker-acceptance-service.ts` |
|
||||
@@ -288,6 +289,45 @@
|
||||
前端在"部分匹配"候选上先 `modal.confirm` 危险确认,再带 `allowPartial: true` 重试,高配充低配的合法玩法保留但不可误触。
|
||||
3. ⏳ 匹配下推 SQL + 批量匹配接口 + 工单列表角标(P2-8)未做:当前仍是"取全量在库 → 内存比对"。
|
||||
|
||||
### 批次 S · 客服手动指定现货匹配(本轮)
|
||||
|
||||
**需求**(用户):客服要能在后台**人工指定**现货与订单匹配起来,而不是只能用系统算出的候选。
|
||||
|
||||
**先说清楚现状**:后端其实早就留了"人工选定现货"的口径(`allowPartial` + 宽松规格复检),
|
||||
只是**没有界面入口**,客服只能从"规格完全对得上"的自动候选里挑;遇到订单规格没写全、
|
||||
订单录错、需要高配充低配时无从下手。
|
||||
|
||||
**改法**(三项决策均由用户确认:允许强制匹配但必须留痕 / 两种交付方式都保留 / 双向入口都加):
|
||||
|
||||
1. ✅ **判定与解释**:新增 `listConsignmentMatchOptions()`/`classifyConsignmentMatch()`,
|
||||
把某订单的**全部**在库现货逐件判定 exact / partial / conflict,conflict 时给出**字段级差异**
|
||||
(`describeConsignmentSpecDifferences`,例如「系统:订单「苹果」/ 现货「安卓」」)。
|
||||
正反两个方向共用同一套判定,避免"界面说能选、接口却拒绝"。
|
||||
2. ✅ **强制匹配 + 留痕**:履约/指派两条链路新增 `allowSpecMismatch` 与 `matchNote`。
|
||||
规格真冲突默认仍拒绝(409 `consignment_spec_mismatch`);显式确认后放行,但
|
||||
**必填原因**(400 `consignment_match_note_required`),原因与差异明细写入工单事件与
|
||||
`material.consignment`(`manualMatch` / `matchType` / `matchNote` / `specConflicts`)。
|
||||
3. ✅ **双向入口**:订单侧 `GET /consignment/matches/:workOrderId/options`(全部在库现货+判定),
|
||||
库存侧 `GET /consignment/inventories/:id/match-orders`(该现货可匹配的待指派/待补资料订单+判定)。
|
||||
4. ✅ **前端一个共享弹窗**:`ConsignmentManualMatchModal`,订单侧(匹配弹窗里「手动指定现货匹配」)
|
||||
与库存侧(寄售仓库行内「手动匹配订单」)共用,避免两套 UI 逻辑漂移。
|
||||
交互:搜索 → 选中(带判定标签与差异说明)→ 选交付方式(内部现货履约 / 指派供货打手)
|
||||
→ 非精确勾选确认 / 冲突勾选「确认规格不一致」+ 必填原因 → 落地。
|
||||
判定规则收敛在纯函数 `consignment-manual-match.ts` 并有单测(4 例)。
|
||||
|
||||
**真实库验证**(订单要「苹果微信区暗潮2钻」,现货为「安卓QQ区苍龙4钻」):
|
||||
|
||||
| 步骤 | 结果 |
|
||||
| --- | --- |
|
||||
| 订单侧选项 | 该件判定 `conflict`,列出 4 项差异(系统/区服/系列/钻石等级) |
|
||||
| 库存侧可匹配订单 | 该订单判定 `conflict`,要求规格解析正确 |
|
||||
| 不填原因强制匹配 | ✅ 被拒 `consignment_match_note_required` |
|
||||
| 不勾选强制、直接履约 | ✅ 被规格复检拒绝 `consignment_spec_mismatch` |
|
||||
| 勾选 + 填原因 | ✅ 成功:订单 `in_progress`、现货 `consumed`,事件与 material 均留痕 |
|
||||
| 接口鉴权 | 未登录访问两个新接口均 401(路由已挂载、权限位生效) |
|
||||
|
||||
临时数据已清理(残留 0)。
|
||||
|
||||
### 批次 R · 售后立案也认寄卖关系(本轮)
|
||||
|
||||
补货款时顺手排查"只认接单人"的地方,发现同类第三处:**售后立案**。
|
||||
|
||||
Reference in New Issue
Block a user