2026-08-25 11:20:36 +08:00
|
|
|
|
openapi: 3.0.3
|
|
|
|
|
|
info:
|
|
|
|
|
|
title: Lastleg Overseas PDA Warehouse Operations API
|
|
|
|
|
|
version: 1.0.0
|
2026-09-01 14:24:59 +08:00
|
|
|
|
description: 海外仓PDA排车拣货发车、一件代发出库、盘点、同仓整托移库、托盘与换标作业;全部范围从PDA Token解析,派送不进入PDA。
|
2026-08-25 11:20:36 +08:00
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
paths:
|
2026-09-01 14:24:59 +08:00
|
|
|
|
/api/pda/v1/last-leg/dispatches:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询Token绑定仓的排车PDA任务
|
|
|
|
|
|
description: 仅 OVERSEAS_WAREHOUSE_PDA_OPERATOR + lastleg:pda:operate;跨客户读取绑定仓任务,不接收customerId或warehouseId。
|
|
|
|
|
|
parameters: [{ name: status, in: query, required: false, schema: { type: string } }]
|
|
|
|
|
|
responses: { '200': { description: 排车任务列表 }, '403': { description: 角色、权限或仓库绑定缺失 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/dispatches/{dispatchNo}:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询绑定仓排车任务详情
|
2026-09-02 14:00:54 +08:00
|
|
|
|
description: 返回 canDepart 与 departBlockReason;PDA 必须以服务端门禁决定是否开放发车,不得仅按本地拣货数量推断。
|
2026-09-01 14:24:59 +08:00
|
|
|
|
parameters: [{ name: dispatchNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
responses: { '200': { description: 排车托盘、目的仓与库存位置详情 }, '404': { description: 当前绑定仓无此排车任务 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/dispatches/{dispatchNo}/items/{itemId}/pick:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码拣取排车托盘包裹
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- { name: dispatchNo, in: path, required: true, schema: { type: string } }
|
|
|
|
|
|
- { name: itemId, in: path, required: true, schema: { type: string, pattern: '^[0-9]+$' } }
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/DispatchPick' } } } }
|
|
|
|
|
|
responses: { '200': { description: 本次及累计拣货结果;同键同请求重放既有结果 }, '409': { description: 跨仓、跨客户、库存、数量或幂等冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/dispatches/{dispatchNo}/complete:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 完成排车拣货
|
|
|
|
|
|
description: 每个要求托盘及全部包裹必须精确完成;不允许部分完成。
|
|
|
|
|
|
parameters: [{ name: dispatchNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/IdempotentAction' } } } }
|
|
|
|
|
|
responses: { '200': { description: READY_TO_DEPART结果 }, '409': { description: 未全部拣货或幂等冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/dispatches/{dispatchNo}/depart:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 排车发车并完成出库门禁
|
|
|
|
|
|
description: 仅完整拣货且存在待出库单时发车;同事务推进出库与排车状态、订单归属并释放托盘锁,不重复扣减扫码时已扣库存。
|
|
|
|
|
|
parameters: [{ name: dispatchNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/DepartAction' } } } }
|
|
|
|
|
|
responses: { '200': { description: DEPARTED结果;同键同请求返回既有结果 }, '409': { description: 拣货、出库或幂等门禁未满足 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/outbound-tasks:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询Token绑定仓的一件代发出库任务
|
|
|
|
|
|
description: 一件代发复用统一出库任务模型;不接收customerId或warehouseId,派送不进入PDA。
|
|
|
|
|
|
parameters: [{ name: status, in: query, required: false, schema: { type: string } }]
|
|
|
|
|
|
responses: { '200': { description: 出库任务列表 } }
|
2026-09-07 20:51:03 +08:00
|
|
|
|
/api/pda/v1/last-leg/outbound-tasks/resolve/{businessNo}:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 解析出库作业扫码业务号
|
|
|
|
|
|
description: 接受一件代发任务号、出库单号或排车单号;按Token绑定仓返回 OUTBOUND 的 taskNo 或 DISPATCH 的 dispatchNo,PDA据此进入正确作业页。
|
|
|
|
|
|
parameters: [{ name: businessNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 正确作业类型及稳定业务编号 }
|
|
|
|
|
|
'404': { description: 当前绑定仓无此出库或排车任务 }
|
2026-09-01 14:24:59 +08:00
|
|
|
|
/api/pda/v1/last-leg/outbound-tasks/{taskNo}:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询一件代发出库任务详情
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 出库任务、出库项及每条可拣库存位置;inventoryPositionId仅作为pick提交键,不作为用户展示编号
|
|
|
|
|
|
content: { application/json: { schema: { $ref: '#/components/schemas/PdaOutboundTaskDetail' } } }
|
|
|
|
|
|
'404': { description: 当前绑定仓无此任务 }
|
|
|
|
|
|
/api/pda/v1/last-leg/outbound-tasks/{taskNo}/pick:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码拣取一件代发箱件
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/OutboundPick' } } } }
|
|
|
|
|
|
responses: { '200': { description: 更新后的统一出库任务 }, '409': { description: 库存、数量或幂等冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/outbound-tasks/{taskNo}/complete:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 完成一件代发出库任务
|
|
|
|
|
|
description: 全部托盘及箱件精确拣完后完成;同一完成幂等键返回既有结果,其他键明确冲突。
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/IdempotentAction' } } } }
|
|
|
|
|
|
responses: { '200': { description: COMPLETED任务 }, '409': { description: 未全部拣货或幂等冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/stocktakes:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询Token绑定仓盘点任务
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
|
|
|
|
|
|
- { name: size, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 20 } }
|
|
|
|
|
|
- { name: status, in: query, schema: { type: string, enum: [IN_PROGRESS, SUBMITTED] } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 盘点任务分页, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeSummaryPageResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
post:
|
|
|
|
|
|
summary: 按库位或托盘创建盘点任务
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeCreate' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 创建后的完整盘点任务, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeDetailResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/stocktakes/{taskNo}:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询盘点任务详情
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 盘点任务及冻结库存位置, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeDetailResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/stocktakes/{taskNo}/counts:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 提交一个库存位置的实盘箱数
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeCount' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 已计数明细, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeItemResponse' } } } }
|
|
|
|
|
|
'409': { description: 版本或幂等冲突 }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/stocktakes/{taskNo}/submit:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 提交盘点并按差异调整库存
|
|
|
|
|
|
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeSubmit' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 已提交盘点任务, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeDetailResponse' } } } }
|
|
|
|
|
|
'409': { description: 未全盘、库存版本变化或负库存风险 }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/inventory-moves:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 同仓整托移库
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/InventoryMove' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 移库结果, content: { application/json: { schema: { $ref: '#/components/schemas/InventoryMoveResponse' } } } }
|
2026-09-04 14:07:18 +08:00
|
|
|
|
'404': { description: 来源托盘不存在(统一响应实际 HTTP 200,body.code=A0404), content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
'409': { description: 跨仓、资源或库存版本冲突 }
|
|
|
|
|
|
/api/pda/v1/last-leg/inventory/resolve:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码查询Token绑定仓库存
|
|
|
|
|
|
description: 支持箱唛、SKU、入仓码、托盘码或库位码;不接收customerId或warehouseId。
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 匹配的库存位置列表, content: { application/json: { schema: { $ref: '#/components/schemas/InventoryScanResponse' } } } }
|
|
|
|
|
|
/api/pda/v1/last-leg/locations/resolve:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码查询Token绑定仓库位
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 库位及占用摘要, content: { application/json: { schema: { $ref: '#/components/schemas/LocationResponse' } } } }
|
|
|
|
|
|
/api/pda/v1/last-leg/pallets/resolve:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码查询Token绑定仓托盘
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 托盘及其库存内容, content: { application/json: { schema: { $ref: '#/components/schemas/PalletResponse' } } } }
|
2026-09-04 14:07:18 +08:00
|
|
|
|
'404': { description: 托盘不存在(统一响应实际 HTTP 200,body.code=A0404), content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
/api/pda/v1/last-leg/operations:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询当前操作人的仓内操作历史
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
|
|
|
|
|
|
- { name: size, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 20 } }
|
|
|
|
|
|
- { name: operationType, in: query, required: false, schema: { type: string } }
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 当前Token绑定仓及操作人的历史分页, content: { application/json: { schema: { $ref: '#/components/schemas/OperationPageResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/pallets/resolve:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 扫码查询托盘及库存内容
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
|
2026-09-04 14:07:18 +08:00
|
|
|
|
responses: { '200': { description: Token绑定仓托盘内容 }, '404': { description: 托盘不存在(统一响应实际 HTTP 200,body.code=A0404), content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/assemble:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 将多个来源托盘的指定库存行组到目标托盘
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletAssemble' } } } }
|
|
|
|
|
|
responses: { '200': { description: 组托及实物托盘状态结果 }, '409': { description: 目的仓、库存或资源版本冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/disassemble:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 将来源托盘库存拆到一个或多个目标托盘
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletDisassemble' } } } }
|
|
|
|
|
|
responses: { '200': { description: 拆托结果 }, '409': { description: 库存或资源版本冲突 } }
|
2026-09-10 17:11:33 +08:00
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/relabel-disassemble:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 按换标箱唛拆托并绑定目标托盘
|
|
|
|
|
|
description: PDA先扫描原托盘,再扫描换标单指定箱唛;服务端按换标单库存快照解析仓位,在同一事务中扣减原托盘并绑定目标托盘。目标托盘须先由仓储服务创建后扫码确认。
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelPalletDisassemble' } } } }
|
|
|
|
|
|
responses: { '200': { description: 箱唛级拆托绑定结果 }, '409': { description: 箱唛、库存或托盘版本冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/swap:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 将整托库存更换到空目标托盘
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletSwap' } } } }
|
|
|
|
|
|
responses: { '200': { description: 换托结果 }, '409': { description: 目标托盘非空或版本冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/pallet-operations/unbind:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 解除整托库存与实物托盘绑定
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletUnbind' } } } }
|
|
|
|
|
|
responses: { '200': { description: 解绑结果 }, '409': { description: 库存或资源版本冲突 } }
|
|
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/candidates:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询Token绑定仓可执行换标任务
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 待认领、处理中或待复核换标任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelCandidatesResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}:
|
|
|
|
|
|
get:
|
|
|
|
|
|
summary: 查询换标现场任务详情
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
'200': { description: 申请明细、逐件事实、照片与历史, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/claim:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 认领换标任务并推进申请至处理中
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/IdempotentAction' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: 已认领任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 仓库、状态或幂等冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/units:
|
|
|
|
|
|
post:
|
2026-09-08 17:58:42 +08:00
|
|
|
|
summary: 扫描我方箱唛并登记整箱正常换标事实;可只传oldLabel由服务端定位箱唛任务
|
2026-08-25 11:20:36 +08:00
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelUnit' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: 更新后的任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 旧标重复、新标不符或版本冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/units/skip:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 登记一件有原因的跳过事实
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelSkip' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: 更新后的任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/exceptions:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 登记一件换标异常事实
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelException' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: 更新后的任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/photos/files:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 上传换标完成现场照片
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { multipart/form-data: { schema: { type: object, required: [file], properties: { file: { type: string, format: binary } } } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: OVERSEAS_RELABEL_PHOTO文件元数据, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelPhotoResponse' } } } } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/complete:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 提交现场任务等待复核,不提前完成申请
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelComplete' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: WAIT_REVIEW任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 箱数未核平、照片或版本冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/review:
|
|
|
|
|
|
post:
|
|
|
|
|
|
summary: 现场复核;APPROVE才完成既有换标申请,REWORK退回处理
|
|
|
|
|
|
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
|
|
|
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelReview' } } } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
responses: { '200': { description: COMPLETED或PROCESSING任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 状态或版本冲突 } }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
components:
|
|
|
|
|
|
securitySchemes:
|
|
|
|
|
|
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
|
|
|
|
|
|
schemas:
|
2026-09-04 12:59:37 +08:00
|
|
|
|
ApiResponse:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [code, data]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
code: { type: string, example: '200' }
|
|
|
|
|
|
message: { type: string, nullable: true }
|
|
|
|
|
|
data: { nullable: true }
|
|
|
|
|
|
requestId: { type: string, nullable: true }
|
|
|
|
|
|
traceId: { type: string, nullable: true }
|
|
|
|
|
|
timestamp: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
StocktakeSummaryPageResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/StocktakeSummaryPage' } }
|
|
|
|
|
|
StocktakeDetailResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/StocktakeDetail' } }
|
|
|
|
|
|
StocktakeItemResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/StocktakeItem' } }
|
|
|
|
|
|
InventoryMoveResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/InventoryMoveResult' } }
|
|
|
|
|
|
InventoryScanResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/InventoryScan' } }
|
|
|
|
|
|
LocationResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/WarehouseLocation' } }
|
|
|
|
|
|
PalletResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/WarehousePallet' } }
|
|
|
|
|
|
OperationPageResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/OperationPage' } }
|
|
|
|
|
|
RelabelCandidatesResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties:
|
|
|
|
|
|
data: { type: array, items: { $ref: '#/components/schemas/RelabelCandidate' } }
|
|
|
|
|
|
RelabelDetailResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/RelabelDetail' } }
|
|
|
|
|
|
RelabelPhotoResponse:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- { $ref: '#/components/schemas/ApiResponse' }
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
properties: { data: { $ref: '#/components/schemas/RelabelPhoto' } }
|
|
|
|
|
|
StocktakeSummaryPage:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [records, page, size, total, pages]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
records: { type: array, items: { $ref: '#/components/schemas/StocktakeSummary' } }
|
|
|
|
|
|
page: { type: integer, format: int64 }
|
|
|
|
|
|
size: { type: integer, format: int64 }
|
|
|
|
|
|
total: { type: integer, format: int64 }
|
|
|
|
|
|
pages: { type: integer, format: int64 }
|
|
|
|
|
|
StocktakeSummary:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [taskNo, scopeType, scopeCode, status, positionCount, countedCount, differenceCount, version, createdAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
taskNo: { type: string }
|
|
|
|
|
|
scopeType: { type: string, enum: [LOCATION, PALLET] }
|
|
|
|
|
|
scopeCode: { type: string }
|
|
|
|
|
|
status: { type: string, enum: [IN_PROGRESS, SUBMITTED] }
|
|
|
|
|
|
positionCount: { type: integer }
|
|
|
|
|
|
countedCount: { type: integer }
|
|
|
|
|
|
differenceCount: { type: integer }
|
|
|
|
|
|
version: { type: integer, format: int64 }
|
|
|
|
|
|
createdAt: { type: string, format: date-time }
|
|
|
|
|
|
submittedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
StocktakeItem:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [itemId, customerId, balanceId, positionId, skuCode, inboundCode, palletId, palletCode, locationId, locationCode, bookPackages, status, positionVersion, version]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
customerId: { type: string }
|
|
|
|
|
|
balanceId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
positionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
skuCode: { type: string }
|
|
|
|
|
|
productName: { type: string, nullable: true }
|
|
|
|
|
|
inboundCode: { type: string }
|
|
|
|
|
|
palletId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
palletCode: { type: string }
|
|
|
|
|
|
locationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
locationCode: { type: string }
|
|
|
|
|
|
bookPackages: { type: integer, format: int64 }
|
|
|
|
|
|
actualPackages: { type: integer, format: int64, nullable: true }
|
|
|
|
|
|
differencePackages: { type: integer, format: int64, nullable: true }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
positionVersion: { type: integer, format: int64 }
|
|
|
|
|
|
version: { type: integer, format: int64 }
|
|
|
|
|
|
StocktakeDetail:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [task, items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
task: { $ref: '#/components/schemas/StocktakeSummary' }
|
|
|
|
|
|
items: { type: array, items: { $ref: '#/components/schemas/StocktakeItem' } }
|
|
|
|
|
|
InventoryMoveResult:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [moveNo, palletId, palletCode, sourceLocationId, sourceLocationCode, targetLocationId, targetLocationCode, customerCount, positionCount, packageCount, palletVersion, status, completedAt, replayed]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
moveNo: { type: string }
|
|
|
|
|
|
palletId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
palletCode: { type: string }
|
|
|
|
|
|
sourceLocationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
sourceLocationCode: { type: string }
|
|
|
|
|
|
targetLocationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
targetLocationCode: { type: string }
|
|
|
|
|
|
customerCount: { type: integer }
|
|
|
|
|
|
positionCount: { type: integer }
|
|
|
|
|
|
packageCount: { type: integer, format: int64 }
|
|
|
|
|
|
palletVersion: { type: integer }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
completedAt: { type: string, format: date-time }
|
|
|
|
|
|
replayed: { type: boolean }
|
|
|
|
|
|
InventoryScan:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [queryCode, items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
queryCode: { type: string }
|
|
|
|
|
|
items: { type: array, items: { $ref: '#/components/schemas/InventoryItem' } }
|
|
|
|
|
|
InventoryItem:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [customerId, balanceId, positionId, skuCode, inboundCode, palletId, palletCode, availablePackages, holdPackages, receivingPackages, status, version]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
customerId: { type: string }
|
|
|
|
|
|
customerName: { type: string, nullable: true }
|
|
|
|
|
|
balanceId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
positionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
skuCode: { type: string }
|
|
|
|
|
|
productName: { type: string, nullable: true }
|
|
|
|
|
|
inboundCode: { type: string }
|
|
|
|
|
|
cartonMark: { type: string, nullable: true }
|
|
|
|
|
|
palletId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
palletCode: { type: string }
|
|
|
|
|
|
locationId: { type: string, pattern: '^[0-9]+$', nullable: true }
|
|
|
|
|
|
locationCode: { type: string, nullable: true }
|
|
|
|
|
|
availablePackages: { type: integer, format: int64 }
|
|
|
|
|
|
holdPackages: { type: integer, format: int64 }
|
|
|
|
|
|
receivingPackages: { type: integer, format: int64 }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
version: { type: integer, format: int64 }
|
|
|
|
|
|
WarehouseLocation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [locationId, locationCode, locationType, status, occupiedPackages, inventoryPositionCount]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
locationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
locationCode: { type: string }
|
|
|
|
|
|
locationType: { type: string }
|
|
|
|
|
|
maxLoadKg: { type: number, nullable: true }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
occupiedPackages: { type: integer, format: int64 }
|
|
|
|
|
|
inventoryPositionCount: { type: integer }
|
|
|
|
|
|
WarehousePallet:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [palletId, palletCode, status, version, locationId, locationCode, occupiedPackages, inventoryPositionCount, inventory]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
palletId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
palletCode: { type: string }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
version: { type: integer }
|
|
|
|
|
|
locationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
locationCode: { type: string }
|
|
|
|
|
|
occupiedPackages: { type: integer, format: int64 }
|
|
|
|
|
|
inventoryPositionCount: { type: integer }
|
|
|
|
|
|
inventory: { type: array, items: { $ref: '#/components/schemas/InventoryItem' } }
|
|
|
|
|
|
OperationPage:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [records, page, size, total, pages]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
records: { type: array, items: { $ref: '#/components/schemas/WarehouseOperation' } }
|
|
|
|
|
|
page: { type: integer, format: int64 }
|
|
|
|
|
|
size: { type: integer, format: int64 }
|
|
|
|
|
|
total: { type: integer, format: int64 }
|
|
|
|
|
|
pages: { type: integer, format: int64 }
|
|
|
|
|
|
WarehouseOperation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [operationId, operationType, businessKey, status, occurredAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
operationId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
operationType: { type: string }
|
|
|
|
|
|
businessKey: { type: string }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
summary: { type: string, nullable: true }
|
|
|
|
|
|
customerId: { type: string, nullable: true }
|
|
|
|
|
|
occurredAt: { type: string, format: date-time }
|
|
|
|
|
|
RelabelCandidate:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [relabelNo, applicationStatus, taskStatus, itemCount, expectedPackages, relabelledPackages, skippedPackages, exceptionPackages, version, claimedByCurrentOperator]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
relabelNo: { type: string }
|
|
|
|
|
|
customerOrderNo: { type: string, nullable: true }
|
|
|
|
|
|
labelDeadline: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
applicationStatus: { type: string }
|
|
|
|
|
|
taskStatus: { type: string }
|
|
|
|
|
|
itemCount: { type: integer }
|
|
|
|
|
|
expectedPackages: { type: integer }
|
|
|
|
|
|
relabelledPackages: { type: integer }
|
|
|
|
|
|
skippedPackages: { type: integer }
|
|
|
|
|
|
exceptionPackages: { type: integer }
|
|
|
|
|
|
version: { type: integer }
|
|
|
|
|
|
claimedByCurrentOperator: { type: boolean }
|
|
|
|
|
|
RelabelDetail:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [relabelNo, applicationStatus, taskStatus, expectedPackages, relabelledPackages, skippedPackages, exceptionPackages, version, completionPhotoFileIds, items, unitFacts, history]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
relabelNo: { type: string }
|
|
|
|
|
|
customerOrderNo: { type: string, nullable: true }
|
|
|
|
|
|
labelDeadline: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
contactName: { type: string, nullable: true }
|
|
|
|
|
|
contactPhone: { type: string, nullable: true }
|
|
|
|
|
|
applicationStatus: { type: string }
|
|
|
|
|
|
taskStatus: { type: string }
|
|
|
|
|
|
expectedPackages: { type: integer }
|
|
|
|
|
|
relabelledPackages: { type: integer }
|
|
|
|
|
|
skippedPackages: { type: integer }
|
|
|
|
|
|
exceptionPackages: { type: integer }
|
|
|
|
|
|
version: { type: integer }
|
|
|
|
|
|
operatorName: { type: string, nullable: true }
|
|
|
|
|
|
reviewerName: { type: string, nullable: true }
|
|
|
|
|
|
completionPhotoFileIds: { type: array, items: { type: string, pattern: '^[0-9]+$' } }
|
|
|
|
|
|
completionRemark: { type: string, nullable: true }
|
|
|
|
|
|
reviewDecision: { type: string, nullable: true }
|
|
|
|
|
|
reviewRemark: { type: string, nullable: true }
|
|
|
|
|
|
claimedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
submittedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
reviewedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
items: { type: array, items: { $ref: '#/components/schemas/RelabelItem' } }
|
|
|
|
|
|
unitFacts: { type: array, items: { $ref: '#/components/schemas/RelabelUnitFact' } }
|
|
|
|
|
|
history: { type: array, items: { $ref: '#/components/schemas/RelabelHistory' } }
|
|
|
|
|
|
RelabelItem:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
properties:
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
skuCode: { type: string, nullable: true }
|
|
|
|
|
|
productNameZh: { type: string, nullable: true }
|
|
|
|
|
|
shipmentNo: { type: string, nullable: true }
|
|
|
|
|
|
trackingCode: { type: string, nullable: true }
|
|
|
|
|
|
newSkuCode: { type: string, nullable: true }
|
|
|
|
|
|
labelRequirement: { type: string, nullable: true }
|
|
|
|
|
|
relabelFileId: { type: string, nullable: true }
|
|
|
|
|
|
relabelFileName: { type: string, nullable: true }
|
|
|
|
|
|
relabelFileUrl: { type: string, nullable: true }
|
2026-09-08 17:58:42 +08:00
|
|
|
|
cartonMark: { type: string, nullable: true, description: 我方箱唛 }
|
|
|
|
|
|
fbaCartonMark: { type: string, nullable: true, description: 新FBA箱唛 }
|
|
|
|
|
|
operationType: { type: string, enum: [CARTON_LABEL, SKU_LABEL, CARTON_AND_SKU] }
|
|
|
|
|
|
skuItems: { type: array, items: { $ref: '#/components/schemas/RelabelSkuItem' } }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
expectedPackages: { type: integer }
|
|
|
|
|
|
relabelledPackages: { type: integer }
|
|
|
|
|
|
skippedPackages: { type: integer }
|
|
|
|
|
|
exceptionPackages: { type: integer }
|
2026-09-08 17:58:42 +08:00
|
|
|
|
RelabelSkuItem:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [skuCode, newSkuCode, quantity]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
skuCode: { type: string }
|
|
|
|
|
|
newSkuCode: { type: string }
|
|
|
|
|
|
quantity: { type: integer, description: 换标件数 }
|
|
|
|
|
|
remark: { type: string, nullable: true }
|
2026-09-04 12:59:37 +08:00
|
|
|
|
RelabelUnitFact:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
properties:
|
|
|
|
|
|
factId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
oldLabel: { type: string, nullable: true }
|
|
|
|
|
|
newLabel: { type: string, nullable: true }
|
|
|
|
|
|
result: { type: string }
|
|
|
|
|
|
exceptionCode: { type: string, nullable: true }
|
|
|
|
|
|
reason: { type: string, nullable: true }
|
|
|
|
|
|
operatorName: { type: string, nullable: true }
|
|
|
|
|
|
occurredAt: { type: string, format: date-time }
|
|
|
|
|
|
RelabelHistory:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
properties:
|
|
|
|
|
|
action: { type: string }
|
|
|
|
|
|
fromStatus: { type: string, nullable: true }
|
|
|
|
|
|
toStatus: { type: string, nullable: true }
|
|
|
|
|
|
operatorName: { type: string, nullable: true }
|
|
|
|
|
|
detail: { type: string, nullable: true }
|
|
|
|
|
|
createdAt: { type: string, format: date-time }
|
|
|
|
|
|
RelabelPhoto:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [fileId, fileName, contentType, sizeBytes]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
fileId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
fileName: { type: string }
|
|
|
|
|
|
contentType: { type: string }
|
|
|
|
|
|
sizeBytes: { type: integer, format: int64 }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
ScanCode:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [code]
|
|
|
|
|
|
properties: { code: { type: string, minLength: 1, maxLength: 128 } }
|
|
|
|
|
|
IdempotentAction:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey]
|
|
|
|
|
|
properties: { idempotencyKey: { type: string, minLength: 1, maxLength: 255 } }
|
2026-09-01 14:24:59 +08:00
|
|
|
|
DepartAction:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
|
|
|
|
|
|
remark: { type: string, maxLength: 1000, nullable: true }
|
|
|
|
|
|
DispatchPick:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [positionId, packages, productQuantity, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
positionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
packages: { type: integer, format: int64, minimum: 1 }
|
|
|
|
|
|
productQuantity: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
|
|
|
|
|
|
remark: { type: string, maxLength: 1000, nullable: true }
|
|
|
|
|
|
OutboundPick:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [outboundPalletItemId, inventoryPositionId, packages, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
outboundPalletItemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
inventoryPositionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
packages: { type: integer, format: int64, minimum: 1 }
|
|
|
|
|
|
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
|
|
|
|
|
|
PdaOutboundTaskDetail:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [task, items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
task:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [taskNo, status, outboundNo]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
taskNo: { type: string }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
outboundNo: { type: string }
|
|
|
|
|
|
pushedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
completedAt: { type: string, format: date-time, nullable: true }
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [outboundPalletItemId, palletNo, skuCode, inboundCode, packageCount, pickedPackageCount, status, positions]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
outboundPalletItemId: { type: string, description: pick请求提交键,不作为用户展示编号 }
|
2026-09-07 20:51:03 +08:00
|
|
|
|
palletNo: { type: string, description: Warehouse 权威实物托盘码 }
|
2026-09-01 14:24:59 +08:00
|
|
|
|
skuCode: { type: string }
|
|
|
|
|
|
inboundCode: { type: string }
|
|
|
|
|
|
packageCount: { type: integer }
|
|
|
|
|
|
pickedPackageCount: { type: integer }
|
|
|
|
|
|
status: { type: string }
|
|
|
|
|
|
positions:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [inventoryPositionId, palletNo, cartonMark, skuCode, inboundCode, availablePackages, pickedPackages]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
inventoryPositionId: { type: string, description: pick请求提交键,不作为用户展示编号 }
|
2026-09-07 20:51:03 +08:00
|
|
|
|
palletNo: { type: string, description: Warehouse 权威实物托盘码 }
|
2026-09-01 14:24:59 +08:00
|
|
|
|
cartonMark: { type: string, nullable: true }
|
|
|
|
|
|
skuCode: { type: string }
|
|
|
|
|
|
inboundCode: { type: string }
|
|
|
|
|
|
availablePackages: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
pickedPackages: { type: integer, format: int64, minimum: 0 }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
StocktakeCreate:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [scopeType, scopeCode, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
scopeType: { type: string, enum: [LOCATION, PALLET] }
|
|
|
|
|
|
scopeCode: { type: string, maxLength: 128 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
StocktakeCount:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [positionId, actualPackages, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
positionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
actualPackages: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
expectedVersion: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
StocktakeSubmit:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [expectedVersion, reason, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
expectedVersion: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
reason: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
InventoryMove:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [sourcePalletCode, targetLocationCode, expectedPalletVersion, idempotencyKey, reason]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
sourcePalletCode: { type: string, maxLength: 128 }
|
|
|
|
|
|
targetLocationCode: { type: string, maxLength: 128 }
|
|
|
|
|
|
expectedPalletVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
reason: { type: string, minLength: 1, maxLength: 500 }
|
|
|
|
|
|
PalletExpectation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [palletCode, expectedVersion]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
palletCode: { type: string, maxLength: 128 }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
PalletMoveLine:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [positionId, packages, expectedPositionVersion]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
positionId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
packages: { type: integer, format: int64, minimum: 1 }
|
|
|
|
|
|
expectedPositionVersion: { type: integer, format: int64, minimum: 0 }
|
|
|
|
|
|
PalletAssemble:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey, target, sources, lines]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
target: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
sources: { type: array, minItems: 1, maxItems: 20, items: { $ref: '#/components/schemas/PalletExpectation' } }
|
|
|
|
|
|
lines: { type: array, minItems: 1, maxItems: 200, items: { $ref: '#/components/schemas/PalletMoveLine' } }
|
|
|
|
|
|
reason: { type: string, maxLength: 500 }
|
|
|
|
|
|
PalletTargetMove:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [target, lines]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
target: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
lines: { type: array, minItems: 1, maxItems: 200, items: { $ref: '#/components/schemas/PalletMoveLine' } }
|
|
|
|
|
|
PalletDisassemble:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey, source, targets]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
source: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
targets: { type: array, minItems: 1, maxItems: 20, items: { $ref: '#/components/schemas/PalletTargetMove' } }
|
|
|
|
|
|
reason: { type: string, maxLength: 500 }
|
2026-09-10 17:11:33 +08:00
|
|
|
|
RelabelPalletDisassemble:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey, relabelNo, source, target, cartonMarks]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
relabelNo: { type: string, maxLength: 64 }
|
|
|
|
|
|
source: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
target: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
cartonMarks: { type: array, minItems: 1, maxItems: 500, uniqueItems: true, items: { type: string, maxLength: 255 } }
|
|
|
|
|
|
reason: { type: string, maxLength: 500 }
|
2026-08-25 11:20:36 +08:00
|
|
|
|
PalletSwap:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey, source, target]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
source: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
target: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
reason: { type: string, maxLength: 500 }
|
|
|
|
|
|
PalletUnbind:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [idempotencyKey, source]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 128 }
|
|
|
|
|
|
source: { $ref: '#/components/schemas/PalletExpectation' }
|
|
|
|
|
|
reason: { type: string, maxLength: 500 }
|
|
|
|
|
|
RelabelUnit:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [itemId, oldLabel, newLabel, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
oldLabel: { type: string, maxLength: 255 }
|
|
|
|
|
|
newLabel: { type: string, maxLength: 255 }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 255 }
|
|
|
|
|
|
RelabelSkip:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [itemId, oldLabel, reason, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
oldLabel: { type: string, maxLength: 255 }
|
|
|
|
|
|
reason: { type: string, maxLength: 1000 }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 255 }
|
|
|
|
|
|
RelabelException:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [itemId, exceptionCode, reason, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
itemId: { type: string, pattern: '^[0-9]+$' }
|
|
|
|
|
|
oldLabel: { type: string, maxLength: 255, nullable: true }
|
|
|
|
|
|
exceptionCode: { type: string, enum: [DAMAGED, MISSING_LABEL, LABEL_MISMATCH, UNREADABLE, OTHER] }
|
|
|
|
|
|
reason: { type: string, maxLength: 1000 }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 255 }
|
|
|
|
|
|
RelabelComplete:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [photoFileIds, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
photoFileIds: { type: array, minItems: 1, maxItems: 20, items: { type: string, pattern: '^[0-9]+$' } }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 255 }
|
|
|
|
|
|
remark: { type: string, maxLength: 1000, nullable: true }
|
|
|
|
|
|
RelabelReview:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [decision, expectedVersion, idempotencyKey]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
decision: { type: string, enum: [APPROVE, REWORK] }
|
|
|
|
|
|
expectedVersion: { type: integer, minimum: 0 }
|
|
|
|
|
|
idempotencyKey: { type: string, maxLength: 255 }
|
|
|
|
|
|
remark: { type: string, maxLength: 1000, nullable: true }
|