# 02 关系与 ER（文字版）

本节用“文字版 ER + 基数（1:1 / 1:N）”描述核心表关系，并提示哪些约束来自数据库（唯一约束/外键/触发器）。

---

## 1. 统一用户体系（复用 `ak_users`）

- `ak_users` 作为统一用户主表，商城域表通过 `user_id/merchant_id` 外键关联。

> 重要前提：RLS 策略通过 `auth.uid()` 映射 `ak_users.auth_id`（详见 `05_rls_permissions_matrix.md`）。因此 `ak_users` 必须具备 `auth_id` 字段并保持唯一性（建议 `unique index`）。

---

## 2. 用户域

### 2.1 `ak_users` 1:1 `ml_user_profiles`

- **关系**：一用户一商城档案
- **依据**：`ml_user_profiles.user_id UNIQUE NOT NULL REFERENCES ak_users(id)`

### 2.2 `ak_users` 1:N `ml_user_addresses`

- **关系**：一个用户多个地址
- **默认地址约束**：同一用户最多一个 `is_default = true`
  - **依据**：触发器 `ensure_single_default_address()`（数据库层自动维护）

---

## 3. 店铺/商家域

### 3.1 `ak_users(merchant)` 1:1 `ml_shops`

- **关系**：一个商家一个店铺（当前模型）
- **依据**：`ml_shops.merchant_id UNIQUE NOT NULL REFERENCES ak_users(id)`

> 影响：订单主表可直接记录 `merchant_id`，无需子订单拆分即可查询店铺信息。

---

## 4. 商品域

### 4.1 `ml_categories` 1:N `ml_categories`（自关联分类树）

- **关系**：父分类包含多个子分类
- **依据**：`ml_categories.parent_id REFERENCES ml_categories(id)`

### 4.2 `ml_categories` 1:N `ml_products`

- **关系**：一个分类包含多个商品
- **依据**：`ml_products.category_id NOT NULL REFERENCES ml_categories(id)`

### 4.3 `ml_brands` 1:N `ml_products`

- **关系**：一个品牌对应多个商品
- **依据**：`ml_products.brand_id REFERENCES ml_brands(id)`（可空）

### 4.4 `ml_products` 1:N `ml_product_skus`

- **关系**：一个商品（SPU）有多个 SKU
- **依据**：`ml_product_skus.product_id NOT NULL REFERENCES ml_products(id) ON DELETE CASCADE`

### 4.5 `ml_products` 1:N `ml_product_specs`

- **关系**：一个商品定义多个规格项
- **依据**：`ml_product_specs.product_id NOT NULL REFERENCES ml_products(id) ON DELETE CASCADE`

### 4.6 库存汇总（触发器关系）

- **事件**：`ml_product_skus` INSERT/UPDATE/DELETE
- **结果**：触发器 `update_product_stock()` 汇总更新 `ml_products.total_stock/available_stock`

---

## 5. 交易域

### 5.1 `ak_users(customer)` 1:N `ml_orders`

- **关系**：用户有多个订单
- **依据**：`ml_orders.user_id NOT NULL REFERENCES ak_users(id)`

### 5.2 `ak_users(merchant)` 1:N `ml_orders`

- **关系**：商家有多个订单
- **依据**：`ml_orders.merchant_id NOT NULL REFERENCES ak_users(id)`

> 当前订单模型为“单商家订单”（`ml_orders` 直接记录 `merchant_id`）。若要支持“一单多商家”，通常需要主/子订单拆分。

### 5.3 `ml_orders` 1:N `ml_order_items`

- **关系**：订单包含多个明细
- **依据**：`ml_order_items.order_id NOT NULL REFERENCES ml_orders(id) ON DELETE CASCADE`

### 5.4 `ml_orders` 1:1 `ml_delivery_tasks`（当前）

- **关系**：一个订单最多一个配送任务
- **依据**：`ml_delivery_tasks.order_id UNIQUE NOT NULL REFERENCES ml_orders(id)`

---

## 6. 营销域

### 6.1 `ml_coupon_templates` 1:N `ml_user_coupons`

- **关系**：一个模板可被多个用户领取
- **依据**：`ml_user_coupons.template_id NOT NULL REFERENCES ml_coupon_templates(id)`

### 6.2 `ml_user_coupons` N:1 `ml_orders`（可选关联）

- **关系**：券在使用时关联订单
- **依据**：`ml_user_coupons.order_id REFERENCES ml_orders(id)`（可空）

---

## 7. 评价域

### 7.1 `ml_orders` 1:N `ml_product_reviews`（概念上）

- **关系**：订单可产生多个评价（通常按明细评价）
- **依据**：`ml_product_reviews.order_id NOT NULL REFERENCES ml_orders(id)`

### 7.2 `ml_order_items` 1:1/N `ml_product_reviews`

- **关系**：明细可对应评价（实现上可以 1:1，也可以允许追评，取决于业务约束）
- **依据**：`ml_product_reviews.order_item_id NOT NULL REFERENCES ml_order_items(id)`

---

## 8. 行为域

- `ak_users` 1:N `ml_user_favorites`
- `ak_users` 1:N `ml_browse_history`
- `ak_users` 0..N `ml_search_history`（可匿名搜索时 user_id 为空）

---

## 9. 订阅域

### 9.1 `ml_subscription_plans` 1:N `ml_user_subscriptions`

- **关系**：一个套餐对应多个用户订阅实例
- **依据**：`ml_user_subscriptions.plan_id REFERENCES ml_subscription_plans(id)`

### 9.2 `ak_users` 1:N `ml_user_subscriptions`

- **关系**：一个用户可有多个订阅记录（例如历史续费、升级降级）
- **依据**：`ml_user_subscriptions.user_id`（当前脚本未声明外键到 `ak_users`，建议在项目侧补齐或在应用层保证一致性）
