Files
junhong_cmp_fiber/openspec/changes/archive/2026-01-12-iot-sim-management/specs/iot-device/spec.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

13 KiB
Raw Blame History

ADDED Requirements

Requirement: 设备实体定义

系统 SHALL 定义设备(Device)实体,用于管理用户的物联网设备(如 GPS 追踪器、智能传感器等),支持设备与 IoT 卡的绑定关系、设备批量分配和设备操作。

核心概念: 设备不在卡管系统中销售,主要用于:

  1. 用户设备管理(用户添加自己的设备,绑定 IoT 卡)
  2. 方便运营人员管理投诉和代理要求(通过设备维度批量查看绑定的所有 IoT 卡)
  3. 设备操作(重启、修改账号密码、重置等)
  4. 设备批量分配(运营人员在别的系统报单后发货,把设备和绑定的 IoT 卡一起分配给代理)

实体字段:

基本属性:

  • id: 设备 ID(主键,BIGINT)
  • device_no: 设备编号(唯一,VARCHAR(50))
  • device_name: 设备名称(VARCHAR(255))
  • device_model: 设备型号(VARCHAR(100))
  • device_type: 设备类型(VARCHAR(50),如 "GPS Tracker"、"Camera"、"Sensor")
  • max_sim_slots: 最大 IoT 卡插槽数量(INT,1-4,默认 4)
  • manufacturer: 设备制造商(VARCHAR(255),可选)
  • batch_no: 批次号(VARCHAR(100),用于批量导入追溯)

所有权和状态:

  • owner_type: 所有者类型(VARCHAR(20),"platform"-平台库存(等待分配) | "agent"-代理商 | "user"-用户)
  • owner_id: 所有者 ID(BIGINT,platform 时为 0,agent/user 时为对应的 ID)
  • status: 设备状态(INT,1-未激活 2-已激活 3-已停用)
  • activated_at: 激活时间(TIMESTAMP,可空)

设备操作配置(预留字段,用于后续设备操作功能):

  • device_username: 设备登录账号(VARCHAR(100),可选)
  • device_password_encrypted: 设备登录密码(加密存储,TEXT,可选)
  • device_api_endpoint: 设备 API 接口地址(VARCHAR(500),可选)

系统字段:

  • created_at: 创建时间(TIMESTAMP,自动填充)
  • updated_at: 更新时间(TIMESTAMP,自动填充)

Scenario: 用户添加设备

  • WHEN 用户添加自己的设备(设备编号为 "GPS-001",设备名称为 "物流车辆追踪器")
  • THEN 系统创建设备记录,owner_type 为 "user",owner_id 为用户 ID,状态为 1(未激活)

Scenario: 平台导入设备到库存

  • WHEN 平台批量导入设备数据(准备发货给代理)
  • THEN 系统创建设备记录,owner_type 为 "platform",owner_id 为 0,状态为 1(未激活)

Scenario: 运营人员批量分配设备给代理

  • WHEN 运营人员将平台库存设备(ID 为 1001)分配给代理商(用户 ID 为 123)
  • THEN 系统将设备的 owner_type 变更为 "agent",owner_id 设置为 123,同时自动分配该设备绑定的所有 IoT 卡给代理

Requirement: 设备状态流转

系统 SHALL 管理设备的状态流转,确保状态变更符合业务规则。

状态定义:

  • 1-未激活: 设备尚未激活使用
  • 2-已激活: 设备已被用户激活使用
  • 3-已停用: 设备已停用,不可使用

状态流转规则:

  • 未激活(1) → 已激活(2): 用户激活设备
  • 已激活(2) → 已停用(3): 用户或平台主动停用设备
  • 已停用(3) → 已激活(2): 用户或平台主动恢复设备(仅在符合业务规则时)

Scenario: 用户激活设备

  • WHEN 用户激活自己的设备
  • THEN 系统将设备状态从 1(未激活) 变更为 2(已激活),activated_at 记录激活时间

Scenario: 用户停用设备

  • WHEN 用户停用已激活的设备
  • THEN 系统将设备状态从 2(已激活) 变更为 3(已停用),同时可选择是否停用该设备绑定的所有 IoT 卡

Requirement: 设备与 IoT 卡绑定关系

系统 SHALL 管理设备与 IoT 卡的绑定关系,一个设备可以绑定 1-4 张 IoT 卡。

绑定规则:

  • 一个设备最多绑定 4 张 IoT 卡(由 max_sim_slots 字段控制)
  • 一个 IoT 卡同一时间只能绑定一个设备
  • 绑定时记录插槽位置(slot_position: 1, 2, 3, 4)
  • 绑定时记录绑定时间和绑定状态(1-已绑定 2-已解绑)
  • 设备绑定 IoT 卡后,IoT 卡的 owner_type 变更为 "device",owner_id 变更为设备 ID

中间表 device_sim_bindings:

  • id: 绑定记录 ID(主键,BIGINT)
  • device_id: 设备 ID(BIGINT)
  • iot_card_id: IoT 卡 ID(BIGINT)
  • slot_position: 插槽位置(INT,1-4)
  • bind_status: 绑定状态(INT,1-已绑定 2-已解绑)
  • bind_time: 绑定时间(TIMESTAMP)
  • unbind_time: 解绑时间(TIMESTAMP,可空)
  • created_at: 创建时间(TIMESTAMP,自动填充)
  • updated_at: 更新时间(TIMESTAMP,自动填充)

Scenario: 绑定 IoT 卡到设备

  • WHEN 用户将 IoT 卡(ID 为 101)绑定到设备(ID 为 1001)的插槽 1
  • THEN 系统创建绑定记录,device_id 为 1001,iot_card_id 为 101,slot_position 为 1,bind_status 为 1(已绑定),bind_time 为当前时间,IoT 卡的 owner_type 变更为 "device",owner_id 变更为 1001

Scenario: 绑定超过最大插槽数量

  • WHEN 用户尝试将第 5 张 IoT 卡绑定到最大插槽数为 4 的设备
  • THEN 系统拒绝绑定,返回错误信息"设备插槽已满,最多支持 4 张 IoT 卡"

Scenario: 绑定已被占用的 IoT 卡

  • WHEN 用户尝试绑定已被其他设备绑定的 IoT 卡
  • THEN 系统拒绝绑定,返回错误信息"该 IoT 卡已被其他设备绑定"

Scenario: 解绑 IoT 卡

  • WHEN 用户解绑设备的 IoT 卡(绑定记录 ID 为 10)
  • THEN 系统将绑定记录的 bind_status 从 1(已绑定) 变更为 2(已解绑),unbind_time 记录解绑时间,IoT 卡的 owner_typeowner_id 重置

Scenario: 查询设备当前绑定的 IoT 卡

  • WHEN 用户查询设备(ID 为 1001)当前绑定的 IoT 卡
  • THEN 系统返回 device_id 为 1001 且 bind_status 为 1(已绑定) 的所有绑定记录,包含 IoT 卡信息(ICCID、运营商、激活状态等)和插槽位置

Requirement: 设备套餐购买和流量共享

系统 SHALL 支持用户为设备购买套餐,套餐自动分配到设备绑定的所有 IoT 卡,流量在设备级别共享。

设备套餐业务规则:

  • 用户为设备购买套餐时,套餐会分配到设备绑定的所有 IoT 卡(1-4 张)
  • 套餐的流量是设备级别共享的(例如 3000G/月共享,不管用哪张卡)
  • 分佣只计算一次(不按卡数倍增)
  • 订单表通过 device_id 字段关联设备,通过 device_sim_bindings 表查找绑定的所有 IoT 卡

套餐分配示例:

  • 设备绑定 3 张 IoT 卡
  • 用户购买套餐:399 元/年,每月 3000G 流量,长期佣金 100 元
  • 用户支付:399 元
  • 套餐分配:设备的 3 张 IoT 卡都获得该套餐
  • 流量使用:3000G/月 在 3 张卡之间共享(不是每张卡 3000G,而是总共 3000G)
  • 分佣:代理获得 100 元分佣(只分一次,不是 3 × 100 元)

Scenario: 用户为设备购买套餐

  • WHEN 用户为设备(ID 为 1001,绑定 3 张 IoT 卡)购买套餐(套餐 ID 为 3001,399 元/年,3000G/月)
  • THEN 系统创建套餐订单,device_id 为 1001,package_id 为 3001,订单金额为 399 元,将套餐分配到设备绑定的 3 张 IoT 卡,设置流量共享模式为设备级别

Scenario: 设备级流量共享

  • WHEN 设备(ID 为 1001)的套餐流量为 3000G/月,设备绑定 3 张 IoT 卡
  • THEN 系统设置流量共享模式,3 张 IoT 卡共享 3000G/月(不是每张卡 3000G),无论使用哪张卡,都从这个流量池扣除

Scenario: 设备套餐分佣

  • WHEN 用户为设备购买套餐,订单金额为 399 元,代理的长期分佣规则为 100 元
  • THEN 系统为代理创建一条分佣记录,分佣金额为 100 元(只分一次,不按设备绑定的卡数倍增)

Requirement: 设备批量分配

系统 SHALL 支持运营人员批量分配设备给代理,设备分配时自动分配该设备绑定的所有 IoT 卡。

分配规则:

  • 只能分配 owner_type 为 "platform" 的设备(平台库存)
  • 分配时,设备的 owner_type 变更为 "agent",owner_id 设置为代理用户 ID
  • 分配时,设备绑定的所有 IoT 卡的 owner_type 也变更为 "agent",owner_id 设置为代理用户 ID
  • 分配操作记录到操作日志

Scenario: 运营人员批量分配设备

  • WHEN 运营人员将 10 台设备(平台库存)分配给代理商(用户 ID 为 123)
  • THEN 系统将这 10 台设备的 owner_type 变更为 "agent",owner_id 设置为 123,同时将这些设备绑定的所有 IoT 卡也分配给代理 123

Scenario: 分配已分配的设备

  • WHEN 运营人员尝试分配 owner_type 为 "agent" 的设备
  • THEN 系统拒绝分配,返回错误信息"该设备已分配给代理,不能重复分配"

Requirement: 设备操作

系统 SHALL 支持对设备的远程操作(重启、修改账号密码、重置等),用于设备管理和故障排查。

设备操作类型:

  • 重启设备: 远程重启设备
  • 修改账号密码: 修改设备的登录账号和密码
  • 重置设备: 将设备恢复到出厂设置
  • 查询设备状态: 查询设备的在线状态、运行状态等
  • 设备配置更新: 更新设备的配置参数

操作说明:

  • 本阶段只设计数据模型字段和接口定义,不实现设备操作的具体代码
  • 后续 Service 层将调用设备厂商提供的 API 或通过 MQTT/HTTP 协议与设备通信
  • 设备操作需要记录操作日志(操作类型、操作人、操作时间、操作结果)

Scenario: 重启设备

  • WHEN 用户或运营人员请求重启设备(ID 为 1001)
  • THEN 系统调用设备 API 发送重启命令,记录操作日志,返回操作结果

Scenario: 修改设备密码

  • WHEN 用户或运营人员修改设备(ID 为 1001)的登录密码
  • THEN 系统更新设备的 device_password_encrypted 字段(加密存储),调用设备 API 同步密码修改,记录操作日志

Requirement: 设备批量导入

系统 SHALL 支持批量导入设备数据,用于平台库存管理。

导入字段:

  • 设备编号(必填)
  • 设备名称(必填)
  • 设备型号(必填)
  • 设备类型(必填)
  • 最大插槽数(可选,默认 4)
  • 设备制造商(可选)
  • 批次号(必填)

导入规则:

  • 设备编号必须唯一,重复编号将被拒绝
  • 导入的设备默认 owner_type 为 "platform",owner_id 为 0,状态为 1(未激活)
  • 导入成功后记录操作日志

Scenario: 批量导入设备成功

  • WHEN 平台上传包含 50 条设备数据的 CSV 文件
  • THEN 系统创建 50 条设备记录,owner_type 为 "platform",owner_id 为 0,状态为 1(未激活),返回导入成功消息

Scenario: 批量导入包含重复编号

  • WHEN 平台上传的 CSV 文件中包含已存在的设备编号
  • THEN 系统拒绝重复编号的设备,返回错误信息并列出重复编号,其他有效设备正常导入

Requirement: 设备查询和筛选

系统 SHALL 支持多维度查询和筛选设备,包括状态、所有者、批次号、设备类型等。

查询条件:

  • 设备编号(精确匹配或模糊匹配)
  • 设备名称(模糊匹配)
  • 设备状态(单选或多选)
  • 所有者类型(platform | agent | user)
  • 所有者 ID(仅当所有者类型为 agent/user 时有效)
  • 批次号(精确匹配)
  • 设备类型(单选或多选)
  • 设备制造商(模糊匹配)
  • 激活时间范围(开始时间 - 结束时间)
  • 创建时间范围(开始时间 - 结束时间)

分页:

  • 默认每页 20 条,最大每页 100 条
  • 返回总记录数和总页数

Scenario: 查询平台库存设备

  • WHEN 运营人员查询平台库存设备
  • THEN 系统返回 owner_type 为 "platform" 的设备列表

Scenario: 代理查询自己的设备

  • WHEN 代理商(用户 ID 为 123)查询自己的设备
  • THEN 系统返回 owner_type 为 "agent" 且 owner_id 为 123 的设备列表

Scenario: 用户查询自己的设备

  • WHEN 用户(用户 ID 为 2001)查询自己的设备
  • THEN 系统返回 owner_type 为 "user" 且 owner_id 为 2001 的设备列表,包含设备绑定的所有 IoT 卡信息

Scenario: 运营人员通过设备查看绑定的所有 IoT 卡

  • WHEN 运营人员需要处理投诉,查询设备(ID 为 1001)绑定的所有 IoT 卡
  • THEN 系统返回设备信息和绑定的所有 IoT 卡详细信息(ICCID、运营商、激活状态、流量使用等),方便统一查看和管理

Requirement: 设备数据校验

系统 SHALL 对设备数据进行校验,确保数据完整性和一致性。

校验规则:

  • 设备编号(device_no):必填,长度 1-50 字符,唯一
  • 设备名称(device_name):必填,长度 1-255 字符
  • 设备型号(device_model):必填,长度 1-100 字符
  • 设备类型(device_type):必填,长度 1-50 字符
  • 最大插槽数(max_sim_slots):必填,1-4 之间的整数
  • 所有者类型(owner_type):必填,枚举值 "platform" | "agent" | "user"
  • 所有者 ID(owner_id):必填,≥ 0,当 owner_type 为 "platform" 时必须为 0
  • 设备状态(status):必填,枚举值 1(未激活) | 2(已激活) | 3(已停用)

Scenario: 创建设备时插槽数超出范围

  • WHEN 用户创建设备,最大插槽数为 5
  • THEN 系统拒绝创建,返回错误信息"最大插槽数必须在 1-4 之间"

Scenario: 创建设备时设备编号重复

  • WHEN 用户创建设备,设备编号为已存在的 "DEV-001"
  • THEN 系统拒绝创建,返回错误信息"设备编号已存在"