Files
dukang/docs/杜康好客-v4.0.13-开发文档.md
T
jacy c6b01def4c
CI / verify (push) Has been cancelled
feat(trade): v4.0.13 收货禁全市与小飞侠拒单可感知
拦截伪区县写入与下单;推单失败挂 fulfillmentHold,HQ 可见超区/推单失败。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 17:20:40 +08:00

94 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 杜康好客 · v4.0.13 开发文档
> **2026-09-02** · mini-user / iam / trade / fulfillment / admin-web / h5-partner / domain
> **主题**:收货地址严格把关(禁「全市」)+ 小飞侠拒单履约可感知
需求背景:订单 `DK2026090220803` 自动推小飞侠失败,原因 `超出服务区`;收货区县为门店筛选用伪值「全市」。
**不做(本版明确排除)**:仓坐标补全、收件 `chooseLocation` / `toCoordinate` 坐标链路。
---
## 1. 版本目标
| # | 任务 | 类型 | 交付 |
|---|------|------|------|
| 1 | 收货选区与门店筛选语义拆分 | 缺陷/体验 | `RegionPicker mode=shipping` 无「全市」 |
| 2 | 地址保存硬闸 | 缺陷 | 前后端拒伪区县;详细地址最短 8 字 |
| 3 | 下单/预览拦截脏地址 | 缺陷 | preview `addressOk=false`;确认页不可提交 |
| 4 | 地址簿存量提示 | 体验 | 「需完善」置顶;结账选址强制去编辑 |
| 5 | 推单失败可感知 | 缺陷 | `fulfillmentHold` + 原因码;HQ 标签/发货弹窗 |
---
## 2. 规则
### 2.1 收货地址
- 伪区县:`全市`、`全部`、空 —— **禁止**写入 `user_address` / 下单快照 / 合伙人代下单。
- 详细地址:必填且长度 ≥ 8;含「全市」且无街道路牌关键词时前端软提示(不单独硬失败)。
- 门店列表筛选仍可使用「全市」(`mode=filter`)。
- 现场取货地址快照(`现场/现场/取货`)不走本校验。
### 2.2 履约拦截(推单失败)
| `fulfillment_hold_reason` | 含义 | HQ 展示 |
|---------------------------|------|---------|
| `LARGE_ORDER_GE_10_BOXES` | 大单≥10箱 | 大单 |
| `COURIER_OUT_OF_SERVICE` | 小飞侠返回超出服务区 | 超区 |
| `COURIER_DISPATCH_FAILED` | 其它自动推单失败 | 推单失败 |
- 失败后仍写 `MANUAL` 配送记录(待发货),**同时**挂 `fulfillmentHold`,避免静默像「没推过」。
- HQ 手动推小飞侠或填快递成功后仍清 hold(既有逻辑)。
---
## 3. 变更面
| 层 | 路径 |
|----|------|
| domain | `packages/domain/src/shipping-address.ts` |
| shared-types | `FULFILLMENT_HOLD_REASON_LABELS` + 常量 |
| API | `UserAddressService`;`TradeService` preview/create/代下单;`FulfillmentService.markCourierDispatchHold` |
| C 端 | `RegionPicker`、`address-edit`、`addresses`、`order-confirm`、`shipping-address.ts` |
| 合伙人 | `ProxyOrderPage` 校验 |
| HQ | `OrdersPage` 拦截筛选文案与标签 |
---
## 4. API 行为变化
| 接口 | 变化 |
|------|------|
| `POST/PUT /user/addresses` | 伪区县 / 详情过短 → `400` |
| `POST /trade/orders/preview` | 脏地址 → `addressOk=false` + message |
| `POST /trade/orders` | 脏地址 → `400` |
| 合伙人代下单 | 同上校验 |
| 支付后自动推单 | 失败写 hold reason(库字段,无新 path) |
---
## 5. 验收
- [ ] 新增/编辑地址:区县列表无「全市」;选真实区县 + 足够详细地址可保存
- [ ] 保存「全市」或过短详情被拒(前端 toast + 后端 400)
- [ ] 历史脏地址在地址簿标「需完善」;结账选择时跳转编辑
- [ ] 确认订单页脏地址不可提交;preview 提示完善区县
- [ ] 合伙人代下单伪区县/过短详情被拒
- [ ] 模拟小飞侠「超出服务区」后:订单 `fulfillment_hold=1`、`reason=COURIER_OUT_OF_SERVICE`;HQ 列表「超区」、发货弹窗有说明
- [ ] 门店列表筛选「全市」行为不变
---
## 6. 存量建议(运维,非代码)
```sql
-- 生产排查脏地址(只读)
SELECT id, user_id, province, city, district, detail, updated_at
FROM user_address
WHERE district IN ('全市','全部','') OR district IS NULL
ORDER BY id DESC LIMIT 100;
```
可选:运营通知用户进「地址管理」完善;本版不自动改写历史行。