- 添加 IoT 核心业务表:运营商、IoT 卡、设备、号卡、套餐、订单等 - 添加分佣系统表:分佣规则、分佣记录、运营商结算等 - 添加轮询和流量管理表:轮询配置、流量使用记录等 - 添加财务和系统管理表:佣金提现、换卡申请等 - 实现完整的 GORM 模型和常量定义 - 添加数据库迁移脚本和详细文档 - 集成 OpenSpec 工作流工具(opsx 命令和 skills) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
18 KiB
IoT SIM 管理系统 - 数据模型总结
概述
本文档总结了 IoT SIM 管理系统的数据模型层实现,包括 26 张数据库表和对应的 GORM 模型定义。
实现范围
- ✅ 数据库迁<E5BA93><E8BF81><EFBFBD>脚本 (migrations/000005_create_iot_sim_management_tables.up/down.sql)
- ✅ GORM 模型定义 (internal/iot/model/*.go)
- ✅ 业务常量定义 (pkg/constants/iot.go)
- ❌ API Handler 层 (不在本阶段范围)
- ❌ Service 业务逻辑层 (不在本阶段范围)
- ❌ Store 数据访问层 (不在本阶段范围)
核心业务实体
1. 运营商管理 (Carrier)
表名: carriers
核心字段:
carrier_code: 运营商编码 (CMCC/CUCC/CTCC)carrier_name: 运营商名称 (中国移动/中国联通/中国电信)api_endpoint: API 接口地址api_credentials: API 凭证 (JSONB)
预置数据: 初始化三大运营商数据
文件位置: internal/iot/model/carrier.go:5
2. IoT 卡管理 (IotCard)
表名: iot_cards
核心字段:
iccid: IoT 卡唯一标识 (20 位数字)card_category: 卡业务类型 (normal-普通卡, industry-行业卡)carrier_id: 所属运营商 IDowner_type: 所有者类型 (platform/agent/user/device)owner_id: 所有者 IDactivation_status: 激活状态 (0-未激活, 1-已激活)real_name_status: 实名状态 (0-未实名, 1-已实名)network_status: 网络状态 (0-停机, 1-开机)enable_polling: 是否参与轮询
特殊机制:
- 支持行业卡(无需实名)和普通卡(需实名)
- 多所有者模式 (owner_type + owner_id)
- 轮询开关控制 (enable_polling)
- 流量使用累计 (data_usage_mb)
- Gateway 同步时间戳 (last_sync_time)
文件位置: internal/iot/model/iot_card.go:8
3. 设备管理 (Device)
表名: devices
核心字段:
device_code: 设备唯一编码device_name: 设备名称device_type: 设备类型sim_slots: SIM 卡槽数量 (1-4)owner_type: 所有者类型 (platform/agent/user)owner_id: 所有者 ID
关联关系:
- 通过
device_sim_bindings表关联 1-4 张 IoT 卡
文件位置: internal/iot/model/device.go:5
4. 号卡管理 (NumberCard)
表名: number_cards
核心字段:
virtual_product_code: 虚拟商品编码 (用于对应运营商订单)card_name: 号卡名称carrier: 运营商data_amount_mb: 流量额度 (MB)price: 价格 (元)
业务说明: 号卡是完全独立的业务线,从上游平台下单,使用虚拟商品编码映射运营商订单。
文件位置: internal/iot/model/number_card.go:8
套餐与流量管理
5. 套餐系列 (PackageSeries)
表名: package_series
核心字段:
series_code: 系列编码series_name: 系列名称description: 描述
用途: 套餐分组,用于一次性分佣规则配置。
文件位置: internal/iot/model/package.go:7
6. 套餐 (Package)
表名: packages
核心字段:
package_code: 套餐编码package_name: 套餐名称series_id: 所属套餐系列 IDpackage_type: 套餐类型 (formal-正式套餐, addon-附加套餐)duration_months: 套餐时长 (月数)data_type: 流量类型 (real-真流量, virtual-虚流量)real_data_mb: 真流量额度 (MB)virtual_data_mb: 虚流量额度 (MB)data_amount_mb: 总流量额度 (MB)price: 套餐价格 (元)
特殊机制:
- 支持真流量/虚流量共存
- 停机判断基于虚流量
- 支持正式套餐和附加套餐
文件位置: internal/iot/model/package.go:23
7. 代理套餐分配 (AgentPackageAllocation)
表名: agent_package_allocations
核心字段:
agent_id: 代理用户 IDpackage_id: 套餐 IDcost_price: 成本价 (元)retail_price: 零售价 (元)
用途: 为直属下级代理分配套餐,设置佣金模式。
文件位置: internal/iot/model/package.go:48
8. 设备-IoT 卡绑定 (DeviceSimBinding)
表名: device_sim_bindings
核心字段:
device_id: 设备 IDiot_card_id: IoT 卡 IDslot_position: 插槽位置 (1, 2, 3, 4)bind_status: 绑定状态 (1-已绑定, 2-已解绑)bind_time: 绑定时间unbind_time: 解绑时间
用途: 管理设备与 IoT 卡的多对多绑定关系 (1 设备绑定 1-4 张 IoT 卡)。
文件位置: internal/iot/model/package.go:66
9. 套餐使用情况 (PackageUsage)
表名: package_usages
核心字段:
order_id: 订单 IDpackage_id: 套餐 IDusage_type: 使用类型 (single_card-单卡套餐, device-设备级套餐)iot_card_id: IoT 卡 ID (单卡套餐时有值)device_id: 设备 ID (设备级套餐时有值)data_limit_mb: 流量限额 (MB)data_usage_mb: 已使用流量 (MB)real_data_usage_mb: 真流量使用 (MB)virtual_data_usage_mb: 虚流量使用 (MB)activated_at: 套餐生效时间expires_at: 套餐过期时间status: 状态 (1-生效中, 2-已用完, 3-已过期)last_package_check_at: 最后一次套餐流量检查时间
用途: 跟踪单卡套餐和设备级套餐的流量使用。
文件位置: internal/iot/model/package.go:85
10. 轮询配置 (PollingConfig)
表名: polling_configs
核心字段:
config_name: 配置名称 (如 未实名卡、实名卡)card_condition: 卡状态条件 (not_real_name/real_name/activated/suspended)carrier_id: 运营商 ID (NULL 表示所有运营商)real_name_check_enabled: 是否启用实名检查real_name_check_interval: 实名检查间隔 (秒)card_data_check_enabled: 是否启用卡流量检查card_data_check_interval: 卡流量检查间隔 (秒)package_check_enabled: 是否启用套餐流量检查package_check_interval: 套餐流量检查间隔 (秒)priority: 优先级 (数字越小优先级越高)
特殊机制: 支持梯度轮询策略 (实名检查、卡流量检查、套餐流量检查)。
文件位置: internal/iot/model/polling.go:7
11. 流量使用记录 (DataUsageRecord)
表名: data_usage_records
核心字段:
iot_card_id: IoT 卡 IDusage_date: 使用日期data_usage_mb: 流量使用 (MB)carrier_sync_data: 运营商同步数据 (JSONB)synced_at: 同步时间
用途: 记录 IoT 卡每日流量使用情况 (历史数据)。
文件位置: internal/iot/model/data_usage.go:5
订单管理
12. 订单 (Order)
表名: orders
核心字段:
order_no: 订单号 (唯一标识)order_type: 订单类型 (1-套餐订单, 2-号卡订单)iot_card_id: IoT 卡 ID (单卡套餐订单时有值)device_id: 设备 ID (设备级套餐订单时有值)number_card_id: 号卡 ID (号卡订单时有值)package_id: 套餐 ID (套餐订单时有值)user_id: 用户 IDagent_id: 代理用户 IDamount: 订单金额 (元)payment_method: 支付方式 (wallet/online/carrier)status: 状态 (1-待支付, 2-已支付, 3-已完成, 4-已取消, 5-已退款)carrier_order_id: 运营商订单 IDcarrier_order_data: 运营商订单原始数据 (JSONB)
支持场景:
- 套餐订单 (单卡套餐 / 设备级套餐)
- 号卡订单
文件位置: internal/iot/model/order.go:11
分佣系统
13. 代理层级关系 (AgentHierarchy)
表名: agent_hierarchies
核心字段:
agent_id: 代理用户 IDparent_agent_id: 上级代理用户 IDagent_level: 代理层级 (1-一级代理, 2-二级代理, ...)agent_path: 代理路径 (如 /1/2/3/)
用途: 管理代理的树形层级关系。
文件位置: internal/iot/model/commission.go:8
14. 分佣规则 (CommissionRule)
表名: commission_rules
核心字段:
rule_name: 规则名称rule_type: 规则类型 (one_time-一次性分佣, long_term-长期分佣, combined-组合分佣)package_series_id: 套餐系列 IDcommission_type: 分佣方式 (fixed-固定金额, percentage-百分比)commission_value: 分佣值target_level: 目标层级 (NULL 表示所有层级)enable_ladder: 是否启用阶梯freeze_days: 冻结天数 (长期分佣)freeze_data_mb: 冻结流量 (MB, 长期分佣)unfreeze_mode: 解冻模式 (auto-自动, manual-手动)
分佣类型说明:
- 一次性分佣: 订单完成后立即发放
- 长期分佣: 订单完成后冻结,满足解冻条件后发放
- 组合分佣: 同时包含一次性和长期分佣
文件位置: internal/iot/model/commission.go:24
15. 分佣阶梯 (CommissionLadder)
表名: commission_ladder
核心字段:
rule_id: 分佣规则 IDmin_quantity: 最小数量max_quantity: 最大数量commission_type: 分佣方式 (fixed/percentage)commission_value: 分佣值
用途: 为分佣规则配置阶梯奖励 (订单数量越多,分佣越高)。
文件位置: internal/iot/model/commission.go:47
16. 组合分佣条件 (CommissionCombinedCondition)
表名: commission_combined_conditions
核心字段:
rule_id: 分佣规则 IDcondition_type: 条件类型 (one_time-一次性, long_term-长期)commission_type: 分佣方式 (fixed/percentage)commission_value: 分佣值freeze_days: 冻结天数 (长期分佣)freeze_data_mb: 冻结流量 (MB, 长期分佣)
用途: 定义组合分佣规则的具体条件 (一次性部分 + 长期部分)。
文件位置: internal/iot/model/commission.go:68
17. 分佣记录 (CommissionRecord)
表名: commission_records
核心字段:
order_id: 订单 IDagent_id: 代理用户 IDrule_id: 分佣规则 IDcommission_type: 分佣类型 (one_time/long_term/combined)commission_amount: 分佣金额 (元)status: 状态 (1-待发放, 2-已发放, 3-已冻结, 4-已取消)freeze_days: 冻结天数freeze_data_mb: 冻结流量 (MB)unfreeze_conditions: 解冻条件 (JSONB)unfrozen_at: 解冻时间distributed_at: 发放时间
特殊机制: 支持 OR 条件解冻 (时间到期 OR 流量达标,满足其一即可解冻)。
文件位置: internal/iot/model/commission.go:88
18. 分佣审批 (CommissionApproval)
表名: commission_approvals
核心字段:
commission_record_id: 分佣记录 IDagent_id: 代理用户 IDapproval_status: 审批状态 (1-待审批, 2-已通过, 3-已拒绝)approver_id: 审批人 IDapproval_reason: 审批原因approved_at: 审批时间
用途: 管理需要手动审批的分佣记录。
文件位置: internal/iot/model/commission.go:116
19. 分佣模板 (CommissionTemplate)
表名: commission_templates
核心字段:
template_name: 模板名称template_data: 模板数据 (JSONB)description: 描述
用途: 快速创建分佣规则的预设模板。
文件位置: internal/iot/model/commission.go:137
20. 运营商结算 (CarrierSettlement)
表名: carrier_settlements
核心字段:
carrier_id: 运营商 IDsettlement_month: 结算月份 (YYYY-MM)total_orders: 总订单数total_amount: 总金额 (元)settlement_status: 结算状态 (1-待结算, 2-已结算, 3-已支付)settled_at: 结算时间paid_at: 支付时间
用途: 记录与运营商的月度结算情况。
文件位置: internal/iot/model/commission.go:155
财务管理
21. 提现申请 (CommissionWithdrawalRequest)
表名: commission_withdrawal_requests
核心字段:
agent_id: 代理用户 IDwithdrawal_amount: 提现金额 (元)withdrawal_method: 提现方式 (bank_card/alipay/wechat)account_info: 账户信息 (JSONB)status: 状态 (1-待审核, 2-已通过, 3-已拒绝, 4-已打款, 5-已取消)reviewer_id: 审核人 IDreview_reason: 审核原因reviewed_at: 审核时间paid_at: 打款时间
用途: 管理代理用户的佣金提现申请。
文件位置: internal/iot/model/financial.go:8
22. 提现设置 (CommissionWithdrawalSetting)
表名: commission_withdrawal_settings
核心字段:
agent_id: 代理用户 IDmin_withdrawal_amount: 最小提现金额 (元)max_withdrawal_amount: 最大提现金额 (元)withdrawal_fee_rate: 提现手续费率 (小数)auto_approval_enabled: 是否启用自动审批
用途: 配置代理用户的提现规则。
文件位置: internal/iot/model/financial.go:31
23. 收款商户设置 (PaymentMerchantSetting)
表名: payment_merchant_settings
核心字段:
merchant_name: 商户名称merchant_type: 商户类型 (alipay/wechat/bank)merchant_config: 商户配置 (JSONB)is_default: 是否默认商户
用途: 配置收款商户信息 (支付宝、微信、银行)。
文件位置: internal/iot/model/financial.go:51
系统管理
24. 开发能力配置 (DevCapabilityConfig)
表名: dev_capability_configs
核心字段:
capability_name: 能力名称capability_code: 能力编码capability_config: 能力配置 (JSONB)description: 描述
用途: 管理系统开发能力配置 (如 API 开关、功能权限等)。
文件位置: internal/iot/model/system.go:5
25. 换卡申请 (CardReplacementRequest)
表名: card_replacement_requests
核心字段:
old_iot_card_id: 旧卡 IDnew_iot_card_id: 新卡 IDuser_id: 用户 IDreplacement_reason: 换卡原因status: 状态 (1-待审核, 2-已通过, 3-已拒绝, 4-已完成)reviewer_id: 审核人 IDreviewed_at: 审核时间completed_at: 完成时间
用途: 管理 IoT 卡的换卡申请流程。
文件位置: internal/iot/model/system.go:25
数据库设计原则
1. 无外键约束
- 数据库表之间禁止建立外键约束 (Foreign Key Constraints)
- 关联关系通过存储关联 ID 字段手动维护
- 关联数据查询在代码层面显式执行
设计理由:
- 灵活性:业务逻辑完全在代码中控制
- 性能:无数据库层面的引用完整性检查开销
- 可控性:开发者完全掌控何时查询关联数据
- 分布式友好:在微服务场景下更容易扩展
2. GORM 模型规范
- 所有字段必须显式指定
column:标签 - 禁止使用 ORM 关联关系 (
foreignKey,references,hasMany,belongsTo) - 所有字段必须添加中文注释
- 字符串字段长度必须明确定义 (VARCHAR(100)/VARCHAR(255)/TEXT)
- 数值字段精度必须明确定义 (DECIMAL(10,2)/BIGINT)
- 时间字段使用 GORM 自动管理 (
autoCreateTime,autoUpdateTime)
3. 命名规范
- 数据库字段名:下划线命名法 (snake_case),如
user_id,created_at - Go 结构体字段名:驼峰命名法 (PascalCase),如
UserID,CreatedAt - 表名:复数形式,如
iot_cards,orders,commission_rules - 常量名:大写驼峰 + 前缀,如
IotOrderStatusPending,CarrierCodeCMCC
常量定义
所有业务常量统一定义在 pkg/constants/iot.go 文件中,包括:
- 卡类型、卡业务类型、激活状态、实名状态、网络状态
- 所有者类型、卡状态、设备状态
- 套餐类型、流量类型、套餐使用状态
- 订单类型、订单状态、支付方式
- 轮询卡状态条件
- 分佣规则类型、分佣方式、分佣状态、解冻模式
- 提现状态、提现方式、商户类型
- 换卡申请状态、审批状态
文件位置: pkg/constants/iot.go:1
数据库迁移
迁移脚本
-
UP 脚本:
migrations/000005_create_iot_sim_management_tables.up.sql- 创建 26 张表
- 创建所有必需的索引
- 添加完整的中文注释
- 初始化三大运营商数据
-
DOWN 脚本:
migrations/000005_create_iot_sim_management_tables.down.sql- 按反向依赖顺序删除所有表
迁移测试
# 应用迁移
source .env && migrate -database "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE}" -path migrations up
# 回滚迁移
source .env && migrate -database "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE}" -path migrations down 1
# 查看版本
source .env && migrate -database "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE}" -path migrations version
测试结果
- ✅ UP 迁移成功 (耗时 616ms)
- ✅ DOWN 迁移成功 (耗时 602ms)
- ✅ 数据库版本正确切换 (4 → 5 → 4 → 5)
文件清单
数据库迁移脚本
migrations/000005_create_iot_sim_management_tables.up.sql(1102 行)migrations/000005_create_iot_sim_management_tables.down.sql(27 行)
GORM 模型定义
internal/iot/model/carrier.go(17 行)internal/iot/model/iot_card.go(40 行)internal/iot/model/device.go(27 行)internal/iot/model/number_card.go(26 行)internal/iot/model/package.go(108 行)internal/iot/model/order.go(36 行)internal/iot/model/polling.go(29 行)internal/iot/model/data_usage.go(20 行)internal/iot/model/commission.go(175 行)internal/iot/model/financial.go(70 行)internal/iot/model/system.go(46 行)
常量定义
pkg/constants/iot.go(164 行)
代码质量
- ✅
go fmt格式化通过 - ✅
goimports导入整理通过 - ✅
golangci-lint质量检查通过 (0 issues) - ✅
go build编译通过 - ✅
go mod tidy依赖管理通过
下一步工作
根据 OpenSpec 规范,本阶段只实现数据模型层,以下工作不在本阶段范围:
- ❌ API Handler 层
- ❌ Service 业务逻辑层
- ❌ Store 数据访问层
- ❌ 单元测试
- ❌ 集成测试
- ❌ API 文档生成
这些工作将在后续阶段按照 OpenSpec 流程逐步实现。
参考文档
文档版本: v1.0 最后更新: 2026-01-12 维护人员: Claude Sonnet 4.5