282 lines
16 KiB
YAML
282 lines
16 KiB
YAML
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:
|
|
- {name: cabinetNo, in: query, required: false, schema: {type: string}}
|
|
- {name: loadingPlanId, in: query, required: false, schema: {type: integer, format: int64}}
|
|
- {name: warehouseId, in: query, required: true, schema: {type: integer, format: int64, minimum: 1}}
|
|
responses:
|
|
'200':
|
|
description: Task with assignment, review, stable carton codes and item-level versions
|
|
content: {application/json: {schema: {$ref: '#/components/schemas/Task'}}}
|
|
/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':
|
|
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
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: {$ref: '#/components/schemas/PendingTask'}
|
|
/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:
|
|
'200':
|
|
description: Task with current transport display and ACTIVE container lifecycle fields
|
|
content: {application/json: {schema: {$ref: '#/components/schemas/Task'}}}
|
|
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/claim:
|
|
post:
|
|
summary: Atomically claim an unassigned task for the authenticated operator
|
|
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.
|
|
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}
|
|
/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'}}}
|
|
/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
|
|
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.
|
|
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}}
|
|
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/batch:
|
|
post:
|
|
summary: Atomically submit the complete online PDA draft once
|
|
description: A batch containing PICK or PARTIAL idempotently advances associated inbound process status to LOADING before evidence operations become available.
|
|
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:
|
|
'200': {description: 'Completed task, identical replay result, or A0409 when any snapshot changed'}
|
|
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/review:
|
|
post:
|
|
summary: 人工确认装柜完成的兼容入口
|
|
parameters: [{$ref: '#/components/parameters/TaskId'}]
|
|
requestBody:
|
|
required: true
|
|
content: {application/json: {schema: {$ref: '#/components/schemas/ReviewRequest'}}}
|
|
responses:
|
|
'200': {description: 操作员明确确认后完成装柜}
|
|
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/complete:
|
|
post:
|
|
summary: PDA拣货全部处理后人工确认装柜完成
|
|
description: 短事务校验任务版本、全部明细和operationId请求摘要,持久化可靠完成命令并将任务置为COMPLETING后立即返回PROCESSING事实。后台worker按稳定入库单顺序以checkpoint恢复Order、Warehouse、入库状态、计划和事件;请求事务内不调用任何远程服务。同operationId重放立即返回相同PROCESSING或最终结果;不同operationId在处理期间返回A0409。
|
|
parameters: [{$ref: '#/components/parameters/TaskId'}]
|
|
requestBody:
|
|
required: true
|
|
content: {application/json: {schema: {$ref: '#/components/schemas/CompleteLoadingRequest'}}}
|
|
responses:
|
|
'200': {description: 已可靠受理;taskStatus=COMPLETING且workflowStatus=PROCESSING,或幂等返回最终COMPLETED结果;冲突返回A0409}
|
|
/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:
|
|
Task:
|
|
type: object
|
|
required: [id, loadingPlanId, containerBookingId, inboundId, inboundVersion, loadingVersion, cabinetNo, sourceType, recordStatus, taskStatus, workflowStatus, version, items]
|
|
properties:
|
|
id: {type: integer, format: int64}
|
|
loadingPlanId: {type: integer, format: int64}
|
|
containerBookingId: {type: integer, format: int64}
|
|
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}
|
|
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}
|
|
cabinetNo: {type: string}
|
|
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}
|
|
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}
|
|
taskStatus: {type: string, enum: [LOADING, COMPLETING, COMPLETION_FAILED, COMPLETED]}
|
|
workflowStatus: {type: string, enum: [UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW, PROCESSING, COMPLETION_FAILED, COMPLETED]}
|
|
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}
|
|
PendingTask:
|
|
type: object
|
|
required: [taskId, loadingPlanId, containerBookingId, cabinetNo, sourceType, recordStatus, warehouseId, taskStatus, workflowStatus, version, assignmentVersion, itemCount, pendingItemCount]
|
|
properties:
|
|
taskId: {type: integer, format: int64}
|
|
loadingPlanId: {type: integer, format: int64}
|
|
containerBookingId: {type: integer, format: int64}
|
|
cabinetNo: {type: string}
|
|
currentContainerNo: {type: string, nullable: true}
|
|
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}
|
|
warehouseId: {type: integer, format: int64}
|
|
warehouseName: {type: string, nullable: true}
|
|
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}
|
|
version: {type: integer, minimum: 0}
|
|
assignmentVersion: {type: integer, minimum: 0}
|
|
itemCount: {type: integer, minimum: 1}
|
|
pendingItemCount: {type: integer, minimum: 0}
|
|
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}
|
|
BatchRequest:
|
|
type: object
|
|
required: [warehouseId, loadingPlanId, containerBookingId, expectedVersion, inventorySnapshotToken, items]
|
|
properties:
|
|
warehouseId: {type: integer, format: int64, minimum: 1}
|
|
loadingPlanId: {type: integer, format: int64, minimum: 1}
|
|
containerBookingId: {type: integer, format: int64, minimum: 1}
|
|
expectedVersion: {type: integer, minimum: 0}
|
|
inventorySnapshotToken: {type: string, minLength: 64, maxLength: 64}
|
|
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}
|
|
ReviewRequest:
|
|
type: object
|
|
required: [expectedTaskVersion, operationId]
|
|
properties:
|
|
expectedTaskVersion: {type: integer, minimum: 0}
|
|
operationId: {type: string, maxLength: 128}
|
|
remark: {type: string, maxLength: 500}
|
|
CompleteLoadingRequest:
|
|
type: object
|
|
required: [expectedTaskVersion, operationId]
|
|
properties:
|
|
expectedTaskVersion: {type: integer, minimum: 0}
|
|
operationId: {type: string, maxLength: 128}
|
|
remark: {type: string, maxLength: 500}
|
|
InventorySnapshot:
|
|
type: object
|
|
required: [taskId, loadingPlanId, containerBookingId, cabinetNo, taskVersion, warehouseId, capturedAt, snapshotToken, inbounds]
|
|
properties:
|
|
taskId: {type: integer, format: int64}
|
|
loadingPlanId: {type: integer, format: int64}
|
|
containerBookingId: {type: integer, format: int64}
|
|
cabinetNo: {type: string}
|
|
taskVersion: {type: integer, minimum: 0}
|
|
currentContainerNo: {type: string, nullable: true}
|
|
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}
|