material_manage_system/docs/api.md

29 KiB
Raw Blame History

仓库物料管理系统 API 文档

基础地址:/api


阅读说明

认证

除 POST /auth/login 外,所有接口都要求携带 JWT:

请求头 值
Authorization Bearer <token>

缺少或失效的令牌返回 401 Unauthorized。标为「仅管理员」的接口由 AdminOnly 中间件拦截,非管理员返回 403 Forbidden。

统一响应结构

所有接口共用同一个外层结构:

字段 类型 说明
code integer 0 表示成功;失败时等于 HTTP 状态码
message string 提示信息(后端硬编码,目前为英文)
data object 业务数据;无返回值的接口为 null

分页结构

列表接口的 data 不是数组,而是一个分页对象:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [],
    "limit": 20,
    "offset": 0,
    "total": 0,
    "has_more": false
  }
}
字段 类型 说明
items array 当前页数据
limit integer 每页条数,默认 20,上限 100
offset integer 偏移量,默认 0
total integer 符合条件的总条数
has_more boolean 是否还有下一页

limit 传超过 100 的值会被服务端截断为 100,而不是报错。

本文档覆盖范围

本文档详述物料、入库、出库、库存四个资源域。以下分组已实现但未在本文档展开,需要时请直接查阅 internal/handler/api.go 的路由注册:

分组 路径 权限
认证 POST /auth/login、GET /auth/me、POST /auth/logout 登录接口公开,其余需登录
用户 /users 仅管理员
组织 /organizations 仅管理员
角色 / 权限 /roles、/permissions 仅管理员
主数据:物料分类 /material-categories 仅管理员
主数据:计量单位 /units 仅管理员
主数据:编码规则 /code-rules 仅管理员
业务伙伴 /partners 仅管理员
仓库与库位 /warehouses、/warehouses/:id/locations 仅管理员
物料申请 /applications、/applications/my 需登录
操作日志 /logs、/logs/materials/:materialId 需登录
图片上传 POST /upload 需登录

1. 物料接口

物料是主数据,不承载任何库存信息。库存数量和预警阈值分别由库存接口和入库流程维护。

GET /materials

分页查询物料列表。

查询参数:

参数 类型 必填 说明
search string 否 按物料编码或名称模糊搜索
category string 否 当前未生效,服务端接收但未用于过滤
limit integer 否 每页条数,默认 20,上限 100
offset integer 否 偏移量,默认 0

该接口不按物料状态过滤,已作废的物料同样会出现在结果里,调用方需要自己判断 status 字段。

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": 1,
        "organization_id": 1,
        "material_code": "A01-0001",
        "name": "内六角螺栓",
        "material_image": "/uploads/bolt.png",
        "spec": "M8x30",
        "manufacturer_model": "GB/T 70.1",
        "category_id": 12,
        "base_unit_id": 3,
        "unit": "个",
        "status": "active",
        "version": 1,
        "created_at": "2026-01-01T08:00:00Z",
        "updated_at": "2026-01-01T08:00:00Z"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}

material_image、spec、manufacturer_model、category_id、base_unit_id、unit 为空时不会出现在响应里(后端 omitempty),前端取值时需要做空值兜底。

状态码:

  • 200 OK — 成功
  • 401 Unauthorized — 未登录

GET /materials/:id

查询单个物料。

路径参数:

参数 类型 必填 说明
id integer 是 物料 ID

响应: data 为单个物料对象,字段同 GET /materials。

状态码:

  • 200 OK — 成功
  • 400 Bad Request — 物料 ID 非法
  • 404 Not Found — 物料不存在

POST /materials

创建物料。

请求体:

{
  "material_code": "A01-0001",
  "name": "内六角螺栓",
  "spec": "M8x30",
  "manufacturer_model": "GB/T 70.1",
  "category_id": 12,
  "base_unit_id": 3,
  "unit": "个",
  "material_image": "/uploads/bolt.png"
}
字段 类型 必填 说明
material_code string 是 物料编码,组织内唯一
name string 是 物料名称
category_id integer 是 小类分类 ID,必须大于 0 且真实存在
spec string 否 规格
manufacturer_model string 否 厂家型号
base_unit_id integer 否 基本计量单位 ID
unit string 否 单位名称(冗余展示字段)
material_image string 否 图片地址
organization_id integer 否 传入会被忽略,服务端取当前用户的组织

响应: 201 Created,data 为创建后的物料对象。

{
  "code": 0,
  "message": "Material created successfully",
  "data": { "id": 1, "material_code": "A01-0001", "name": "内六角螺栓", "status": "active" }
}

状态码:

  • 201 Created — 创建成功
  • 400 Bad Request — 请求体非法、物料编码已存在,或 category_id 不是有效的小类类型

PUT /materials/:id

更新物料。

路径参数:

参数 类型 必填 说明
id integer 是 物料 ID

请求体:

{
  "material_code": "A01-0001",
  "name": "内六角螺栓(镀锌)",
  "spec": "M8x35",
  "category_id": 12,
  "unit": "个"
}
字段 类型 必填 说明
category_id integer 是 即使不修改分类也必须传
material_code string 否 物料编码
name string 否 物料名称
spec string 否 规格
manufacturer_model string 否 厂家型号
base_unit_id integer 否 基本计量单位 ID
unit string 否 单位名称
material_image string 否 图片地址
status string 否 物料状态

category_id 在更新接口里同样是必填项。只改名称而不传分类会返回 400。

响应: 200 OK,data 为更新后的物料对象。

状态码:

  • 200 OK — 更新成功
  • 400 Bad Request — 请求体非法或缺少 category_id
  • 404 Not Found — 物料不存在

POST /materials/:id/obsolete

作废物料。这是软删除:物料从库存视图(GET /stock、GET /stock/warning)中消失,但记录保留,可以恢复。

注意作废不会把物料从 GET /materials 的列表和物料下拉中移除——那个接口不过滤状态。因此作废物料依然出现在入库、出库、物料申请的物料选择器里,服务端也不会阻止给它入库。物料的可用性判断需要调用方自己看 status 字段。

路径参数:

参数 类型 必填 说明
id integer 是 物料 ID

请求体: 无。

响应:

{
  "code": 0,
  "message": "Material obsoleted successfully",
  "data": null
}

状态码:

  • 200 OK — 作废成功
  • 400 Bad Request — 物料 ID 非法
  • 404 Not Found — 物料不存在
  • 409 Conflict — 仍有库存(在库、预留、锁定或在途数量不为 0),需要先出库清零再作废

不再补货的物料走作废退役,而不是把预警阈值设为 0。作废要求库存为零,所以典型流程是:出库清零 → 作废。


POST /materials/:id/restore

撤销售废,把物料恢复为可用状态。

路径参数:

参数 类型 必填 说明
id integer 是 物料 ID

请求体: 无。

响应:

{
  "code": 0,
  "message": "Material restored successfully",
  "data": null
}

状态码:

  • 200 OK — 恢复成功
  • 400 Bad Request — 物料 ID 非法
  • 404 Not Found — 物料不存在

2. 入库接口

入库是物料进入库存视野的唯一入口:物料的第一行库存记录和第一个预警阈值都在这里产生。入库成功后,服务端会通过 WebSocket 广播库存变更。

GET /inbound

分页查询入库单列表。

查询参数:

参数 类型 必填 说明
search string 否 按经手人或供应商模糊搜索
limit integer 否 每页条数,默认 20,上限 100
offset integer 否 偏移量,默认 0

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": 1,
        "inbound_date": "2026-01-01T08:00:00Z",
        "handler": "张三",
        "supplier": "ABC 钢材",
        "status": "completed",
        "created_at": "2026-01-01T08:00:00Z",
        "updated_at": "2026-01-01T08:00:00Z"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}

单据的 status 字段目前是服务端硬编码的固定值 "completed"(数据库里没有对应的状态列),所有入库单都返回同一个值,不能用于区分单据阶段。出库单同理。

状态码: 200 OK、401 Unauthorized


GET /inbound/:id

查询单个入库单,包含明细行。

路径参数:

参数 类型 必填 说明
id integer 是 入库单 ID

响应:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": 1,
    "inbound_date": "2026-01-01T08:00:00Z",
    "handler": "张三",
    "supplier": "ABC 钢材",
    "status": "completed",
    "created_at": "2026-01-01T08:00:00Z",
    "updated_at": "2026-01-01T08:00:00Z",
    "items": [
      {
        "id": 1,
        "inbound_order_id": 1,
        "material_id": 1,
        "material_code": "A01-0001",
        "material_name": "内六角螺栓",
        "quantity": 500
      }
    ]
  }
}

状态码:

  • 200 OK — 成功
  • 400 Bad Request — 入库单 ID 非法
  • 404 Not Found — 入库单不存在

POST /inbound

创建入库单。创建时库存立即增加,同一个事务内写入预警阈值。

请求体:

{
  "handler": "张三",
  "supplier": "ABC 钢材",
  "items": [
    { "material_id": 1, "quantity": 500, "warning_stock": 100 },
    { "material_id": 2, "quantity": 200 }
  ]
}
字段 类型 必填 说明
handler string 是 经手人
supplier string 是 供应商
items array 是 明细,至少 1 行

明细字段:

字段 类型 必填 说明
material_id integer 是 物料 ID
quantity integer 是 入库数量,必须大于 0
warning_stock number 否 为该物料设置的预警阈值;不传表示不改动已存的阈值

warning_stock 与库存更新在同一个事务里落库,保证物料的第一个阈值和第一行库存同时生效。编辑旧入库单时不传这个字段(而不是传 0),才不会把别处刚调整好的阈值覆盖回去。

本接口不支持备注字段。前端即便提交了 remark,服务端也会忽略。

响应: 201 Created,data 为创建后的入库单,结构同 GET /inbound/:id。

状态码:

  • 201 Created — 创建成功
  • 400 Bad Request — 请求体非法、物料不存在,或 warning_stock 为负数

PUT /inbound/:id

更新入库单。服务端会先冲销原明细的库存,再按新明细重新入库,两步在同一事务内完成。

路径参数:

参数 类型 必填 说明
id integer 是 入库单 ID

请求体: 字段同 POST /inbound。warning_stock 同样遵循「不传即不改动」的语义。

响应: 200 OK,data 为更新后的入库单。

状态码:

  • 200 OK — 更新成功
  • 400 Bad Request — 请求体非法、物料不存在,或 warning_stock 为负数
  • 500 Internal Server Error — 入库单不存在等错误

DELETE /inbound/:id

删除入库单。同时冲销该单带来的库存增加并删除对应的库存流水。

路径参数:

参数 类型 必填 说明
id integer 是 入库单 ID

响应:

{
  "code": 0,
  "message": "Inbound order deleted successfully",
  "data": null
}

状态码:

  • 200 OK — 删除成功
  • 400 Bad Request — 入库单 ID 非法
  • 500 Internal Server Error — 入库单不存在等错误

GET /inbound/materials/:materialId

查询某个物料的入库记录。该接口不分页,data 直接是数组。

路径参数:

参数 类型 必填 说明
materialId integer 是 物料 ID

响应:

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": 1,
      "inbound_id": 1,
      "handler": "张三",
      "supplier": "ABC 钢材",
      "quantity": 500,
      "created_at": "2026-01-01T08:00:00Z"
    }
  ]
}

状态码: 200 OK、400 Bad Request


3. 出库接口

出库会校验可用库存,库存不足时整单失败。出库成功后同样会广播 WebSocket 库存变更。

GET /outbound

分页查询出库单列表。

查询参数:

参数 类型 必填 说明
search string 否 按经手人或领用人模糊搜索
limit integer 否 每页条数,默认 20,上限 100
offset integer 否 偏移量,默认 0

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": 1,
        "outbound_date": "2026-01-01T08:00:00Z",
        "handler": "李四",
        "receiver": "装配车间",
        "status": "completed",
        "created_at": "2026-01-01T08:00:00Z",
        "updated_at": "2026-01-01T08:00:00Z"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}

状态码: 200 OK、401 Unauthorized


GET /outbound/:id

查询单个出库单,包含明细行。

路径参数:

参数 类型 必填 说明
id integer 是 出库单 ID

响应:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": 1,
    "outbound_date": "2026-01-01T08:00:00Z",
    "handler": "李四",
    "receiver": "装配车间",
    "status": "completed",
    "created_at": "2026-01-01T08:00:00Z",
    "updated_at": "2026-01-01T08:00:00Z",
    "items": [
      {
        "id": 1,
        "outbound_order_id": 1,
        "material_id": 1,
        "material_code": "A01-0001",
        "material_name": "内六角螺栓",
        "quantity": 100
      }
    ]
  }
}

状态码:

  • 200 OK — 成功
  • 400 Bad Request — 出库单 ID 非法
  • 404 Not Found — 出库单不存在

POST /outbound

创建出库单。库存立即扣减,库存不足时整单失败。

请求体:

{
  "handler": "李四",
  "receiver": "装配车间",
  "items": [
    { "material_id": 1, "quantity": 100 },
    { "material_id": 2, "quantity": 50 }
  ]
}
字段 类型 必填 说明
handler string 是 经手人
receiver string 是 领用人
items array 是 明细,至少 1 行

明细字段:

字段 类型 必填 说明
material_id integer 是 物料 ID
quantity integer 是 出库数量,必须大于 0

响应: 201 Created,data 为创建后的出库单,结构同 GET /outbound/:id。

状态码:

  • 201 Created — 创建成功
  • 400 Bad Request — 请求体非法、物料不存在,或库存不足

PUT /outbound/:id

更新出库单。服务端先冲销原明细的库存扣减,再按新明细重新扣减,两步在同一事务内完成。

路径参数:

参数 类型 必填 说明
id integer 是 出库单 ID

请求体: 字段同 POST /outbound。

响应: 200 OK,data 为更新后的出库单。

状态码:

  • 200 OK — 更新成功
  • 400 Bad Request — 请求体非法、物料不存在,或库存不足
  • 500 Internal Server Error — 出库单不存在等错误

DELETE /outbound/:id

删除出库单。同时把已扣减的库存加回来并删除对应的库存流水。

路径参数:

参数 类型 必填 说明
id integer 是 出库单 ID

响应:

{
  "code": 0,
  "message": "Outbound order deleted successfully",
  "data": null
}

状态码:

  • 200 OK — 删除成功
  • 400 Bad Request — 出库单 ID 非法
  • 500 Internal Server Error — 出库单不存在等错误

GET /outbound/materials/:materialId

查询某个物料的出库记录。该接口不分页,data 直接是数组。

路径参数:

参数 类型 必填 说明
materialId integer 是 物料 ID

响应:

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": 1,
      "outbound_id": 1,
      "handler": "李四",
      "receiver": "装配车间",
      "quantity": 100,
      "created_at": "2026-01-01T08:00:00Z"
    }
  ]
}

状态码: 200 OK、400 Bad Request


4. 库存接口

库存状态的判定规则

整套预警逻辑只有一句话:

参与预警 = 启用 AND 阈值 > 0
报警     = 参与预警 AND 现有库存 <= 阈值

展开到接口行为上:

  • 库存查询(GET /stock)只列「入过库」的物料。判断依据是存在库存记录行,而不是库存数量大于 0——所以已被领用到 0 的物料仍然会列出,而只存在于主数据、从未入库的物料不会出现。已作废的物料也不列出。
  • 阈值没设过(为 0)的物料不会报警,即使库存已经是 0。没有设定期望值,就不替使用者判断"该补货了"。
  • 阈值被停用的物料不会报警,阈值本身保留,随时可以重新启用。
是否入过库 现有库存 阈值 启用 状态
否 0 0 — 不在列表中
是 0 0 默认 正常
是 5 0 默认 正常
是 0 10 是 库存不足
是 10 10 是 库存不足
是 15 10 是 正常
是 0 10 否 正常

GET /stock

分页查询库存,只包含入过库且未作废的物料。

查询参数:

参数 类型 必填 说明
search string 否 按物料编码或名称模糊搜索
limit integer 否 每页条数,默认 20,上限 100
offset integer 否 偏移量,默认 0

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "material_id": 1,
        "material_code": "A01-0001",
        "name": "内六角螺栓",
        "spec": "M8x30",
        "unit": "个",
        "major_category": "A01",
        "minor_category": "A01-01",
        "total_on_hand": "500",
        "warning_stock": "100",
        "warning_enabled": true,
        "stock_status": "normal"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}
字段 类型 说明
major_category string 大类分类编码
minor_category string 小类分类编码
total_on_hand string 现有库存合计,以字符串返回以免精度丢失
warning_stock string 预警阈值,未设置时为 "0"
warning_enabled boolean 阈值是否启用
stock_status string low(库存不足)或 normal(正常)

状态码: 200 OK、401 Unauthorized


GET /stock/:materialId

查询单个物料的库存。与 GET /stock 不同,这个接口对任何物料都会给出答案,包括从未入库的物料(返回 total_on_hand 为 0)。物料申请和出库表单依赖这个特性逐个查询物料。

路径参数:

参数 类型 必填 说明
materialId integer 是 物料 ID

响应:

{
  "code": 0,
  "message": "success",
  "data": {
    "material_id": 1,
    "material_code": "A01-0001",
    "name": "内六角螺栓",
    "spec": "M8x30",
    "unit": "个",
    "major_category": "A01",
    "minor_category": "A01-01",
    "total_on_hand": "500",
    "warning_stock": "100",
    "warning_enabled": true,
    "stock_status": "normal"
  }
}

状态码:

  • 200 OK — 成功
  • 400 Bad Request — 物料 ID 非法
  • 404 Not Found — 物料不存在

GET /stock/warning

分页查询需要关注的物料:配置了启用状态且大于 0 的阈值,并且现有库存已触达该阈值。

查询参数: limit(默认 20,上限 100)、offset(默认 0)。

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "material_id": 2,
        "material_code": "A02-0003",
        "name": "铝棒",
        "spec": "20mm x 3000mm",
        "unit": "根",
        "major_category": "A02",
        "minor_category": "A02-01",
        "total_on_hand": "30",
        "warning_stock": "100",
        "warning_enabled": true,
        "stock_status": "low"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}

状态码: 200 OK、401 Unauthorized


PUT /stock/:materialId/warning

设置、调整或停用某个物料的预警阈值。

路径参数:

参数 类型 必填 说明
materialId integer 是 物料 ID

请求体:

{
  "warning_stock": 100,
  "enabled": true
}
字段 类型 必填 说明
warning_stock number 是 阈值,必须大于等于 0。只有大于 0 的阈值才能触发预警
enabled boolean 否 默认 true;传 false 停用该物料的预警,阈值本身保留

响应:

{
  "code": 0,
  "message": "Stock warning updated successfully",
  "data": null
}

状态码:

  • 200 OK — 成功
  • 400 Bad Request — 物料 ID 非法,或 warning_stock 为负数

GET /stock/logs

分页查询全部库存流水,按时间倒序。

查询参数: limit(默认 20,上限 100)、offset(默认 0)。

响应(data 为分页对象,此处只展示 items 内元素):

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": 2,
        "material_id": 1,
        "change_type": "outbound",
        "change_quantity": "-100",
        "before_quantity": "500",
        "after_quantity": "400",
        "reference_id": 1,
        "reference_type": "outbound",
        "created_at": "2026-01-01T10:00:00Z"
      }
    ],
    "limit": 20,
    "offset": 0,
    "total": 1,
    "has_more": false
  }
}
字段 类型 说明
change_type string inbound(入库)或 outbound(出库)
change_quantity string 带符号的变动数量,出库为负
before_quantity string 变动前库存
after_quantity string 变动后库存
reference_type string 来源单据类型,如 inbound、outbound
reference_id integer 来源单据 ID

状态码: 200 OK、401 Unauthorized


GET /stock/logs/:materialId

分页查询某个物料的库存流水。

路径参数:

参数 类型 必填 说明
materialId integer 是 物料 ID

查询参数: limit(默认 20,上限 100)、offset(默认 0)。

响应:结构与 GET /stock/logs 相同。

注意:本接口的 change_quantity 是不带符号的正数(方向由 change_type 区分),与 GET /stock/logs 的带符号约定不一致。这是当前实现的实际行为,使用前请留意。

状态码:

  • 200 OK — 成功
  • 404 Not Found — 物料不存在

状态码汇总

状态码 说明
200 请求成功
201 资源创建成功
400 请求体或参数非法、物料不存在、库存不足
401 未登录或令牌失效
403 已登录但权限不足(如非管理员访问管理员接口)
404 资源不存在
409 状态冲突,目前仅用于「物料仍有库存时作废」
500 服务端错误