feat(firstleg): close phase3 outbound customs and schedule gates
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Phase 3 Customs Collaboration API
|
||||
version: 1.0.0
|
||||
description: Immutable checklist and file versions, supplement requests, frozen agent batches, receipts and history.
|
||||
paths:
|
||||
/api/platform/v1/customs/checklist-versions:
|
||||
post:
|
||||
summary: Create an immutable customs document checklist version
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
responses: {'200': {description: Checklist version}}
|
||||
/api/platform/v1/customs/cases:
|
||||
get:
|
||||
summary: Page customs cases
|
||||
responses: {'200': {description: Page result}}
|
||||
post:
|
||||
summary: Create a customer/order/inbound/container scoped customs case
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
responses: {'200': {description: Customs case detail}}
|
||||
/api/platform/v1/customs/cases/{caseId}:
|
||||
parameters: [{$ref: '#/components/parameters/CaseId'}]
|
||||
get:
|
||||
summary: Query complete customs detail and stable history
|
||||
responses: {'200': {description: Detail}}
|
||||
/api/platform/v1/customs/cases/{caseId}/documents:
|
||||
parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
post:
|
||||
summary: Reference a file validated against customer, CUSTOMS_DOCUMENT and case ID
|
||||
responses: {'200': {description: New document version}}
|
||||
/api/platform/v1/customs/cases/{caseId}/documents/upload:
|
||||
parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
post:
|
||||
summary: Upload a document and create a new immutable version
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
required: [itemCode, expectedVersion, file]
|
||||
properties:
|
||||
itemCode: {type: string}
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
file: {type: string, format: binary}
|
||||
responses: {'200': {description: New document version}}
|
||||
/api/platform/v1/customs/cases/{caseId}/documents/{documentId}/review:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/CaseId'}
|
||||
- {name: documentId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {$ref: '#/components/parameters/IdempotencyKey'}
|
||||
post:
|
||||
summary: Approve a current file version or return it with a supplement task
|
||||
responses: {'200': {description: Updated detail}}
|
||||
/api/platform/v1/customs/cases/{caseId}/submission-batches:
|
||||
parameters: [{$ref: '#/components/parameters/CaseId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
post:
|
||||
summary: Submit to customs agent and freeze approved file versions in a batch snapshot
|
||||
responses: {'200': {description: Submission batch}}
|
||||
/api/platform/v1/customs/submission-batches/{batchId}/receipts:
|
||||
parameters:
|
||||
- {name: batchId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {$ref: '#/components/parameters/IdempotencyKey'}
|
||||
post:
|
||||
summary: Reference a customer-owned receipt file with explicit visibility
|
||||
responses: {'200': {description: Receipt version}}
|
||||
/api/platform/v1/customs/submission-batches/{batchId}/receipts/upload:
|
||||
post:
|
||||
summary: Upload a receipt version; RELEASED closes the customs dispatch gate
|
||||
responses: {'200': {description: Receipt version}}
|
||||
/api/merchant/v1/customs/orders/{orderId}:
|
||||
get:
|
||||
summary: Query the authenticated customer's customs case by order
|
||||
responses: {'200': {description: Customer-filtered detail}}
|
||||
/api/merchant/v1/customs/cases/{caseId}/documents/upload:
|
||||
post:
|
||||
summary: Upload or replace a checklist document within authenticated customer scope
|
||||
responses: {'200': {description: New document version}}
|
||||
/api/merchant/v1/customs/cases/{caseId}/receipts/{receiptId}/download:
|
||||
get:
|
||||
summary: Download only CUSTOMER-visible receipts from the authenticated customer's case
|
||||
responses: {'200': {description: Authorized file stream}}
|
||||
components:
|
||||
parameters:
|
||||
IdempotencyKey:
|
||||
name: Idempotency-Key
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string, minLength: 1, maxLength: 128}
|
||||
CaseId:
|
||||
name: caseId
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
@@ -0,0 +1,86 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Phase 3 Loading Evidence and Picking API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/platform/v1/inbounds/{inboundId}/loading/evidence:
|
||||
get:
|
||||
summary: List loading evidence bound to one customer inbound
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}]
|
||||
responses:
|
||||
'200': {description: Business envelope containing the stable evidence array}
|
||||
post:
|
||||
summary: Bind one real File service object to a loading evidence slot
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/UpsertEvidenceRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope; ownership, type and version failures use business error codes}
|
||||
/api/platform/v1/inbounds/{inboundId}/loading/picking/start:
|
||||
post:
|
||||
summary: Start the inbound-level PDA picking review task
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/PickingRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope containing IN_PROGRESS task}
|
||||
/api/platform/v1/inbounds/{inboundId}/loading/picking/complete:
|
||||
post:
|
||||
summary: Complete a started PDA picking task when planned and picked counts match
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/PickingRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope containing COMPLETED task}
|
||||
/api/platform/v1/inbounds/{inboundId}/loading/picking:
|
||||
get:
|
||||
summary: Read the inbound-level PDA picking task
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}]
|
||||
responses:
|
||||
'200': {description: Business envelope containing task or null}
|
||||
/api/platform/v1/inbounds/{inboundId}/loading/complete:
|
||||
post:
|
||||
summary: Complete loading only after picking and PHOTO_STEP_1..4 plus SEAL evidence are complete
|
||||
parameters: [{$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/CompleteLoadingRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope containing LOADED status}
|
||||
components:
|
||||
parameters:
|
||||
InboundId: {name: inboundId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
|
||||
TenantId: {name: tenantId, in: query, required: true, schema: {type: integer, format: int64, minimum: 1}}
|
||||
IdempotencyKey: {name: Idempotency-Key, in: header, required: true, schema: {type: string, maxLength: 128}}
|
||||
schemas:
|
||||
UpsertEvidenceRequest:
|
||||
type: object
|
||||
required: [expectedVersion, evidenceType, fileId]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
evidenceType: {type: string, enum: [PHOTO_STEP_1, PHOTO_STEP_2, PHOTO_STEP_3, PHOTO_STEP_4, SEAL]}
|
||||
fileId: {type: integer, format: int64, minimum: 1}
|
||||
fileName: {type: string, maxLength: 255, deprecated: true, description: Ignored; server uses File metadata}
|
||||
sealNo: {type: string, maxLength: 64, description: Required when evidenceType is SEAL}
|
||||
remark: {type: string, maxLength: 1000}
|
||||
PickingRequest:
|
||||
type: object
|
||||
required: [expectedVersion, expectedCount, pickedCount]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
expectedCount: {type: integer, minimum: 1}
|
||||
pickedCount: {type: integer, minimum: 0}
|
||||
remark: {type: string, maxLength: 1000}
|
||||
CompleteLoadingRequest:
|
||||
type: object
|
||||
required: [expectedVersion]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
remark: {type: string, maxLength: 1000}
|
||||
@@ -0,0 +1,69 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Phase 3 Domestic Outbound Dispatch API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/platform/v1/first-leg/outbound-dispatches:
|
||||
get:
|
||||
summary: Query outbound aggregates by order, inbound or container
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrderId'}
|
||||
- {$ref: '#/components/parameters/InboundId'}
|
||||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||||
responses:
|
||||
'200': {description: Business envelope containing matching aggregates}
|
||||
/api/platform/v1/first-leg/outbound-dispatches/detail:
|
||||
get:
|
||||
summary: Query one aggregate and its unified timeline
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrderId'}
|
||||
- {$ref: '#/components/parameters/InboundId'}
|
||||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||||
responses:
|
||||
'200': {description: Business envelope containing aggregate detail}
|
||||
/api/platform/v1/first-leg/outbound-dispatches/check-gate:
|
||||
get:
|
||||
summary: Evaluate the fail-closed domestic outbound gate
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrderId'}
|
||||
- {$ref: '#/components/parameters/InboundId'}
|
||||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||||
responses:
|
||||
'200': {description: Business envelope containing every gate item}
|
||||
/api/platform/v1/first-leg/outbound-dispatches/confirm-dispatch:
|
||||
post:
|
||||
summary: Confirm domestic dispatch and enter WAITING_FOR_LOADING
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IdempotencyKey'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/ActionRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope; gate or version failures use business error code}
|
||||
/api/platform/v1/first-leg/outbound-dispatches/reverse-dispatch:
|
||||
post:
|
||||
summary: Reverse WAITING_FOR_LOADING to LOADED
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/IdempotencyKey'}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json: {schema: {$ref: '#/components/schemas/ActionRequest'}}
|
||||
responses:
|
||||
'200': {description: Business envelope containing reverted aggregate}
|
||||
components:
|
||||
parameters:
|
||||
OrderId: {name: orderId, in: query, schema: {type: integer, format: int64, minimum: 1}}
|
||||
InboundId: {name: inboundId, in: query, schema: {type: integer, format: int64, minimum: 1}}
|
||||
ContainerBookingId: {name: containerBookingId, in: query, schema: {type: integer, format: int64, minimum: 1}}
|
||||
IdempotencyKey: {name: Idempotency-Key, in: header, required: true, schema: {type: string, maxLength: 128}}
|
||||
schemas:
|
||||
ActionRequest:
|
||||
type: object
|
||||
required: [inboundId, containerBookingId, expectedVersion]
|
||||
properties:
|
||||
inboundId: {type: integer, format: int64, minimum: 1}
|
||||
containerBookingId: {type: integer, format: int64, minimum: 1}
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
remark: {type: string, maxLength: 500}
|
||||
@@ -0,0 +1,114 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Platform Port Schedule API
|
||||
version: 1.0.0
|
||||
description: Independent port and vessel schedule observations linked to ocean bookings and allocated containers.
|
||||
paths:
|
||||
/api/platform/v1/port-schedules:
|
||||
get:
|
||||
summary: Query schedules by customer, ocean booking, allocated container or expiry
|
||||
parameters:
|
||||
- {name: customerId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {name: oceanBookingId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {name: containerBookingId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {name: expired, in: query, schema: {type: boolean}}
|
||||
- {name: keyword, in: query, schema: {type: string, maxLength: 128}}
|
||||
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
|
||||
responses:
|
||||
'200':
|
||||
description: HTTP 200 business envelope containing a page of schedule views
|
||||
post:
|
||||
summary: Create a source observation linked to a real ocean booking
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/CreateRequest'}
|
||||
responses:
|
||||
'200': {description: Created detail in the standard business envelope}
|
||||
/api/platform/v1/port-schedules/{portScheduleId}:
|
||||
parameters: [{$ref: '#/components/parameters/PortScheduleId'}]
|
||||
get:
|
||||
summary: Get schedule and immutable history
|
||||
responses:
|
||||
'200': {description: Schedule detail with computed expired flag}
|
||||
put:
|
||||
summary: Update source observation with optimistic locking
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/UpdateRequest'}
|
||||
responses:
|
||||
'200': {description: Updated detail or A0409 conflict in the business envelope}
|
||||
/api/platform/v1/port-schedules/{portScheduleId}/history:
|
||||
parameters: [{$ref: '#/components/parameters/PortScheduleId'}]
|
||||
get:
|
||||
summary: Query immutable source observation history
|
||||
responses:
|
||||
'200': {description: Ordered CREATE and UPDATE history records}
|
||||
components:
|
||||
parameters:
|
||||
PortScheduleId:
|
||||
name: portScheduleId
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
IdempotencyKey:
|
||||
name: Idempotency-Key
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string, minLength: 1, maxLength: 128}
|
||||
schemas:
|
||||
ScheduleData:
|
||||
type: object
|
||||
required:
|
||||
- customerId
|
||||
- oceanBookingId
|
||||
- sourceType
|
||||
- sourceName
|
||||
- sourceRef
|
||||
- vesselName
|
||||
- voyageNo
|
||||
- departurePortCode
|
||||
- destinationPortCode
|
||||
- observedAt
|
||||
- expiresAt
|
||||
properties:
|
||||
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
oceanBookingId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
containerBookingId: {type: string, nullable: true, pattern: '^[1-9][0-9]*$'}
|
||||
sourceType: {type: string, enum: [MANUAL, CARRIER, TERMINAL, API]}
|
||||
sourceName: {type: string, maxLength: 128}
|
||||
sourceRef: {type: string, maxLength: 255}
|
||||
vesselName: {type: string, maxLength: 128}
|
||||
voyageNo: {type: string, maxLength: 64}
|
||||
departurePortCode: {type: string, maxLength: 32}
|
||||
departurePortName: {type: string, nullable: true, maxLength: 128}
|
||||
destinationPortCode: {type: string, maxLength: 32}
|
||||
destinationPortName: {type: string, nullable: true, maxLength: 128}
|
||||
etdAt: {type: string, format: date-time, nullable: true}
|
||||
etaAt: {type: string, format: date-time, nullable: true}
|
||||
bookingCutoffAt: {type: string, format: date-time, nullable: true, description: Booking cutoff}
|
||||
customsCutoffAt: {type: string, format: date-time, nullable: true, description: Customs cutoff}
|
||||
portCutoffAt: {type: string, format: date-time, nullable: true, description: Port gate cutoff}
|
||||
observedAt: {type: string, format: date-time}
|
||||
expiresAt: {type: string, format: date-time}
|
||||
remark: {type: string, nullable: true, maxLength: 1000}
|
||||
CreateRequest:
|
||||
type: object
|
||||
required: [expectedVersion, data]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0, maximum: 0}
|
||||
data: {$ref: '#/components/schemas/ScheduleData'}
|
||||
reason: {type: string, nullable: true, maxLength: 1000}
|
||||
UpdateRequest:
|
||||
type: object
|
||||
required: [expectedVersion, data]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
data: {$ref: '#/components/schemas/ScheduleData'}
|
||||
reason: {type: string, nullable: true, maxLength: 1000}
|
||||
Reference in New Issue
Block a user