## 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 错误
