+119
-75
@@ -1,101 +1,145 @@
|
||||
# 杜康好客 · v3.5.4 商品规格(SPU + SKU)
|
||||
# 杜康好客 · v3.5.4 开发文档
|
||||
|
||||
> **2026-08-21** · mini-user / admin-web / h5-partner / API / Prisma
|
||||
> 目标:商品详情页内可选销售规格;价格、权益、69 码、履约、上下架按 SKU;箱装按瓶当量起购与物流。
|
||||
> **生产 commit**:`5fdddae`(规格主图与门店使用规则合并入 `main`)及后续客户端版本号 `3.5.4`
|
||||
> **主题**:商品规格(SPU + SKU)上线 + 同批次发票 / 文案 / 门店详情体验
|
||||
|
||||
## 范围
|
||||
---
|
||||
|
||||
| # | 项 | 交付 |
|
||||
## 1. 版本目标
|
||||
|
||||
1. 商品由单规格升级为 **SPU + 多 SKU**:价格、权益、69 码、履约、上下架、主图按规格。
|
||||
2. 箱装按 **瓶当量** 起购与物流,不改城市起购阈值口径。
|
||||
3. **旧客户端兼容**:不传 `skuId` 仍可下单;无 SKU 回落 SPU,禁止「商品暂无可售规格」误伤。
|
||||
4. 同批次补齐:发票品类、权益文案、收银台 logo、门店详情「使用规则」、C 端版本号。
|
||||
|
||||
**不做**:SKU 库存、把现有酒祖 10/15/20 合并为一个 SPU。
|
||||
|
||||
---
|
||||
|
||||
## 2. 功能清单(完整)
|
||||
|
||||
### 2.1 商品规格(核心)
|
||||
|
||||
| # | 模块 | 交付说明 |
|
||||
|---|------|----------|
|
||||
| 1 | 数据模型 | `common_product_item` 作 SPU;新增 `spec_attr` / `spec_value` / `sku` / `sku_spec`;订单快照 `sku_id` / `sale_unit` / `bottles_per_unit` |
|
||||
| 2 | 存量迁移 | 每商品默认 1 个瓶装 SKU;SQL `migrate-product-sku-v354.sql`;脚本 `backfill-product-skus.ts` |
|
||||
| 3 | Catalog | 列表 `specEnabled`/`saleUnit`;详情 `specAttrs`/`skus`/`defaultSkuId`;旧字段拍平保留 |
|
||||
| 4 | Trade | preview/create 可选 `skuId`;有可售 SKU → 默认/唯一;**0 可售 → 回落 SPU**;订单 `sku_id` 可空 |
|
||||
| 5 | Domain | 起购/大单/物流按 `quantity × bottlesPerUnit` 瓶当量 |
|
||||
| 6 | Admin | `PUT .../specs`、`PUT .../skus`;抽屉加宽;「填写」弹窗;规格轴 + SKU 矩阵 |
|
||||
| 7 | mini-user | 详情规格 chips;确认页带 `skuId`;箱装数量文案;选规格切主图 |
|
||||
| 8 | 代下单 | HQ / 合伙人可选规格 SKU |
|
||||
|
||||
### 2.2 SKU 码与 69 码
|
||||
|
||||
| # | 项 | 说明 |
|
||||
|---|----|------|
|
||||
| 1 | 数据模型 | `common_product_item` 升级为 SPU;新增 `spec_attr` / `spec_value` / `sku` / `sku_spec`;订单快照 `sku_id` / `sale_unit` / `bottles_per_unit` |
|
||||
| 2 | 存量迁移 | 每商品 1 个默认瓶装 SKU;SQL:`prisma/migrate-product-sku-v354.sql`;脚本:`prisma/backfill-product-skus.ts` |
|
||||
| 3 | Catalog | 列表附加 `specEnabled`/`saleUnit`;详情附加 `specAttrs`/`skus`/`defaultSkuId`;旧字段拍平保留 |
|
||||
| 4 | Trade | preview/create 可选 `skuId`;无 SKU 回落 SPU;有可售 SKU 用默认/唯一 |
|
||||
| 5 | Admin | `PUT /admin/products/:id/specs`、`PUT .../skus`;商品抽屉加宽;规格弹窗填写;每规格主图 |
|
||||
| 6 | mini-user | 详情规格 chips;选规格切主图;确认页带 `skuId`;箱装数量文案 |
|
||||
| 7 | 代下单 | HQ / 合伙人可选规格 SKU |
|
||||
| 8 | 权益文案 | 「好客权益券」→「好客权益」;首页角标「享{amount}好客权益」(去掉门店 icon) |
|
||||
| 9 | SKU 码 | 系统生成 `DK` + 6 位数字,后台不可填;每规格独立 69 码 |
|
||||
| 10 | 规格主图 | `common_product_sku.image_url` 可选;空则 C 端回落商品封面 |
|
||||
| 9 | SKU 码 | 系统生成 `DK` + 6 位数字,后台不可手填;脚本 `rewrite-sku-codes-dk.ts` 改存量 |
|
||||
| 10 | 69 码 | **每规格独立**;同商品内 + 跨商品唯一;不可与其它 SKU 冲突 |
|
||||
|
||||
**不做**:库存、把现有酒祖 10/15/20 合并为一个 SPU。
|
||||
### 2.3 规格主图
|
||||
|
||||
## 兼容规则(线上)
|
||||
| # | 项 | 说明 |
|
||||
|---|----|------|
|
||||
| 11 | DB | `common_product_sku.image_url`(`migrate-sku-image.sql`) |
|
||||
| 12 | Admin | 弹窗可为每 SKU 上传主图 |
|
||||
| 13 | C 端 | 选规格优先 SKU 主图,空则回落商品封面 |
|
||||
|
||||
- 不改 `/api/v1` 前缀;**只增字段,不删旧字段语义**。
|
||||
### 2.4 发票(同批次)
|
||||
|
||||
| # | 项 | 说明 |
|
||||
|---|----|------|
|
||||
| 14 | 品类 | `user_invoice.invoice_category`:`LIQUOR` 酒水类 / `CATERING` 餐饮类 |
|
||||
| 15 | C 端申请 | 票种写死「增值税普通发票」;类型选酒水/餐饮;备注写入申请 |
|
||||
| 16 | 抬头 | 必填项打 `*`;强调邮箱必填 |
|
||||
| 17 | Admin | 发票列表展示品类;专票仍可走后台 |
|
||||
|
||||
### 2.5 文案与 UI(同批次)
|
||||
|
||||
| # | 位置 | 变更 |
|
||||
|---|------|------|
|
||||
| 18 | 全局权益文案 | 「好客权益券」→「好客权益」 |
|
||||
| 19 | 首页角标 | 「享{amount}好客权益」,去掉门店 icon |
|
||||
| 20 | 商品详情 | 规格区与「好客权益」说明加大间距 |
|
||||
| 21 | 待支付/收银台 | 顶部 logo 用 `logo2.png`(杜康印章) |
|
||||
| 22 | 门店详情 | 「使用规则」红色,置于「门店详情」上方;详情正文限高可滚动 |
|
||||
| 23 | 客户端版本号 | `package.json` + `client-version.ts` → **3.5.4**(「我的」页展示) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 兼容规则(线上)
|
||||
|
||||
- 不改 `/api/v1`;**只增字段,不删旧字段语义**。
|
||||
- 旧客户端不传 `skuId`:
|
||||
- 有 ≥1 个可售 SKU → 用默认(或第一个)可售 SKU
|
||||
- **没有任何可售 SKU(未回填)→ 回落 SPU 字段,照常下单**(禁止再报「商品暂无可售规格」)
|
||||
- 传入 `skuId`(新客户端选规格)→ 按该 SKU 校验。
|
||||
- 旧 admin `PUT /admin/products/:id` 不传规格时:仅同步**唯一**默认 SKU(多规格时不同步,防误改);不同步覆盖已生成的 DK 码。
|
||||
- SPU 上 `sku_code` / `barcode_69` 去掉唯一约束,唯一下沉到 `common_product_sku`;SPU 列保留为默认 SKU 冗余。
|
||||
- 订单 `sku_id` 可空;无规格快照走商品 69 码 / 价格。
|
||||
- ≥1 个可售 SKU → 默认(或第一个)可售 SKU
|
||||
- **0 个可售 SKU → 回落 SPU,照常下单**
|
||||
- 新客户端传 `skuId` → 按该 SKU 校验。
|
||||
- 旧 admin 不传规格:仅同步**唯一**默认 SKU;不覆盖已生成的 DK 码。
|
||||
- SPU 上 `sku_code` / `barcode_69` 唯一约束下沉到 SKU;SPU 列保留冗余。
|
||||
|
||||
## 发版一并执行
|
||||
---
|
||||
|
||||
按顺序在**目标环境库**执行(先测试后生产)。本机 `npx ts-node …` 只改本地 `.env` 库,不会自动打线上。
|
||||
## 4. 发版与生产执行记录
|
||||
|
||||
1. **规格表** `server/dukang-api/prisma/migrate-product-sku-v354.sql`
|
||||
建 spec/sku 表,订单加 `sku_id` / `sale_unit` / `bottles_per_unit`。
|
||||
2. **回填默认 SKU**
|
||||
`cd server/dukang-api && npx ts-node prisma/backfill-product-skus.ts`
|
||||
尚无 SKU 的商品各建 1 条默认瓶装 SKU(码用 DK)。
|
||||
3. **SKU 主图列** `server/dukang-api/prisma/migrate-sku-image.sql`
|
||||
```sql
|
||||
ALTER TABLE `common_product_sku`
|
||||
ADD COLUMN `image_url` VARCHAR(512) NULL AFTER `sort_order`;
|
||||
```
|
||||
4. **SKU 码改 DK**(生产须在服务器用 `.env.production` 的 `DATABASE_URL`)
|
||||
`npx dotenv -e .env.production -- npx ts-node prisma/rewrite-sku-codes-dk.ts`
|
||||
已是 `DK`+数字的不动;`JZ-10` / `QX-001` 等会改。**不改 69 码、订单、价格。**
|
||||
5. **发票品类列**(同批次)`server/dukang-api/prisma/migrate-invoice-category.sql`
|
||||
```sql
|
||||
ALTER TABLE `user_invoice`
|
||||
ADD COLUMN `invoice_category` VARCHAR(16) NOT NULL DEFAULT 'LIQUOR' AFTER `invoice_kind`;
|
||||
```
|
||||
6. 发布 API + mini-user + admin-web。
|
||||
**此时不要给商品加第二规格**,等新小程序上线后再配「单瓶 / 整箱」。
|
||||
按序在目标库执行(先测后产)。本机脚本只打本地 `.env`。
|
||||
|
||||
## 起购与物流
|
||||
| 步骤 | 动作 | 生产状态(2026-08-21) |
|
||||
|------|------|------------------------|
|
||||
| 1 | `migrate-product-sku-v354.sql` / Prisma sync | ✅ `db push` 已对齐 |
|
||||
| 2 | `backfill-product-skus.ts` | ✅ 回填 9 个默认 SKU(扫 10 商品) |
|
||||
| 3 | `migrate-sku-image.sql` / schema `image_url` | ✅ |
|
||||
| 4 | `rewrite-sku-codes-dk.ts` | ✅ 13 条均已 DK,改写 0 |
|
||||
| 5 | `migrate-invoice-category.sql` | ✅ schema 已含 |
|
||||
| 6 | 发 API + mini-user H5 + admin | ✅ `mini-user 200` / `api 200` |
|
||||
| 7 | 微信小程序 weapp 上传 | ⚠️ 需单独上传后「我的」页才见 v3.5.4 |
|
||||
|
||||
运营注意:新包上线前**不要**给商品加第二规格;上线后再配「单瓶 / 整箱」。
|
||||
|
||||
---
|
||||
|
||||
## 5. 起购与物流
|
||||
|
||||
- `bottleQty = quantity × bottlesPerUnit`
|
||||
- 城市起购阈值仍是瓶;箱装 SKU(`bottlesPerUnit=6`)数量 1 即可过同城 2 / 跨城 6。
|
||||
- 大单拦截、承运商 `goodsNum` 使用瓶当量。
|
||||
- 城市起购仍按瓶;箱装(`bottlesPerUnit=6`)数量 1 即可过同城 2 / 跨城 6
|
||||
- 大单拦截、承运商 `goodsNum` 用瓶当量
|
||||
|
||||
## 关键表摘要
|
||||
---
|
||||
|
||||
## 6. 关键表 / 字段摘要
|
||||
|
||||
- `common_product_spec_attr` / `common_product_spec_value`
|
||||
- `common_product_sku`(`sale_unit`=`BOTTLE|BOX`,`bottles_per_unit`,`image_url` 可选)
|
||||
- `common_product_sku`(`sale_unit`、`bottles_per_unit`、`image_url`)
|
||||
- `common_product_sku_spec`
|
||||
- `user_order.sku_id` / `sale_unit` / `bottles_per_unit`
|
||||
- `user_invoice.invoice_category`:`LIQUOR` 酒水类 / `CATERING` 餐饮类;票种 C 端固定增值税普通发票
|
||||
- `user_invoice.invoice_category`
|
||||
|
||||
## SKU 码与 69 码
|
||||
---
|
||||
|
||||
- SKU 码:服务端生成 `DK000001` 起,后台只展示。
|
||||
- 每个规格必须填写**互不相同**的 69 码(全局不可与其它商品 SKU 冲突)。
|
||||
- 总部「规格与 SKU」点「填写」弹窗编辑 69 码 / 价 / 履约 / 主图。
|
||||
## 7. 关键路径(便于排查)
|
||||
|
||||
## 权益与小程序 UI(同批次)
|
||||
| 域 | 路径 |
|
||||
|----|------|
|
||||
| Prisma / 脚本 | `server/dukang-api/prisma/migrate-product-sku-v354.sql`、`backfill-product-skus.ts`、`rewrite-sku-codes-dk.ts`、`migrate-sku-image.sql`、`migrate-invoice-category.sql` |
|
||||
| 规格工具 | `server/.../catalog/product-sku.util.ts` |
|
||||
| Admin 规格 | `apps/admin-web/src/components/ProductSpecsEditor.tsx` |
|
||||
| C 端详情 | `apps/mini-user/src/pages/product-detail/` |
|
||||
| 版本号 | `apps/mini-user/src/lib/client-version.ts` |
|
||||
| 门店详情 | `apps/mini-user/src/pages/store-detail/` |
|
||||
| 发票 | `apps/mini-user/src/pages/invoice-apply/`、`invoice-titles/` |
|
||||
|
||||
| 位置 | 变更 |
|
||||
|------|------|
|
||||
| 门店详情等 | 「好客权益券」→「好客权益」 |
|
||||
| 首页商品角标 `CouponBadge` | 纯文案 **「享{amount}好客权益」**,无门店 icon |
|
||||
| 商品详情 | 规格区与「好客权益」说明之间加大间距 |
|
||||
| 待支付 / 收银台 | 顶部 logo 使用 `public/images/logo2.png`(杜康印章) |
|
||||
| 门店详情 | 「使用规则」四字红色,放在「门店详情」**上面**;门店详情正文限高,超出上下滚动 |
|
||||
| 发票申请 | 票种写死增值税普通发票;类型选酒水类/餐饮类;申请备注;抬头邮箱必填打 `*` |
|
||||
---
|
||||
|
||||
其它页 `BenefitFigure`(我的/权益/核销等)仍保留门店核销图标,仅首页角标去 icon。
|
||||
## 8. 验收清单
|
||||
|
||||
## 验收
|
||||
|
||||
- [ ] 未配规格:旧小程序/H5/代下单路径与现网一致(无 SKU 也能下单)
|
||||
- [ ] 多规格:详情选规格后价格/权益/履约/主图变化
|
||||
- [ ] 整箱 SKU:数量 1 过起购;订单快照 `bottles_per_unit=6`
|
||||
- [ ] `GET /catalog/products/:id` 仍含 `id/name/price/spec/skuCode/...`
|
||||
- [ ] 小程序无「好客权益券」字样;首页角标为「享{金额}好客权益」且无门店 icon
|
||||
- [ ] 后台 SKU 码为 DK 开头且不可手填;每规格独立 69 码与主图
|
||||
- [ ] 门店详情「使用规则」红色且在门店详情上方;门店详情超长可滚动
|
||||
- [ ] 待支付页顶部为 logo2 印章
|
||||
- [ ] 未配规格:旧端下单与现网一致(无 SKU 也能下)
|
||||
- [ ] 多规格:选规格后价格/权益/履约/主图变化;漏选 400
|
||||
- [ ] 整箱:数量 1 过起购;订单 `bottles_per_unit=6`
|
||||
- [ ] 详情 API 仍含 `id/name/price/spec/skuCode/...`
|
||||
- [ ] 后台 SKU 码 DK 开头不可手填;每规格独立 69 码与主图
|
||||
- [ ] 无「好客权益券」;首页角标「享{金额}好客权益」无门店 icon
|
||||
- [ ] 门店详情「使用规则」红色且在详情上方;详情超长可滚
|
||||
- [ ] 待支付页为 logo2 印章
|
||||
- [ ] 发票:普票固定 + 酒水/餐饮品类 + 邮箱必填
|
||||
- [ ] 「我的」页版本 **杜康好客 v3.5.4**(需 weapp 新包)
|
||||
|
||||
Reference in New Issue
Block a user