Files
baiyue-firstleg/firstleg/src/main/resources/openapi/phase3-pda-convergence-v1.yaml
T

282 lines
16 KiB
YAML
Raw Normal View History

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}}
- {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'}}}
/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.
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'}}}
/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.
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
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.
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'}
/api/platform/v1/first-leg/pda-loading/tasks/{taskId}/review:
post:
2026-08-12 13:34:26 +08:00
summary: 人工确认装柜完成的兼容入口
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-17 15:55:11 +08:00
description: PDA拣货只锁定数量和仓储资源。本接口先无写入校验全部关联入库单的RELEASED订舱、稳定bridge和五类ACTIVE证据;拖车状态不是前置门禁。若当前稳定containerBookingId没有有效拖车则直接继续;恰有一条有效拖车时由服务端加锁推进为COMPLETED并写历史;多条有效拖车或并发修改返回A0409且全部Firstleg本地状态回滚。随后在同一事务内结算资源、完成task/plan并推进inbound为LOADED。同operationId重放返回冻结结果,不重复推进拖车或写历史。
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:
'200': {description: 完成任务;存在未处理明细或版本冲突时返回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:
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-12 09:25:53 +08:00
taskStatus: {type: string, enum: [LOADING, COMPLETED]}
workflowStatus: {type: string, enum: [UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW, 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}
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}
taskStatus: {type: string, enum: [LOADING]}
2026-08-17 16:17:20 +08:00
workflowStatus: {type: string, enum: [UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW], description: Server projection aligned with task detail; assigned LOADING tasks with pendingItemCount=0 remain visible as AWAITING_REVIEW}
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}
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
2026-08-12 17:29:30 +08:00
required: [warehouseId, loadingPlanId, containerBookingId, expectedVersion, inventorySnapshotToken, items]
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}
expectedVersion: {type: integer, minimum: 0}
2026-08-11 18:43:50 +08:00
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}
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}