优化
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Carrier Schedule Internal Handoff API
|
||||
version: 1.0.0
|
||||
description: Internal-only handoff contract; it is not a platform or merchant frontend API.
|
||||
paths:
|
||||
/internal/firstleg/v1/carrier-schedule-queries/{queryId}/stop:
|
||||
post:
|
||||
summary: Stop tracking after the overseas pickup handoff has completed
|
||||
parameters:
|
||||
- {name: queryId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
|
||||
- {name: X-Internal-Service-Token, in: header, required: true, schema: {type: string}}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [reason]
|
||||
properties:
|
||||
reason: {type: string, minLength: 1, maxLength: 500}
|
||||
responses:
|
||||
'200': {description: Idempotent STOPPED task detail}
|
||||
@@ -2,7 +2,7 @@ openapi: 3.0.3
|
||||
info:
|
||||
title: Carrier Schedule Query API
|
||||
version: 1.0.0
|
||||
description: Phase-4 carrier tracking from domestic outbound confirmation through destination pickup readiness.
|
||||
description: Phase-4 carrier tracking from domestic outbound confirmation through actual empty return.
|
||||
paths:
|
||||
/api/platform/v1/carrier-schedule-queries/carriers:
|
||||
get:
|
||||
@@ -43,18 +43,21 @@ paths:
|
||||
summary: Get task, standardized node facts and immutable business history
|
||||
x-permission: platform:firstleg:port-schedule-query:list
|
||||
responses:
|
||||
'200': {description: Stable task detail}
|
||||
'200':
|
||||
description: Stable task detail
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/DetailEnvelope'}}}
|
||||
/api/platform/v1/carrier-schedule-queries/{queryId}/history:
|
||||
parameters: [{$ref: '#/components/parameters/QueryId'}]
|
||||
get:
|
||||
summary: Get immutable task history
|
||||
x-permission: platform:firstleg:port-schedule-query:list
|
||||
responses:
|
||||
'200': {description: CREATE, ATTEMPT and MANUAL_RESULT history}
|
||||
'200': {description: Immutable business history; scheduler attempts are not exposed}
|
||||
/api/platform/v1/carrier-schedule-queries/{queryId}/manual-results:
|
||||
parameters: [{$ref: '#/components/parameters/QueryId'}]
|
||||
post:
|
||||
summary: Link a validated manual port-schedule observation without pretending automated success
|
||||
description: This legacy port-schedule association does not append a standard node and never stops tracking; phase-4 manual facts use /manual-nodes.
|
||||
x-permission: platform:firstleg:port-schedule-query:manual
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
@@ -63,7 +66,24 @@ paths:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ManualResultRequest'}
|
||||
responses:
|
||||
'200': {description: Successful manual fallback and next query time}
|
||||
'200':
|
||||
description: Successful manual fallback and next query time
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/DetailEnvelope'}}}
|
||||
/api/platform/v1/carrier-schedule-queries/{queryId}/manual-nodes:
|
||||
parameters: [{$ref: '#/components/parameters/QueryId'}]
|
||||
post:
|
||||
summary: Append one immutable manual estimated or actual standard-node fact
|
||||
x-permission: platform:firstleg:port-schedule-query:manual
|
||||
parameters: [{$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ManualNodeRequest'}
|
||||
responses:
|
||||
'200':
|
||||
description: Idempotent fact append; only actualAt advances and actual EMPTY_RETURNED stops
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/DetailEnvelope'}}}
|
||||
components:
|
||||
parameters:
|
||||
QueryId: {name: queryId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
|
||||
@@ -71,8 +91,11 @@ components:
|
||||
schemas:
|
||||
CarrierCode: {type: string, enum: [MATSON, SML, ZIM, COSCO, EMC, HEDE]}
|
||||
TrackingType: {type: string, enum: [BOOKING_NO, BILL_OF_LADING, CONTAINER_NO]}
|
||||
QueryStatus: {type: string, enum: [READY, MANUAL_REQUIRED, ARRIVED, PICKUP_READY, STOPPED]}
|
||||
StandardNode: {type: string, enum: [DEPARTED_WAREHOUSE, AT_ORIGIN_PORT, DEPARTED_ORIGIN_PORT, IN_TRANSIT, ARRIVED, PICKUP_READY]}
|
||||
QueryStatus: {type: string, enum: [READY, MANUAL_REQUIRED, STOPPED]}
|
||||
StandardNode:
|
||||
type: string
|
||||
enum: [DEPARTED_WAREHOUSE, AT_ORIGIN_PORT, LOADED_ON_VESSEL, DEPARTED_ORIGIN_PORT, IN_TRANSIT, ARRIVED_DESTINATION_PORT, DISCHARGED_FROM_VESSEL, PICKUP_READY, PICKED_UP, EMPTY_RETURNED]
|
||||
ExceptionCode: {type: string, enum: [CUSTOMS_HOLD, TERMINAL_HOLD, DOCUMENT_HOLD, UNKNOWN_HOLD]}
|
||||
CreateRequest:
|
||||
type: object
|
||||
required: [expectedVersion, customerId, oceanBookingId, carrierCode, trackingType, trackingNo]
|
||||
@@ -92,9 +115,112 @@ components:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
portScheduleId: {type: integer, format: int64, minimum: 1}
|
||||
reason: {type: string, minLength: 1, maxLength: 1000}
|
||||
ManualNodeRequest:
|
||||
type: object
|
||||
required: [expectedVersion, standardNode, observedAt, reason]
|
||||
description: estimatedAt and actualAt cannot both be null; estimatedAt never advances the latest actual node.
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
standardNode: {$ref: '#/components/schemas/StandardNode'}
|
||||
observedAt: {type: string, format: date-time}
|
||||
estimatedAt: {type: string, format: date-time, nullable: true}
|
||||
actualAt: {type: string, format: date-time, nullable: true}
|
||||
locationCode: {type: string, maxLength: 32, nullable: true}
|
||||
locationName: {type: string, maxLength: 128, nullable: true}
|
||||
reason: {type: string, minLength: 1, maxLength: 1000}
|
||||
Task:
|
||||
type: object
|
||||
required: [id, queryNo, customerId, oceanBookingId, carrierCode, trackingType, trackingNo, status, triggerSource, version]
|
||||
properties:
|
||||
id: {type: integer, format: int64}
|
||||
queryNo: {type: string}
|
||||
customerId: {type: integer, format: int64}
|
||||
oceanBookingId: {type: integer, format: int64}
|
||||
containerBookingId: {type: integer, format: int64, nullable: true}
|
||||
carrierCode: {$ref: '#/components/schemas/CarrierCode'}
|
||||
trackingType: {$ref: '#/components/schemas/TrackingType'}
|
||||
trackingNo: {type: string}
|
||||
officialUrl: {type: string, nullable: true}
|
||||
accessMode: {type: string, nullable: true}
|
||||
status: {$ref: '#/components/schemas/QueryStatus'}
|
||||
triggerSource: {type: string}
|
||||
latestActualNode: {allOf: [{$ref: '#/components/schemas/StandardNode'}], nullable: true}
|
||||
latestActualAt: {type: string, format: date-time, nullable: true}
|
||||
lastSuccessAt: {type: string, format: date-time, nullable: true}
|
||||
sourceUpdatedAt: {type: string, format: date-time, nullable: true}
|
||||
expiresAt: {type: string, format: date-time, nullable: true}
|
||||
resultPortScheduleId: {type: integer, format: int64, nullable: true}
|
||||
manualReason: {type: string, nullable: true}
|
||||
lastErrorCode: {type: string, nullable: true}
|
||||
lastErrorMessage: {type: string, nullable: true}
|
||||
stoppedAt: {type: string, format: date-time, nullable: true}
|
||||
stopReason: {type: string, nullable: true}
|
||||
version: {type: integer, minimum: 0}
|
||||
QueryView:
|
||||
type: object
|
||||
required: [query, expired]
|
||||
properties:
|
||||
query: {type: object, description: Includes triggerSource, latestStandardNode, latestNodeObservedAt, source freshness and stop fields; scheduler leases and raw attempts are never exposed}
|
||||
query: {$ref: '#/components/schemas/Task'}
|
||||
expired: {type: boolean}
|
||||
NodeFact:
|
||||
type: object
|
||||
required: [id, providerCode, providerEventId, providerNodeCode, standardNode, nodeSequence, observedAt, rawPayloadHash, createdAt]
|
||||
properties:
|
||||
id: {type: integer, format: int64}
|
||||
providerCode: {type: string, maxLength: 32}
|
||||
providerEventId: {type: string, maxLength: 128}
|
||||
providerNodeCode: {type: string, maxLength: 64}
|
||||
standardNode: {$ref: '#/components/schemas/StandardNode'}
|
||||
nodeSequence: {type: integer, enum: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]}
|
||||
observedAt: {type: string, format: date-time}
|
||||
estimatedAt: {type: string, format: date-time, nullable: true}
|
||||
actualAt: {type: string, format: date-time, nullable: true}
|
||||
locationCode: {type: string, maxLength: 32, nullable: true}
|
||||
locationName: {type: string, maxLength: 128, nullable: true}
|
||||
sourceReference: {type: string, maxLength: 500, nullable: true}
|
||||
rawPayloadHash: {type: string, pattern: '^[0-9a-f]{64}$'}
|
||||
createdAt: {type: string, format: date-time}
|
||||
ExceptionFact:
|
||||
type: object
|
||||
required: [id, providerCode, providerEventId, providerStatus, exceptionCode, active, observedAt, rawPayloadHash, createdAt]
|
||||
properties:
|
||||
id: {type: integer, format: int64}
|
||||
providerCode: {type: string, maxLength: 32}
|
||||
providerEventId: {type: string, maxLength: 128}
|
||||
providerStatus: {type: string, maxLength: 128}
|
||||
exceptionCode: {$ref: '#/components/schemas/ExceptionCode'}
|
||||
active: {type: boolean, description: true means hold occurred; false means released}
|
||||
observedAt: {type: string, format: date-time}
|
||||
locationCode: {type: string, maxLength: 32, nullable: true}
|
||||
locationName: {type: string, maxLength: 128, nullable: true}
|
||||
sourceReference: {type: string, maxLength: 500, nullable: true}
|
||||
rawPayloadHash: {type: string, pattern: '^[0-9a-f]{64}$'}
|
||||
createdAt: {type: string, format: date-time}
|
||||
History:
|
||||
type: object
|
||||
required: [id, action, createdAt]
|
||||
properties:
|
||||
id: {type: integer, format: int64}
|
||||
action: {type: string, enum: [CREATE, AUTO_CREATE, MANUAL_RESULT, MANUAL_NODE, NODE_OBSERVED, EXCEPTION_OBSERVED, PROVIDER_QUERY]}
|
||||
fromVersion: {type: integer, nullable: true}
|
||||
toVersion: {type: integer, nullable: true}
|
||||
reason: {type: string, nullable: true}
|
||||
operatorId: {type: integer, format: int64, nullable: true}
|
||||
operatorName: {type: string, nullable: true}
|
||||
createdAt: {type: string, format: date-time}
|
||||
Detail:
|
||||
type: object
|
||||
required: [query, nodes, exceptions, histories]
|
||||
description: Scheduler lease, attempt and internal execution fields are intentionally absent.
|
||||
properties:
|
||||
query: {$ref: '#/components/schemas/QueryView'}
|
||||
nodes: {type: array, items: {$ref: '#/components/schemas/NodeFact'}}
|
||||
exceptions: {type: array, items: {$ref: '#/components/schemas/ExceptionFact'}}
|
||||
histories: {type: array, items: {$ref: '#/components/schemas/History'}}
|
||||
DetailEnvelope:
|
||||
type: object
|
||||
required: [code, data]
|
||||
properties:
|
||||
code: {type: string, example: '200'}
|
||||
message: {type: string, nullable: true}
|
||||
data: {$ref: '#/components/schemas/Detail'}
|
||||
|
||||
Reference in New Issue
Block a user