1
0
forked from erp-dev/erp
Files
erpnew/docs/api_v1_shipment_api_2026-07-08.md

22 KiB
Raw Blame History

Shipment 模块 API v1 文档

面向前端对接,基于当前代码生成。接口统一前缀为 /api/v1/

通用说明

  • 认证:所有接口均要求登录认证。
  • 商户隔离:普通用户只能访问自己员工所属商户的数据;超级管理员部分接口可跨商户,具体见接口说明。
  • 分页:列表接口使用 limitoffset,分页响应一般为 { "count": 0, "next": null, "previous": null, "results": [] }
  • 错误:业务校验失败通常返回 400 { "detail": "错误原因" };不存在通常返回 404

枚举

出货单状态 ShipmentStatus

含义
1 草稿(未发布)
2 已发布
3 已取消
4 已驳回
5 已审核

送货单状态 ShipmentDeliveryStatus

含义
1 待送货
2 送货中
3 已送达

销售品单位 UnitChoices

含义
1
2
3
4

公共响应结构

Shipment

{
  "id": 1,
  "merchant_id": 1,
  "merchant_name": "测试印花厂",
  "customer": 10,
  "customer_name": "客户A",
  "address_id": 5,
  "fabric": "面料信息",
  "order_description": "订单描述",
  "shipment_date": "2026-01-14",
  "address": "杭州市测试路 1 号",
  "contact_name": "张三",
  "contact_phone": "13800138000",
  "area": "华东",
  "coordinates": "120.1551,30.2741",
  "remark": "备注",
  "status": 1,
  "status_display": "草稿(未发布)",
  "external_id": null,
  "geo_coordinates": null,
  "extra": {"source": "customer_address"},
  "delivery_id": null,
  "status_modified_at": null,
  "cancelled_by_id": null,
  "cancelled_by_name": null,
  "approved_by_id": null,
  "approved_by_name": null,
  "items_count": 2,
  "created_by_id": 1,
  "created_by_name": "张三",
  "external_finished_products_count": 0,
  "sales_items": [],
  "external_finished_products": [],
  "created_at": "2026-01-14T10:00:00Z",
  "updated_at": "2026-01-14T10:00:00Z"
}

字段说明:

字段 类型 说明
address_id integer/null 关联客户地址 ID只表示关联关系
address string 出货单地址快照,由请求体写入
contact_name string 联系人快照,由请求体写入
contact_phone string 联系电话快照,由请求体写入
area string 地区快照,最大 100 字符
coordinates string/null 经纬度字符串,最大 100 字符
geo_coordinates object/array/null 历史 Geo 字段,保留兼容老数据
extra object/array/null 扩展 JSON

重要行为:传 address_id 时,后端只校验并保存关联,不会用 CustomerAddress 自动覆盖 address/contact_name/contact_phone/area/coordinates/extra。这些快照字段仍以请求体为准。

SalesItem

{
  "id": 1,
  "name": "销售品A",
  "quantity": "100.00",
  "unit": 1,
  "unit_display": "米",
  "position": "A1-01",
  "remark": "备注",
  "printing_job_id": 123,
  "printing_order_id": 456,
  "external_order_id": "KD20441758",
  "customer_id": 10,
  "customer_name": "客户A",
  "shipment_id": null,
  "shipment_date": null,
  "merge_remark": null,
  "created_at": "2026-01-14T10:00:00Z",
  "created_by_id": 1,
  "created_by_name": "张三"
}

详情接口额外包含:

字段 类型 说明
product_image_url string/null 关联生产任务产品主图 URL

ShipmentDelivery

{
  "id": 1,
  "merchant_id": 1,
  "merchant_name": "测试印花厂",
  "driver_name": "司机A",
  "vehicle_trip": "浙A12345",
  "contact_phone": "13800138000",
  "vehicle_capacity": "4.2米",
  "remark": "备注",
  "internal_remark": "内部备注",
  "shipment_order_ids": [1, 2, 3],
  "status": 1,
  "status_display": "待送货",
  "started_at": null,
  "delivered_at": null,
  "cancelled_at": null,
  "shipments_count": 2,
  "shipments": [],
  "created_by_id": 1,
  "created_by_name": "张三",
  "operator_id": null,
  "operator_name": null,
  "cancelled_by_id": null,
  "cancelled_by_name": null,
  "created_at": "2026-01-14T10:00:00Z",
  "updated_at": "2026-01-14T10:00:00Z"
}

shipments 内元素为送货单内出货单摘要:

{
  "id": 1,
  "customer": 10,
  "customer_name": "客户A",
  "fabric": "面料信息",
  "order_description": "订单描述",
  "shipment_date": "2026-01-14",
  "status": 5,
  "status_display": "已审核",
  "external_id": null,
  "delivery_id": 1
}

出货单接口

查询出货单列表

GET /api/v1/shipment/shipments/

查询参数:

参数 类型 必填 说明
customer integer 客户 ID
status integer 出货单状态
delivery_id integer 送货单 ID空字符串、nullnone 不触发过滤
delivery_isnull boolean true/1/yes 查未绑定送货单,false/0/no 查已绑定送货单
external_id string 外部订单号精确匹配
shipment_date_from date 出货日期起始,YYYY-MM-DD
shipment_date_to date 出货日期结束,YYYY-MM-DD
only_address_null boolean true 查地址为空字符串,false 查地址非空
limit integer 分页大小
offset integer 分页偏移

响应:分页 Shipment[]

创建出货单

POST /api/v1/shipment/shipments/

请求体:

{
  "customer": 10,
  "address_id": 5,
  "shipment_date": "2026-01-14",
  "address": "杭州市测试路 1 号",
  "contact_name": "张三",
  "contact_phone": "13800138000",
  "area": "华东",
  "coordinates": "120.1551,30.2741",
  "extra": {"source": "customer_address"},
  "remark": "备注",
  "sales_items": [1, 2, 3]
}

请求字段:

字段 类型 必填 说明
customer integer 客户 ID
address_id integer/null 客户地址 ID仅校验和关联
shipment_date date 出货日期
address string 地址快照,默认 "",最大 255
contact_name string 联系人快照,默认 "",最大 100
contact_phone string 联系电话快照,默认 "",最大 50
area string 地区快照,默认 "",最大 100
coordinates string/null 经纬度字符串,最大 100
extra JSON/null 扩展信息
remark string 出货单备注,默认 ""
sales_items integer[] 要关联的销售品 ID 列表,默认 [],后端会去重

业务规则:

  • 用户必须关联商户。
  • 客户必须属于当前商户。
  • address_id 存在时,客户地址必须存在、未软删除、属于当前商户、属于请求中的 customer
  • sales_items 非空时,销售品必须存在、未删除、未绑定其他出货单、属于当前商户,并且都来自同一个生产订单。

响应:201 Shipment

创建外部出货单

POST /api/v1/shipment/shipments/external/

用于没有内部销售品、但需要记录外部成品表的出货单。

请求体:

{
  "customer": 10,
  "shipment_date": "2026-01-14",
  "address": "杭州市测试路 1 号",
  "contact_name": "张三",
  "contact_phone": "13800138000",
  "area": "华东",
  "coordinates": "120.1551,30.2741",
  "extra": {"source": "external"},
  "remark": "备注",
  "external_id": "EXT-001",
  "external_finished_products": [
    {
      "style_name": "款式A",
      "num_of_rolls": 10,
      "remark": "成品备注"
    }
  ]
}

请求字段:

字段 类型 必填 说明
customer integer 客户 ID
shipment_date date 出货日期
address string 地址,最大 255
contact_name string 联系人,最大 100
contact_phone string 联系电话,最大 50
area string 地区,最大 100
coordinates string/null 经纬度字符串,最大 100
extra JSON/null 扩展信息
remark string 备注
external_id string 外部订单号,不能为空,最大 120
external_finished_products array 外部成品表,不能为空

external_finished_products 元素:

字段 类型 必填 说明
style_name string 款式名,最大 200
num_of_rolls integer 卷数,最小 0
remark string/null 备注,最大 200

响应:201 Shipment

获取出货单详情

GET /api/v1/shipment/shipments/{id}/

查询参数:

参数 类型 必填 说明
status integer 可选状态过滤;不匹配则返回 404

响应:200 Shipment

更新出货单

PATCH /api/v1/shipment/shipments/{id}/

PUT /api/v1/shipment/shipments/{id}/

当前 PUT 行为等同 PATCH,允许只传部分字段。

请求体:

{
  "customer": 10,
  "shipment_date": "2026-01-15",
  "address": "新地址",
  "contact_name": "李四",
  "contact_phone": "13900139000",
  "area": "华南",
  "coordinates": null,
  "extra": null,
  "remark": "新备注",
  "external_id": "EXT-002",
  "geo_coordinates": {"lng": 120.1, "lat": 30.2}
}

可更新字段:

字段 类型 说明
customer integer 客户 ID
shipment_date date 出货日期
address string 地址,最大 255
contact_name string 联系人,最大 100
contact_phone string 联系电话,最大 50
area string 地区,最大 100
coordinates string/null 经纬度字符串;传 null 可清空
extra JSON/null 扩展信息;传 null 可清空
remark string 备注
external_id string/null 外部订单号;空字符串或 null 会清空
geo_coordinates JSON/null 当前 serializer 接收该字段,但业务更新服务未保存它,前端不建议使用

业务规则:

  • 已关联送货单的出货单不允许修改业务数据。
  • 修改客户时,新客户必须存在且属于同一商户。

响应:200 Shipment

修改出货单状态

PATCH /api/v1/shipment/shipments/{id}/status/

PUT /api/v1/shipment/shipments/{id}/status/

请求体:

{
  "status": 5
}

响应:200 Shipment

送货单接口

查询送货单列表

GET /api/v1/shipment/deliveries/

查询参数:

参数 类型 必填 说明
status integer 送货单状态
driver_name string 司机名模糊匹配
vehicle_trip string 车次模糊匹配
limit integer 分页大小
offset integer 分页偏移

响应:分页 ShipmentDelivery[]

创建送货单

POST /api/v1/shipment/deliveries/

请求体:

{
  "driver_name": "司机A",
  "vehicle_trip": "浙A12345",
  "contact_phone": "13800138000",
  "vehicle_capacity": "4.2米",
  "remark": "备注",
  "internal_remark": "内部备注",
  "shipment_order_ids": [3, 2, 1],
  "shipments": [1, 2, 3]
}

请求字段:

字段 类型 必填 说明
driver_name string 司机名,最大 100
vehicle_trip string 车次,最大 100
contact_phone string 联系电话,默认 "",最大 50
vehicle_capacity string 车辆容量,默认 "",最大 100
remark string 备注,默认 "",最大 200
internal_remark string 内部备注,默认 "",最大 200
shipment_order_ids array/null 前端自管出货单排序 ID 数组,可为 null
shipments integer[] 要关联的出货单 ID 列表,默认 [],后端会去重

响应:201 ShipmentDelivery

按生产订单查询送货单

GET /api/v1/shipment/deliveries/by-printing-order/{printing_order_id}/

路径参数:

  • printing_order_id 支持内部 PrintingOrder.idexternal_order_id
  • 如果 external_order_id 匹配多个生产订单,返回 500 { "message": "...请改用内部ID查询" }

查询参数:

参数 类型 必填 说明
status integer 送货单状态
driver_name string 模糊匹配
vehicle_trip string 模糊匹配
contact_phone string 模糊匹配
vehicle_capacity string 模糊匹配
remark string 模糊匹配
internal_remark string 模糊匹配
started_at_from date/datetime 开始送货时间起
started_at_to date/datetime 开始送货时间止
delivered_at_from date/datetime 送达时间起
delivered_at_to date/datetime 送达时间止
cancelled_at_from date/datetime 取消时间起
cancelled_at_to date/datetime 取消时间止
created_at_from date/datetime 创建时间起
created_at_to date/datetime 创建时间止
shipment_date_from date 关联出货日期起
shipment_date_to date 关联出货日期止
ordering string 可选 id/created_at/updated_at/started_at/delivered_at/cancelled_at/status,支持前缀 -
limit integer 分页大小
offset integer 分页偏移

响应:分页 ShipmentDelivery[],字段使用专用 DTO不包含 cancelled_by_id/cancelled_by_name

获取送货单详情

GET /api/v1/shipment/deliveries/{id}/

响应:200 ShipmentDelivery

更新送货单

PATCH /api/v1/shipment/deliveries/{id}/

PUT /api/v1/shipment/deliveries/{id}/

当前 PUT 行为等同 PATCH

请求体:

{
  "driver_name": "司机B",
  "vehicle_trip": "浙B12345",
  "contact_phone": "13900139000",
  "vehicle_capacity": "9.6米",
  "remark": "新备注",
  "internal_remark": "新内部备注",
  "shipment_order_ids": [2, 1],
  "shipments": [1, 2]
}

可更新字段:

字段 类型 说明
driver_name string 司机名,最大 100不允许空字符串
vehicle_trip string 车次,最大 100不允许空字符串
contact_phone string 联系电话,最大 50
vehicle_capacity string 车辆容量,最大 100
remark string 备注,最大 200
internal_remark string 内部备注,最大 200
shipment_order_ids array/null 前端自管排序 ID 数组,传入即更新
shipments integer[] 传入即替换当前绑定出货单

响应:200 ShipmentDelivery

删除送货单

DELETE /api/v1/shipment/deliveries/{id}/

响应:204 No Content

修改送货单状态

POST /api/v1/shipment/deliveries/{id}/status/

请求体:

{
  "status": 2
}

允许状态:123

响应:200 ShipmentDelivery

取消送货单

POST /api/v1/shipment/deliveries/{id}/cancel/

权限:需要 shipment.cancel_shipmentdelivery

响应:200 ShipmentDelivery

追加绑定出货单到送货单

POST /api/v1/shipment/deliveries/{id}/bind-shipments/

请求体:

{
  "shipments": [4, 5]
}

请求字段:

字段 类型 必填 说明
shipments integer[] 要追加绑定的出货单 ID不能为空后端会去重

响应:200 ShipmentDelivery

销售品接口

查询当前可出货客户

GET /api/v1/shipment/sales-items/customers/

从未出货销售品反推出客户列表。

查询参数:

参数 类型 必填 说明
merchant integer 超级管理员必填 超级管理员必须传商户 ID普通用户忽略
customer_name string 客户名称模糊匹配
limit integer 分页大小
offset integer 分页偏移

响应:

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "customer_id": 10,
      "customer_name": "客户A",
      "mobile": "13900139000",
      "area": "杭州",
      "unshipped_sales_items_count": 3
    }
  ]
}

按客户查询销售品

GET /api/v1/shipment/sales-items/by-customer/{customer_id}/

查询参数:

参数 类型 必填 说明
include_already_has_shipment boolean 是否包含已关联出货单销售品,默认 false;只有字符串 true 会视为真
external_order_id string 按生产订单外部订单号过滤
limit integer 分页大小
offset integer 分页偏移

响应:分页 SalesItem[]

按客户查询销售品分组

GET /api/v1/shipment/sales-items/by-customer/{customer_id}/group/

第一层按 external_order_id 分组并分页,第二层按 name 分组。

查询参数同“按客户查询销售品”。

响应:

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "external_order_id": "KD20441758",
      "count": 2,
      "name_groups": [
        {
          "name": "销售品A",
          "count": 2,
          "items": []
        }
      ]
    }
  ]
}

排序:external_order_id = null 排最后。

按生产订单查询销售品

GET /api/v1/shipment/sales-items/by-printing-order/{printing_order_id}/

路径参数:

  • printing_order_id 支持内部 PrintingOrder.idexternal_order_id
  • 如果 external_order_id 匹配多个生产订单,此接口返回 400 { "detail": "...请改用内部ID查询" }

查询参数:

参数 类型 必填 说明
include_already_has_shipment boolean 是否包含已关联出货单销售品,默认 false;只有字符串 true 会视为真

响应:

{
  "count": 2,
  "results": []
}

resultsSalesItem[],该接口不使用标准分页。

按生产订单查询销售品分组

GET /api/v1/shipment/sales-items/by-printing-order/{printing_order_id}/group/

printing_job_id 分组并分页。

查询参数:

参数 类型 必填 说明
include_already_has_shipment boolean 是否包含已关联出货单销售品,默认 false
limit integer 分页大小,作用于分组数量
offset integer 分页偏移,作用于分组数量

响应:

{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "printing_job_id": 123,
      "count": 2,
      "items": []
    }
  ]
}

手动创建销售品

POST /api/v1/shipment/sales-items/

请求体:

{
  "printing_job_id": 123,
  "name": "销售品A",
  "quantity": "100.50",
  "unit": 1,
  "customer_id": 10,
  "remark": "备注",
  "position": "A1-01",
  "merge_remark": {
    "merge_type": "merge",
    "jobs": [1, 2],
    "main_job": 1,
    "quantity": "100.50",
    "unit": "米",
    "job_count": 2
  }
}

请求字段:

字段 类型 必填 说明
printing_job_id integer 生产任务 ID最小 1
name string 销售品名称,最大 200
quantity string 数量,最大 20支持小数
unit integer 单位:1/2/3/4
customer_id integer/null 客户 ID不传时默认从生产订单获取
remark string 备注,最大 200
position string 货位,最大 200
merge_remark object/null 合卷备注 JSON结构严格校验

merge_remark 必须只包含这些字段:merge_typejobsmain_jobquantityunitjob_count

响应:201 SalesItem

获取销售品详情

GET /api/v1/shipment/sales-items/{id}/

响应:200 SalesItem,包含 product_image_url

更新销售品

PATCH /api/v1/shipment/sales-items/{id}/

请求体只能包含以下字段:

{
  "quantity": "80.00",
  "remark": "新备注",
  "position": "B2-01"
}

可更新字段:

字段 类型 说明
quantity string 数量,支持小数
remark string 备注,最大 200
position string 货位,最大 200

如果请求包含其他字段,返回 400

响应:200 SalesItem,包含 product_image_url

删除销售品

DELETE /api/v1/shipment/sales-items/{id}/

权限:需要 shipment.soft_delete_salesitem

响应:

{
  "detail": "销售品已标记为删除"
}

重建销售品

POST /api/v1/shipment/sales-items/{id}/rebuild/

仅销售品创建者可执行。

请求体:

{
  "new_printing_job_id": 456,
  "quantity": "50.00"
}

请求字段:

字段 类型 必填 说明
new_printing_job_id integer 新生产任务 ID最小 1
quantity string 新数量;不传则沿用原销售品数量

响应:200 SalesItem

前端重点注意

  • 创建出货单时,address_id 不会自动填充地址快照。前端若选择客户地址,需要同时把地址表中的 address/contact_name/contact_phone/area/coordinates/extra 放入创建请求。
  • coordinates 是新的字符串字段,前端不要再把新数据写到 geo_coordinates
  • geo_coordinates 是历史兼容字段,读取时可能存在旧值,但更新接口目前不保存它。
  • area 现在最大 100 字符,可以直接承载客户地址的 area
  • extra 可用于承载客户地址扩展信息,允许对象、数组或 null
  • 更新出货单时,传 coordinates: nullextra: null 可以清空对应字段;不传则不修改。
  • 按生产订单查送货单的 external_order_id 多匹配错误返回 500 + message;按生产订单查销售品的同类错误返回 400 + detail