2026-08-09 11:21:38 +08:00
openapi : 3.0.3
info :
title : Phase 3 Container PDA Picking API
version : 1.0.0
paths :
/api/platform/v1/first-leg/pda-loading/tasks :
get :
summary : Find the active container picking task in one platform warehouse
parameters :
2026-08-12 17:45:45 +08:00
- {name : cabinetNo, in : query, required : false, schema : {type : string}}
- {name : loadingPlanId, in : query, required : false, schema : {type : integer, format : int64}}
2026-08-09 11:21:38 +08:00
- {name : warehouseId, in : query, required : true, schema : {type : integer, format : int64, minimum : 1 }}
responses :
2026-08-12 09:25:53 +08:00
'200' :
description : Task with assignment, review, stable carton codes and item-level versions
content : {application/json : {schema : {$ref : '#/components/schemas/Task' }}}
2026-08-11 20:39:28 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/pending :
get :
summary : List active tasks available to the authenticated PDA operator
parameters :
- {name : keyword, in : query, required : false, schema : {type : string, maxLength : 64 }}
responses :
'200' :
2026-08-17 16:17:20 +08:00
description : Unassigned tasks and tasks assigned to the current operator, including AWAITING_REVIEW tasks with zero unresolved items so PDA can enter evidence and final completion; no customer selector required
2026-08-11 20:39:28 +08:00
content :
application/json :
schema :
type : array
items : {$ref : '#/components/schemas/PendingTask' }
2026-08-12 17:29:30 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}:
get :
summary : Read one PDA task by stable task identity
parameters :
- {$ref : '#/components/parameters/TaskId' }
- {name : warehouseId, in : query, required : true, schema : {type : integer, format : int64, minimum : 1 }}
responses :
2026-08-17 14:46:44 +08:00
'200' :
description : Task with current transport display and ACTIVE container lifecycle fields
content : {application/json : {schema : {$ref : '#/components/schemas/Task' }}}
2026-08-09 11:21:38 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/claim:
post :
summary : Atomically claim an unassigned task for the authenticated operator
2026-08-15 09:57:46 +08:00
description : Claiming the canonical PDA task idempotently starts its plan and advances every associated inbound from WAIT_SPLIT to LOADING with optimistic locking; workflowStatus may later become AWAITING_REVIEW while the task remains LOADING until manual completion.
2026-08-09 11:21:38 +08:00
parameters : [ {$ref : '#/components/parameters/TaskId' }]
requestBody :
required : true
content : {application/json : {schema : {$ref : '#/components/schemas/ClaimRequest' }}}
responses :
'200' : {description : Claimed task or A0409 when another operator owns it}
2026-08-11 18:43:50 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/inventory-snapshot:
get :
summary : Read the current Warehouse inventory snapshot before atomic submission
parameters :
- {$ref : '#/components/parameters/TaskId' }
- {name : warehouseId, in : query, required : true, schema : {type : integer, format : int64, minimum : 1 }}
responses :
'200' :
description : Current occupied resources grouped by inbound order with a stable snapshot token
content : {application/json : {schema : {$ref : '#/components/schemas/InventorySnapshot' }}}
2026-08-09 11:21:38 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/assign:
post :
summary : Assign or reassign a task with optimistic locking
parameters : [ {$ref : '#/components/parameters/TaskId' }]
requestBody :
required : true
content : {application/json : {schema : {$ref : '#/components/schemas/AssignRequest' }}}
responses :
'200' : {description : Assigned task or A0409 on assignment version conflict}
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/pick:
post :
summary : Increment a picked item owned by the authenticated assignee
2026-08-15 09:57:46 +08:00
description : The first successful pick also repairs the same WAIT_SPLIT to LOADING transition when the plan was already started, without using containerNo as an association key.
2026-08-09 11:21:38 +08:00
parameters : [ {$ref : '#/components/parameters/TaskId' }, {$ref : '#/components/parameters/ItemId' }]
responses : {'200' : {description : Updated task}}
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/partial:
post :
summary : Record the final partial quantity for one assigned item
parameters : [ {$ref : '#/components/parameters/TaskId' }, {$ref : '#/components/parameters/ItemId' }]
responses : {'200' : {description : Task awaiting review when every item is resolved}}
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/skip:
post :
summary : Resolve an untouched assigned item as skipped
parameters : [ {$ref : '#/components/parameters/TaskId' }, {$ref : '#/components/parameters/ItemId' }]
responses : {'200' : {description : Task awaiting review when every item is resolved}}
2026-08-11 11:24:59 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/batch:
post :
summary : Atomically submit the complete online PDA draft once
2026-08-15 09:57:46 +08:00
description : A batch containing PICK or PARTIAL idempotently advances associated inbound process status to LOADING before evidence operations become available.
2026-08-11 11:24:59 +08:00
parameters :
- {$ref : '#/components/parameters/TaskId' }
- {name : Idempotency-Key, in : header, required : true, schema : {type : string, maxLength : 128 }}
requestBody :
required : true
content : {application/json : {schema : {$ref : '#/components/schemas/BatchRequest' }}}
responses :
2026-08-25 12:27:47 +08:00
'200' : {description : 'Completed task, identical replay result, or A0409 when any snapshot changed' }
2026-08-09 11:21:38 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/review:
post :
2026-08-12 13:34:26 +08:00
summary : 人工确认装柜完成的兼容入口
2026-08-09 11:21:38 +08:00
parameters : [ {$ref : '#/components/parameters/TaskId' }]
requestBody :
required : true
content : {application/json : {schema : {$ref : '#/components/schemas/ReviewRequest' }}}
responses :
2026-08-12 13:34:26 +08:00
'200' : {description : 操作员明确确认后完成装柜}
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/complete:
post :
summary : PDA拣货全部处理后人工确认装柜完成
2026-08-27 14:53:27 +08:00
description : 短事务校验任务版本、全部明细和operationId请求摘要,持久化可靠完成命令并将任务置为COMPLETING后立即返回PROCESSING事实。后台worker按稳定入库单顺序以checkpoint恢复Order、Warehouse、入库状态、计划和事件;请求事务内不调用任何远程服务。同operationId重放立即返回相同PROCESSING或最终结果;不同operationId在处理期间返回A0409。
2026-08-12 13:34:26 +08:00
parameters : [ {$ref : '#/components/parameters/TaskId' }]
requestBody :
required : true
content : {application/json : {schema : {$ref : '#/components/schemas/CompleteLoadingRequest' }}}
responses :
2026-08-27 14:53:27 +08:00
'200' : {description : 已可靠受理;taskStatus=COMPLETING且workflowStatus=PROCESSING,或幂等返回最终COMPLETED结果;冲突返回A0409}
2026-08-09 11:21:38 +08:00
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/operations:
get :
summary : Read immutable task-level claim, assignment and review audit records
parameters : [ {$ref : '#/components/parameters/TaskId' }]
responses :
'200' : {description : Ordered operation history}
components :
parameters :
TaskId : {name : taskId, in : path, required : true, schema : {type : integer, format : int64, minimum : 1 }}
ItemId : {name : itemId, in : path, required : true, schema : {type : integer, format : int64, minimum : 1 }}
schemas :
2026-08-12 09:25:53 +08:00
Task :
type : object
2026-08-17 14:46:44 +08:00
required : [ id, loadingPlanId, containerBookingId, inboundId, inboundVersion, loadingVersion, cabinetNo, sourceType, recordStatus, taskStatus, workflowStatus, version, items]
2026-08-12 09:25:53 +08:00
properties :
id : {type : integer, format : int64}
loadingPlanId : {type : integer, format : int64}
2026-08-12 17:29:30 +08:00
containerBookingId : {type : integer, format : int64}
2026-08-15 10:05:03 +08:00
inboundId : {type : integer, format : int64, description : Stable inbound identity selected from the task item; evidence identity is taskId+inboundId+loadingPlanId+containerBookingId}
inboundVersion : {type : integer, minimum : 0, description : Current fl_inbound_order.version for inboundId; never inferred from PDA task version}
2026-08-15 10:09:04 +08:00
loadingVersion : {type : integer, minimum : 0, description : Compatibility alias of inboundVersion from the same fl_inbound_order row; /loading/complete uses this inbound loading-stage version}
2026-08-12 17:29:30 +08:00
cabinetNo : {type : string}
2026-08-13 19:19:29 +08:00
currentContainerNo : {type : string, nullable : true, description : Mutable transport display field; changing it never resynchronizes the task or item versions and it is never task identity}
2026-08-17 14:46:44 +08:00
sourceType : {type : string, enum : [SIMULATION, OCEAN_BOOKING], description : Source of the surviving stable container identity}
recordStatus : {type : string, enum : [ACTIVE], description : Task detail is served only from the ACTIVE container booking currently owned by the loading plan}
mergedIntoContainerBookingId : {type : integer, format : int64, nullable : true, description : Always null for the surviving ACTIVE operational container; populated only on hidden MERGED source history}
2026-08-27 14:53:27 +08:00
taskStatus : {type : string, enum : [ LOADING, COMPLETING, COMPLETION_FAILED, COMPLETED]}
workflowStatus : {type : string, enum : [ UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW, PROCESSING, COMPLETION_FAILED, COMPLETED]}
2026-08-12 09:25:53 +08:00
version : {type : integer, minimum : 0 }
assignment : {type : object, nullable : true }
review : {type : object, nullable : true }
items :
type : array
items : {$ref : '#/components/schemas/PickItem' }
PickItem :
type : object
required : [ id, loadingPlanItemId, tenantId, inboundId, inboundDetailId, boxCodes, plannedPackageCount, pickedPackageCount, itemStatus, version]
properties :
id : {type : integer, format : int64}
loadingPlanItemId : {type : integer, format : int64}
tenantId : {type : integer, format : int64, description : Hidden isolation key for subsequent PDA evidence calls}
inboundId : {type : integer, format : int64}
inboundDetailId : {type : integer, format : int64}
orderNo : {type : string, nullable : true }
inboundCode : {type : string, nullable : true }
cargoName : {type : string, nullable : true }
boxCodes :
type : array
description : Stable carton label codes; one successful scan represents one carton
items : {type : string}
plannedPackageCount : {type : integer, minimum : 1 }
pickedPackageCount : {type : integer, minimum : 0 }
itemStatus : {type : string, enum : [ PENDING, PICKING, PICKED, PARTIAL, SKIPPED]}
version : {type : integer, minimum : 0 }
2026-08-11 20:39:28 +08:00
PendingTask :
type : object
2026-08-17 14:46:44 +08:00
required : [ taskId, loadingPlanId, containerBookingId, cabinetNo, sourceType, recordStatus, warehouseId, taskStatus, workflowStatus, version, assignmentVersion, itemCount, pendingItemCount]
2026-08-11 20:39:28 +08:00
properties :
taskId : {type : integer, format : int64}
loadingPlanId : {type : integer, format : int64}
2026-08-12 17:29:30 +08:00
containerBookingId : {type : integer, format : int64}
cabinetNo : {type : string}
currentContainerNo : {type : string, nullable : true }
2026-08-17 14:46:44 +08:00
sourceType : {type : string, enum : [ SIMULATION, OCEAN_BOOKING]}
recordStatus : {type : string, enum : [ACTIVE], description : Enforced by the server-side pending-task query; PDA clients must not infer or relax this filter}
mergedIntoContainerBookingId : {type : integer, format : int64, nullable : true, description : Always null for an ACTIVE pending task}
2026-08-11 20:39:28 +08:00
warehouseId : {type : integer, format : int64}
warehouseName : {type : string, nullable : true }
2026-08-27 14:53:27 +08:00
taskStatus : {type : string, enum : [ LOADING, COMPLETING, COMPLETION_FAILED]}
workflowStatus : {type : string, enum : [UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW, PROCESSING, COMPLETION_FAILED], description : Server projection aligned with task detail; completion acceptance is returned immediately as PROCESSING}
2026-08-11 20:39:28 +08:00
version : {type : integer, minimum : 0 }
assignmentVersion : {type : integer, minimum : 0 }
itemCount : {type : integer, minimum : 1 }
pendingItemCount : {type : integer, minimum : 0 }
2026-08-09 11:21:38 +08:00
ClaimRequest :
type : object
required : [ expectedAssignmentVersion, operationId]
properties :
expectedAssignmentVersion : {type : integer, minimum : 0 }
operationId : {type : string, maxLength : 128 }
AssignRequest :
type : object
required : [ assigneeId, assigneeName, expectedAssignmentVersion, operationId]
properties :
assigneeId : {type : integer, format : int64, minimum : 1 }
assigneeName : {type : string, maxLength : 64 }
expectedAssignmentVersion : {type : integer, minimum : 0 }
operationId : {type : string, maxLength : 128 }
2026-08-11 11:24:59 +08:00
BatchRequest :
type : object
2026-08-12 17:29:30 +08:00
required : [ warehouseId, loadingPlanId, containerBookingId, expectedVersion, inventorySnapshotToken, items]
2026-08-11 11:24:59 +08:00
properties :
warehouseId : {type : integer, format : int64, minimum : 1 }
2026-08-12 17:29:30 +08:00
loadingPlanId : {type : integer, format : int64, minimum : 1 }
containerBookingId : {type : integer, format : int64, minimum : 1 }
2026-08-11 11:24:59 +08:00
expectedVersion : {type : integer, minimum : 0 }
2026-08-11 18:43:50 +08:00
inventorySnapshotToken : {type : string, minLength : 64, maxLength : 64 }
2026-08-11 11:24:59 +08:00
items :
type : array
minItems : 1
maxItems : 500
items : {$ref : '#/components/schemas/BatchItemRequest' }
BatchItemRequest :
type : object
required : [ itemId, action, version]
properties :
itemId : {type : integer, format : int64, minimum : 1 }
action : {type : string, enum : [ PICK, PARTIAL, SKIP]}
pickedPackageCount : {type : integer, minimum : 1, description : Incremental count required by PICK}
finalPickedPackageCount : {type : integer, minimum : 1, description : Final actual count required by PARTIAL}
releaseMode : {type : string, enum : [ AUTO, MANUAL]}
reservationIds :
type : array
items : {type : integer, format : int64, minimum : 1 }
version : {type : integer, minimum : 0 }
reason : {type : string, maxLength : 500, description : Required by SKIP}
2026-08-09 11:21:38 +08:00
ReviewRequest :
type : object
required : [ expectedTaskVersion, operationId]
properties :
expectedTaskVersion : {type : integer, minimum : 0 }
operationId : {type : string, maxLength : 128 }
remark : {type : string, maxLength : 500 }
2026-08-12 13:34:26 +08:00
CompleteLoadingRequest :
type : object
required : [ expectedTaskVersion, operationId]
properties :
expectedTaskVersion : {type : integer, minimum : 0 }
operationId : {type : string, maxLength : 128 }
remark : {type : string, maxLength : 500 }
2026-08-11 18:43:50 +08:00
InventorySnapshot :
type : object
2026-08-12 17:29:30 +08:00
required : [ taskId, loadingPlanId, containerBookingId, cabinetNo, taskVersion, warehouseId, capturedAt, snapshotToken, inbounds]
2026-08-11 18:43:50 +08:00
properties :
taskId : {type : integer, format : int64}
2026-08-12 17:29:30 +08:00
loadingPlanId : {type : integer, format : int64}
containerBookingId : {type : integer, format : int64}
cabinetNo : {type : string}
2026-08-11 18:43:50 +08:00
taskVersion : {type : integer, minimum : 0 }
2026-08-12 17:29:30 +08:00
currentContainerNo : {type : string, nullable : true }
2026-08-11 18:43:50 +08:00
warehouseId : {type : integer, format : int64}
capturedAt : {type : string, format : date-time}
snapshotToken : {type : string, minLength : 64, maxLength : 64 }
inbounds :
type : array
items : {$ref : '#/components/schemas/InboundInventory' }
InboundInventory :
type : object
required : [ inboundId, availablePackageCount, resources]
properties :
inboundId : {type : integer, format : int64}
availablePackageCount : {type : integer, minimum : 0 }
resources :
type : array
items : {$ref : '#/components/schemas/InventoryResource' }
InventoryResource :
type : object
required : [ reservationId, occupancyId, palletId, locationId, sharedOverflow, availablePackageCount]
properties :
reservationId : {type : integer, format : int64}
occupancyId : {type : integer, format : int64}
palletId : {type : integer, format : int64}
locationId : {type : integer, format : int64}
locationCode : {type : string, nullable : true }
sharedOverflow : {type : boolean}
availablePackageCount : {type : integer, minimum : 1 }