Files
junhong_cmp_fiber/openspec/changes/archive/2026-01-12-iot-sim-management/tasks.md
huang 034f00e2e7 实现 IoT SIM 管理模块数据模型和数据库结构
- 添加 IoT 核心业务表:运营商、IoT 卡、设备、号卡、套餐、订单等
- 添加分佣系统表:分佣规则、分佣记录、运营商结算等
- 添加轮询和流量管理表:轮询配置、流量使用记录等
- 添加财务和系统管理表:佣金提现、换卡申请等
- 实现完整的 GORM 模型和常量定义
- 添加数据库迁移脚本和详细文档
- 集成 OpenSpec 工作流工具(opsx 命令和 skills)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 15:44:23 +08:00

442 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# IoT SIM 管理 - 数据模型与数据库表结构实现任务
本任务清单聚焦于 IoT SIM 管理模块的数据模型定义和数据库表结构实现,不包含业务逻辑代码。
---
## 1. 数据库迁移脚本
### 1.1 核心业务表
- [x] 1.1.1 创建迁移脚本文件:`migrations/YYYYMMDDHHMMSS_create_iot_sim_management_tables.up.sql``*.down.sql`
- [x] 1.1.2 创建运营商表(carriers)及其索引
- 主键索引
- `carrier_code` 唯一索引
- 初始数据:中国移动(CMCC)、中国联通(CUCC)、中国电信(CTCC)
- [x] 1.1.3 创建 IoT 卡表(iot_cards)及其索引
- 主键索引
- `iccid` 唯一索引
- `card_category` 字段:枚举值 "normal"(普通卡) | "industry"(行业卡),默认 "normal"
- `carrier_id` 索引(关联运营商表)
- `owner_type` + `owner_id` + `status` 组合索引
- `batch_no` 索引
- `activated_at` 索引
- `card_category` 索引(用于区分普通卡和行业卡)
- `enable_polling` + `activation_status` + `last_data_check_at` 组合索引(卡流量轮询查询优化)
- `enable_polling` + `real_name_status` + `last_real_name_check_at` 组合索引(实名轮询查询优化)
- [x] 1.1.4 创建设备表(devices)及其索引
- 主键索引
- `device_no` 唯一索引
- `owner_type` + `owner_id` + `status` 组合索引
- [x] 1.1.5 创建号卡表(number_cards)及其索引
- 主键索引
- `virtual_product_code` 唯一索引
- `agent_id` + `status` 组合索引
- [x] 1.1.6 创建套餐系列表(package_series)及其索引
- 主键索引
- `series_code` 唯一索引
- [x] 1.1.7 创建套餐表(packages)及其索引
- 主键索引
- `package_code` 唯一索引
- `series_id` + `status` 组合索引
- [x] 1.1.8 创建代理套餐分配表(agent_package_allocations)及其索引
- 主键索引
- `agent_id` + `package_id` 唯一组合索引
- [x] 1.1.9 创建设备-IoT卡绑定关系表(device_sim_bindings)及其索引
- 主键索引
- `device_id` + `bind_status` 组合索引
- `iot_card_id` + `bind_status` 组合索引
- `iot_card_id` 部分唯一索引(WHERE bind_status = 1)
- [x] 1.1.10 创建订单表(orders)及其索引
- 主键索引
- `order_no` 唯一索引
- `user_id` + `status` 组合索引
- `agent_id` + `status` 组合索引
- `iot_card_id` 索引
- `device_id` 索引
- `number_card_id` 索引
### 1.2 套餐和轮询相关表
- [x] 1.2.1 创建套餐使用情况表(package_usages)及其索引
- 主键索引
- `order_id` 索引
- `package_id` 索引
- `iot_card_id` 索引
- `device_id` 索引
- `status` + `expires_at` + `last_package_check_at` 组合索引(套餐流量检查优化)
- [x] 1.2.2 创建轮询配置表(polling_configs)及其索引
- 主键索引
- `config_name` 唯一索引
- `status` + `card_condition` + `carrier_id` + `priority` 组合索引(配置匹配优化)
- [x] 1.2.3 创建流量使用记录表(data_usage_records)及其索引
- 主键索引
- `iot_card_id` + `check_time` 组合索引(按卡和时间查询)
- `check_time` 索引(按时间范围查询)
- 注意:此表数据量会快速增长,建议定期清理 90 天前的记录或使用分区表
### 1.3 分佣相关表
- [x] 1.3.1 创建代理层级关系表(agent_hierarchies)及其索引
- 主键索引
- `agent_id` 唯一索引
- `parent_agent_id` 索引
- [x] 1.3.2 创建分佣规则表(commission_rules)及其索引
- 主键索引
- `agent_id` + `business_type` + `card_type` 组合索引
- [x] 1.3.3 创建阶梯分佣配置表(commission_ladder)及其索引
- 主键索引
- `rule_id` 索引
- [x] 1.3.4 创建组合分佣条件表(commission_combined_conditions)及其索引
- 主键索引
- `rule_id` 唯一索引
- [x] 1.3.5 创建分佣记录表(commission_records)及其索引
- 主键索引
- `agent_id` + `status` 组合索引
- `order_id` 索引
- `rule_id` 索引
- [x] 1.3.6 创建分佣审批表(commission_approvals)及其索引
- 主键索引
- `commission_record_id` 索引
- `status` 索引
- [x] 1.3.7 创建分佣模板表(commission_templates)及其索引
- 主键索引
- `template_name` 唯一索引
- [x] 1.3.8 创建号卡运营商结算表(carrier_settlements)及其索引
- 主键索引
- `commission_record_id` 唯一索引
- `agent_id` + `status` 组合索引
### 1.4 财务管理表
- [x] 1.4.1 创建佣金提现申请表(commission_withdrawal_requests)及其索引
- 主键索引
- `agent_id` + `status` 组合索引
- `created_at` 索引
- [x] 1.4.2 创建佣金提现设置表(commission_withdrawal_settings)及其索引
- 主键索引
- `status` 索引
- [x] 1.4.3 创建收款商户设置表(payment_merchant_settings)及其索引
- 主键索引
- `user_id` + `is_default` 组合索引
- `merchant_type` + `status` 组合索引
### 1.5 系统管理表
- [x] 1.5.1 创建开发能力配置表(dev_capability_configs)及其索引
- 主键索引
- `app_id` 唯一索引
- `user_id` + `status` 组合索引
- [x] 1.5.2 创建换卡申请表(card_replacement_requests)及其索引
- 主键索引
- `user_id` + `status` 组合索引
- `old_iccid` 索引
- `new_iccid` 索引
### 1.6 迁移脚本验证
- [x] 1.6.1 编写迁移脚本的 down 部分(删除所有表)
- [x] 1.6.2 在本地测试数据库执行 up 迁移
- [x] 1.6.3 验证所有表和索引创建成功
- [x] 1.6.4 执行 down 迁移验证回滚成功
- [x] 1.6.5 编写迁移脚本的 README 说明(执行步骤、注意事项)
---
## 2. GORM 模型定义
### 2.1 目录结构
- [x] 2.1.1 创建 `internal/iot/model` 目录
- [x] 2.1.2 创建模型文件结构:
- `carrier.go` - 运营商模型
- `iot_card.go` - IoT 卡模型
- `device.go` - 设备模型
- `number_card.go` - 号卡模型
- `package.go` - 套餐、套餐系列、套餐使用情况模型
- `order.go` - 订单模型
- `polling.go` - 轮询配置模型
- `data_usage.go` - 流量使用记录模型
- `commission.go` - 分佣相关模型
- `financial.go` - 财务管理模型
- `system.go` - 系统管理模型
### 2.2 核心业务模型
- [x] 2.2.1 定义运营商(Carrier)模型
- 字段包括id, carrier_code, carrier_name, description, status, created_at, updated_at
- 初始数据:中国移动(CMCC)、中国联通(CUCC)、中国电信(CTCC)
- [x] 2.2.2 定义 IoT 卡(IotCard)模型
- 所有字段必须显式指定 `gorm:"column:字段名"`
- 添加中文字段注释(comment 标签)
- 字段包括id, iccid, card_type, card_category, carrier_id, imsi, msisdn, batch_no, supplier, cost_price, distribute_price, status, owner_type, owner_id, activated_at, activation_status, real_name_status, network_status, data_usage_mb, enable_polling, last_data_check_at, last_real_name_check_at, last_sync_time, created_at, updated_at
- **关键调整**
- `card_category` 字段:枚举值 "normal"(普通卡) | "industry"(行业卡),默认 "normal"
- `carrier_id` 关联运营商表(替代原来的 carrier 字符串字段)
- `enable_polling` 控制是否参与轮询(默认 true
- `last_data_check_at` 卡流量检查时间
- `last_real_name_check_at` 实名检查时间
- 行业卡可以在 `real_name_status` 为 0 的情况下激活使用
- [x] 2.2.3 定义设备(Device)模型
- 字段包括id, device_no, device_name, device_model, device_type, max_sim_slots, manufacturer, batch_no, owner_type, owner_id, status, activated_at, device_username, device_password_encrypted, device_api_endpoint, created_at, updated_at
- [x] 2.2.4 定义号卡(NumberCard)模型
- 字段包括id, virtual_product_code, card_name, card_type, carrier, data_amount_mb, price, agent_id, status, created_at, updated_at
- [x] 2.2.5 定义套餐系列(PackageSeries)模型
- 字段包括id, series_code, series_name, description, status, created_at, updated_at
- [x] 2.2.6 定义套餐(Package)模型
- 字段包括id, package_code, package_name, series_id, package_type, duration_months, data_type, real_data_mb, virtual_data_mb, data_amount_mb, price, status, created_at, updated_at
- [x] 2.2.7 定义代理套餐分配(AgentPackageAllocation)模型
- 字段包括id, agent_id, package_id, cost_price, retail_price, status, created_at, updated_at
- [x] 2.2.8 定义设备-IoT卡绑定关系(DeviceSimBinding)模型
- 字段包括id, device_id, iot_card_id, slot_number, bind_status, bound_at, unbound_at, created_at, updated_at
- [x] 2.2.9 定义订单(Order)模型
- 字段包括id, order_no, order_type, iot_card_id, device_id, number_card_id, package_id, user_id, agent_id, amount, payment_method, status, carrier_order_id, carrier_order_data, paid_at, completed_at, created_at, updated_at
### 2.3 套餐和轮询相关模型
- [x] 2.3.1 定义套餐使用情况(PackageUsage)模型
- 字段包括id, order_id, package_id, usage_type, iot_card_id, device_id, data_limit_mb, data_usage_mb, real_data_usage_mb, virtual_data_usage_mb, activated_at, expires_at, status, last_package_check_at, created_at, updated_at
- **业务逻辑**
- `usage_type` = "single_card" 时,`iot_card_id` 有值,`device_id` 为 NULL
- `usage_type` = "device" 时,`device_id` 有值,`iot_card_id` 为 NULL
- `data_usage_mb` 通过汇总卡的流量计算(单卡套餐直接读卡流量,设备级套餐汇总所有卡流量)
- [x] 2.3.2 定义轮询配置(PollingConfig)模型
- 字段包括id, config_name, description, card_condition, carrier_id, real_name_check_enabled, real_name_check_interval, card_data_check_enabled, card_data_check_interval, package_check_enabled, package_check_interval, priority, status, created_at, updated_at
- **配置说明**
- `carrier_id` 为 NULL 表示匹配所有运营商
- `priority` 数字越小优先级越高
- 支持独立配置实名检查、卡流量检查、套餐流量检查
- [x] 2.3.3 定义流量使用记录(DataUsageRecord)模型
- 字段包括id, iot_card_id, data_usage_mb, data_increase_mb, check_time, source, created_at
- **业务逻辑**
- Worker 每次轮询卡流量后插入一条记录
- `data_increase_mb` = 本次流量 - 上次流量
- `source` 数据来源polling-轮询 manual-手动 gateway-回调)
### 2.4 分佣相关模型
- [x] 2.4.1 定义代理层级关系(AgentHierarchy)模型
- 字段包括id, agent_id, parent_agent_id, agent_path, level, created_at, updated_at
- [x] 2.4.2 定义分佣规则(CommissionRule)模型
- 字段包括id, agent_id, business_type, card_type, commission_type, commission_mode, commission_value, unfreeze_days, min_activation_for_unfreeze, approval_type, status, created_at, updated_at
- [x] 2.4.3 定义阶梯分佣配置(CommissionLadder)模型
- 字段包括id, rule_id, ladder_type, threshold_value, commission_mode, commission_value, created_at, updated_at
- [x] 2.4.4 定义组合分佣条件(CommissionCombinedCondition)模型
- 字段包括id, rule_id, one_time_commission_mode, one_time_commission_value, long_term_commission_mode, long_term_commission_value, long_term_unfreeze_days, long_term_min_activation, created_at, updated_at
- [x] 2.4.5 定义分佣记录(CommissionRecord)模型
- 字段包括id, agent_id, order_id, rule_id, commission_type, amount, status, unfrozen_at, released_at, created_at, updated_at
- [x] 2.4.6 定义分佣审批(CommissionApproval)模型
- 字段包括id, commission_record_id, approver_id, status, reason, created_at, updated_at
- [x] 2.4.7 定义分佣模板(CommissionTemplate)模型
- 字段包括id, template_name, business_type, card_type, commission_type, commission_mode, commission_value, unfreeze_days, min_activation_for_unfreeze, approval_type, created_at, updated_at
- [x] 2.4.8 定义号卡运营商结算(CarrierSettlement)模型
- 字段包括id, commission_record_id, agent_id, settlement_month, settlement_amount, status, created_at, updated_at
### 2.5 财务管理模型
- [x] 2.5.1 定义佣金提现申请(CommissionWithdrawalRequest)模型
- 字段包括id, agent_id, amount, withdrawal_method, merchant_id, account_info, status, approved_by, approved_at, rejected_reason, paid_at, created_at, updated_at
- [x] 2.5.2 定义佣金提现设置(CommissionWithdrawalSetting)模型
- 字段包括id, min_withdrawal_amount, max_withdrawal_amount, daily_withdrawal_limit, fee_rate, status, created_at, updated_at
- [x] 2.5.3 定义收款商户设置(PaymentMerchantSetting)模型
- 字段包括id, user_id, merchant_type, account_name, account_number, bank_name, is_verified, is_default, status, created_at, updated_at
### 2.6 系统管理模型
- [x] 2.6.1 定义开发能力配置(DevCapabilityConfig)模型
- 字段包括id, user_id, app_id, app_secret, callback_url, status, created_at, updated_at
- [x] 2.6.2 定义换卡申请(CardReplacementRequest)模型
- 字段包括id, user_id, old_iccid, new_iccid, reason, status, processed_by, processed_at, created_at, updated_at
---
## 3. 常量定义
### 3.1 核心业务常量
- [x] 3.1.1 在 `pkg/constants/iot.go` 中定义以下常量:
- IoT 卡状态IotCardStatusInStock(1), IotCardStatusDistributed(2), IotCardStatusActivated(3), IotCardStatusSuspended(4)
- 设备状态DeviceStatusInStock(1), DeviceStatusDistributed(2), DeviceStatusActivated(3), DeviceStatusSuspended(4)
- 号卡状态NumberCardStatusOnSale(1), NumberCardStatusOffSale(2)
- IoT 卡激活状态ActivationStatusInactive(0), ActivationStatusActive(1)
- IoT 卡实名状态RealNameStatusNotVerified(0), RealNameStatusVerified(1)
- IoT 卡网络状态NetworkStatusOffline(0), NetworkStatusOnline(1)
- 套餐流量类型DataTypeReal("real"), DataTypeVirtual("virtual")
- 套餐类型PackageTypeFormal("formal"), PackageTypeAddon("addon")
- 订单类型OrderTypePackage(1), OrderTypeNumberCard(2)
- 订单状态OrderStatusPending(1), OrderStatusPaid(2), OrderStatusCompleted(3), OrderStatusCancelled(4), OrderStatusRefunded(5)
- 支付方式PaymentMethodWallet("wallet"), PaymentMethodOnline("online"), PaymentMethodCarrier("carrier")
- 所有者类型OwnerTypePlatform("platform"), OwnerTypeAgent("agent"), OwnerTypeUser("user"), OwnerTypeDevice("device")
- 绑定状态BindStatusBound(1), BindStatusUnbound(2)
### 3.2 套餐和轮询相关常量
- [x] 3.2.1 定义套餐使用类型常量:
- PackageUsageTypeSingleCard("single_card") - 单卡套餐
- PackageUsageTypeDevice("device") - 设备级套餐
- [x] 3.2.2 定义套餐使用状态常量:
- PackageUsageStatusActive(1) - 生效中
- PackageUsageStatusExhausted(2) - 已用完
- PackageUsageStatusExpired(3) - 已过期
- [x] 3.2.3 定义轮询配置卡条件常量:
- CardConditionNotRealName("not_real_name") - 未实名
- CardConditionRealName("real_name") - 已实名
- CardConditionActivated("activated") - 已激活
- CardConditionSuspended("suspended") - 已停用
- [x] 3.2.4 定义流量使用记录来源常量:
- DataUsageSourcePolling("polling") - 轮询
- DataUsageSourceManual("manual") - 手动
- DataUsageSourceGateway("gateway") - Gateway 回调
### 3.3 分佣相关常量
- [x] 3.3.1 定义分佣相关常量:
- 分佣类型CommissionTypeOneTime("one_time"), CommissionTypeLongTerm("long_term"), CommissionTypeCombined("combined")
- 分佣模式CommissionModeFixed("fixed"), CommissionModePercent("percent")
- 分佣状态CommissionStatusFrozen(1), CommissionStatusUnfreezing(2), CommissionStatusReleased(3), CommissionStatusInvalid(4)
- 阶梯类型LadderTypeActivation("activation"), LadderTypePickup("pickup"), LadderTypeDeposit("deposit")
- 卡类型CardTypeNumberCard("number_card"), CardTypeIotCard("iot_card")
- 审批类型ApprovalTypeAuto("auto"), ApprovalTypeManual("manual")
- 审批状态ApprovalStatusPending(1), ApprovalStatusApproved(2), ApprovalStatusRejected(3)
### 3.4 财务管理常量
- [x] 3.4.1 定义财务相关常量:
- 提现状态WithdrawalStatusPending(1), WithdrawalStatusApproved(2), WithdrawalStatusRejected(3), WithdrawalStatusPaid(4)
- 提现方式WithdrawalMethodAlipay("alipay"), WithdrawalMethodWechat("wechat"), WithdrawalMethodBank("bank")
- 商户类型MerchantTypeAlipay("alipay"), MerchantTypeWechat("wechat"), MerchantTypeBank("bank")
### 3.5 系统管理常量
- [x] 3.5.1 定义系统管理常量:
- 换卡申请状态ReplacementStatusPending(1), ReplacementStatusApproved(2), ReplacementStatusRejected(3), ReplacementStatusCompleted(4)
- 开发能力配置状态DevCapabilityStatusEnabled(1), DevCapabilityStatusDisabled(2)
---
## 4. 模型和表结构文档
### 4.1 代码注释
- [x] 4.1.1 为所有 GORM 模型添加中文结构体注释(描述表的业务用途)
- [x] 4.1.2 为所有模型字段添加清晰的中文注释
- [x] 4.1.3 为所有常量添加中文注释(说明枚举值含义)
- [x] 4.1.4 在迁移脚本中为所有表和字段添加 SQL COMMENT
### 4.2 数据库设计文档
- [x] 4.2.1 在 `docs/iot-sim-management/` 目录下创建 `数据库设计.md`
- [x] 4.2.2 使用 Markdown 表格描述所有表结构(字段名、类型、约束、说明)
- [x] 4.2.3 使用 dbdiagram.io 或 draw.io 创建数据库 ERD 图
- [x] 4.2.4 导出 ERD 图并保存到 `docs/iot-sim-management/erd.png`
- [x] 4.2.5 在 `数据库设计.md` 中嵌入 ERD 图
### 4.3 模型使用说明
- [x] 4.3.1 创建 `docs/iot-sim-management/模型说明.md`
- [x] 4.3.2 说明每个模型的用途和关键字段含义
- [x] 4.3.3 说明表之间的关联关系(虽然没有外键,但逻辑关联需要说明)
- [x] 4.3.4 说明关键枚举字段的取值和含义
- [x] 4.3.5 说明特殊设计决策(如无外键约束、owner_type/owner_id 模式等)
### 4.4 轮询机制说明文档
- [x] 4.4.1 创建 `docs/iot-sim-management/轮询机制说明.md`
- [x] 4.4.2 说明三个独立轮询流程:实名状态轮询、卡流量轮询、套餐流量检查
- [x] 4.4.3 说明轮询配置的匹配规则和优先级
- [x] 4.4.4 说明 `enable_polling` 字段的使用场景
- [x] 4.4.5 说明流量使用记录表的数据保留策略
### 4.5 项目文档更新
- [x] 4.5.1 更新 `README.md`,添加 IoT SIM 管理模块描述
- [x] 4.5.2 在 README 中添加数据库设计文档链接
- [x] 4.5.3 在 README 中添加模型说明文档链接
- [x] 4.5.4 在 README 中添加轮询机制说明文档链接
---
## 5. 数据迁移验证
### 5.1 本地验证
- [x] 5.1.1 在本地 PostgreSQL 测试数据库执行迁移脚本 up
- [x] 5.1.2 使用 `\dt``\d table_name` 验证所有表创建成功
- [x] 5.1.3 验证所有字段类型、默认值、NOT NULL 约束正确
- [x] 5.1.4 使用 `\di` 验证所有索引创建成功
- [x] 5.1.5 验证唯一索引和组合索引的正确性
### 5.2 数据完整性验证
- [x] 5.2.1 插入测试数据验证唯一索引生效(尝试插入重复 ICCID 应失败)
- [x] 5.2.2 插入测试数据验证 NOT NULL 约束生效
- [x] 5.2.3 插入测试数据验证 CHECK 约束生效(如金额 >= 0)
- [x] 5.2.4 查询测试数据验证组合索引生效(使用 EXPLAIN ANALYZE)
- [x] 5.2.5 验证运营商初始数据插入成功
### 5.3 回滚验证
- [x] 5.3.1 执行迁移脚本 down
- [x] 5.3.2 验证所有表和索引删除成功
- [x] 5.3.3 重新执行 up 验证迁移脚本可重复执行
---
## 6. 代码质量检查
### 6.1 代码格式化
- [x] 6.1.1 使用 `go fmt` 格式化所有模型代码
- [x] 6.1.2 使用 `goimports` 整理导入语句
- [x] 6.1.3 使用 `golangci-lint` 检查代码质量
### 6.2 命名规范检查
- [x] 6.2.1 验证所有 Go 字段名遵循驼峰命名法(PascalCase)
- [x] 6.2.2 验证所有数据库字段名遵循下划线命名法(snake_case)
- [x] 6.2.3 验证所有常量命名遵循 Go 规范(如 IotCardStatusInStock)
- [x] 6.2.4 验证所有模型文件名遵循 Go 规范(snake_case如 iot_card.go)
### 6.3 GORM 标签检查
- [x] 6.3.1 验证所有字段都有 `gorm:"column:字段名"` 标签
- [x] 6.3.2 验证所有字段都有 `json:"字段名"` 标签
- [x] 6.3.3 验证所有字段的 `comment` 标签包含中文说明
- [x] 6.3.4 验证字符串字段的 `type` 标签指定了长度(如 `type:varchar(100)`)
- [x] 6.3.5 验证数值字段的 `type` 标签指定了精度(如 `type:decimal(10,2)`)
---
## 完成标准
本阶段任务完成后,应该具备:
1. ✅ 完整的数据库迁移脚本(up 和 down)
2. ✅ 完整的 GORM 模型定义(所有表对应的 Go 结构体)
3. ✅ 完整的常量定义(所有枚举值)
4. ✅ 完整的数据库设计文档(ERD 图 + 表结构说明)
5. ✅ 完整的模型使用说明文档
6. ✅ 完整的轮询机制说明文档
7. ✅ 数据库迁移在本地测试通过
8. ✅ 所有代码遵循项目开发规范(命名、注释、格式)
**不包含**业务逻辑实现、API 接口、Service 层、Store 层、DTO、错误码、Redis Key 等。
---
## 关键设计说明
### 运营商表 (carriers)
- 存储运营商基础信息(中国移动、中国联通、中国电信)
- IoT 卡表通过 `carrier_id` 关联运营商表
### IoT 卡表 (iot_cards)
- `card_category` 字段:枚举值 "normal"(普通卡) | "industry"(行业卡),默认 "normal"
- **普通卡**: 需要实名认证才能激活使用
- **行业卡**: 不需要实名认证,可以在 `real_name_status` 为 0 的情况下激活使用
- `carrier_id` 关联运营商表(替代原来的 carrier 字符串字段)
- `enable_polling` 控制是否参与轮询(默认 true可手动禁用
- `last_data_check_at` 记录卡流量检查时间
- `last_real_name_check_at` 记录实名检查时间
### 套餐使用情况表 (package_usages)
- 核心业务表,跟踪套餐的激活、使用、过期情况
- 单卡套餐:`usage_type` = "single_card"`iot_card_id` 有值
- 设备级套餐:`usage_type` = "device"`device_id` 有值
- `data_usage_mb` 通过汇总卡的流量计算(不是实时轮询,而是定期统计)
### 轮询配置表 (polling_configs)
- 支持梯度配置(未实名卡、实名卡使用不同的轮询策略)
- 支持按运营商配置不同的轮询频率
- 独立配置三种轮询:实名检查、卡流量检查、套餐流量检查
- `priority` 数字越小优先级越高
### 流量使用记录表 (data_usage_records)
- 记录每次卡流量检查的结果
- 支持按卡、按时间范围查询流量历史
- 数据量会快速增长,建议定期清理 90 天前的记录或使用分区表
### 轮询逻辑(概念说明)
1. **卡流量轮询**:只轮询有生效套餐的卡,`enable_polling = true`
2. **套餐流量检查**:定期汇总卡的流量,判断套餐是否超额
3. **实名状态轮询**:定期检查卡的实名状态,实名后降低轮询频率
- **行业卡特殊处理**: 行业卡的实名状态检查应该被禁用或设置为低优先级
4. **三个流程独立运行**:互不干扰,通过轮询配置表动态控制
### 分佣解冻逻辑(概念说明)
1. **一次性分佣**: 普通卡需要实名认证后才能解冻;行业卡无需实名认证,只需满足激活和充值条件
2. **长期分佣**: 普通卡需要实名认证后才能开始长期分佣;行业卡无需实名认证,满足其他条件即可
3. **组合分佣**: 行业卡的时间点条件从激活时开始计算(不是实名时)