# IoT SIM 管理系统 - 数据模型总结 ## 概述 本文档总结了 IoT SIM 管理系统的数据模型层实现,包括 26 张数据库表和对应的 GORM 模型定义。 ## 实现范围 - ✅ 数据库迁���脚本 (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`: 所属运营商 ID - `owner_type`: 所有者类型 (platform/agent/user/device) - `owner_id`: 所有者 ID - `activation_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`: 所属套餐系列 ID - `package_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`: 代理用户 ID - `package_id`: 套餐 ID - `cost_price`: 成本价 (元) - `retail_price`: 零售价 (元) **用途**: 为直属下级代理分配套餐,设置佣金模式。 **文件位置**: `internal/iot/model/package.go:48` --- ### 8. 设备-IoT 卡绑定 (DeviceSimBinding) **表名**: `device_sim_bindings` **核心字段**: - `device_id`: 设备 ID - `iot_card_id`: IoT 卡 ID - `slot_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`: 订单 ID - `package_id`: 套餐 ID - `usage_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 卡 ID - `usage_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`: 用户 ID - `agent_id`: 代理用户 ID - `amount`: 订单金额 (元) - `payment_method`: 支付方式 (wallet/online/carrier) - `status`: 状态 (1-待支付, 2-已支付, 3-已完成, 4-已取消, 5-已退款) - `carrier_order_id`: 运营商订单 ID - `carrier_order_data`: 运营商订单原始数据 (JSONB) **支持场景**: - 套餐订单 (单卡套餐 / 设备级套餐) - 号卡订单 **文件位置**: `internal/iot/model/order.go:11` --- ## 分佣系统 ### 13. 代理层级关系 (AgentHierarchy) **表名**: `agent_hierarchies` **核心字段**: - `agent_id`: 代理用户 ID - `parent_agent_id`: 上级代理用户 ID - `agent_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`: 套餐系列 ID - `commission_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`: 分佣规则 ID - `min_quantity`: 最小数量 - `max_quantity`: 最大数量 - `commission_type`: 分佣方式 (fixed/percentage) - `commission_value`: 分佣值 **用途**: 为分佣规则配置阶梯奖励 (订单数量越多,分佣越高)。 **文件位置**: `internal/iot/model/commission.go:47` --- ### 16. 组合分佣条件 (CommissionCombinedCondition) **表名**: `commission_combined_conditions` **核心字段**: - `rule_id`: 分佣规则 ID - `condition_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`: 订单 ID - `agent_id`: 代理用户 ID - `rule_id`: 分佣规则 ID - `commission_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`: 分佣记录 ID - `agent_id`: 代理用户 ID - `approval_status`: 审批状态 (1-待审批, 2-已通过, 3-已拒绝) - `approver_id`: 审批人 ID - `approval_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`: 运营商 ID - `settlement_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`: 代理用户 ID - `withdrawal_amount`: 提现金额 (元) - `withdrawal_method`: 提现方式 (bank_card/alipay/wechat) - `account_info`: 账户信息 (JSONB) - `status`: 状态 (1-待审核, 2-已通过, 3-已拒绝, 4-已打款, 5-已取消) - `reviewer_id`: 审核人 ID - `review_reason`: 审核原因 - `reviewed_at`: 审核时间 - `paid_at`: 打款时间 **用途**: 管理代理用户的佣金提现申请。 **文件位置**: `internal/iot/model/financial.go:8` --- ### 22. 提现设置 (CommissionWithdrawalSetting) **表名**: `commission_withdrawal_settings` **核心字段**: - `agent_id`: 代理用户 ID - `min_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`: 旧卡 ID - `new_iot_card_id`: 新卡 ID - `user_id`: 用户 ID - `replacement_reason`: 换卡原因 - `status`: 状态 (1-待审核, 2-已通过, 3-已拒绝, 4-已完成) - `reviewer_id`: 审核人 ID - `reviewed_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` - 按反向依赖顺序删除所有表 ### 迁移测试 ```bash # 应用迁移 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 流程逐步实现。 --- ## 参考文档 - [表结构详细说明](./表结构详细说明.md) - [轮询机制说明](./轮询机制说明.md) - [分佣系统说明](./分佣系统说明.md) --- **文档版本**: v1.0 **最后更新**: 2026-01-12 **维护人员**: Claude Sonnet 4.5