# API v1:预销售单 / 预采购单(前端对接) 本文档面向前端,描述预销售单(PreSalesOrder)与预采购单(PrePurchaseOrder)的 API、字段与参数。 - API 前缀:`/api/v1/` - 认证:接口均要求登录(`IsAuthenticated`)。 - 权限:要求当前用户绑定员工(`request.user.employee`),否则返回 `403`。 ## 分页(Limit/Offset) 预销售单列表、预采购单列表均使用 DRF `LimitOffsetPagination`: - `limit`:返回条数,默认 `20`,最大 `100` - `offset`:偏移量,默认 `0` 分页响应结构: ```json { "count": 123, "next": "http://.../api/v1/pre-sales-orders/?limit=20&offset=20", "previous": null, "results": [ { "id": 1, "human_id": "YS...", "items": [] } ] } ``` ## 列表查询参数(已支持) 预销售单列表 `GET /pre-sales-orders/`: - `limit` / `offset` - `customer` / `customer_id`(int) - `warehouse` / `warehouse_id`(int) - `kind`(int) - `human_id__icontains`(string) - `created_at_from`(datetime 或 date) - `created_at_to`(datetime 或 date) 预采购单列表 `GET /pre-purchase-orders/`: - `limit` / `offset` - `supplier` / `supplier_id`(int) - `warehouse` / `warehouse_id`(int) - `kind`(int) - `human_id__icontains`(string) - `created_at_from`(datetime 或 date) - `created_at_to`(datetime 或 date) --- # 预销售单 PreSalesOrder ## 1) 列表 - `GET /api/v1/pre-sales-orders/?limit=20&offset=0` - 查询参数: - `limit`(可选,int,默认 20,最大 100) - `offset`(可选,int,默认 0) - 响应:`200 OK`,分页结构,`results` 为预销售单数组 ## 2) 创建 - `POST /api/v1/pre-sales-orders/` 请求体参数(JSON): - `customer` / `customer_id`(必填,int):客户 ID - `warehouse` / `warehouse_id`(必填,int):仓库 ID - `kind`(可选,int):预销售单类型 - `1`:大货 - `2`:样板 - 默认 `1` - `remarks`(可选,string) - `items`(必填,array,非空):明细列表 `items[]` 字段: - `product_id` / `product`(必填,int):产品 ID - `quantity`(必填,string 或 number):数量(会被转换为 Decimal) - `unit`(可选,string):单位;为空时会尝试使用产品默认单位 - `product_name`(可选,string):产品名称(弱关联承载) - `color`(可选,string) - `spec`(可选,string) - `quantity_of_rolls`(可选,string):各条数数量(原样保存) - `num_of_rolls`(可选,int):条数,必须 > 0,默认 `1` - `order_quantity`(可选,int):下单数量,必须为非负整数 - `remarks`(可选,string):明细备注 响应:`201 CREATED`,返回预销售单详情(含 `items`)。 示例请求: ```json { "customer": 1, "warehouse": 2, "kind": 1, "remarks": "预销售单备注", "items": [ { "product_id": 10, "quantity": "12.5", "unit": "米", "order_quantity": 7, "remarks": "明细备注" } ] } ``` ## 3) 详情 - `GET /api/v1/pre-sales-orders/{id}/` - 响应:`200 OK`,返回预销售单详情 ## 4) 更新(全量/部分) - `PUT /api/v1/pre-sales-orders/{id}/` - `PATCH /api/v1/pre-sales-orders/{id}/` 请求体参数: - `customer` / `customer_id`(可选,int) - `warehouse` / `warehouse_id`(可选,int) - `kind`(可选,int) - `remarks`(可选,string) - `items`(必填,array,非空):更新时必须提供,否则会返回 `400` 响应:`200 OK`,返回更新后的详情。 ## 5) 删除 - `DELETE /api/v1/pre-sales-orders/{id}/` - 响应:`204 NO CONTENT` ## 6) 转换为销售单(仅严进严出仓库) - `POST /api/v1/pre-sales-orders/{id}/convert-to-sales/` 约束: - 仅支持仓库模式为 **严进严出(RESTRICT_IN_OUT)** 的预销售单 - 若不是严进严出,返回 `403` - 需要已存在有效配货记录(用于生成销售单明细的 `consume_detail_ids`) 响应:`201 CREATED` ```json { "id": 1001, "human_id": "XS20260202000001", "status": 1, "message": "预销售单已转换为销售单,等待审批" } ``` 错误示例(403): ```json { "error": "仅支持严进严出仓库模式" } ``` 错误示例(400): ```json { "error": "明细 123 缺少配货库存明细" } ## 7) 配货记录(Allocations) ### 7.1 创建配货记录 - `POST /api/v1/pre-sales-order-items/{item_id}/allocations/` 请求体参数(JSON): ```json { "stock_ids": [1, 2, 3], "quantity": "10.00", "unit": "KG", "remarks": "备注信息" } ``` 响应:`201 CREATED`,返回配货记录详情。 ### 7.2 撤销配货记录(含解冻库存) - `DELETE /api/v1/pre-sales-order-items/{item_id}/allocations/{pk}/` 行为说明: - 将配货记录状态置为撤销(status=2) - **同时解冻**该配货记录创建时冻结的库存(StockFreeze.status=取消) 响应:`200 OK`,返回配货记录详情。 ``` ## 预销售单字段说明(响应) 预销售单对象字段(`results[]` 与详情一致): - `id`(int):主键 - `human_id`(string):人类可读编号(如 `YSYYYYMMDD000001`) - `merchant`(int):所属商户 ID - `merchant`(int):商户 ID(调试字段) - `customer`(int):客户 ID - `customer_name`(string,只读) - `warehouse`(int):仓库 ID - `warehouse_name`(string,只读) - `operator`(int|null):经办人(员工)ID(创建时由后端从登录用户推导) - `operator_name`(string,只读) - `kind`(int):类型(1/2) - `remarks`(string|null) - `created_at`(datetime string) - `items`(array):明细(只读) `items[]` 字段(响应): - `id`(int) - `product_id`(int|null) - `product_name`(string) - `color`(string|null) - `quantity`(string|null,通常为两位小数,如 `"20.00"`) - `unit`(string) - `spec`(string|null) - `remarks`(string|null) --- # 预采购单 PrePurchaseOrder ## 1) 列表 - `GET /api/v1/pre-purchase-orders/?limit=20&offset=0` - 查询参数: - `limit`(可选,int,默认 20,最大 100) - `offset`(可选,int,默认 0) - 响应:`200 OK`,分页结构 ## 2) 创建 - `POST /api/v1/pre-purchase-orders/` 请求体参数(JSON): - `supplier` / `supplier_id`(必填,int):供应商 ID - `warehouse` / `warehouse_id`(必填,int):仓库 ID - `kind`(可选,int):预采购单类型 - `1`:大货 - `2`:样板 - 默认 `1` - `remarks`(可选,string) - `items`(必填,array,非空):明细列表(字段同预销售明细) 响应:`201 CREATED`,返回预采购单详情(含 `items`)。 示例请求: ```json { "supplier": 1, "warehouse": 2, "kind": 1, "remarks": "预采购单备注", "items": [ { "product_id": 10, "quantity": "12.5", "unit": "米", "order_quantity": 7, "remarks": "明细备注" } ] } ``` ## 3) 详情 - `GET /api/v1/pre-purchase-orders/{id}/` - 响应:`200 OK` ## 4) 更新(全量/部分) - `PUT /api/v1/pre-purchase-orders/{id}/` - `PATCH /api/v1/pre-purchase-orders/{id}/` 请求体参数: - `supplier` / `supplier_id`(可选,int) - `warehouse` / `warehouse_id`(可选,int) - `kind`(可选,int) - `remarks`(可选,string) - `items`(必填,array,非空):更新时必须提供,否则会返回 `400` 响应:`200 OK` ## 5) 删除 - `DELETE /api/v1/pre-purchase-orders/{id}/` - 响应:`204 NO CONTENT` ## 预采购单字段说明(响应) 预采购单对象字段(`results[]` 与详情一致): - `id`(int) - `human_id`(string):人类可读编号(如 `YCYYYYMMDD000001`) - `merchant`(int) - `merchant`(int):商户 ID(调试字段) - `supplier`(int) - `supplier_name`(string,只读) - `warehouse`(int) - `warehouse_name`(string,只读) - `operator`(int|null) - `operator_name`(string,只读) - `kind`(int,1/2) - `remarks`(string|null) - `created_at` - `items`(array,只读) `items[]` 字段同预销售明细响应。 --- # 错误响应约定(两类接口通用) - `400 BAD REQUEST`:参数校验失败 - 示例:`{"error": "items 需要为非空数组"}` - `401 UNAUTHORIZED`:未登录 - `403 FORBIDDEN`:无员工信息/无权限 - 示例:`{"error": "无权限访问"}` - `404 NOT FOUND`:订单不存在 - 示例:`{"error": "预销售单不存在"}` / `{"error": "预采购单不存在"}`