docs: 初始化 Docs 仓库
This commit is contained in:
641
Document/03_数据库设计.md
Normal file
641
Document/03_数据库设计.md
Normal file
@@ -0,0 +1,641 @@
|
||||
# 外卖SaaS系统 - 数据库设计
|
||||
|
||||
## 1. 数据库设计原则
|
||||
|
||||
### 1.1 命名规范
|
||||
- **表名**:小写字母,下划线分隔,复数形式(如:`orders`, `order_items`)
|
||||
- **字段名**:小写字母,下划线分隔(如:`created_at`, `total_amount`)
|
||||
- **主键**:统一使用 `id`,类型为 UUID
|
||||
- **外键**:`表名_id`(如:`order_id`, `merchant_id`)
|
||||
- **索引**:`idx_表名_字段名`(如:`idx_orders_merchant_id`)
|
||||
|
||||
### 1.2 通用字段
|
||||
所有表都包含以下字段:
|
||||
- `id`:UUID,主键
|
||||
- `created_at`:TIMESTAMP,创建时间
|
||||
- `updated_at`:TIMESTAMP,更新时间
|
||||
- `deleted_at`:TIMESTAMP,软删除时间(可选)
|
||||
- `tenant_id`:UUID,租户ID(多租户隔离)
|
||||
|
||||
### 1.3 数据类型规范
|
||||
- **金额**:DECIMAL(18,2)
|
||||
- **时间**:TIMESTAMP WITH TIME ZONE
|
||||
- **布尔**:BOOLEAN
|
||||
- **枚举**:VARCHAR 或 INTEGER
|
||||
- **JSON数据**:JSONB
|
||||
|
||||
## 2. 核心表结构
|
||||
|
||||
### 2.1 租户管理
|
||||
|
||||
#### tenants(租户表)
|
||||
```sql
|
||||
CREATE TABLE tenants (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
code VARCHAR(50) UNIQUE NOT NULL,
|
||||
contact_name VARCHAR(50),
|
||||
contact_phone VARCHAR(20),
|
||||
contact_email VARCHAR(100),
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:正常 2:冻结 3:过期
|
||||
subscription_plan VARCHAR(50), -- 订阅套餐
|
||||
subscription_start_date TIMESTAMP WITH TIME ZONE,
|
||||
subscription_end_date TIMESTAMP WITH TIME ZONE,
|
||||
max_merchants INTEGER DEFAULT 10, -- 最大商家数
|
||||
max_orders_per_day INTEGER DEFAULT 1000, -- 每日订单限额
|
||||
settings JSONB, -- 租户配置
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tenants_code ON tenants(code);
|
||||
CREATE INDEX idx_tenants_status ON tenants(status);
|
||||
```
|
||||
|
||||
### 2.2 商家管理
|
||||
|
||||
#### merchants(商家表)
|
||||
```sql
|
||||
CREATE TABLE merchants (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
logo_url VARCHAR(500),
|
||||
description TEXT,
|
||||
contact_phone VARCHAR(20),
|
||||
contact_person VARCHAR(50),
|
||||
business_license VARCHAR(100), -- 营业执照号
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:正常 2:休息 3:停业
|
||||
rating DECIMAL(3,2) DEFAULT 0, -- 评分
|
||||
total_sales INTEGER DEFAULT 0, -- 总销量
|
||||
settings JSONB, -- 商家配置
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_merchants_tenant_id ON merchants(tenant_id);
|
||||
CREATE INDEX idx_merchants_status ON merchants(status);
|
||||
```
|
||||
|
||||
#### merchant_stores(门店表)
|
||||
```sql
|
||||
CREATE TABLE merchant_stores (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
merchant_id UUID NOT NULL REFERENCES merchants(id),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
address VARCHAR(500) NOT NULL,
|
||||
latitude DECIMAL(10,7), -- 纬度
|
||||
longitude DECIMAL(10,7), -- 经度
|
||||
phone VARCHAR(20),
|
||||
business_hours JSONB, -- 营业时间 {"monday": {"open": "09:00", "close": "22:00"}}
|
||||
delivery_range INTEGER DEFAULT 3000, -- 配送范围(米)
|
||||
min_order_amount DECIMAL(18,2) DEFAULT 0, -- 起送价
|
||||
delivery_fee DECIMAL(18,2) DEFAULT 0, -- 配送费
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_merchant_stores_merchant_id ON merchant_stores(merchant_id);
|
||||
CREATE INDEX idx_merchant_stores_location ON merchant_stores USING GIST(point(longitude, latitude));
|
||||
```
|
||||
|
||||
### 2.3 菜品管理
|
||||
|
||||
#### categories(菜品分类表)
|
||||
```sql
|
||||
CREATE TABLE categories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
merchant_id UUID NOT NULL REFERENCES merchants(id),
|
||||
name VARCHAR(50) NOT NULL,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_categories_merchant_id ON categories(merchant_id);
|
||||
```
|
||||
|
||||
#### dishes(菜品表)
|
||||
```sql
|
||||
CREATE TABLE dishes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
merchant_id UUID NOT NULL REFERENCES merchants(id),
|
||||
category_id UUID REFERENCES categories(id),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
image_url VARCHAR(500),
|
||||
price DECIMAL(18,2) NOT NULL,
|
||||
original_price DECIMAL(18,2), -- 原价
|
||||
unit VARCHAR(20) DEFAULT '份', -- 单位
|
||||
stock INTEGER, -- 库存(NULL表示不限)
|
||||
sales_count INTEGER DEFAULT 0, -- 销量
|
||||
rating DECIMAL(3,2) DEFAULT 0, -- 评分
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:上架 2:下架
|
||||
tags JSONB, -- 标签 ["热销", "新品"]
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dishes_merchant_id ON dishes(merchant_id);
|
||||
CREATE INDEX idx_dishes_category_id ON dishes(category_id);
|
||||
CREATE INDEX idx_dishes_status ON dishes(status);
|
||||
```
|
||||
|
||||
#### dish_specs(菜品规格表)
|
||||
```sql
|
||||
CREATE TABLE dish_specs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
dish_id UUID NOT NULL REFERENCES dishes(id),
|
||||
name VARCHAR(50) NOT NULL, -- 规格名称(如:大份、小份)
|
||||
price DECIMAL(18,2) NOT NULL,
|
||||
stock INTEGER,
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dish_specs_dish_id ON dish_specs(dish_id);
|
||||
```
|
||||
|
||||
### 2.4 用户管理
|
||||
|
||||
#### users(用户表)
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
phone VARCHAR(20) UNIQUE NOT NULL,
|
||||
nickname VARCHAR(50),
|
||||
avatar_url VARCHAR(500),
|
||||
gender INTEGER, -- 0:未知 1:男 2:女
|
||||
birthday DATE,
|
||||
balance DECIMAL(18,2) DEFAULT 0, -- 余额
|
||||
points INTEGER DEFAULT 0, -- 积分
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
last_login_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_phone ON users(phone);
|
||||
```
|
||||
|
||||
#### user_addresses(用户地址表)
|
||||
```sql
|
||||
CREATE TABLE user_addresses (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
contact_name VARCHAR(50) NOT NULL,
|
||||
contact_phone VARCHAR(20) NOT NULL,
|
||||
province VARCHAR(50),
|
||||
city VARCHAR(50),
|
||||
district VARCHAR(50),
|
||||
address VARCHAR(500) NOT NULL,
|
||||
house_number VARCHAR(50), -- 门牌号
|
||||
latitude DECIMAL(10,7),
|
||||
longitude DECIMAL(10,7),
|
||||
is_default BOOLEAN DEFAULT FALSE,
|
||||
label VARCHAR(20), -- 标签:家、公司等
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_addresses_user_id ON user_addresses(user_id);
|
||||
```
|
||||
|
||||
### 2.5 订单管理
|
||||
|
||||
#### orders(订单表)
|
||||
```sql
|
||||
CREATE TABLE orders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_no VARCHAR(50) UNIQUE NOT NULL, -- 订单号
|
||||
merchant_id UUID NOT NULL REFERENCES merchants(id),
|
||||
store_id UUID NOT NULL REFERENCES merchant_stores(id),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
|
||||
-- 收货信息
|
||||
delivery_address VARCHAR(500) NOT NULL,
|
||||
delivery_latitude DECIMAL(10,7),
|
||||
delivery_longitude DECIMAL(10,7),
|
||||
contact_name VARCHAR(50) NOT NULL,
|
||||
contact_phone VARCHAR(20) NOT NULL,
|
||||
|
||||
-- 金额信息
|
||||
dish_amount DECIMAL(18,2) NOT NULL, -- 菜品金额
|
||||
delivery_fee DECIMAL(18,2) DEFAULT 0, -- 配送费
|
||||
package_fee DECIMAL(18,2) DEFAULT 0, -- 打包费
|
||||
discount_amount DECIMAL(18,2) DEFAULT 0, -- 优惠金额
|
||||
total_amount DECIMAL(18,2) NOT NULL, -- 总金额
|
||||
actual_amount DECIMAL(18,2) NOT NULL, -- 实付金额
|
||||
|
||||
-- 订单状态
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:待支付 2:待接单 3:制作中 4:待配送 5:配送中 6:已完成 7:已取消
|
||||
payment_status INTEGER DEFAULT 0, -- 0:未支付 1:已支付 2:已退款
|
||||
payment_method VARCHAR(20), -- 支付方式
|
||||
payment_time TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- 时间信息
|
||||
estimated_delivery_time TIMESTAMP WITH TIME ZONE, -- 预计送达时间
|
||||
accepted_at TIMESTAMP WITH TIME ZONE, -- 接单时间
|
||||
cooking_at TIMESTAMP WITH TIME ZONE, -- 开始制作时间
|
||||
delivered_at TIMESTAMP WITH TIME ZONE, -- 送达时间
|
||||
completed_at TIMESTAMP WITH TIME ZONE, -- 完成时间
|
||||
cancelled_at TIMESTAMP WITH TIME ZONE, -- 取消时间
|
||||
|
||||
remark TEXT, -- 备注
|
||||
cancel_reason TEXT, -- 取消原因
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_orders_tenant_id ON orders(tenant_id);
|
||||
CREATE INDEX idx_orders_order_no ON orders(order_no);
|
||||
CREATE INDEX idx_orders_merchant_id ON orders(merchant_id);
|
||||
CREATE INDEX idx_orders_user_id ON orders(user_id);
|
||||
CREATE INDEX idx_orders_status ON orders(status);
|
||||
CREATE INDEX idx_orders_created_at ON orders(created_at);
|
||||
```
|
||||
|
||||
#### order_items(订单明细表)
|
||||
```sql
|
||||
CREATE TABLE order_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_id UUID NOT NULL REFERENCES orders(id),
|
||||
dish_id UUID NOT NULL REFERENCES dishes(id),
|
||||
dish_name VARCHAR(100) NOT NULL, -- 冗余字段,防止菜品被删除
|
||||
dish_image_url VARCHAR(500),
|
||||
spec_id UUID REFERENCES dish_specs(id),
|
||||
spec_name VARCHAR(50),
|
||||
price DECIMAL(18,2) NOT NULL, -- 单价
|
||||
quantity INTEGER NOT NULL, -- 数量
|
||||
amount DECIMAL(18,2) NOT NULL, -- 小计
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
|
||||
CREATE INDEX idx_order_items_dish_id ON order_items(dish_id);
|
||||
```
|
||||
|
||||
### 2.6 配送管理
|
||||
|
||||
#### delivery_drivers(配送员表)
|
||||
```sql
|
||||
CREATE TABLE delivery_drivers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
merchant_id UUID REFERENCES merchants(id), -- NULL表示平台配送员
|
||||
name VARCHAR(50) NOT NULL,
|
||||
phone VARCHAR(20) UNIQUE NOT NULL,
|
||||
id_card VARCHAR(18), -- 身份证号
|
||||
vehicle_type VARCHAR(20), -- 车辆类型:电动车、摩托车
|
||||
vehicle_number VARCHAR(20), -- 车牌号
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:空闲 2:配送中 3:休息 4:离线
|
||||
current_latitude DECIMAL(10,7), -- 当前位置
|
||||
current_longitude DECIMAL(10,7),
|
||||
rating DECIMAL(3,2) DEFAULT 0,
|
||||
total_deliveries INTEGER DEFAULT 0, -- 总配送单数
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_delivery_drivers_merchant_id ON delivery_drivers(merchant_id);
|
||||
CREATE INDEX idx_delivery_drivers_status ON delivery_drivers(status);
|
||||
```
|
||||
|
||||
#### delivery_tasks(配送任务表)
|
||||
```sql
|
||||
CREATE TABLE delivery_tasks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_id UUID NOT NULL REFERENCES orders(id),
|
||||
driver_id UUID REFERENCES delivery_drivers(id),
|
||||
pickup_address VARCHAR(500) NOT NULL, -- 取餐地址
|
||||
pickup_latitude DECIMAL(10,7),
|
||||
pickup_longitude DECIMAL(10,7),
|
||||
delivery_address VARCHAR(500) NOT NULL, -- 送餐地址
|
||||
delivery_latitude DECIMAL(10,7),
|
||||
delivery_longitude DECIMAL(10,7),
|
||||
distance INTEGER, -- 配送距离(米)
|
||||
estimated_time INTEGER, -- 预计时长(分钟)
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:待分配 2:待取餐 3:配送中 4:已送达 5:异常
|
||||
assigned_at TIMESTAMP WITH TIME ZONE, -- 分配时间
|
||||
picked_at TIMESTAMP WITH TIME ZONE, -- 取餐时间
|
||||
delivered_at TIMESTAMP WITH TIME ZONE, -- 送达时间
|
||||
delivery_fee DECIMAL(18,2) DEFAULT 0, -- 配送费
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_delivery_tasks_order_id ON delivery_tasks(order_id);
|
||||
CREATE INDEX idx_delivery_tasks_driver_id ON delivery_tasks(driver_id);
|
||||
CREATE INDEX idx_delivery_tasks_status ON delivery_tasks(status);
|
||||
```
|
||||
|
||||
### 2.7 支付管理
|
||||
|
||||
#### payments(支付记录表)
|
||||
```sql
|
||||
CREATE TABLE payments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_id UUID NOT NULL REFERENCES orders(id),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
payment_no VARCHAR(50) UNIQUE NOT NULL, -- 支付单号
|
||||
payment_method VARCHAR(20) NOT NULL, -- 支付方式:wechat、alipay、balance
|
||||
amount DECIMAL(18,2) NOT NULL,
|
||||
status INTEGER NOT NULL DEFAULT 0, -- 0:待支付 1:支付中 2:成功 3:失败 4:已退款
|
||||
third_party_no VARCHAR(100), -- 第三方支付单号
|
||||
paid_at TIMESTAMP WITH TIME ZONE,
|
||||
callback_data JSONB, -- 回调数据
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_payments_order_id ON payments(order_id);
|
||||
CREATE INDEX idx_payments_payment_no ON payments(payment_no);
|
||||
CREATE INDEX idx_payments_user_id ON payments(user_id);
|
||||
```
|
||||
|
||||
#### refunds(退款记录表)
|
||||
```sql
|
||||
CREATE TABLE refunds (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_id UUID NOT NULL REFERENCES orders(id),
|
||||
payment_id UUID NOT NULL REFERENCES payments(id),
|
||||
refund_no VARCHAR(50) UNIQUE NOT NULL,
|
||||
amount DECIMAL(18,2) NOT NULL,
|
||||
reason TEXT,
|
||||
status INTEGER NOT NULL DEFAULT 0, -- 0:待审核 1:退款中 2:成功 3:失败
|
||||
third_party_no VARCHAR(100),
|
||||
refunded_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_refunds_order_id ON refunds(order_id);
|
||||
CREATE INDEX idx_refunds_payment_id ON refunds(payment_id);
|
||||
```
|
||||
|
||||
### 2.8 营销管理
|
||||
|
||||
#### coupons(优惠券表)
|
||||
```sql
|
||||
CREATE TABLE coupons (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
merchant_id UUID REFERENCES merchants(id), -- NULL表示平台券
|
||||
name VARCHAR(100) NOT NULL,
|
||||
type INTEGER NOT NULL, -- 1:满减券 2:折扣券 3:代金券
|
||||
discount_type INTEGER NOT NULL, -- 1:固定金额 2:百分比
|
||||
discount_value DECIMAL(18,2) NOT NULL, -- 优惠值
|
||||
min_order_amount DECIMAL(18,2) DEFAULT 0, -- 最低消费
|
||||
max_discount_amount DECIMAL(18,2), -- 最大优惠金额(折扣券用)
|
||||
total_quantity INTEGER NOT NULL, -- 总数量
|
||||
received_quantity INTEGER DEFAULT 0, -- 已领取数量
|
||||
used_quantity INTEGER DEFAULT 0, -- 已使用数量
|
||||
valid_start_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
valid_end_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:正常 2:停用
|
||||
description TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_coupons_merchant_id ON coupons(merchant_id);
|
||||
CREATE INDEX idx_coupons_status ON coupons(status);
|
||||
```
|
||||
|
||||
#### user_coupons(用户优惠券表)
|
||||
```sql
|
||||
CREATE TABLE user_coupons (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
coupon_id UUID NOT NULL REFERENCES coupons(id),
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:未使用 2:已使用 3:已过期
|
||||
used_order_id UUID REFERENCES orders(id),
|
||||
received_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
used_at TIMESTAMP WITH TIME ZONE,
|
||||
expired_at TIMESTAMP WITH TIME ZONE NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_coupons_user_id ON user_coupons(user_id);
|
||||
CREATE INDEX idx_user_coupons_coupon_id ON user_coupons(coupon_id);
|
||||
CREATE INDEX idx_user_coupons_status ON user_coupons(status);
|
||||
```
|
||||
|
||||
### 2.9 评价管理
|
||||
|
||||
#### reviews(评价表)
|
||||
```sql
|
||||
CREATE TABLE reviews (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
order_id UUID NOT NULL REFERENCES orders(id),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
merchant_id UUID NOT NULL REFERENCES merchants(id),
|
||||
rating INTEGER NOT NULL, -- 评分 1-5
|
||||
taste_rating INTEGER, -- 口味评分
|
||||
package_rating INTEGER, -- 包装评分
|
||||
delivery_rating INTEGER, -- 配送评分
|
||||
content TEXT,
|
||||
images JSONB, -- 评价图片
|
||||
is_anonymous BOOLEAN DEFAULT FALSE,
|
||||
reply_content TEXT, -- 商家回复
|
||||
reply_at TIMESTAMP WITH TIME ZONE,
|
||||
status INTEGER NOT NULL DEFAULT 1, -- 1:正常 2:隐藏
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_reviews_order_id ON reviews(order_id);
|
||||
CREATE INDEX idx_reviews_user_id ON reviews(user_id);
|
||||
CREATE INDEX idx_reviews_merchant_id ON reviews(merchant_id);
|
||||
```
|
||||
|
||||
### 2.10 系统管理
|
||||
|
||||
#### system_users(系统用户表)
|
||||
```sql
|
||||
CREATE TABLE system_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id), -- NULL表示平台管理员
|
||||
merchant_id UUID REFERENCES merchants(id), -- NULL表示租户管理员
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
real_name VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
role_id UUID REFERENCES roles(id),
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
last_login_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_system_users_username ON system_users(username);
|
||||
CREATE INDEX idx_system_users_tenant_id ON system_users(tenant_id);
|
||||
```
|
||||
|
||||
#### roles(角色表)
|
||||
```sql
|
||||
CREATE TABLE roles (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id),
|
||||
name VARCHAR(50) NOT NULL,
|
||||
code VARCHAR(50) NOT NULL,
|
||||
description TEXT,
|
||||
permissions JSONB, -- 权限列表
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_roles_tenant_id ON roles(tenant_id);
|
||||
```
|
||||
|
||||
#### operation_logs(操作日志表)
|
||||
```sql
|
||||
CREATE TABLE operation_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID REFERENCES tenants(id),
|
||||
user_id UUID,
|
||||
user_type VARCHAR(20), -- system_user, merchant_user, customer
|
||||
module VARCHAR(50), -- 模块
|
||||
action VARCHAR(50), -- 操作
|
||||
description TEXT,
|
||||
ip_address VARCHAR(50),
|
||||
user_agent TEXT,
|
||||
request_data JSONB,
|
||||
response_data JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_operation_logs_tenant_id ON operation_logs(tenant_id);
|
||||
CREATE INDEX idx_operation_logs_user_id ON operation_logs(user_id);
|
||||
CREATE INDEX idx_operation_logs_created_at ON operation_logs(created_at);
|
||||
```
|
||||
|
||||
## 3. 数据库索引策略
|
||||
|
||||
### 3.1 主键索引
|
||||
- 所有表使用UUID作为主键,自动创建主键索引
|
||||
|
||||
### 3.2 外键索引
|
||||
- 所有外键字段创建索引,提升关联查询性能
|
||||
|
||||
### 3.3 业务索引
|
||||
- 订单号、支付单号等唯一业务字段创建唯一索引
|
||||
- 状态字段创建普通索引
|
||||
- 时间字段(created_at)创建索引,支持时间范围查询
|
||||
|
||||
### 3.4 复合索引
|
||||
```sql
|
||||
-- 订单查询常用复合索引
|
||||
CREATE INDEX idx_orders_merchant_status_created ON orders(merchant_id, status, created_at DESC);
|
||||
|
||||
-- 用户订单查询
|
||||
CREATE INDEX idx_orders_user_status_created ON orders(user_id, status, created_at DESC);
|
||||
```
|
||||
|
||||
### 3.5 地理位置索引
|
||||
```sql
|
||||
-- 使用PostGIS扩展支持地理位置查询
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
|
||||
-- 门店位置索引
|
||||
CREATE INDEX idx_merchant_stores_location ON merchant_stores
|
||||
USING GIST(ST_MakePoint(longitude, latitude));
|
||||
```
|
||||
|
||||
## 4. 数据库优化
|
||||
|
||||
### 4.1 分区策略
|
||||
```sql
|
||||
-- 订单表按月分区
|
||||
CREATE TABLE orders_2024_01 PARTITION OF orders
|
||||
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
|
||||
|
||||
CREATE TABLE orders_2024_02 PARTITION OF orders
|
||||
FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');
|
||||
```
|
||||
|
||||
### 4.2 物化视图
|
||||
```sql
|
||||
-- 商家统计物化视图
|
||||
CREATE MATERIALIZED VIEW merchant_statistics AS
|
||||
SELECT
|
||||
m.id as merchant_id,
|
||||
m.name,
|
||||
COUNT(DISTINCT o.id) as total_orders,
|
||||
SUM(o.actual_amount) as total_revenue,
|
||||
AVG(r.rating) as avg_rating
|
||||
FROM merchants m
|
||||
LEFT JOIN orders o ON m.id = o.merchant_id AND o.status = 6
|
||||
LEFT JOIN reviews r ON m.id = r.merchant_id
|
||||
GROUP BY m.id, m.name;
|
||||
|
||||
CREATE UNIQUE INDEX ON merchant_statistics(merchant_id);
|
||||
```
|
||||
|
||||
### 4.3 查询优化建议
|
||||
- 避免SELECT *,只查询需要的字段
|
||||
- 使用EXPLAIN分析查询计划
|
||||
- 合理使用JOIN,避免过多关联
|
||||
- 大数据量查询使用分页
|
||||
- 使用prepared statement防止SQL注入
|
||||
|
||||
## 5. 数据备份策略
|
||||
|
||||
### 5.1 备份方案
|
||||
- **全量备份**:每天凌晨2点执行
|
||||
- **增量备份**:每4小时执行一次
|
||||
- **WAL归档**:实时归档,支持PITR
|
||||
|
||||
### 5.2 备份脚本示例
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 全量备份
|
||||
pg_dump -h localhost -U postgres -d takeout_saas -F c -f /backup/full_$(date +%Y%m%d).dump
|
||||
|
||||
# 保留最近30天的备份
|
||||
find /backup -name "full_*.dump" -mtime +30 -delete
|
||||
```
|
||||
|
||||
## 6. 数据迁移
|
||||
|
||||
### 6.1 EF Core Migrations
|
||||
```bash
|
||||
# 添加迁移
|
||||
dotnet ef migrations add InitialCreate --project TakeoutSaaS.Infrastructure
|
||||
|
||||
# 更新数据库
|
||||
dotnet ef database update --project TakeoutSaaS.Infrastructure
|
||||
```
|
||||
|
||||
### 6.2 版本控制
|
||||
- 所有数据库变更通过Migration管理
|
||||
- Migration文件纳入版本控制
|
||||
- 生产环境变更需要审核
|
||||
|
||||
Reference in New Issue
Block a user