# Shipment Status API 文档

本文档仅说明 `Shipment` 出货单状态流转接口。

## 接口信息

- URL: `/api/v1/shipment/shipments/{id}/status/`
- Method: `PATCH` / `PUT`
- 认证: 需要登录（JWT Token）

说明：

- 该接口只负责修改 `Shipment.status`
- 业务字段修改仍然使用 `/api/v1/shipment/shipments/{id}/`
- `PATCH` 与 `PUT` 当前行为一致，都是按请求体中的 `status` 执行状态流转
- 当前驳回逻辑有额外副作用：会解绑该出货单当前绑定的销售品，使其重新回到待分配池
- 驳回时后端会把解绑前的销售品 ID 保存到内部审计字段 `rejected_sales_item_ids`
- `rejected_sales_item_ids` 当前仅用于后端审计，暂不在 API 响应中返回

## 请求体

```json
{
  "status": 2
}
```

字段说明：

- `status`: 目标状态
  - `1 = 草稿(未发布)`
  - `2 = 已发布`
  - `3 = 已取消`
  - `4 = 已驳回`
  - `5 = 已审核`

## 状态机规则

- `草稿(未发布)` 只能流转到 `已发布`
- `已发布` 可以流转到 `已审核` / `已驳回` / `已取消`
- `已驳回` 目前只能流转到 `已取消`
- `已审核` 可以流转到 `已取消`
- `已取消` 不可再流转
- 重复设置同一状态时保持幂等

附加规则：

- 进入 `已审核` 时，接口会自动将当前 `request.user` 写入 `approved_by`
- 进入 `已取消` 时，接口会自动将当前 `request.user` 写入 `cancelled_by`
- 进入 `已驳回` 时，接口会先记录当前绑定销售品 ID 的审计快照，再解除这些销售品与当前出货单的绑定
- 驳回完成后，这些销售品会重新出现在默认的“待出货/待分配”查询结果中
- 每次成功状态流转都会更新 `status_modified_at`

说明：

- 由于驳回现在会解绑销售品，`已驳回 -> 已审核` 已暂时关闭，避免出现“空出货单被审核”的状态语义冲突

## 请求示例

### 1. 草稿发布

```http
PATCH /api/v1/shipment/shipments/12/status/
Content-Type: application/json

{
  "status": 2
}
```

### 2. 已发布审核

```http
PUT /api/v1/shipment/shipments/12/status/
Content-Type: application/json

{
  "status": 5
}
```

### 3. 已发布驳回

```http
PATCH /api/v1/shipment/shipments/12/status/
Content-Type: application/json

{
  "status": 4
}
```

## 成功响应示例

```json
{
  "id": 12,
  "merchant_id": 1,
  "merchant_name": "测试印花厂",
  "customer": 8,
  "customer_name": "客户A",
  "shipment_date": "2026-04-06",
  "address": "",
  "contact_name": "",
  "contact_phone": "",
  "area": "",
  "remark": "",
  "status": 5,
  "status_display": "已审核",
  "external_id": null,
  "status_modified_at": "2026-04-06T14:30:00+08:00",
  "cancelled_by_id": null,
  "cancelled_by_name": null,
  "approved_by_id": 3,
  "approved_by_name": "测试员工",
  "items_count": 2,
  "sales_items": [],
  "external_finished_products": [],
  "created_by_id": 3,
  "created_by_name": "测试员工",
  "created_at": "2026-04-06T10:00:00+08:00",
  "updated_at": "2026-04-06T14:30:00+08:00"
}
```

## 错误响应示例

### 1. 非法流转

```json
{
  "detail": "不允许将出货单状态从 草稿(未发布) 修改为 已审核"
}
```

### 2. 已驳回后再次审核

```json
{
  "detail": "不允许将出货单状态从 已驳回 修改为 已审核"
}
```

### 3. 越权或对象不存在

```json
{
  "detail": "Not found."
}
```

### 4. 请求体不合法

```json
{
  "status": [
    "\"99\" is not a valid choice."
  ]
}
```
