Files
medical-mall/docs/sql/07_business_workflows.md

334 lines
7.7 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.
# 07 典型业务流程:落表路径与关键字段
本节用“业务步骤 → 涉及表 → 关键字段/约束/触发器”的方式,把核心链路讲清楚,方便新同事快速理解数据如何流动。
---
## 1. 商品发布与上架流程(商家侧)
### 1.1 创建 SPU商品主表
- **写入表**`ml_products`
- **关键字段**
- `merchant_id`:商家用户(关联 `ak_users.id`
- `category_id/brand_id`
- `base_price`
- `status`:初始可为草稿(3)或上架(1)
- `cid/slug`:对外访问
示例(简化):
```sql
insert into public.ml_products(
merchant_id, category_id, product_code, name, base_price, status
)
values (
'...merchant_uuid...'::uuid,
'...category_uuid...'::uuid,
'P20260001',
'苹果手机',
4999.00,
3
)
returning id, cid;
```
### 1.2 定义规格项(可选)
- **写入表**`ml_product_specs`
- **关键字段**`spec_name``spec_values JSONB`
示例:
```sql
insert into public.ml_product_specs(product_id, spec_name, spec_values)
values
('...product_uuid...'::uuid, '颜色', '["黑","白"]'::jsonb),
('...product_uuid...'::uuid, '容量', '["128G","256G"]'::jsonb);
```
### 1.3 创建 SKU库存与具体价格
- **写入表**`ml_product_skus`
- **关键字段**`specifications JSONB``price``stock``status`
- **数据库规则**
- SKU 变更会触发 `update_product_stock()`,自动汇总刷新 `ml_products.total_stock/available_stock`
示例:
```sql
insert into public.ml_product_skus(product_id, sku_code, specifications, price, stock)
values
(
'...product_uuid...'::uuid,
'SKU-001',
'{"颜色":"黑","容量":"128G"}'::jsonb,
4999.00,
10
);
-- 插入 SKU 后,触发器会把商品 total_stock/available_stock 更新为 10
```
### 1.4 上架商品
- **更新表**`ml_products`
- **关键字段**`status = 1``published_at`(若使用)
示例:
```sql
update public.ml_products
set status = 1, published_at = now()
where id = '...product_uuid...'::uuid;
```
---
## 2. 浏览与收藏(用户侧)
### 2.1 浏览记录
- **写入表**`ml_browse_history`
- **约束**`UNIQUE(user_id, product_id)`
- **含义**:倾向记录“最后一次浏览”而不是“浏览流水”。
典型写法:
- 插入失败后转更新upsert
```sql
insert into public.ml_browse_history(user_id, product_id, browse_duration)
values ('...user_uuid...'::uuid, '...product_uuid...'::uuid, 20)
on conflict (user_id, product_id)
do update set browse_duration = excluded.browse_duration, updated_at = now();
```
### 2.2 收藏
- **写入表**`ml_user_favorites`
- **约束**`UNIQUE(user_id, target_type, target_id)`
```sql
insert into public.ml_user_favorites(user_id, target_type, target_id)
values ('...user_uuid...'::uuid, 1, '...product_uuid...'::uuid)
on conflict do nothing;
```
---
## 3. 加购与结算(用户侧)
### 3.1 加入购物车
- **写入表**`ml_shopping_cart`
- **约束**`UNIQUE(user_id, product_id, sku_id)`
常见做法:重复加购时做累加:
```sql
insert into public.ml_shopping_cart(user_id, product_id, sku_id, quantity, selected)
values ('...user_uuid...'::uuid, '...product_uuid...'::uuid, '...sku_uuid...'::uuid, 1, true)
on conflict (user_id, product_id, sku_id)
do update set quantity = public.ml_shopping_cart.quantity + 1, updated_at = now();
```
### 3.2 计算购物车金额
- **读取函数**`public.calculate_cart_total(p_user_id)`
```sql
select public.calculate_cart_total('...user_uuid...'::uuid);
```
---
## 4. 下单(创建订单 + 明细快照)
### 4.1 订单号生成
- **函数**`public.generate_order_no()`(基于 `ml_order_seq`
```sql
select public.generate_order_no();
```
### 4.2 创建订单主表(地址快照)
- **写入表**`ml_orders`
- **关键字段**
- `shipping_address JSONB`:下单时把地址“快照化”写进订单
- `order_status/payment_status/shipping_status`
示例(简化):
```sql
insert into public.ml_orders(
order_no, user_id, merchant_id,
product_amount, discount_amount, shipping_fee, total_amount,
shipping_address,
order_status, payment_status, shipping_status
)
values (
public.generate_order_no(),
'...user_uuid...'::uuid,
'...merchant_uuid...'::uuid,
4999.00, 0.00, 10.00, 5009.00,
'{"receiver":"张三","phone":"138...","province":"广东","city":"深圳","district":"南山","detail":"xxx"}'::jsonb,
1, 1, 1
)
returning id;
```
### 4.3 创建订单明细(商品快照)
- **写入表**`ml_order_items`
- **关键点**:把 `product_name/sku_name/specifications/image_url/price` 等写入明细,防止商品后改影响历史。
```sql
insert into public.ml_order_items(
order_id, product_id, sku_id,
product_name, sku_name, specifications, image_url,
price, quantity, total_amount
)
values (
'...order_uuid...'::uuid,
'...product_uuid...'::uuid,
'...sku_uuid...'::uuid,
'苹果手机',
'黑/128G',
'{"颜色":"黑","容量":"128G"}'::jsonb,
'https://.../1.png',
4999.00,
1,
4999.00
);
```
> 注意:当前可见 SQL 未体现“扣库存/冻结库存”动作,通常需要在同一事务中由应用层或额外 DB 函数完成(详见 `08_data_consistency_boundaries.md`)。
---
## 5. 支付、发货、完成(状态流转)
### 5.1 支付完成
- **更新表**`ml_orders`
- **预期**`order_status: 1 -> 2`,并写 `paid_amount/payment_status`
- **数据库副作用complete 脚本)**:触发器 `handle_order_status_change()` 自动写 `paid_at`
```sql
update public.ml_orders
set order_status = 2,
payment_status = 2,
paid_amount = total_amount
where id = '...order_uuid...'::uuid;
```
### 5.2 发货
```sql
update public.ml_orders
set order_status = 3,
shipping_status = 2
where id = '...order_uuid...'::uuid;
-- complete 脚本的触发器会在 2->3 时写 shipped_at
```
### 5.3 收货完成
```sql
update public.ml_orders
set order_status = 4,
shipping_status = 4
where id = '...order_uuid...'::uuid;
-- complete 脚本触发器在 3->4 时写 delivered_at/completed_at并累计商品 sale_count
```
---
## 6. 评价
- **写入表**`ml_product_reviews`
- **约束设计**:强绑定 `order_id``order_item_id`,保证评价来自真实订单。
```sql
insert into public.ml_product_reviews(
order_id, order_item_id, user_id, product_id, merchant_id,
rating, content, images
)
values (
'...order_uuid...'::uuid,
'...order_item_uuid...'::uuid,
'...user_uuid...'::uuid,
'...product_uuid...'::uuid,
'...merchant_uuid...'::uuid,
5,
'很好用',
'["https://.../a.png"]'::jsonb
);
```
---
## 7. 优惠券:发放与使用
### 7.1 领券
- **写入表**`ml_user_coupons`
- **券码**:可使用 `generate_coupon_code()` 生成
```sql
insert into public.ml_user_coupons(user_id, template_id, coupon_code, status, expire_at)
values (
'...user_uuid...'::uuid,
'...template_uuid...'::uuid,
public.generate_coupon_code(),
1,
now() + interval '30 days'
);
```
### 7.2 用券归因
```sql
update public.ml_user_coupons
set status = 2,
used_at = now(),
order_id = '...order_uuid...'::uuid
where id = '...user_coupon_uuid...'::uuid
and status = 1;
```
---
## 8. 订阅:开通/续费/到期
### 8.1 创建套餐
- `ml_subscription_plans`
```sql
insert into public.ml_subscription_plans(plan_code, name, price, billing_period)
values ('PRO_MONTH', '专业版(月付)', 99.00, 'monthly');
```
### 8.2 用户订阅
- `ml_user_subscriptions`
```sql
insert into public.ml_user_subscriptions(user_id, plan_id, status, start_date, next_billing_date)
values (
'...user_uuid...'::uuid,
'...plan_uuid...'::uuid,
'trial',
now(),
now() + interval '30 days'
);
```
> 说明:订阅模块脚本未与 `ml_orders` 建立外键关联,支付/对账链路通常在应用层或另一个交易子系统实现。