# 设备 CSV 批量分配功能总结

## 功能边界

本功能复用现有设备导入任务的对象存储、任务状态、Asynq 队列、进度统计和失败明细能力。复用的是异步任务外壳，原多列 Excel 创建设备与绑卡逻辑保持不变。

新增任务创建接口：

```text
POST /api/admin/devices/import/allocations
```

请求参数：

```json
{
  "file_key": "device-batch-allocations/2026/07/25/example.csv",
  "operation_type": "assign_shop",
  "target_id": 1001
}
```

- `assign_shop`：`target_id` 为目标代理店铺 ID。
- `assign_series`：`target_id` 为目标套餐系列 ID。
- 每个任务只能选择一种操作和一个目标，不能逐行指定不同目标。

## CSV 格式

CSV 只能有一列，每行填写一个设备标识，支持 VirtualNo、IMEI 或 SN。首行可选使用 `device_identifier` 或 `设备标识` 表头。文件必须使用上传用途 `device_batch_allocation` 获取对象存储 Key，最多 1000 个设备且不超过 10MB。

## 规则复用与幂等

Worker 批量解析设备后调用现有业务方法：

- 分配代理调用 `DeviceService.AllocateDevices`，沿用直属下级、平台库存、绑定卡归属同步、分配记录和资产审计规则。
- 设置套餐系列调用 `DeviceService.BatchSetSeriesBinding`，沿用套餐系列有效性、代理授权、设备归属和资产审计规则。

任务创建时冻结操作者 ID、类型和店铺 ID，Worker 重建权限上下文，不能因异步执行丢失数据范围。重复消费时，已经属于目标店铺或已经绑定目标系列的设备直接按成功处理；任务完成或失败后不重复执行。CSV 内重复设备记录为跳过，不产生重复副作用。

## 任务查询与回滚

继续使用现有接口查询任务：

```text
GET /api/admin/devices/import/tasks
GET /api/admin/devices/import/tasks/:id
```

响应新增 `operation_type`、`operation_name` 和 `target_id`，逐行失败原因继续通过原详情结构返回。

回滚应用版本前应先停止新任务入口并等待处理中的任务结束。迁移新增列保持兼容，不删除既有任务；已经完成的设备归属、套餐系列关系、分配记录和资产审计不得通过清表回滚，应使用现有回收或系列绑定接口前向修正。
