# API v2 Agent 接口文档

本文档面向 AI Agent 及外部自动化调用方，描述 `/api/v2/ai/` 前缀下的所有接口。

## 基本约定

- Base URL: `/api/v2/ai`
- 认证：所有接口使用固定 API Key，通过 `Authorization` 请求头直接传入（无 `Bearer` 前缀）
- 多商户隔离：每个接口均需传入 `merchant_id` 查询参数，后端以此确定数据范围

### 认证方式

```
# API v2 Agent 接口

本文档描述 `api/v2/ai/...` 下供内部 agent 调用的简化鉴权接口。

## 鉴权方式

- 使用请求头 `Authorization`
- 直接传入固定密钥
- 不使用 `Bearer` 前缀

示例：

```bash
curl -X GET \
  'https://api.example.com/api/v2/ai/mes/devices/?merchant_id=1' \
  -H 'Authorization: your-agent-access-key'
```

配置项：

- [`AGENT_ACCESS_KEY`](/home/f/coding/flower/flower/settings.py)

---

## 查询未进入送货单的出货单

- **URL**: `/api/v2/ai/shipments/unshipped/`
- **Method**: `GET`

### 查询参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | int | 是 | 商户 ID |
| `area` | string | 是 | 地区，精确匹配 |
| `limit` | int | 否 | 分页大小 |
| `offset` | int | 否 | 分页偏移 |

### 错误响应

#### 401 Unauthorized

```json
{
  "detail": "AGENT_ACCESS_KEY 无效"
}
```

#### 400 Bad Request

```json
{
  "merchant_id": ["This field is required."]
}
```

## 查询 MES 设备列表

- **URL**: `/api/v2/ai/mes/devices/`
- **Method**: `GET`

### 查询参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | int | 是 | 商户 ID |
| `limit` | int | 否 | 分页大小 |
| `offset` | int | 否 | 分页偏移 |

### 说明

- 返回当前商户下全部 MES 设备
- 每条记录包含所属设备分类信息
- 使用与其他 agent 接口相同的固定密钥鉴权方式，不走 JWT

## 查询指定日期范围内的 MES 生产安排

- **URL**: `/api/v2/ai/mes/production-assignments/`
- **Method**: `GET`

### 查询参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | int | 是 | 商户 ID |
| `start_date` | date | 是 | 开始日期，格式 `YYYY-MM-DD` |
| `end_date` | date | 是 | 结束日期，格式 `YYYY-MM-DD` |
| `device_id` | int | 否 | 设备 ID，可选筛选 |
| `status` | int | 否 | 状态值，可选筛选 |
| `limit` | int | 否 | 分页大小 |
| `offset` | int | 否 | 分页偏移 |

### 当前实现说明

- 当前 MES 模型没有单独的排产日期字段
- 所以本接口当前是按 `created_at` 的日期范围过滤生产安排
- 也就是说，它查的是“这个时间范围内创建的生产安排”

说明：

- `material_capacities` 表示该车辆对不同物料的最大装载量（单位：条）
- 只返回 `merchant_id` 对应商户的车辆
- `VehicleType`（旧版车辆类型字典）和 `VehicleTransportRecord`（旧版司机车次记录）是已废弃的模型，不在此接口返回

## 运输车辆详情

- URL: `/api/v2/ai/transport-vehicles/<license_plate>/`
- Method: `GET`

路径参数：

| 参数 | 说明 |
|------|------|
| `license_plate` | 车牌号码（URL 编码，如 `粤A12345` → `%E7%B2%A4A12345`） |

查询参数：

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | int | 是 | 商户 ID |

说明：

- 同一商户内 `license_plate` 唯一（数据库 `unique_together: merchant + license_plate`），因此 `merchant_id + license_plate` 可精确定位一辆车
- 不同商户可能存在相同车牌号，`merchant_id` 参数是必须的
- 车辆不存在时返回 `404`

成功响应：`TransportVehicle`

---

## 未出货出货单列表

- URL: `/api/v2/ai/shipments/unshipped/`
- Method: `GET`

查询参数：

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | int | 是 | 商户 ID |
| `area` | string | 是 | 地区筛选（精确匹配） |
| `limit` | int | 否 | 分页每页数量 |
| `offset` | int | 否 | 分页偏移量 |

说明：

- "未出货"定义：`delivery` 为空，即尚未关联送货单
- `delivery_id` 始终返回送货单ID；未关联时为 `null`
- `fabric` 来自该出货单所关联销售品对应生产订单的 `fabric`；若当前出货单没有销售品则返回 `null`
- `order_description` 当前来自该出货单所关联销售品对应生产订单的 `rolling_warn`；若当前出货单没有销售品则返回 `null`
- 结果按 `created_at` 降序排列
- 只返回 `merchant_id` 对应商户的数据
- `sales_items` 包含该出货单的所有销售品（软删除的条目自动排除）
- `sales_items[].printing_job_width`：对应 `PrintingJob → PrintingOrder.width`；若无关联印染任务则为 `null`

响应为分页结构，`results` 中每条为 `Shipment`。
