1
0
forked from erp-dev/erp
Files
erpnew/docs/business_purchase.md

129 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Business 模块采购单 API
## 创建采购单(默认待审批)
- **URL**: `POST /api/v1/purchase-orders/`
- **权限**: 需要登录且具备员工身份
- **描述**: 创建业务模块的 `PurchaseOrder`,默认状态为 `PENDING`(审批中)。此时不会立即生成入库记录,需在审批通过后才会触发库存入库任务。
### 请求体
```json
{
"supplier": 1,
"warehouse_id": 2,
"order_date": "2025-11-26",
"remarks": "测试采购单",
"items": [
{
"product_id": 10,
"quantity": 120,
"num_of_rolls": 3,
"price": "12.50",
"unit": "米",
"empty_diff_percent": "0"
}
]
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| supplier | integer | ✅ | 供应商 ID必须隶属于当前商户 |
| warehouse / warehouse_id | integer | ✅ | 入库仓库 ID两字段二选一推荐 `warehouse_id` |
| order_date | string (date) | ✅ | 订单日期(`YYYY-MM-DD` |
| remarks | string | 否 | 备注 |
| items | array | ✅ | 入库明细,根据仓库模式提供不同字段 |
#### items 结构说明
- **宽进仓UNRESTRICTED**
- 必填:`product_id``quantity``num_of_rolls`
- `quantity_of_rolls` 会自动置空,并以 `{value, num_of_rolls}` 的形式传递给 `StockFlowService.stock_in` 的宽松模式。
- **严进仓RESTRICT_IN / RESTRICT_IN_OUT**
- 必填:`product_id``numbers`(数组)
- 后端会以数组长度设置 `num_of_rolls`,把所有数值拼为 `quantity_of_rolls="10,5,8"`,同时求和得到 `quantity`,并生成 `{'quantities': ['10','5','8']}` 传递给严谨模式。
公共可选字段:`price``unit``color``empty_diff_percent``batch_number``remarks`。缺省时默认使用 0 或产品单位。
⚠️ 当仓库模式与 items 字段不匹配(例如严进仓缺少 `numbers`、宽进仓提供 `numbers`)时将返回 `400`,提示“仓库为 ×× 模式items[n] 需要提供 …”。
### 响应
```json
{
"id": 35,
"status": 1,
"message": "采购单创建成功,等待审批"
}
```
创建成功即刻返回,状态为 `审批中`。只有在审批通过后才会调用库存入库任务。
### 错误示例
| 状态码 | 示例 | 说明 |
|--------|------|------|
| 400 | `{"error": "缺少仓库 ID"}` | 请求缺失关键字段 |
| 400 | `{"error": "仓库为严进模式items[0] 需要提供 numbers 数组"}` | 参数与仓库模式不匹配 |
| 400 | `{"error": "供应商 99 不存在"}` | 供应商不属于当前商户 |
| 403 | `{"error": "无权限访问"}` | 当前用户无员工信息 |
## 审批 / 作废采购单API & Service
- **URL**: `POST /api/v1/purchase-orders/<id>/review/`
- **权限**: 登录 + 员工身份
- **请求体**:
```json
{
"action": "approve" // 可选: approve / cancel
}
```
`action=approve` 时,会调用 `business.services.review_purchase_order` 将采购单状态更新为 `APPROVED`,并在商户设置 `auto_create_stock_change_tasks=True` 时自动触发 `create_purchase_order_stock_entries` Celery 任务(根据采购单明细重建 `StockFlowService.stock_in` 所需 payload
`action=cancel` 时,会尝试将采购单状态改为 `CANCELLED`。如果该采购单已经生成过出入库记录(`source_type=PURCHASE``source_id=采购单ID`),接口会返回 `400`,提示“采购单已生成出入库记录,无法作废”。
### 响应示例
```json
{
"id": 12,
"status": 2,
"supplier_name": "供应商A",
"warehouse_name": "严进仓",
"total_amount": "1500.00",
"diff_quantity": "0.00",
"total_quantity": "120.00",
"items": [
{
"id": 33,
"product": 10,
"quantity": "120.00",
"unit": "米",
"spec": "50D",
"num_of_rolls": 3
}
]
}
```
### 错误示例
| 状态码 | 示例 | 说明 |
|--------|------|------|
| 400 | `{"action": ["This field is required."]}` | 缺少 `action` |
| 400 | `{"error": "采购单已生成出入库记录,无法作废"}` | 尝试作废但已生成出入库单 |
| 404 | `{"error": "采购单不存在"}` | ID 不在当前商户下 |
### 关联任务business/tasks.py
`create_purchase_order_stock_entries` 任务会接收 `purchase_order_id``warehouse_id`、已转换好的 `items` 信息,并通过 `StockFlowService.stock_in` 创建入库记录。只有当采购单审批通过且商户开启自动入库设置时才会派发该任务。
### 测试
- `business/tests.PurchaseOrderServiceTestCase`:覆盖创建采购单、审批触发任务、作废校验以及宽/严模式的 payload 生成逻辑。
- `business/tests.PurchaseOrderStockServiceTestCase``PurchaseOrderStockTaskTestCase`:继续验证 service 层生成入库单及 Celery 任务封装逻辑。