# 企业设备授权功能实现总结

## 概述

实现了企业设备授权功能，取代原有的"设备捆绑"机制。新功能支持以设备为单位进行授权，授权后设备绑定的所有卡自动授权给企业。

## 核心变更

### 1. 数据库层

**新增表：`tb_enterprise_device_authorization`**
- 设备授权主表
- 关键字段：enterprise_id, device_id, authorized_by, authorized_at, revoked_at
- 唯一约束：一个设备同时只能授权给一个企业（通过部分唯一索引实现）

**修改表：`tb_enterprise_card_authorization`**
- 新增字段：`device_auth_id`（NULLABLE）
- 用途：标识卡是通过设备授权（有值）还是单卡授权（NULL）
- 关联：指向 `tb_enterprise_device_authorization.id`

### 2. Model 层

**新增模型**
- `model.EnterpriseDeviceAuthorization`：设备授权模型

**修改模型**
- `model.EnterpriseCardAuthorization`：添加 DeviceAuthID 字段

### 3. DTO 层

**新增 DTO（`dto/enterprise_device_authorization_dto.go`）**
- AllocateDevicesReq/Resp：授权设备
- RecallDevicesReq/Resp：撤销设备授权
- EnterpriseDeviceListReq/Resp：设备列表
- EnterpriseDeviceDetailResp：设备详情（含绑定卡）
- DeviceCardOperationReq/Resp：卡操作（停机/复机）

**废弃 DTO（`dto/enterprise_card_authorization_dto.go`）**
- DeviceBundle、DeviceBundleCard、AllocatedDevice 标记为 Deprecated

### 4. Store 层

**新增 Store**
- `postgres.EnterpriseDeviceAuthorizationStore`
  - Create/BatchCreate：创建授权
  - GetByID/GetByDeviceID/GetByEnterpriseID：查询授权
  - ListByEnterprise：分页查询
  - RevokeByIDs：撤销授权
  - GetActiveAuthsByDeviceIDs：批量检查授权状态

**修改 Store**
- `postgres.EnterpriseCardAuthorizationStore`
  - 新增 RevokeByDeviceAuthID()：级联撤销卡授权

### 5. Service 层

**新增 Service（`service/enterprise_device/service.go`）**
- AllocateDevices()：授权设备给企业
  - 验证设备状态（必须是"已分销"）
  - 验证设备所有权
  - 事务中创建设备授权 + 自动创建绑定卡授权
- RecallDevices()：撤销设备授权
  - 撤销设备授权
  - 级联撤销所有绑定卡授权
- ListDevices()：后台管理设备列表
- ListDevicesForEnterprise()：H5企业用户设备列表
- GetDeviceDetail()：设备详情（含绑定卡）
- SuspendCard/ResumeCard()：H5停机/复机

**Breaking Change：修改 Service**
- `service/enterprise_card/service.go`
  - AllocateCardsPreview()：移除 DeviceBundle 逻辑，绑定设备的卡直接拒绝
  - AllocateCards()：移除 ConfirmDeviceBundles 参数，只能授权单卡

### 6. Handler 层

**新增 Admin Handler（`handler/admin/enterprise_device.go`）**
- AllocateDevices：`POST /api/admin/enterprises/:id/allocate-devices`
- RecallDevices：`POST /api/admin/enterprises/:id/recall-devices`
- ListDevices：`GET /api/admin/enterprises/:id/devices`

**新增 H5 Handler（`handler/h5/enterprise_device.go`）**
- ListDevices：`GET /api/h5/enterprise/devices`
- GetDeviceDetail：`GET /api/h5/enterprise/devices/:device_id`
- SuspendCard：`POST /api/h5/enterprise/devices/:device_id/cards/:card_id/suspend`
- ResumeCard：`POST /api/h5/enterprise/devices/:device_id/cards/:card_id/resume`

### 7. 错误码

新增错误码（`pkg/errors/codes.go`）：
- `CodeDeviceAlreadyAuthorized` (1083)：设备已授权给此企业
- `CodeDeviceNotAuthorized` (1084)：设备未授权给此企业
- `CodeDeviceAuthorizedToOther` (1085)：设备已授权给其他企业
- `CodeCannotAuthorizeOthersDevice` (1086)：无权操作他人设备

## 业务规则

### 授权规则
1. **设备状态检查**：只能授权状态为"已分销"（status=2）的设备
2. **所有权验证**：代理用户只能授权自己店铺的设备
3. **唯一性约束**：一个设备同时只能授权给一个企业
4. **自动级联**：授权设备时，所有绑定的卡自动授权

### 撤销规则
1. **级联撤销**：撤销设备授权时，自动撤销所有绑定卡授权
2. **软删除**：通过设置 revoked_at 时间戳实现，保留历史记录

### H5 操作规则
1. **设备详情**：只能查看已授权给当前企业的设备
2. **停机/复机**：
   - 卡必须属于已授权设备
   - 卡必须通过设备授权方式授权（device_auth_id 不为空）
   - 只能操作当前企业的设备

## 数据权限

- **后台管理**：基于用户类型自动过滤（SuperAdmin/Platform 全部可见，Agent 只能看到自己店铺及下级）
- **H5企业用户**：自动过滤为当前企业的数据

## API 路由

### 后台管理 API
```
POST   /api/admin/enterprises/:id/allocate-devices   # 授权设备
POST   /api/admin/enterprises/:id/recall-devices     # 撤销授权
GET    /api/admin/enterprises/:id/devices            # 设备列表
```

### H5 企业 API
```
GET    /api/h5/enterprise/devices                              # 设备列表
GET    /api/h5/enterprise/devices/:device_id                   # 设备详情
POST   /api/h5/enterprise/devices/:device_id/cards/:card_id/suspend  # 停机
POST   /api/h5/enterprise/devices/:device_id/cards/:card_id/resume   # 复机
```

## 迁移说明

### 数据库迁移
已创建迁移文件：
- `migrations/000031_add_enterprise_device_authorization.up.sql`
- `migrations/000032_add_device_auth_id_to_enterprise_card_authorization.up.sql`

迁移已执行并验证成功。

### Breaking Changes

**企业卡授权 API 行为变更：**
1. `POST /api/admin/enterprises/:id/allocate-cards`
   - 不再接受 `confirm_device_bundles` 参数
   - 绑定设备的卡直接返回失败：`"该卡已绑定设备，请使用设备授权功能"`
   
2. **前端需要调整**：
   - 移除 DeviceBundle 相关 UI 和逻辑
   - 添加设备授权入口
   - 卡授权流程中处理"卡已绑定设备"错误

## 测试状态

### 已完成
- ✅ 数据库迁移验证
- ✅ 代码编译验证
- ✅ LSP 诊断通过

### 待完成（低优先级）
- ⏳ Store 层单元测试
- ⏳ Service 层单元测试
- ⏳ 修改 enterprise_card 服务测试（适配 Breaking Change）
- ⏳ 集成测试

## 文件清单

### 新增文件
- `migrations/000031_add_enterprise_device_authorization.up.sql`
- `migrations/000032_add_device_auth_id_to_enterprise_card_authorization.up.sql`
- `internal/model/enterprise_device_authorization.go`
- `internal/model/dto/enterprise_device_authorization_dto.go`
- `internal/store/postgres/enterprise_device_authorization_store.go`
- `internal/service/enterprise_device/service.go`
- `internal/handler/admin/enterprise_device.go`
- `internal/handler/h5/enterprise_device.go`
- `internal/routes/enterprise_device.go`
- `internal/routes/h5_enterprise_device.go`

### 修改文件
- `internal/model/enterprise_card_authorization.go`（添加 DeviceAuthID 字段）
- `internal/model/dto/enterprise_card_authorization_dto.go`（废弃 DeviceBundle）
- `internal/store/postgres/enterprise_card_authorization_store.go`（添加 RevokeByDeviceAuthID）
- `internal/service/enterprise_card/service.go`（移除 DeviceBundle 逻辑）
- `internal/bootstrap/stores.go`（注册新 Store）
- `internal/bootstrap/services.go`（注册新 Service）
- `internal/bootstrap/handlers.go`（注册新 Handler）
- `internal/bootstrap/types.go`（添加 Handler 字段）
- `internal/routes/admin.go`（注册后台路由）
- `internal/routes/h5.go`（注册 H5 路由）
- `pkg/errors/codes.go`（添加错误码）

## 后续工作

### 必要工作
1. **前端适配**：
   - 移除设备捆绑相关 UI
   - 添加设备授权管理界面
   - 处理新的错误码

2. **文档更新**：
   - 更新 API 文档（需要运行文档生成器）
   - 更新用户使用手册

### 可选工作
1. **测试补充**：按需补充单元测试和集成测试
2. **性能优化**：如有性能问题，可优化查询逻辑
3. **功能扩展**：如需要批量操作优化，可添加批量接口

## 总结

企业设备授权功能已完整实现，包括：
- ✅ 数据库表结构变更
- ✅ 完整的四层架构实现（Model/Store/Service/Handler）
- ✅ 后台管理 API 和 H5 API
- ✅ 错误处理和数据权限
- ✅ 事务保证和级联操作

功能已通过编译验证，可以部署测试。前端需要配合调整以支持新的授权流程。
