# 禅道补充需求：代理系列套餐批量授权

> 来源：禅道 #43。最终口径以标准评审稿为准。

## 一、现状与范围

系统已经存在代理系列授权和套餐授权数据，后端 `PUT /api/admin/shop-series-grants/{id}/packages` 也已经接受套餐数组。本需求不是重建授权模型，而是补齐套餐候选 Query 和前端批量交互。

当前主要问题：

- 前端只能逐个授权套餐。
- 首次授权系列和后续管理套餐时，看不出哪些套餐已经授权给当前代理。
- 公司成本价、代理授权成本价和建议售价缺少明确区分。

## 二、套餐候选 Query

新增：

```text
GET /api/admin/shop-series-grants/{id}/package-options
```

查询参数支持套餐名称、编码和授权状态。响应：

```json
{
  "package_id": 1001,
  "package_name": "移动月包",
  "package_code": "CMCC-M01",
  "company_cost_price": 5000,
  "authorized_cost_price": 6500,
  "suggested_retail_price": 8800,
  "is_authorized": true,
  "shelf_status": 1,
  "status": 1
}
```

金额单位统一为分。`authorized_cost_price` 在未授权时返回 `null`。

## 三、批量授权

继续使用现有批量写接口：

```text
PUT /api/admin/shop-series-grants/{id}/packages
```

请求一次提交多个套餐：

```json
{
  "packages": [
    {"package_id": 1001, "cost_price": 6500},
    {"package_id": 1002, "cost_price": 7000}
  ]
}
```

- 同一请求内套餐 ID 必须去重。
- 已经授权且价格相同的套餐按幂等成功处理。
- 已经授权但价格不同的套餐不能被“新增授权”静默改价，应走明确的价格更新操作。
- 套餐必须属于当前授权系列，后端不能只相信前端候选列表。
- 批量写入在同一事务完成，任一套餐不合法则整批失败。

## 四、前端

首次创建系列授权和后续“管理套餐”共用同一个套餐选择组件：

- 表格使用复选框多选。
- 展示套餐名称、编码、公司成本价、当前授权成本价和建议售价。
- 已授权套餐显示“已授权”标签并置灰，不可选择。
- 支持只看未授权套餐和关键词搜索。
- 提交前显示本次新增套餐数量和价格摘要。

已授权置灰只是交互反馈，后端仍负责幂等和归属校验。

## 五、权限与审计

公司成本价属于敏感字段，只有具备系列授权和成本价查看权限的角色可以读取。审计记录代理、系列、套餐列表、授权价格、操作人和变更前后数据。

