- 添加 IoT 核心业务表:运营商、IoT 卡、设备、号卡、套餐、订单等 - 添加分佣系统表:分佣规则、分佣记录、运营商结算等 - 添加轮询和流量管理表:轮询配置、流量使用记录等 - 添加财务和系统管理表:佣金提现、换卡申请等 - 实现完整的 GORM 模型和常量定义 - 添加数据库迁移脚本和详细文档 - 集成 OpenSpec 工作流工具(opsx 命令和 skills) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
35 KiB
IoT SIM 管理系统 - 表结构详细说明
本文档详细说明了 IoT SIM 管理系统的 26 张数据库表的结构、字段定义、索引设计和业务约束。
目录
核心业务表
1. carriers - 运营商
表名: carriers
用途: 管理三大运营商信息及其 API 配置
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 运营商ID |
| carrier_code | VARCHAR(50) | UNIQUE, NOT NULL | 运营商编码(CMCC/CUCC/CTCC) |
| carrier_name | VARCHAR(100) | NOT NULL | 运营商名称(中国移动/中国联通/中国电信) |
| api_endpoint | VARCHAR(500) | API 接口地址 | |
| api_credentials | JSONB | API 凭证(JSON格式) | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
carrier_code
预置数据:
INSERT INTO carriers (carrier_code, carrier_name, status) VALUES
('CMCC', '中国移动', 1),
('CUCC', '中国联通', 1),
('CTCC', '中国电信', 1);
GORM 模型: internal/iot/model/carrier.go:5
2. iot_cards - IoT 卡
表名: iot_cards
用途: 物联网卡/流量卡的统一管理实体,支持平台自营、代理分销、用户购买等所有权模式
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | IoT 卡 ID |
| iccid | VARCHAR(50) | UNIQUE, NOT NULL | ICCID(唯一标识,20位数字) |
| card_type | VARCHAR(50) | NOT NULL | 卡类型 |
| card_category | VARCHAR(20) | NOT NULL, DEFAULT 'normal' | 卡业务类型 normal-普通卡 industry-行业卡 |
| carrier_id | BIGINT | NOT NULL | 运营商ID |
| imsi | VARCHAR(50) | IMSI | |
| msisdn | VARCHAR(20) | MSISDN(手机号码) | |
| batch_no | VARCHAR(100) | 批次号 | |
| supplier | VARCHAR(255) | 供应商 | |
| cost_price | DECIMAL(10,2) | DEFAULT 0 | 成本价(元) |
| distribute_price | DECIMAL(10,2) | DEFAULT 0 | 分销价(元) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-在库 2-已分销 3-已激活 4-已停用 |
| owner_type | VARCHAR(20) | NOT NULL, DEFAULT 'platform' | 所有者类型 platform-平台 agent-代理 user-用户 device-设备 |
| owner_id | BIGINT | NOT NULL, DEFAULT 0 | 所有者ID |
| activated_at | TIMESTAMPTZ | 激活时间 | |
| activation_status | INT | NOT NULL, DEFAULT 0 | 激活状态 0-未激活 1-已激活 |
| real_name_status | INT | NOT NULL, DEFAULT 0 | 实名状态 0-未实名 1-已实名(行业卡可以保持0) |
| network_status | INT | NOT NULL, DEFAULT 0 | 网络状态 0-停机 1-开机 |
| data_usage_mb | BIGINT | DEFAULT 0 | 累计流量使用(MB) |
| enable_polling | BOOLEAN | DEFAULT true | 是否参与轮询 true-参与 false-不参与 |
| last_data_check_at | TIMESTAMPTZ | 最后一次流量检查时间 | |
| last_real_name_check_at | TIMESTAMPTZ | 最后一次实名检查时间 | |
| last_sync_time | TIMESTAMPTZ | 最后一次与Gateway同步时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
iccid - 组合索引:
(carrier_id, status) - 组合索引:
(owner_type, owner_id) - 单列索引:
batch_no
业务约束:
iccid必须唯一,通常为 20 位数字card_category = 'industry'时,real_name_status可以保持 0 (行业卡无需实名)card_category = 'normal'时,必须实名才能激活owner_type和owner_id组合表示所有权enable_polling = false的卡不参与轮询检查
GORM 模型: internal/iot/model/iot_card.go:8
3. devices - 设备
表名: devices
用途: 设备管理,支持 1-4 张 SIM 卡
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 设备ID |
| device_code | VARCHAR(100) | UNIQUE, NOT NULL | 设备唯一编码 |
| device_name | VARCHAR(255) | NOT NULL | 设备名称 |
| device_type | VARCHAR(100) | 设备类型 | |
| sim_slots | INT | DEFAULT 1 | SIM卡槽数量(1-4) |
| owner_type | VARCHAR(20) | NOT NULL, DEFAULT 'platform' | 所有者类型 platform-平台 agent-代理 user-用户 |
| owner_id | BIGINT | NOT NULL, DEFAULT 0 | 所有者ID |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-在库 2-已激活 3-已停用 |
| activated_at | TIMESTAMPTZ | 激活时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
device_code - 组合索引:
(owner_type, owner_id)
业务约束:
sim_slots取值范围 1-4- 通过
device_sim_bindings表管理设备与 IoT 卡的绑定关系
GORM 模型: internal/iot/model/device.go:5
4. number_cards - 号卡
表名: number_cards
用途: 号卡业务(完全独立的业务线),从上游平台下单
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 号卡ID |
| virtual_product_code | VARCHAR(100) | UNIQUE, NOT NULL | 虚拟商品编码(用于对应运营商订单) |
| card_name | VARCHAR(255) | NOT NULL | 号卡名称 |
| card_type | VARCHAR(50) | 号卡类型 | |
| carrier | VARCHAR(50) | 运营商 | |
| data_amount_mb | BIGINT | 流量额度(MB) | |
| price | DECIMAL(10,2) | 价格(元) | |
| agent_id | BIGINT | 代理用户ID | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-在售 2-下架 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
virtual_product_code - 单列索引:
agent_id
业务说明:
- 号卡是完全独立的业务线,与 IoT 卡无关
- 使用虚拟商品编码映射运营商订单
- 从上游平台下单,不涉及本地库存管理
GORM 模型: internal/iot/model/number_card.go:8
套餐与流量管理表
5. package_series - 套餐系列
表名: package_series
用途: 套餐的分组,用于一次性分佣规则配置
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 套餐系列ID |
| series_code | VARCHAR(100) | UNIQUE, NOT NULL | 系列编码 |
| series_name | VARCHAR(255) | NOT NULL | 系列名称 |
| description | TEXT | 描述 | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
series_code
业务说明:
- 套餐系列用于分组管理套餐
- 分佣规则可以按套餐系列统一配置
GORM 模型: internal/iot/model/package.go:7
6. packages - 套餐
表名: packages
用途: 套餐定义,只适用于 IoT 卡,支持真流量/虚流量共存机制
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 套餐ID |
| package_code | VARCHAR(100) | UNIQUE, NOT NULL | 套餐编码 |
| package_name | VARCHAR(255) | NOT NULL | 套餐名称 |
| series_id | BIGINT | 套餐系列ID | |
| package_type | VARCHAR(50) | NOT NULL | 套餐类型 formal-正式套餐 addon-附加套餐 |
| duration_months | INT | NOT NULL | 套餐时长(月数) 1-月套餐 12-年套餐 |
| data_type | VARCHAR(20) | 流量类型 real-真流量 virtual-虚流量 | |
| real_data_mb | BIGINT | DEFAULT 0 | 真流量额度(MB) |
| virtual_data_mb | BIGINT | DEFAULT 0 | 虚流量额度(MB,用于停机判断) |
| data_amount_mb | BIGINT | DEFAULT 0 | 总流量额度(MB) |
| price | DECIMAL(10,2) | NOT NULL | 套餐价格(元) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
package_code - 单列索引:
series_id
业务约束:
data_amount_mb = real_data_mb + virtual_data_mb- 停机判断基于
virtual_data_mb(虚流量用完即停机) package_type = 'formal'表示正式套餐,'addon'表示附加套餐
GORM 模型: internal/iot/model/package.go:23
7. agent_package_allocations - 代理套餐分配
表名: agent_package_allocations
用途: 为直属下级代理分配套餐,设置佣金模式
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 分配ID |
| agent_id | BIGINT | NOT NULL | 代理用户ID |
| package_id | BIGINT | NOT NULL | 套餐ID |
| cost_price | DECIMAL(10,2) | NOT NULL | 成本价(元) |
| retail_price | DECIMAL(10,2) | NOT NULL | 零售价(元) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合唯一索引:
(agent_id, package_id)
业务说明:
- 平台或上级代理为下级代理分配套餐
cost_price是代理的采购成本retail_price是代理的零售价格- 佣金 =
retail_price - cost_price
GORM 模型: internal/iot/model/package.go:48
8. device_sim_bindings - 设备-IoT卡绑定
表名: device_sim_bindings
用途: 管理设备与 IoT 卡的多对多绑定关系(1 设备绑定 1-4 张 IoT 卡)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 绑定ID |
| device_id | BIGINT | NOT NULL | 设备ID |
| iot_card_id | BIGINT | NOT NULL | IoT卡ID |
| slot_position | INT | 插槽位置(1, 2, 3, 4) | |
| bind_status | INT | DEFAULT 1 | 绑定状态 1-已绑定 2-已解绑 |
| bind_time | TIMESTAMPTZ | 绑定时间 | |
| unbind_time | TIMESTAMPTZ | 解绑时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合索引:
(device_id, iot_card_id) - 单列索引:
iot_card_id
业务约束:
- 一个设备最多绑定 4 张 IoT 卡
slot_position取值范围 1-4- 同一设备的同一插槽位置只能绑定一张激活状态的 IoT 卡
GORM 模型: internal/iot/model/package.go:66
9. package_usages - 套餐使用情况
表名: package_usages
用途: 跟踪单卡套餐和设备级套餐的流量使用
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 套餐使用ID |
| order_id | BIGINT | NOT NULL | 订单ID |
| package_id | BIGINT | NOT NULL | 套餐ID |
| usage_type | VARCHAR(20) | NOT NULL | 使用类型 single_card-单卡套餐 device-设备级套餐 |
| iot_card_id | BIGINT | IoT卡ID(单卡套餐时有值) | |
| device_id | BIGINT | 设备ID(设备级套餐时有值) | |
| data_limit_mb | BIGINT | NOT NULL | 流量限额(MB) |
| data_usage_mb | BIGINT | DEFAULT 0 | 已使用流量(MB) |
| real_data_usage_mb | BIGINT | DEFAULT 0 | 真流量使用(MB) |
| virtual_data_usage_mb | BIGINT | DEFAULT 0 | 虚流量使用(MB) |
| activated_at | TIMESTAMPTZ | NOT NULL | 套餐生效时间 |
| expires_at | TIMESTAMPTZ | NOT NULL | 套餐过期时间 |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-生效中 2-已用完 3-已过期 |
| last_package_check_at | TIMESTAMPTZ | 最后一次套餐流量检查时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
order_id - 单列索引:
iot_card_id - 单列索引:
device_id - 组合索引:
(status, last_package_check_at)
业务约束:
usage_type = 'single_card'时,iot_card_id有值,device_id为空usage_type = 'device'时,device_id有值,iot_card_id为空data_usage_mb = real_data_usage_mb + virtual_data_usage_mb- 轮询检查时更新
last_package_check_at
GORM 模型: internal/iot/model/package.go:85
10. polling_configs - 轮询配置
表名: polling_configs
用途: 轮询配置,支持梯度轮询策略(实名检查、卡流量检查、套餐流量检查)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 轮询配置ID |
| config_name | VARCHAR(100) | UNIQUE, NOT NULL | 配置名称(如 未实名卡、实名卡) |
| description | VARCHAR(500) | 配置描述 | |
| card_condition | VARCHAR(50) | 卡状态条件 not_real_name-未实名 real_name-已实名 activated-已激活 suspended-已停用 | |
| carrier_id | BIGINT | 运营商ID(NULL表示所有运营商) | |
| real_name_check_enabled | BOOLEAN | DEFAULT false | 是否启用实名检查 |
| real_name_check_interval | INT | DEFAULT 60 | 实名检查间隔(秒) |
| card_data_check_enabled | BOOLEAN | DEFAULT false | 是否启用卡流量检查 |
| card_data_check_interval | INT | DEFAULT 60 | 卡流量检查间隔(秒) |
| package_check_enabled | BOOLEAN | DEFAULT false | 是否启用套餐流量检查 |
| package_check_interval | INT | DEFAULT 60 | 套餐流量检查间隔(秒) |
| priority | INT | NOT NULL, DEFAULT 100 | 优先级(数字越小优先级越高) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
config_name - 单列索引:
carrier_id - 单列索引:
priority
业务说明:
- 支持三种独立的轮询检查类型
- 可以按卡状态和运营商配置不同的轮询策略
- 优先级控制多个配置的执行顺序
GORM 模型: internal/iot/model/polling.go:7
11. data_usage_records - 流量使用记录
表名: data_usage_records
用途: 记录 IoT 卡每日流量使用情况(历史数据)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 流量使用记录ID |
| iot_card_id | BIGINT | NOT NULL | IoT卡ID |
| usage_date | DATE | NOT NULL | 使用日期 |
| data_usage_mb | BIGINT | DEFAULT 0 | 流量使用(MB) |
| carrier_sync_data | JSONB | 运营商同步数据(JSON格式) | |
| synced_at | TIMESTAMPTZ | 同步时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合唯一索引:
(iot_card_id, usage_date) - 单列索引:
usage_date
业务说明:
- 每日记录一次 IoT 卡的流量使用情况
carrier_sync_data存储从运营商 Gateway 同步的原始数据- 用于历史查询和统计分析
GORM 模型: internal/iot/model/data_usage.go:5
订单管理表
12. orders - 订单
表名: orders
用途: 订单管理,支持两种订单类型:套餐订单(单卡/设备级)、号卡订单
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 订单ID |
| order_no | VARCHAR(100) | UNIQUE, NOT NULL | 订单号(唯一标识) |
| order_type | INT | NOT NULL | 订单类型 1-套餐订单 2-号卡订单 |
| iot_card_id | BIGINT | IoT卡ID(单卡套餐订单时有值) | |
| device_id | BIGINT | 设备ID(设备级套餐订单时有值) | |
| number_card_id | BIGINT | 号卡ID(号卡订单时有值) | |
| package_id | BIGINT | 套餐ID(套餐订单时有值) | |
| user_id | BIGINT | NOT NULL | 用户ID |
| agent_id | BIGINT | 代理用户ID | |
| amount | DECIMAL(10,2) | NOT NULL | 订单金额(元) |
| payment_method | VARCHAR(20) | 支付方式 wallet-钱包 online-在线支付 carrier-运营商支付 | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-待支付 2-已支付 3-已完成 4-已取消 5-已退款 |
| carrier_order_id | VARCHAR(255) | 运营商订单ID | |
| carrier_order_data | JSONB | 运营商订单原始数据(JSON) | |
| paid_at | TIMESTAMPTZ | 支付时间 | |
| completed_at | TIMESTAMPTZ | 完成时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
order_no - 单列索引:
user_id - 单列索引:
agent_id - 组合索引:
(status, created_at)
业务约束:
order_type = 1(套餐订单):- 单卡套餐:
iot_card_id有值,device_id为空 - 设备级套餐:
device_id有值,iot_card_id为空 package_id必须有值
- 单卡套餐:
order_type = 2(号卡订单):number_card_id必须有值package_id为空
GORM 模型: internal/iot/model/order.go:11
分佣系统表
13. agent_hierarchies - 代理层级关系
表名: agent_hierarchies
用途: 管理代理的树形层级关系
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 层级ID |
| agent_id | BIGINT | UNIQUE, NOT NULL | 代理用户ID |
| parent_agent_id | BIGINT | 上级代理用户ID | |
| agent_level | INT | NOT NULL | 代理层级(1-一级代理, 2-二级代理, ...) |
| agent_path | VARCHAR(500) | 代理路径(如 /1/2/3/) | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
agent_id - 单列索引:
parent_agent_id - 单列索引:
agent_level
业务说明:
agent_path存储完整的代理路径,便于查询上级链- 一级代理的
parent_agent_id为 NULL
GORM 模型: internal/iot/model/commission.go:8
14. commission_rules - 分佣规则
表名: commission_rules
用途: 定义分佣规则,支持一次性分佣、长期分佣、组合分佣
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 规则ID |
| rule_name | VARCHAR(255) | NOT NULL | 规则名称 |
| rule_type | VARCHAR(50) | NOT NULL | 规则类型 one_time-一次性分佣 long_term-长期分佣 combined-组合分佣 |
| package_series_id | BIGINT | 套餐系列ID | |
| commission_type | VARCHAR(20) | NOT NULL | 分佣方式 fixed-固定金额 percentage-百分比 |
| commission_value | DECIMAL(10,4) | NOT NULL | 分佣值 |
| target_level | INT | 目标层级(NULL表示所有层级) | |
| enable_ladder | BOOLEAN | DEFAULT false | 是否启用阶梯 |
| freeze_days | INT | DEFAULT 0 | 冻结天数(长期分佣) |
| freeze_data_mb | BIGINT | DEFAULT 0 | 冻结流量(MB,长期分佣) |
| unfreeze_mode | VARCHAR(20) | DEFAULT 'auto' | 解冻模式 auto-自动 manual-手动 |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
package_series_id - 组合索引:
(rule_type, status)
业务约束:
rule_type = 'one_time': 订单完成后立即发放rule_type = 'long_term': 订单完成后冻结,满足解冻条件后发放rule_type = 'combined': 同时包含一次性和长期分佣,通过commission_combined_conditions表定义条件unfreeze_mode = 'auto': 时间到期 OR 流量达标,满足其一即可自动解冻unfreeze_mode = 'manual': 需要人工审批解冻
GORM 模型: internal/iot/model/commission.go:24
15. commission_ladder - 分佣阶梯
表名: commission_ladder
用途: 为分佣规则配置阶梯奖励(订单数量越多,分佣越高)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 阶梯ID |
| rule_id | BIGINT | NOT NULL | 分佣规则ID |
| min_quantity | INT | NOT NULL | 最小数量 |
| max_quantity | INT | 最大数量(NULL表示无上限) | |
| commission_type | VARCHAR(20) | NOT NULL | 分佣方式 fixed-固定金额 percentage-百分比 |
| commission_value | DECIMAL(10,4) | NOT NULL | 分佣值 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
rule_id
业务示例:
1-10 单: 10元/单
11-50 单: 15元/单
51+ 单: 20元/单
GORM 模型: internal/iot/model/commission.go:47
16. commission_combined_conditions - 组合分佣条件
表名: commission_combined_conditions
用途: 定义组合分佣规则的具体条件(一次性部分 + 长期部分)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 条件ID |
| rule_id | BIGINT | NOT NULL | 分佣规则ID |
| condition_type | VARCHAR(20) | NOT NULL | 条件类型 one_time-一次性 long_term-长期 |
| commission_type | VARCHAR(20) | NOT NULL | 分佣方式 fixed-固定金额 percentage-百分比 |
| commission_value | DECIMAL(10,4) | NOT NULL | 分佣值 |
| freeze_days | INT | DEFAULT 0 | 冻结天数(长期分佣) |
| freeze_data_mb | BIGINT | DEFAULT 0 | 冻结流量(MB,长期分佣) |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合索引:
(rule_id, condition_type)
业务说明:
- 组合分佣规则可以定义多个条件
- 一次性条件立即发放
- 长期条件冻结后按规则解冻
GORM 模型: internal/iot/model/commission.go:68
17. commission_records - 分佣记录
表名: commission_records
用途: 记录每笔分佣的详细信息,支持 OR 条件解冻
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 分佣记录ID |
| order_id | BIGINT | NOT NULL | 订单ID |
| agent_id | BIGINT | NOT NULL | 代理用户ID |
| rule_id | BIGINT | NOT NULL | 分佣规则ID |
| commission_type | VARCHAR(50) | NOT NULL | 分佣类型 one_time/long_term/combined |
| commission_amount | DECIMAL(10,2) | NOT NULL | 分佣金额(元) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-待发放 2-已发放 3-已冻结 4-已取消 |
| freeze_days | INT | DEFAULT 0 | 冻结天数 |
| freeze_data_mb | BIGINT | DEFAULT 0 | 冻结流量(MB) |
| unfreeze_conditions | JSONB | 解冻条件(JSON格式,支持OR逻辑) | |
| unfrozen_at | TIMESTAMPTZ | 解冻时间 | |
| distributed_at | TIMESTAMPTZ | 发放时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
order_id - 单列索引:
agent_id - 组合索引:
(status, unfrozen_at)
业务约束:
unfreeze_conditions支持 OR 条件:{ "time_based": {"days": 30, "deadline": "2025-02-10T00:00:00Z"}, "data_based": {"data_mb": 1000} }- 满足时间到期 OR 流量达标,任一条件满足即可自动解冻
GORM 模型: internal/iot/model/commission.go:88
18. commission_approvals - 分佣审批
表名: commission_approvals
用途: 管理需要手动审批的分佣记录
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 审批ID |
| commission_record_id | BIGINT | UNIQUE, NOT NULL | 分佣记录ID |
| agent_id | BIGINT | NOT NULL | 代理用户ID |
| approval_status | INT | NOT NULL, DEFAULT 1 | 审批状态 1-待审批 2-已通过 3-已拒绝 |
| approver_id | BIGINT | 审批人ID | |
| approval_reason | TEXT | 审批原因 | |
| approved_at | TIMESTAMPTZ | 审批时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
commission_record_id - 单列索引:
agent_id - 组合索引:
(approval_status, created_at)
业务说明:
- 当分佣规则的
unfreeze_mode = 'manual'时,需要创建审批记录 - 审批通过后才能解冻和发放佣金
GORM 模型: internal/iot/model/commission.go:116
19. commission_templates - 分佣模板
表名: commission_templates
用途: 快速创建分佣规则的预设模板
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 模板ID |
| template_name | VARCHAR(255) | NOT NULL | 模板名称 |
| template_data | JSONB | NOT NULL | 模板数据(JSON格式) |
| description | TEXT | 描述 | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id
业务说明:
template_data存储分佣规则的完整配置- 可以基于模板快速创建新的分佣规则
GORM 模型: internal/iot/model/commission.go:137
20. carrier_settlements - 运营商结算
表名: carrier_settlements
用途: 记录与运营商的月度结算情况
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 结算ID |
| carrier_id | BIGINT | NOT NULL | 运营商ID |
| settlement_month | VARCHAR(7) | NOT NULL | 结算月份(YYYY-MM) |
| total_orders | INT | DEFAULT 0 | 总订单数 |
| total_amount | DECIMAL(10,2) | DEFAULT 0 | 总金额(元) |
| settlement_status | INT | NOT NULL, DEFAULT 1 | 结算状态 1-待结算 2-已结算 3-已支付 |
| settled_at | TIMESTAMPTZ | 结算时间 | |
| paid_at | TIMESTAMPTZ | 支付时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合唯一索引:
(carrier_id, settlement_month) - 组合索引:
(settlement_status, settlement_month)
业务说明:
- 按月统计与运营商的交易情况
- 支持结算和支付状态跟踪
GORM 模型: internal/iot/model/commission.go:155
财务管理表
21. commission_withdrawal_requests - 提现申请
表名: commission_withdrawal_requests
用途: 管理代理用户的佣金提现申请
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 提现申请ID |
| agent_id | BIGINT | NOT NULL | 代理用户ID |
| withdrawal_amount | DECIMAL(10,2) | NOT NULL | 提现金额(元) |
| withdrawal_method | VARCHAR(20) | NOT NULL | 提现方式 bank_card/alipay/wechat |
| account_info | JSONB | NOT NULL | 账户信息(JSON格式) |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-待审核 2-已通过 3-已拒绝 4-已打款 5-已取消 |
| reviewer_id | BIGINT | 审核人ID | |
| review_reason | TEXT | 审核原因 | |
| reviewed_at | TIMESTAMPTZ | 审核时间 | |
| paid_at | TIMESTAMPTZ | 打款时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
agent_id - 组合索引:
(status, created_at)
业务说明:
account_info存储提现账户信息:{ "account_name": "张三", "account_number": "6222021234567890", "bank_name": "中国工商银行" }
GORM 模型: internal/iot/model/financial.go:8
22. commission_withdrawal_settings - 提现设置
表名: commission_withdrawal_settings
用途: 配置代理用户的提现规则
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 设置ID |
| agent_id | BIGINT | UNIQUE, NOT NULL | 代理用户ID |
| min_withdrawal_amount | DECIMAL(10,2) | DEFAULT 0 | 最小提现金额(元) |
| max_withdrawal_amount | DECIMAL(10,2) | DEFAULT 0 | 最大提现金额(元) |
| withdrawal_fee_rate | DECIMAL(5,4) | DEFAULT 0 | 提现手续费率(小数) |
| auto_approval_enabled | BOOLEAN | DEFAULT false | 是否启用自动审批 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
agent_id
业务说明:
- 每个代理可以有独立的提现规则
withdrawal_fee_rate为 0.005 表示 0.5% 手续费
GORM 模型: internal/iot/model/financial.go:31
23. payment_merchant_settings - 收款商户设置
表名: payment_merchant_settings
用途: 配置收款商户信息(支付宝、微信、银行)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 商户设置ID |
| merchant_name | VARCHAR(255) | NOT NULL | 商户名称 |
| merchant_type | VARCHAR(20) | NOT NULL | 商户类型 alipay/wechat/bank |
| merchant_config | JSONB | NOT NULL | 商户配置(JSON格式) |
| is_default | BOOLEAN | DEFAULT false | 是否默认商户 |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 组合索引:
(merchant_type, is_default)
业务说明:
merchant_config存储商户的 API 配置:{ "app_id": "2021001234567890", "private_key": "...", "public_key": "...", "notify_url": "https://..." }
GORM 模型: internal/iot/model/financial.go:51
系统管理表
24. dev_capability_configs - 开发能力配置
表名: dev_capability_configs
用途: 管理系统开发能力配置(如 API 开关、功能权限等)
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 配置ID |
| capability_name | VARCHAR(255) | NOT NULL | 能力名称 |
| capability_code | VARCHAR(100) | UNIQUE, NOT NULL | 能力编码 |
| capability_config | JSONB | NOT NULL | 能力配置(JSON格式) |
| description | TEXT | 描述 | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-启用 2-禁用 |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 唯一索引:
capability_code
业务说明:
- 用于配置系统的开发能力开关
capability_config存储能力的详细配置
GORM 模型: internal/iot/model/system.go:5
25. card_replacement_requests - 换卡申请
表名: card_replacement_requests
用途: 管理 IoT 卡的换卡申请流程
字段说明:
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGSERIAL | PRIMARY KEY | 换卡申请ID |
| old_iot_card_id | BIGINT | NOT NULL | 旧卡ID |
| new_iot_card_id | BIGINT | 新卡ID | |
| user_id | BIGINT | NOT NULL | 用户ID |
| replacement_reason | TEXT | 换卡原因 | |
| status | INT | NOT NULL, DEFAULT 1 | 状态 1-待审核 2-已通过 3-已拒绝 4-已完成 |
| reviewer_id | BIGINT | 审核人ID | |
| reviewed_at | TIMESTAMPTZ | 审核时间 | |
| completed_at | TIMESTAMPTZ | 完成时间 | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 更新时间 |
索引:
- 主键索引:
id - 单列索引:
old_iot_card_id - 单列索引:
user_id - 组合索引:
(status, created_at)
业务流程:
- 用户提交换卡申请 (status=1)
- 管理员审核 (status=2/3)
- 审核通过后完成换卡 (status=4)
GORM 模型: internal/iot/model/system.go:25
数据库设计原则总结
1. 无外键约束
- 所有表之间没有数据库级别的外键约束
- 关联关系通过存储关联 ID 字段手动维护
- 提供灵活性和性能优势
2. 字段命名规范
- 数据库字段名: 下划线命名法 (snake_case)
- Go 结构体字段名: 驼峰命名法 (PascalCase)
- 所有字段必须添加中文注释
3. 数据类型规范
- 主键:
BIGSERIAL - 字符串:
VARCHAR(长度)或TEXT - 数值:
INT,BIGINT,DECIMAL(10,2) - 时间:
TIMESTAMPTZ - JSON:
JSONB - 布尔:
BOOLEAN
4. 索引设计原则
- 所有主键自动创建索引
- 唯一字段创建唯一索引
- 外键字段创建单列索引
- 常用查询条件创建组合索引
- 时间字段按需创建索引
5. 时间戳字段
created_at: 创建时间,自动设置updated_at: 更新时间,自动更新- 使用
TIMESTAMPTZ类型存储带时区的时间戳
文档版本: v1.0 最后更新: 2026-01-12 维护人员: Claude Sonnet 4.5