c6b01def4c
CI / verify (push) Has been cancelled
拦截伪区县写入与下单;推单失败挂 fulfillmentHold,HQ 可见超区/推单失败。 Co-authored-by: Cursor <cursoragent@cursor.com>
3.8 KiB
3.8 KiB
杜康好客 · 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. 存量建议(运维,非代码)
-- 生产排查脏地址(只读)
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;
可选:运营通知用户进「地址管理」完善;本版不自动改写历史行。