## ADDED Requirements ### Requirement: 设备授权企业数据模型 系统 SHALL 定义 EnterpriseDeviceAuthorization 实体,记录设备与企业的授权关系。 **实体字段**: - `id`: 主键(BIGSERIAL) - `enterprise_id`: 被授权企业ID(BIGINT,NOT NULL) - `device_id`: 被授权设备ID(BIGINT,NOT NULL) - `authorized_by`: 授权人账号ID(BIGINT,NOT NULL) - `authorized_at`: 授权时间(TIMESTAMP,NOT NULL) - `authorizer_type`: 授权人类型(SMALLINT,2=平台用户 3=代理账号) - `revoked_by`: 回收人账号ID(BIGINT,可空) - `revoked_at`: 回收时间(TIMESTAMP,可空) - `remark`: 备注(VARCHAR(500)) - `created_at`, `updated_at`, `deleted_at`: 标准时间字段 **唯一性约束**: - 一个设备同时只能授权给一个企业:`UNIQUE (device_id) WHERE revoked_at IS NULL AND deleted_at IS NULL` **表名**:`tb_enterprise_device_authorization` #### Scenario: 创建设备授权记录 - **WHEN** 授权设备给企业时 - **THEN** 系统创建 EnterpriseDeviceAuthorization 记录,authorized_at 设置为当前时间,revoked_at 为 NULL #### Scenario: 设备重复授权被拒绝 - **WHEN** 尝试将已授权给企业A的设备(未回收)再授权给企业B - **THEN** 系统拒绝操作,返回错误"设备已授权给其他企业" #### Scenario: 回收后可重新授权 - **WHEN** 设备授权已被回收后,重新授权给同一企业或其他企业 - **THEN** 系统允许创建新的授权记录 --- ### Requirement: 卡授权记录关联设备授权 系统 SHALL 在 EnterpriseCardAuthorization 表中添加 device_auth_id 字段,关联设备授权记录。 **新增字段**: - `device_auth_id`: 关联的设备授权ID(BIGINT,可空) - NULL = 通过单卡授权创建 - 有值 = 通过设备授权创建 **索引**: - `idx_eca_device_auth ON tb_enterprise_card_authorization(device_auth_id)` #### Scenario: 设备授权创建关联卡授权 - **WHEN** 通过设备授权创建卡授权记录时 - **THEN** 卡授权记录的 device_auth_id 字段设置为对应的设备授权ID #### Scenario: 单卡授权不关联设备 - **WHEN** 通过单卡授权创建卡授权记录时 - **THEN** 卡授权记录的 device_auth_id 字段为 NULL --- ### Requirement: 设备授权管理功能 系统 SHALL 提供设备授权给企业的功能,支持批量授权和回收。 **授权规则**: - 代理只能授权自己店铺的设备给自己店铺下的企业 - 平台可以授权任意设备给任意企业 - 设备 MUST 属于操作者(平台或代理店铺) - 设备 MUST 处于"已分销"状态(status=2) - 设备 MUST 未授权给其他企业(唯一性约束) **授权联动**: - 授权设备时,系统 SHALL 自动授权设备下所有已绑定的卡 - 卡授权记录的 device_auth_id 指向设备授权记录 - 如果设备没有绑定卡,仍然创建设备授权记录(无卡授权) #### Scenario: 代理授权设备给自己的企业 - **WHEN** 代理(shop_id=10)将自己店铺的设备授权给企业(owner_shop_id=10) - **THEN** 系统创建设备授权记录,并为设备下所有已绑定的卡创建卡授权记录 #### Scenario: 平台授权任意设备 - **WHEN** 平台管理员授权设备给任意企业 - **THEN** 系统创建授权记录,不检查设备和企业的归属关系 #### Scenario: 代理无法授权其他店铺的设备 - **WHEN** 代理(shop_id=10)尝试授权其他店铺的设备(shop_id=20) - **THEN** 系统拒绝操作,返回权限错误 #### Scenario: 设备授权联动卡授权 - **WHEN** 授权一个绑定了3张卡的设备给企业 - **THEN** 系统创建1条设备授权记录和3条卡授权记录,所有卡授权的 device_auth_id 指向该设备授权 --- ### Requirement: 批量授权设备接口 系统 SHALL 提供批量授权设备给企业的后台接口。 **接口设计**: - 路径:`POST /api/admin/enterprises/:id/allocate-devices` - 请求体: ```json { "device_nos": ["D001", "D002", "D003"], "remark": "批量授权备注" } ``` - 响应体: ```json { "success_count": 2, "fail_count": 1, "failed_items": [ { "device_no": "D003", "reason": "设备不存在" } ], "authorized_devices": [ { "device_id": 1, "device_no": "D001", "card_count": 3 }, { "device_id": 2, "device_no": "D002", "card_count": 2 } ] } ``` **处理流程**: 1. 验证企业存在且有权限 2. 验证每个设备的授权权限 3. 检查设备状态和唯一性约束 4. 在事务内创建设备授权和卡授权记录 5. 返回处理结果 #### Scenario: 批量授权成功 - **WHEN** 平台批量授权3个符合条件的设备给企业 - **THEN** 系统创建3条设备授权记录和对应的卡授权记录,返回全部成功 #### Scenario: 批量授权部分成功 - **WHEN** 代理批量授权3个设备,其中1个已授权给其他企业 - **THEN** 系统创建2条设备授权记录,返回2个成功、1个失败及失败原因 --- ### Requirement: 设备授权回收功能 系统 SHALL 提供回收设备授权的功能,回收时同步回收关联的卡授权。 **回收规则**: - 代理可以回收自己授权的设备 - 平台可以回收任何设备授权 - 回收操作在事务内完成 **回收联动**: - 回收设备授权时,系统 SHALL 同步回收所有 device_auth_id 指向该设备授权的卡授权记录 - 更新 revoked_at 和 revoked_by 字段 **接口设计**: - 路径:`POST /api/admin/enterprises/:id/recall-devices` - 请求体: ```json { "device_nos": ["D001", "D002"] } ``` #### Scenario: 回收设备授权联动回收卡授权 - **WHEN** 回收一个绑定了3张卡的设备的授权 - **THEN** 系统更新设备授权的 revoked_at,同时更新3条关联卡授权的 revoked_at #### Scenario: 回收后企业无法访问设备和卡 - **WHEN** 设备授权被回收后,企业用户查询设备或卡 - **THEN** 系统不返回该设备和其下的卡 --- ### Requirement: 后台企业设备列表 系统 SHALL 提供后台管理查询企业授权设备列表的接口。 **接口设计**: - 路径:`GET /api/admin/enterprises/:id/devices` - 查询参数:`page`, `page_size`, `device_no`, `status` - 响应:设备列表,包含设备信息和绑定卡数量 **数据权限**: - 平台用户可查看所有企业的授权设备 - 代理用户只能查看自己店铺下企业的授权设备 #### Scenario: 查询企业授权设备列表 - **WHEN** 管理员查询企业ID=5的授权设备 - **THEN** 系统返回该企业所有授权设备列表,每个设备包含绑定卡数量 --- ### Requirement: 企业端设备列表 系统 SHALL 提供企业用户查询自己授权设备列表的 H5 接口。 **接口设计**: - 路径:`GET /api/h5/enterprise/devices` - 查询参数:`page`, `page_size`, `device_no` - 响应: ```json { "list": [ { "device_id": 1, "device_no": "D001", "device_name": "GPS追踪器-001", "device_model": "GT-100", "card_count": 3, "authorized_at": "2025-01-29T10:00:00Z" } ], "total": 10 } ``` **数据权限**: - 企业用户只能看到授权给自己企业的设备 - 通过 GORM Callback 自动过滤 #### Scenario: 企业用户查看设备列表 - **WHEN** 企业用户查询设备列表 - **THEN** 系统返回授权给该企业的所有设备,包含设备信息和卡数量 #### Scenario: 企业用户无法看到未授权设备 - **WHEN** 企业用户查询设备列表 - **THEN** 系统不返回未授权给该企业的设备 --- ### Requirement: 企业端设备详情 系统 SHALL 提供企业用户查询设备详情的 H5 接口,包含设备绑定的卡列表。 **接口设计**: - 路径:`GET /api/h5/enterprise/devices/:device_id` - 响应: ```json { "device": { "device_id": 1, "device_no": "D001", "device_name": "GPS追踪器-001", "device_model": "GT-100", "device_type": "GPS", "authorized_at": "2025-01-29T10:00:00Z" }, "cards": [ { "card_id": 101, "iccid": "8986001234567890", "msisdn": "1380000001", "carrier_name": "中国联通", "network_status": 1, "network_status_name": "开机" } ] } ``` **可见信息**: - 设备基本信息:设备号、名称、型号、类型 - 卡信息:ICCID、MSISDN、运营商、网络状态 **不可见信息**: - 成本价、分销价、供应商等商业敏感信息 #### Scenario: 企业用户查看设备详情 - **WHEN** 企业用户查看授权设备ID=1的详情 - **THEN** 系统返回设备信息和该设备绑定的所有卡信息 #### Scenario: 企业用户无法查看未授权设备 - **WHEN** 企业用户尝试查看未授权的设备详情 - **THEN** 系统返回 404 错误 --- ### Requirement: 企业端设备卡停机复机 系统 SHALL 提供企业用户对设备下的卡进行停机/复机操作的 H5 接口。 **接口设计**: - 停机:`POST /api/h5/enterprise/devices/:device_id/cards/:card_id/suspend` - 复机:`POST /api/h5/enterprise/devices/:device_id/cards/:card_id/resume` **权限校验**: - 设备 MUST 授权给当前企业 - 卡 MUST 属于该设备(通过 device_sim_binding 验证) - 卡 MUST 通过设备授权(device_auth_id 不为空且有效) #### Scenario: 企业用户停机设备下的卡 - **WHEN** 企业用户对授权设备下的卡执行停机操作 - **THEN** 系统更新卡的 network_status 为 0(停机) #### Scenario: 企业用户复机设备下的卡 - **WHEN** 企业用户对授权设备下的卡执行复机操作 - **THEN** 系统更新卡的 network_status 为 1(开机) #### Scenario: 无法操作未授权设备的卡 - **WHEN** 企业用户尝试操作未授权设备下的卡 - **THEN** 系统返回 403 错误