Files
dukang/杜康好客-preV1编码手册.md
T

436 lines
18 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.
# 杜康好客 · preV1 编码手册(Mock 联调版)
> **V3 交付提示**:preV1 不再作为交付验收标准。核销规则以 [`杜康好客-v3编码手册.md`](./杜康好客-v3编码手册.md) §3 为准(无 ¥500 上限)。
> **版本**:preV1(在 V2 完整规格之上的**裁剪实现阶段**)
> **完整规格(V2)**[`杜康好客-V2编码手册.md`](./杜康好客-V2编码手册.md) — PRD、DB v3.1、API、任务卡均以 V2 为准
> **原则**:**不删表、不删 V2 API 路径、不改 V2 字段语义**preV1 用 Mock / Feature Flag / Seed 跳过外部依赖,开关关闭即切回 V2 真实流程。
---
## 文档索引
| 章节 | 内容 |
|------|------|
| §0 | 版本关系(preV1 vs V2 |
| §1 | preV1 范围:六条裁剪规则 |
| §2 | 三端 H5 与仓库结构 |
| §3 | 认证 Mock(无微信) |
| §4 | 支付 Mock |
| §5 | 配送与订单状态 Mock |
| §6 | 无总部端:能力替代 |
| §7 | preV1 功能清单 |
| §8 | Feature Flag 与 V2 切换 |
| §9 | preV1 里程碑与任务卡 |
| §10 | API / 数据行为差异速查 |
---
# §0、版本关系
| 维度 | preV1(本文) | V2(完整版) |
|------|---------------|--------------|
| 定位 | 三端 H5 联调,跑通购酒→发券→核销主链路 | 四端小程序/H5 + 真实微信/物流/支付 |
| 客户端 | **用户 / 门店 / 合伙人 均为 H5** | C端+合伙人+总部小程序,门店 H5 |
| 总部 HQ | **无独立端** | `pages/hq/` + AdminAuth |
| 登录 | **仅手机号 + 固定验证码** | 短信 + 微信授权/绑定 |
| 支付 | **Mock 即时成功** | 微信 JSAPI + 回调 |
| 配送 | **Mock 状态推进** | 小飞侠/物流回调 |
| 数据库 | **同 V2 v3.128 表)** | 同左 |
| API 路径 | **同 V2 §六**(行为可 Mock) | 完整实现 |
**升级路径**:preV1 完成后,按 §8 逐项打开 Flag、补小程序端与 HQ 端,**无需重构表结构**。
---
# §1、preV1 范围:六条裁剪规则
### 1.1 删掉 HQ 端
- **不做**`apps/mini-hq``pages/hq/` 任何页面、AdminAuth 前端。
- **保留**`hq_account` 表、§六 全部 `/admin/*` 路由(preV1 可不实现 Controller,或仅内部/脚本调用)。
- **替代**:见 §6。
### 1.2 用户 / 门店 / 合伙人 均改为 H5
| V2 端 | preV1 App | `X-Client-App` | 原型参照 |
|-------|-----------|----------------|----------|
| C端小程序 | `apps/h5-user` | `USER_H5` | `pages/user/` |
| 门店 H5 | `apps/h5-shop` | `SHOP_H5` | `pages/shop/` |
| 合伙人小程序 | `apps/h5-partner` | `PARTNER_H5` | `pages/partner/` |
- JWT `actorType` 不变:`USER` / `STORE` / `PARTNER`
- V2 的 `USER_MINI` / `PARTNER_MINI` / `HQ_MINI` 枚举**保留**,preV1 不用即可。
### 1.3 微信登录与授权暂不走
- **不调用**:微信 `code2session`、获取手机号组件、微信 OAuth。
- **不写入**`wx_open_id` / `wx_union_id`(保持 NULL)。
- **仅实现**`POST /auth/sms/send` + `POST /auth/login/sms`(及三端等价路径 `/shop/auth/*``/partner/auth/*`)。
- V2 的 `POST /auth/login/wechat``/auth/wechat/bind-phone`**保留路由**preV1 返回 `501 FEATURE_DISABLED` 或 Flag 关闭时不注册。
### 1.4 手机号验证固定 Mock
| 项 | preV1 约定 |
|----|------------|
| 验证码 | 固定 **`123456`**(全端、全 scene 通用) |
| 开关 | `MOCK_SMS=true` 时:不调用短信网关,不写入 `log_third_party(SMS)` 真实外呼 |
| 校验 | `AuthService.verifyCode(phone, code)` 内:`if (MOCK_SMS && code === '123456') return ok` |
| 限流 | preV1 可放宽;V2 打开真实短信后启用频率限制 |
**测试账号(Seed,见 §6.1**
| 角色 | 手机号 | 表 |
|------|--------|-----|
| C端用户 | `13800000001` | `user_user` |
| 门店 | `13900000001` | `store_account` |
| 合伙人主账号 | `13700000001` | `partner_account` |
### 1.5 配送与订单状态 Mock(跳过第三方)
- **不调用**:小飞侠 API、物流查询 API;`log_third_party``XFX` / `LOGISTICS` 在 preV1 可不写入(或写 MOCK 占位)。
- **仍创建**:支付成功后 `user_order_delivery` 空壳(与 V2 一致 1:1)。
- **状态推进**(任选其一,推荐 A+B):
- **A. 自动任务**`MOCK_DELIVERY_AUTO=true` 时,支付成功 30s 后 BullMQ 任务:`PENDING_SHIP → OUT_WAREHOUSE → SHIPPING → PENDING_RECEIVE → COMPLETED`,并写 `common_event(ORDER_STATUS)`
- **B. 合伙人手动**`POST /partner/orders/:id/mock-advance-delivery`(preV1 专用,V2 可保留为内部测试接口或 Flag 保护)。
- **user_order** 冗余时间字段 `shipped_at` / `completed_at``user_order_delivery.shipping_at` / `delivered_at` **双写**(同 V2)。
### 1.6 跳过支付
- **不调用**:微信统一下单、支付回调验签。
- **用户侧**:确认订单页按钮文案可为「提交订单(Mock 支付)」;仍调用 **`POST /trade/orders/:id/pay`**(路径与 V2 相同)。
- **服务端**`MOCK_PAY=true``PayService` 同步:
1. `user_order.pay_status=PAID``paid_at=NOW()``pay_external_no='MOCK-{orderNo}'`
2. 可选写 `log_third_party(WECHAT_PAY, scene=ORDER_PAY, status=SUCCESS, external_no=MOCK-...)`
3. 订单 `status=PENDING_SHIP` + `common_event(ORDER_STATUS)`
4. 调用 `BenefitService.grantOnOrderPaid(orderId)`(**真实发券逻辑,非 Mock**)
5. 预创建 `user_order_delivery`
- V2 切换:`MOCK_PAY=false` 时走 `wechatpay-node-v3` + `/callbacks/wechat/pay`
---
# §2、三端 H5 与仓库结构
preV1 Monorepo(在 V2 目标结构上演进,**暂不建 mini-* / mini-hq**):
```
dukang/
├── apps/
│ ├── h5-user/ # C端 H5Taro H5 或 Vite+React,与 V2 技术栈一致即可)
│ ├── h5-shop/ # 门店 H5
│ └── h5-partner/ # 合伙人 H5
├── packages/
│ ├── shared-types/ # 含 USER_H5 / PARTNER_H5 / SHOP_H5
│ └── domain/
├── server/dukang-api/ # 同 V2 单体 NestJS
├── pages/{user,shop,partner}/ # UI 参照(hq 仅 V2 用)
├── 杜康好客-V2编码手册.md
└── 杜康好客-preV1编码手册.md # 本文
```
**请求头**:各 H5 固定 `X-Client-App: USER_H5 | SHOP_H5 | PARTNER_H5`
**页面实现**:字段、Tab、跳转以 V2 手册 §二、§三 原型为准;C 端订单 **5 Tab(含待发货)** 不变。
---
# §3、认证 Mock(无微信)
### 3.1 实现的登录路径
| 端 | 发送验证码 | 登录 |
|----|------------|------|
| C端 | `POST /auth/sms/send` scene=`USER_LOGIN` | `POST /auth/login/sms` |
| 门店 | `POST /auth/sms/send` scene=`STORE_LOGIN` | `POST /shop/auth/login/sms` |
| 合伙人 | `POST /auth/sms/send` scene=`PARTNER_LOGIN` | `POST /partner/auth/login/sms` |
### 3.2 preV1 不实现的登录路径
| 路径 | preV1 行为 |
|------|------------|
| `POST /auth/login/wechat` | 501 或 Flag 关闭 |
| `POST /auth/wechat/bind-phone` | 501 |
| `POST /shop/auth/login/wechat` | 501 |
| `POST /partner/auth/login/wechat` | 501 |
| `POST /admin/auth/*` | 不暴露给前端(无 HQ 端) |
### 3.3 实现要点(便于 V2 切换)
```typescript
// packages/shared-types 或 server config
export const AppConfig = {
mockSms: process.env.MOCK_SMS === 'true',
mockSmsCode: process.env.MOCK_SMS_CODE ?? '123456',
mockPay: process.env.MOCK_PAY === 'true',
mockDeliveryAuto: process.env.MOCK_DELIVERY_AUTO === 'true',
};
// AuthService — 单一验证码入口,V2 只改内部实现
async verifySmsCode(phone: string, code: string, scene: string) {
if (AppConfig.mockSms && code === AppConfig.mockSmsCode) return;
// V2: 查 Redis / log_third_party / 真实短信平台
}
```
---
# §4、支付 Mock
### 4.1 用户流程(与 V2 UI 一致,跳过收银台)
```
确认订单 → POST /trade/orders(锁单 PENDING_PAY
→ POST /trade/orders/:id/pay
[MOCK_PAY=true] 同步成功,无跳转微信
→ 订单列表可见「待发货」
→ 权益页可见新券
```
### 4.2 字段与表(与 V2 相同)
| 写入 | 说明 |
|------|------|
| `user_order.pay_status` | `PAID` |
| `user_order.paid_at` | 当前时间 |
| `user_order.pay_external_no` | `MOCK-{orderNo}` |
| `user_order.status` | `PENDING_SHIP` |
| `log_third_party` | 可选 MOCK 记录,便于 V2 对账逻辑联调 |
| `user_benefit_coupon` + `common_event(BENEFIT_LEDGER,GRANT)` | **真实业务**,非 Mock |
### 4.3 preV1 不做的支付相关能力
- 微信 prepay 参数、支付回调、`/callbacks/wechat/pay` 验签(路由保留,Mock 模式不触发)。
- 退款微信 APIpreV1 **整模块可跳过**(§7);表与 `common_ticket(REFUND)` 仍保留。
---
# §5、配送与订单状态 Mock
### 5.1 自动推进状态机(推荐默认开启)
`MOCK_DELIVERY_AUTO=true` 时,支付成功后注册延时任务:
| 延时 | from → to | 配送表 |
|------|-----------|--------|
| T+0 | `PENDING_SHIP``OUT_WAREHOUSE` | `out_warehouse_at` |
| T+10s | → `SHIPPING` | `shipping_at``user_order.shipped_at` |
| T+30s | → `PENDING_RECEIVE` | — |
| T+60s | → `COMPLETED` | `delivered_at``user_order.completed_at` |
每次 transition 写 `common_event(ORDER_STATUS)``provider``MANUAL``MOCK`
### 5.2 合伙人端手动推进(可选)
`POST /partner/orders/:id/mock-advance-delivery`
- Guard`PartnerAuth` + 订单 `city_id` 属合伙人辖区。
- Body`{ targetStatus: 'SHIPPING' | 'COMPLETED' | ... }`
- preV1 专用;V2 生产环境 `MOCK_DELIVERY=false` 时返回 403。
### 5.3 改址拦截(preV1 简化)
- V2 PRD:用户改址 → 合伙人拦截配送。
- preV1`PUT /trade/orders/:id/address` **仅更新** `user_order` 收货字段 + `common_event`;**不**调第三方、不建复杂 intercept 表(V2 仍用 `common_ticket(ALERT)`preV1 可省略工单)。
---
# §6、无总部端:能力替代
HQ 能力在 preV1 通过 **Seed + 合伙人 H5 子集 + 可选内部 API** 覆盖,**表结构不删**。
### 6.1 启动 Seed`prisma/seed-prev1.ts` 或 SQL
| 数据 | 内容 |
|------|------|
| `common_city` | 郑州 `ACTIVE``local_min_qty=2``cross_min_qty=6` |
| `common_city_commission_rule` | 默认佣金比例 |
| `common_product_item` | 4 款清香型 `ON_SALE`,含 `barcode_69` |
| `common_store_category` | 火锅/地方菜等 |
| `partner_partner` + `partner_account` | 郑州合伙人 + 主账号 `13700000001` |
| `store_store` + `store_account` | 至少 2 家 `OPEN` 门店 |
| `user_user` | 测试用户 `13800000001` |
| `hq_account` | 可 Seed 1 条供未来 V2preV1 无 UI |
商品图/门头图:preV1 可用 **占位 URL**`common_resource` 写死 CDN;V2 换 OSS 上传流程即可。
### 6.2 原 HQ 功能 → preV1 替代
| V2 HQ 功能 | preV1 替代 |
|------------|------------|
| 开城 / 商品 CRUD | **Seed 固定**;变更改 Seed 或直连 DB(开发环境) |
| 门店审核 | 合伙人提交后 **`AUTO_APPROVE_STORE=true` 自动通过**,写 `common_event(STORE_AUDIT,APPROVED)` |
| 订单中心 / 发货 | 合伙人 H5 看辖区订单;跨城发货 preV1 跳过或 Mock 运单号 |
| 推广码 | **跳过 UI**`channel_source` 可手填或 Seed 一条 `common_promo_code` |
| 退款 / 客服工单 | **跳过**(或合伙人 H5 仅查看,不发起微信退款) |
| 结算中心 T+1/T+30 | **Mock 状态**:核销后 `store_payout.status=PENDING`;合伙人 `partner_bill` 可 Seed 一条 `CONFIRMED` 演示 |
| 数据报表 / 埋点 | 埋点 **可写 `log_user_analytics`**;总部报表 **不做** |
### 6.3 合伙人 H5 在 preV1 的扩展(承接部分 HQ)
在 V2 合伙人 API 基础上,preV1 **额外开放**Flag 保护):
| 能力 | 说明 |
|------|------|
| 门店审核自动通过 | 配置项,非新表 |
| Mock 推进配送 | §5.2 |
| 查看辖区订单 | V2 已有 `GET /partner/orders` |
---
# §7、preV1 功能清单
### 7.1 必做(跑通主链路)
| 模块 | 功能 | V2 预留 |
|------|------|---------|
| IAM | 三端短信 Mock 登录 | 微信登录路由保留 |
| Catalog | 读商品/开城(Seed | `/admin/products` 未实现 |
| Trade | 预览、下单、Mock 支付、5 Tab 订单、改址 | 真实微信支付 |
| Benefit | 发券、券列表、明细 | 同 V2 |
| Redeem | Redis 核销码、门店扫码确认、评价 | 同 V2 |
| Store | C 端门店列表/详情;合伙人录店;**自动审核** | HQ 人工审核 |
| Settlement | 核销后 `store_payout` PENDING | T+1 打款任务可 Mock 为手动改 PAID |
| Analytics | 可选:批量写 `log_user_analytics` | 同 V2 |
### 7.2 preV1 明确跳过(V2 补)
| 模块 | 跳过内容 |
|------|----------|
| HQ 端 | 全部页面与 AdminAuth 前端 |
| 微信 | 登录、支付、退款、订阅消息 |
| 第三方 | 小飞侠、物流、真实短信 |
| 运营 | 退款工单、推广码管理 UI、总部报表 |
| 合伙人 | 拦截配送完整流程、T+30 真实打款、提现 |
| 小程序 | 全部(preV1 仅 H5 |
### 7.3 业务规则(与 V2 相同,Mock 不减免)
- 同城起购 **2 瓶** / 跨城 **6 瓶**`packages/domain`
- 权益金额 `benefit_amount ?? price`
- 核销上限 **¥500**Redis 码 **5 分钟**
- C 端门店仅 **`OPEN`**
- 订单 **5 Tab**(含 `pending_ship`
---
# §8、Feature Flag 与 V2 切换
### 8.1 环境变量(`.env.example`
```bash
# preV1 Mock 开关(true = Mock 模式)
MOCK_SMS=true
MOCK_SMS_CODE=123456
MOCK_PAY=true
MOCK_DELIVERY_AUTO=true
AUTO_APPROVE_STORE=true
# V2 就绪后逐项 false,并配置真实密钥
WECHAT_PAY_ENABLED=false
WECHAT_AUTH_ENABLED=false
XFX_ENABLED=false
SMS_PROVIDER=mock
```
### 8.2 切换检查表(preV1 → V2
| 步骤 | 动作 |
|------|------|
| 1 | `MOCK_PAY=false`,配置商户号,启用 `/callbacks/wechat/pay` |
| 2 | `MOCK_SMS=false`,接入短信,`log_third_party(SMS)` |
| 3 | `MOCK_DELIVERY_AUTO=false`,对接小飞侠/物流回调 |
| 4 | `AUTO_APPROVE_STORE=false`,上线 `apps/mini-hq` + 门店审核 |
| 5 | 新增 `apps/mini-user``apps/mini-partner``X-Client-App` 改 MINI |
| 6 | `WECHAT_AUTH_ENABLED=true`,实现 wechat 登录/bind-phone |
| 7 | 启用退款、结算 Job、推广码 HQ 页面 |
### 8.3 代码组织(避免 Mock 散落)
```
server/dukang-api/src/
├── integrations/
│ ├── sms/
│ │ ├── sms.interface.ts # ISmsProvider
│ │ ├── sms.mock.provider.ts # preV1
│ │ └── sms.aliyun.provider.ts # V2
│ ├── pay/
│ │ ├── pay.interface.ts
│ │ ├── pay.mock.provider.ts
│ │ └── pay.wechat.provider.ts
│ └── delivery/
│ ├── delivery.interface.ts
│ ├── delivery.mock.provider.ts
│ └── delivery.xfx.provider.ts
```
`TradeModule` / `AuthModule` 只依赖 **interface**,由 `ConfigModule` 注入 Mock 或 Real 实现。
---
# §9、preV1 里程碑与任务卡
> 详细 API/表结构见 V2 手册 §五、§六;任务 ID 前缀 **`P1-`**,与 V2 `M0~M6` 并行命名空间。
| 里程碑 | 交付 | 出口标准 |
|--------|------|----------|
| **P1-M0** | Monorepo 三 H5 + API 骨架 + Seed | 三端登录页、`GET /health`、Seed 郑州+4 SKU |
| **P1-M1** | IAM Mock + 商品/门店读 | 三端 Mock 登录;C 端首页 4 款酒 |
| **P1-M2** | 下单 + Mock 支付 + 5 Tab 订单 | 2 瓶起购;支付后待发货+发券 |
| **P1-M3** | 权益 + 核销 + 门店 H5 | 端到端核销;`store_payout` PENDING |
| **P1-M4** | 合伙人录店 + 自动审核 | C 端可见新门店 |
| **P1-M5** | Mock 配送自动推进 | 订单可到已完成 |
| **P1-M6** | 埋点可选 + 联调修复 | 主链路冒烟通过 |
### 任务卡(精简)
| ID | 任务 | 验收 |
|----|------|------|
| P1-M0-001 | pnpm workspace + `h5-user/shop/partner` | 三端 `dev` 可编译 |
| P1-M0-002 | `shared-types` + Mock Flags | 导出 `AppConfig` |
| P1-M0-003 | NestJS + Prisma + `init_v3.sql` | `prisma validate` |
| P1-M0-004 | `seed-prev1.ts` | 郑州/4SKU/测试账号 |
| P1-M1-001 | `SmsMockProvider` + 三端 login/sms | 123456 登录 |
| P1-M1-002 | C 端首页/详情 Public catalog | 对照 `pages/user/2,3` |
| P1-M2-001 | preview + create order | 起购校验 |
| P1-M2-002 | `PayMockProvider` + grant benefit | Mock 支付发券 |
| P1-M2-003 | 订单 5 Tab | `pending_ship` 有数据 |
| P1-M3-001 | 权益页 + redeem token | ¥500 上限 |
| P1-M3-002 | 门店扫码核销 | `pages/shop/3~5` |
| P1-M4-001 | 合伙人录店 + AUTO_APPROVE | C 端门店可见 |
| P1-M5-001 | `DeliveryMockProvider` 自动推进 | 订单 COMPLETED |
---
# §10、API / 数据行为差异速查
| API / 行为 | V2 | preV1 |
|------------|-----|-------|
| `X-Client-App` | USER_MINI / … | USER_H5 / SHOP_H5 / PARTNER_H5 |
| `/admin/*` | AdminAuth 小程序 | 无前端;Seed/脚本 |
| `/auth/login/wechat` | 实现 | 501 或 Flag 关 |
| `/auth/sms/send` | 真实短信 | 固定码,不外呼 |
| `/trade/orders/:id/pay` | 微信 prepay | 同步 Mock 成功 |
| `/callbacks/wechat/pay` | 验签回调 | 不触发 |
| `/callbacks/xfx/delivery` | 配送回调 | 不触发 |
| `log_third_party` | 真实流水 | 可选 MOCK 行或跳过 |
| 门店审核 | HQ 审 | `AUTO_APPROVE_STORE` |
| 退款 | HQ 工单+微信退款 | **跳过** |
| 推广码 UI | HQ | **跳过** |
| 核销 / 权益 / 订单表 | 真实 | **真实(同 V2** |
---
## 原型参照(preV1 仍用 V2 映射)
| H5 App | 原型目录 |
|--------|----------|
| h5-user | `pages/user/` |
| h5-shop | `pages/shop/` |
| h5-partner | `pages/partner/` |
C 端订单列表:**5 Tab(含待发货)**;个人中心无会员标签;城市示例以 **郑州** 为准。
---
*preV1 为 V2 的 Mock 联调阶段;完整 PRD、DB DDL、全量 API 见 [`杜康好客-V2编码手册.md`](./杜康好客-V2编码手册.md)。*