# 任务配货功能 API 需求文档

> **业务背景：** 布行预销售单场景，客户预定布料（如5000米），需要仓库人员配货、扫码录入每条布的米数，确认后转为正式销售单。
>
> **前端项目：** app-ui（移动端 Web 应用）
>
> **生成日期：** 2026-02-01

---

## 一、业务流程概述

```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  创建预销售单  │ -> │  生成任务配货  │ -> │  仓库扫码录入  │ -> │  确认转销售单  │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
     │                   │                   │                   │
     ▼                   ▼                   ▼                   ▼
  客户预定           任务分配给          扫码录入每条         客户确认数量
  5000米布料        仓库配货人员        布料的实际米数       转为正式销售单
```

### 角色说明

| 角色 | 操作 |
|------|------|
| 销售人员 | 创建预销售单，确认配货结果，转销售单 |
| 仓库人员 | 接收任务配货，扫码录入每条布的米数 |
| 客户 | 确认最终数量（可选，由销售人员代为确认） |

### 状态流转

```
预销售单状态：
  待配货(pending) → 配货中(allocating) → 待确认(confirming) → 已完成(completed) / 已取消(cancelled)

任务配货状态：
  待接收(pending) → 进行中(in_progress) → 已完成(completed) / 已取消(cancelled)
```

---

## 二、需要新增的 API

### 2.1 预销售单 API（移动端）

> 注：antd-demo 已有预销售单 API，需确认 app-ui 是否复用同一套接口

**复用现有接口：**
- `POST /api/v1/pre-sales-orders/` - 创建预销售单
- `GET /api/v1/pre-sales-orders/` - 预销售单列表
- `GET /api/v1/pre-sales-orders/{id}/` - 预销售单详情

**需要新增/调整：**
- 创建预销售单时**自动创建任务配货**（后端处理，或前端调用两个接口）
- 预销售单需要新增 `status` 字段表示配货状态

---

### 2.2 任务配货 API（新增）

#### 2.2.1 创建任务配货

> 可选择在创建预销售单时由后端自动创建，或由前端单独调用

- **路径：** `POST /api/v1/task-allocations/`
- **权限：** 需登录，需员工权限

**请求参数：**
```typescript
{
  pre_sales_order_id: number;     // 必填，关联的预销售单 ID
  assignee_id?: number;           // 可选，指派给哪个仓库员工（不填则待分配）
  priority?: number;              // 可选，优先级：1=普通，2=加急，默认1
  expected_date?: string;         // 可选，期望完成日期（ISO 8601）
  remarks?: string;               // 可选，备注
}
```

**响应数据：**
```typescript
{
  code: 200,
  message: "success",
  data: {
    id: number;                   // 任务配货 ID
    task_no: string;              // 任务编号（如 PH20260201000001）
    pre_sales_order_id: number;   // 关联预销售单 ID
    pre_sales_order_no: string;   // 预销售单编号（只读）
    customer_id: number;          // 客户 ID（从预销售单继承）
    customer_name: string;        // 客户名称（只读）
    warehouse_id: number;         // 仓库 ID（从预销售单继承）
    warehouse_name: string;       // 仓库名称（只读）
    assignee_id: number | null;   // 被指派的员工 ID
    assignee_name: string | null; // 被指派的员工名称（只读）
    status: number;               // 状态：1=待接收，2=进行中，3=已完成，4=已取消
    priority: number;             // 优先级
    expected_date: string | null; // 期望完成日期
    remarks: string | null;       // 备注
    created_by: number;           // 创建者 ID
    created_by_name: string;      // 创建者名称（只读）
    created_at: string;           // 创建时间
    
    // 配货需求（从预销售单明细复制）
    items: TaskAllocationItem[];
  }
}
```

**任务配货明细 `TaskAllocationItem`：**
```typescript
{
  id: number;                     // 明细 ID
  product_id: number;             // 产品 ID
  product_name: string;           // 产品名称
  spec: string | null;            // 规格
  color: string | null;           // 颜色
  required_quantity: string;      // 需求数量（如 "5000.00"）
  allocated_quantity: string;     // 已配货数量（如 "4800.00"）
  unit: string;                   // 单位
  status: number;                 // 明细状态：1=待配货，2=配货中，3=已完成
  
  // 扫码录入的布条记录
  rolls: TaskAllocationRoll[];
}
```

**布条记录 `TaskAllocationRoll`：**
```typescript
{
  id: number;                     // 记录 ID
  roll_code: string;              // 布条码/二维码内容
  quantity: string;               // 该条的米数（如 "50.00"）
  scanned_by: number;             // 扫码人员 ID
  scanned_by_name: string;        // 扫码人员名称（只读）
  scanned_at: string;             // 扫码时间
}
```

---

#### 2.2.2 任务配货列表

- **路径：** `GET /api/v1/task-allocations/`
- **权限：** 需登录，需员工权限

**查询参数：**
```typescript
{
  limit?: number;                 // 分页，默认20，最大100
  offset?: number;                // 偏移量，默认0
  status?: number;                // 按状态筛选：1/2/3/4
  assignee_id?: number;           // 按被指派人筛选（仓库人员查自己的任务）
  warehouse_id?: number;          // 按仓库筛选
  priority?: number;              // 按优先级筛选
  date_from?: string;             // 创建时间起始（ISO 8601）
  date_to?: string;               // 创建时间结束
}
```

**响应数据：**
```typescript
{
  count: number;
  next: string | null;
  previous: string | null;
  results: TaskAllocation[];      // 任务配货列表（不含 rolls 明细）
}
```

---

#### 2.2.3 任务配货详情

- **路径：** `GET /api/v1/task-allocations/{id}/`
- **权限：** 需登录

**响应数据：**
```typescript
{
  code: 200,
  data: TaskAllocation            // 完整数据，包含 items 和 rolls
}
```

---

#### 2.2.4 接收任务

> 仓库人员接收任务，状态从"待接收"变为"进行中"

- **路径：** `POST /api/v1/task-allocations/{id}/accept/`
- **权限：** 需登录，需仓库员工权限

**请求参数：** 无（后端自动设置当前用户为 assignee）

**响应数据：**
```typescript
{
  code: 200,
  message: "任务已接收",
  data: TaskAllocation
}
```

---

#### 2.2.5 扫码录入布条 ⭐

> 仓库人员扫码录入每条布的米数

- **路径：** `POST /api/v1/task-allocations/{id}/scan/`
- **权限：** 需登录，需仓库员工权限

**请求参数：**
```typescript
{
  item_id: number;                // 哪个产品明细
  roll_code: string;              // 布条码/二维码内容
  quantity: string | number;      // 该条的米数
}
```

**响应数据：**
```typescript
{
  code: 200,
  message: "录入成功",
  data: {
    roll: TaskAllocationRoll;     // 新增的布条记录
    item: TaskAllocationItem;     // 更新后的明细（含最新 allocated_quantity）
    task: {
      id: number;
      total_allocated: string;    // 总已配货数量
      total_required: string;     // 总需求数量
      progress: number;           // 进度百分比（0-100）
    }
  }
}
```

**错误响应：**
```typescript
// 布条码重复
{
  code: 400,
  message: "该布条已录入",
  data: {
    existing_roll: TaskAllocationRoll  // 已存在的记录
  }
}

// 超出需求数量
{
  code: 400,
  message: "配货数量已超出需求，是否继续？",
  data: {
    required: "5000.00",
    allocated: "5050.00",
    overflow: "50.00"
  }
}
```

---

#### 2.2.6 删除布条记录

> 录错了，删除某条扫码记录

- **路径：** `DELETE /api/v1/task-allocations/{id}/rolls/{roll_id}/`
- **权限：** 需登录，需仓库员工权限

**响应数据：**
```typescript
{
  code: 200,
  message: "删除成功",
  data: {
    item: TaskAllocationItem;     // 更新后的明细
  }
}
```

---

#### 2.2.7 完成配货

> 仓库人员完成配货，状态变为"已完成"

- **路径：** `POST /api/v1/task-allocations/{id}/complete/`
- **权限：** 需登录，需仓库员工权限

**请求参数：**
```typescript
{
  remarks?: string;               // 可选，完成备注
}
```

**响应数据：**
```typescript
{
  code: 200,
  message: "配货完成",
  data: TaskAllocation
}
```

**校验规则：**
- 所有明细的 `allocated_quantity` 必须 > 0
- 如果某明细未配货，返回 400 错误

---

#### 2.2.8 确认配货结果并转销售单 ⭐

> 销售人员/客户确认配货数量，将预销售单转为正式销售单

- **路径：** `POST /api/v1/task-allocations/{id}/confirm-and-convert/`
- **权限：** 需登录，需销售员工权限

**请求参数：**
```typescript
{
  confirmed_items: Array<{
    item_id: number;              // 明细 ID
    confirmed_quantity: string;   // 确认的数量（可能与实际配货数量不同）
  }>;
  remarks?: string;               // 可选，确认备注
}
```

**响应数据：**
```typescript
{
  code: 200,
  message: "已转为销售单",
  data: {
    task_allocation: TaskAllocation;  // 更新后的任务配货（状态变更）
    sales_order: {
      id: number;
      human_id: string;           // 销售单编号（如 XS20260201000001）
      // ... 其他销售单字段
    }
  }
}
```

---

### 2.3 预销售单状态扩展

现有预销售单 API 需要新增以下字段：

```typescript
// 响应中新增
{
  // ... 原有字段 ...
  
  allocation_status: number;      // 配货状态：1=待配货，2=配货中，3=待确认，4=已完成
  allocation_status_display: string;  // 配货状态文字（只读）
  task_allocation_id: number | null;  // 关联的任务配货 ID
  converted_sales_order_id: number | null;  // 转换后的销售单 ID
}
```

---

## 三、状态枚举值

### 3.1 任务配货状态

| 值 | 名称 | 说明 |
|----|------|------|
| 1 | pending | 待接收 |
| 2 | in_progress | 进行中 |
| 3 | completed | 已完成 |
| 4 | cancelled | 已取消 |

### 3.2 任务配货明细状态

| 值 | 名称 | 说明 |
|----|------|------|
| 1 | pending | 待配货 |
| 2 | allocating | 配货中 |
| 3 | completed | 已完成 |

### 3.3 预销售单配货状态

| 值 | 名称 | 说明 |
|----|------|------|
| 1 | pending | 待配货 |
| 2 | allocating | 配货中 |
| 3 | confirming | 待确认 |
| 4 | completed | 已完成 |

### 3.4 优先级

| 值 | 名称 | 说明 |
|----|------|------|
| 1 | normal | 普通 |
| 2 | urgent | 加急 |

---

## 四、API 路径汇总

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/v1/task-allocations/` | 创建任务配货 |
| GET | `/api/v1/task-allocations/` | 任务配货列表 |
| GET | `/api/v1/task-allocations/{id}/` | 任务配货详情 |
| POST | `/api/v1/task-allocations/{id}/accept/` | 接收任务 |
| POST | `/api/v1/task-allocations/{id}/scan/` | 扫码录入布条 |
| DELETE | `/api/v1/task-allocations/{id}/rolls/{roll_id}/` | 删除布条记录 |
| POST | `/api/v1/task-allocations/{id}/complete/` | 完成配货 |
| POST | `/api/v1/task-allocations/{id}/confirm-and-convert/` | 确认并转销售单 |

---

## 五、前端页面规划

### 5.1 页面路由

| 路由 | 页面 | 角色 |
|------|------|------|
| `/workstation/sales/pre-order` | 预销售单列表 | 销售 |
| `/workstation/sales/pre-order/create` | 创建预销售单 | 销售 |
| `/workstation/sales/pre-order/:id` | 预销售单详情 | 销售 |
| `/workstation/warehouse/task-allocation` | 任务配货列表 | 仓库 |
| `/workstation/warehouse/task-allocation/:id` | 任务配货详情/扫码录入 | 仓库 |
| `/workstation/warehouse/task-allocation/:id/scan` | 扫码录入页面 | 仓库 |
| `/workstation/sales/pre-order/:id/confirm` | 确认配货结果 | 销售 |

### 5.2 页面功能

**仓库人员 - 任务配货扫码页面：**
```
┌─────────────────────────────────┐
│  任务配货 PH20260201000001      │
│  客户：XXX布业   仓库：主仓库     │
├─────────────────────────────────┤
│  产品：涤纶面料-红色             │
│  需求：5000.00 米               │
│  已配：4800.00 米  [96%]        │
│  ████████████████████░░         │
├─────────────────────────────────┤
│  ┌───────────────────────────┐  │
│  │     [扫码区域/摄像头]      │  │
│  │                           │  │
│  └───────────────────────────┘  │
│                                 │
│  或手动输入：                    │
│  布条码：[____________]         │
│  米  数：[____________]         │
│  [录入]                         │
├─────────────────────────────────┤
│  已录入布条（3条）：             │
│  ┌───────────────────────────┐  │
│  │ R001  50.00米  张三 10:30  │  │
│  │ R002  48.50米  张三 10:32  │  │
│  │ R003  51.50米  张三 10:35  │  │
│  └───────────────────────────┘  │
├─────────────────────────────────┤
│  [完成配货]                      │
└─────────────────────────────────┘
```

---

## 六、确认事项

请后端同事确认：

1. [ ] 任务配货是否在创建预销售单时自动创建？还是需要手动创建？
2. [ ] 布条码的格式规范是什么？是否需要校验格式？
3. [ ] 一条布可能属于多个产品吗？还是一对一关系？
4. [ ] 配货超出需求数量时，是警告还是阻止？
5. [ ] 转销售单时，价格如何处理？（预销售单是否有价格字段？）
6. [ ] 是否需要支持"部分配货"后转销售单？
7. [ ] 任务配货是否需要支持"退回"操作（从进行中退回到待接收）？
8. [ ] 预销售单和任务配货是否一对一关系？还是一对多？

---

**前端负责人：** [待填写]  
**后端负责人：** [待填写]  
**评审日期：** [待填写]
