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

16 KiB
Raw Blame History

Stock Management API Documentation

This document provides detailed documentation for the stock management module APIs, focusing on the three main stock change creation modes: Full, Relaxed, and Restricted.

Table of Contents

  1. Overview
  2. Stock Models
  3. Stock Change Modes
  4. API Endpoints
  5. Examples
  6. Error Handling

Overview

The stock management system handles all inventory movement operations including stock-in (入库) and stock-out (出库) transactions. The system supports three different modes of operation:

  1. Full Mode: Standard operation with explicit quantity lists
  2. Relaxed Mode: Automatically splits quantities based on total and unit count
  3. Restricted Mode: Strict "restricted-in/out" mode for warehouse operations

Stock Models

StockChangeRecord

Represents a stock change record (either stock-in or stock-out).

Fields:

  • id: Record ID
  • type: Change type (1=Stock-in, 2=Stock-out)
  • warehouse: Associated warehouse
  • source_type: Source of the change (1=Purchase, 6=Sales, etc.)
  • source_id: ID of the source document (optional)
  • created_by: User who created the record
  • is_finished: Whether the stock change is completed
  • finished_at: When the record was completed
  • remarks: Additional notes

StockChangeDetail

Represents detailed items within a stock change record.

Fields:

  • id: Detail ID
  • product: Associated product
  • stock_change_record: Parent stock change record
  • quantity: Quantity of the product
  • unit: Unit of measurement
  • is_consumed: Whether this detail has been consumed (for restricted mode)
  • consume_with: Reference to the inbound detail being consumed (for restricted mode)

Inventory

Represents current inventory levels for a product in a warehouse.

Fields:

  • id: Inventory ID
  • product: Associated product
  • warehouse: Warehouse location
  • quantity: Current quantity
  • num_of_rolls: Number of rolls
  • spec: Product specification
  • description: Additional notes

Stock Change Modes

Source Types

The system supports various source types for stock changes:

Incoming (入库) Sources:

  • 1: Purchase (采购)
  • 2: Sales Return (销退)
  • 3: Transport In (调入)
  • 4: Recheck Addition (盘盈)
  • 5: Combine (合并)

Outgoing (出库) Sources:

  • 6: Sales (销售)
  • 7: Purchase Return (采购退货)
  • 8: Transport Out (调出)
  • 9: Recheck Removal (盘亏)
  • 10: Explode (拆卷)

Warehouse Modes

Warehouses can operate in different modes:

  • 1: Restricted In (严进) - Strict control on stock-in
  • 2: Restricted In/Out (严进严出) - Strict control on both stock-in and stock-out
  • 3: Unrestricted (宽进宽出) - Relaxed controls for both directions

API Endpoints

1. Full Mode Stock Change

URL: POST /api/v1/stock-change/

Description: Creates a stock change record with explicit quantity lists for each product.

Request Parameters:

{
  "type": 1,  // 1=入库, 2=出库
  "warehouse": 1,  // 仓库ID
  "source_type": 1,  // 来源类型,见上文说明
  "source_id": 123,  // 可选来源单据ID
  "products": [
    {
      "product": 1,  // 产品ID
      "quantity": [85.5, 75.2, 90.0]  // 数量列表,每个值对应一条明细
    },
    {
      "product": 2,
      "quantity": [120.0]
    }
  ]
}

Response:

{
  "stock_change_record": {
    "id": 15,
    "type": 1,
    "warehouse": 1,
    "source_type": 1,
    "source_id": 123,
    "is_finished": false,
    "created_at": "2025-11-25T10:30:00Z",
    "updated_at": "2025-11-25T10:30:00Z"
  },
  "details": [
    {
      "id": 45,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 85.5,
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 15,
      "is_consumed": false,
      "consume_with_id": null
    },
    {
      "id": 46,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 75.2,
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 15,
      "is_consumed": false,
      "consume_with_id": null
    }
    // ... 更多明细
  ],
  "message": "成功创建库存变动记录及 3 条明细",
  "created_details_count": 3
}

2. Relaxed Mode Stock Change

URL: POST /api/v1/stock-change/relaxed/

Description: Creates a stock change record using total quantity and unit count to automatically split into details.

Request Parameters:

{
  "type": 1,  // 1=入库, 2=出库
  "warehouse": 1,  // 仓库ID
  "source_type": 1,  // 来源类型
  "source_id": 123,  // 可选来源单据ID
  "products": [
    {
      "product": 1,  // 产品ID
      "quantity": {
        "value": 250.8,  // 总数量
        "unit_count": 2.5  // 单条数量默认为1
      }
    }
  ]
}

Response:

{
  "stock_change_record": {
    "id": 16,
    "type": 1,
    "warehouse": 1,
    "source_type": 1,
    "source_id": 123,
    "is_finished": false,
    "created_at": "2025-11-25T11:00:00Z",
    "updated_at": "2025-11-25T11:00:00Z"
  },
  "details": [
    {
      "id": 48,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 100.0,  // 自动拆分
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 16,
      "is_consumed": false,
      "consume_with_id": null
    },
    {
      "id": 49,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 100.0,  // 自动拆分
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 16,
      "is_consumed": false,
      "consume_with_id": null
    },
    {
      "id": 50,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 50.8,  // 剩余数量
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 16,
      "is_consumed": false,
      "consume_with_id": null
    }
  ],
  "message": "成功创建库存变动记录及 3 条明细",
  "created_details_count": 3
}

3. Restricted Mode Stock Change

URL: POST /api/v1/stock-change/restrict/

Description: Creates a stock change record in "restricted-in-out" mode where outbound details must reference existing inbound details.

Request Parameters:

{
  "type": 2,  // 1=入库, 2=出库
  "warehouse": 1,  // 仓库ID必须为严进严出模式
  "source_type": 6,  // 来源类型
  "source_id": 123,  // 可选来源单据ID
  "products": [
    {
      "product": 1,  // 产品ID
      "quantity": [150.5],  // 数量列表
      "consume_with": [23, 24]  // 必须指定消耗的入库明细ID列表
    }
  ]
}

Response:

{
  "stock_change_record": {
    "id": 17,
    "type": 2,
    "warehouse": 1,
    "source_type": 6,
    "source_id": 123,
    "is_finished": false,
    "created_at": "2025-11-25T11:15:00Z",
    "updated_at": "2025-11-25T11:15:00Z"
  },
  "details": [
    {
      "id": 51,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 75.25,
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 17,
      "is_consumed": false,
      "consume_with_id": 23  // 消耗的入库明细ID
    },
    {
      "id": 52,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 75.25,
      "unit": 1,
      "unit_display": "米",
      "stock_change_record": 17,
      "is_consumed": false,
      "consume_with_id": 24  // 消耗的入库明细ID
    }
  ],
  "message": "成功创建库存变动记录及 2 条明细",
  "created_details_count": 2
}

List Stock Changes

URL: GET /api/v1/stock-changes/

Response: List of stock change records with pagination

{
  "count": 100,
  "next": "http://example.com/api/v1/stock-changes/?page=2",
  "previous": null,
  "results": [
    {
      "id": 15,
      "type": 1,
      "type_display": "入库",
      "warehouse": 1,
      "source_type": 1,
      "source_type_display": "采购",
      "is_finished": true,
      "finished_at": "2025-11-25T12:00:00Z",
      "created_at": "2025-11-25T10:30:00Z"
    }
  ]
}

Get Stock Change Details

URL: GET /api/v1/stock-change/<id>/

Response: Detailed view of a specific stock change record with its details

{
  "stock_change_record": {
    "id": 15,
    "type": 1,
    "type_display": "入库",
    "warehouse": 1,
    "source_type": 1,
    "source_type_display": "采购",
    "is_finished": true,
    "finished_at": "2025-11-25T12:00:00Z",
    "created_at": "2025-11-25T10:30:00Z"
  },
  "details": [
    {
      "id": 45,
      "product": 1,
      "product_name": "纯棉印花布",
      "quantity": 85.5,
      "unit": 1,
      "unit_display": "米",
      "is_consumed": false,
      "consume_with_id": null
    }
  ]
}

4. Stock Snapshot List

  • URL: GET /api/v1/stock-snapshots/
  • Description: Read-only list of StockSnapshot entries. Supports limit/offset pagination,搜索与过滤。
  • Query Parameters:
    参数 说明
    product / product_name / product_code 指定产品或模糊搜索
    warehouse / warehouse_name 指定仓库或模糊搜索
    stock_change_record 关联的出入库记录 ID
    unit 单位过滤
    cancelled true/false,是否被标记取消
    has_offset true/false,筛选是否存在冲抵记录
    date_from / date_to 创建时间范围(YYYY-MM-DD
    search 针对产品名、产品编码、仓库名的全文搜索
    ordering 排序字段,默认 -created_at

Response 示例

{
  "count": 2,
  "results": [
    {
      "id": 901,
      "product": 15,
      "product_name": "纯棉印花布",
      "warehouse": 3,
      "warehouse_name": "严进仓",
      "delta": "120.00",
      "quantity_before": "80.00",
      "quantity_after": "200.00",
      "stock_change_record": 456,
      "stock_change_record_type": "入库",
      "stock_change_record_source": "采购",
      "unit": 1,
      "unit_display": "米",
      "num_of_rolls": 3,
      "offset_to": null,
      "cancelled": false,
      "created_at": "2025-11-25T12:05:00Z"
    }
  ]
}

5. Merchant Auto Complete Setting

  • URL: POST /api/v1/set-merchant-auto-complete-stock-change/
  • Description: 为当前商户开启 / 关闭“创建出入库记录后自动完成”功能。开启后,create_* 接口在事务内会立即调用 stock.services.make_stock_change_completed,自动写入库存与快照。
  • Request:
{
  "auto_complete": true
}
  • Response:
{
  "status": "success"
}

只有具备员工身份的登录用户才可调用该接口。

6. Stock Change Completion Behavior

  • 自动完成:当商户开启 auto_complete_stock_change 时,任意模式的创建接口都会立即调用 make_stock_change_completed,更新 Inventory 并生成 StockSnapshot
  • 手动完成:当需要补处理或未开启自动完成时,可调用 POST /api/v1/stock-change/<id>/finish/ 手动触发 make_stock_change_completed,也可直接在后台脚本里调用服务函数。
  • 状态字段StockChangeRecord.is_finished / finished_at 会在完成时标记,用于列表和详情接口判断记录是否已经生效。

7. Finish Stock Change Record (Manual)

  • URL: POST /api/v1/stock-change/<id>/finish/
  • Description: 手动触发指定出入库记录的库存扣减与快照写入,适用于未开启自动完成或需要补处理的场景。仅当前商户下且仓库可见的员工可调用。
  • Request: 无需请求体,只需保证 URL 中的 <id> 为目标 StockChangeRecord 的 ID。
  • Response:
{
  "status": "success",
  "message": "库存变动记录已标记为完成",
  "stock_change_record": {
    "id": 17,
    "type": 1,
    "warehouse": 1,
    "warehouse_name": "严谨仓",
    "source_type": 1,
    "source_type_display": "采购",
    "source_id": 123,
    "is_finished": true,
    "finished_at": "2025-11-25T12:30:00Z",
    "created_at": "2025-11-25T11:50:00Z",
    "created_by": "stock_admin",
    "remarks": null
  }
}

8. Stock Change Offset (Red Flush Placeholder)

  • URL: POST /api/v1/stock-change/<id>/offset/
  • Description: 面向未来的库存红冲入口。当前仅提供占位实现,用于锁定最终接口形态;实际红冲逻辑尚未上线,因此调用会返回 501 Not Implemented,方便前端或上游业务在流程编排中预留节点。
  • Request:
{
  "reason": "审批错误,需要冲销",
  "items": [
    {
      "product_id": 1,
      "quantities": ["50.00"]
    }
  ],
  "request_id": "po-123-offset",
  "extra_meta": {
    "source": "purchase_order",
    "operator": "warehouse_admin"
  }
}
  • Response当前占位行为:
{
  "error": "stock_offset_not_ready",
  "message": "库存红冲功能尚未实现",
  "record_id": 25
}

Examples

Example 1: Creating a Stock-in Record (Full Mode)

curl -X POST http://example.com/api/v1/stock-change/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_token" \
  -d '{
    "type": 1,
    "warehouse": 1,
    "source_type": 1,
    "products": [
      {
        "product": 1,
        "quantity": [100.5, 75.3, 120.0]
      }
    ]
  }'

Example 2: Creating a Stock-out Record (Relaxed Mode)

curl -X POST http://example.com/api/v1/stock-change/relaxed/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_token" \
  -d '{
    "type": 2,
    "warehouse": 1,
    "source_type": 6,
    "products": [
      {
        "product": 2,
        "quantity": {
          "value": 250.8,
          "unit_count": 2.5
        }
      }
    ]
  }'

Example 3: Creating a Stock-out Record (Restricted Mode)

curl -X POST http://example.com/api/v1/stock-change/restrict/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_token" \
  -d '{
    "type": 2,
    "warehouse": 1,
    "source_type": 6,
    "products": [
      {
        "product": 3,
        "quantity": [100.0, 50.0],
        "consume_with": [45, 46]
      }
    ]
  }'

Example 4: Finish a Stock Change Record Manually

curl -X POST http://example.com/api/v1/stock-change/17/finish/ \
  -H "Authorization: Bearer your_token"

Error Handling

Common Error Responses

Authentication Error

{
  "error": "无权限访问"
}

Missing Required Parameters

{
  "error": "缺少必要参数",
  "message": "请提供 type, warehouse, source_type"
}

Validation Error

{
  "error": "产品数据验证失败",
  "details": {
    "products": [
      "产品列表中存在重复的产品ID"
    ]
  }
}

Warehouse/Product Visibility Error

{
  "error": "仓库ID 1 对当前用户不可见"
}

Business Logic Error

{
  "error": "仓库出入库模式为【严进严出】,该模式暂未支持当前操作"
}

Business Rules

  1. Warehouse Mode Restrictions:

    • Full mode works with all warehouse modes
    • Relaxed mode requires "unrestricted" (宽进宽出) or "restricted-in" (严进) warehouses
    • Restricted mode requires "restricted-in-out" (严进严出) warehouses
  2. Stock Change Validation:

    • Stock-in can only use incoming source types (1, 2, 3, 4, 5)
    • Stock-out can only use outgoing source types (6, 7, 8, 9, 10)
  3. Restricted Mode Specific Rules:

    • Outbound details must reference existing inbound details
    • Referenced details must belong to the same warehouse
    • Referenced details must not already be consumed
  4. Permission Checks:

    • Users can only access warehouses they have permission to see
    • Users can only access products they have permission to see
    • All stock change operations require proper authentication