235 lines
16 KiB
YAML
235 lines
16 KiB
YAML
openapi: 3.0.3
|
|
info: {title: Firstleg Terminal Drayage API, version: 1.0.0}
|
|
paths:
|
|
/api/platform/v1/terminal-drayages/calendar:
|
|
get:
|
|
summary: 美国目的仓相关的提柜预约日历
|
|
description: 平台身份,同时要求预约列表和码头拖车列表权限。已提柜按船节点权威实际提柜日期、尚未提柜按原预约日期查询,改期不移动已执行事实;原预约与实际时间分别返回,不以预计到仓替代。美国范围按启用目的仓国家确认,不代表已确认港口所在国。原字段未提供港口时区,timeBasis明确待核实,禁止当作UTC或套用收货仓时区。最多42天,原预约和船节点实际日期候选分别读取1001条检测截断,经各自所属服务读取并按柜去重;返回最多1000条美国范围记录,未知目的仓计入unclassifiedCount,不能将缺失数据当零。
|
|
x-permissions: [platform:appointment:list, 'platform:firstleg:terminal-drayage:list']
|
|
parameters:
|
|
- {name: from, in: query, required: true, schema: {type: string, format: date}, description: 包含的原业务当地日期}
|
|
- {name: to, in: query, required: true, schema: {type: string, format: date}, description: 不包含的原业务当地日期}
|
|
responses:
|
|
'200':
|
|
description: 业务响应,code为200;仓库目录不可用则返回错误,不假装空列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code: {type: string}
|
|
data:
|
|
type: object
|
|
required: [records, truncated, unclassifiedCount, scopeBasis, timeBasis]
|
|
properties:
|
|
truncated: {type: boolean}
|
|
unclassifiedCount: {type: integer, minimum: 0}
|
|
scopeBasis: {type: string, enum: [US_DESTINATION_WAREHOUSE]}
|
|
timeBasis: {type: string, enum: [SOURCE_LOCAL_UNSPECIFIED]}
|
|
records:
|
|
type: array
|
|
maxItems: 1000
|
|
items:
|
|
type: object
|
|
properties:
|
|
containerBookingId: {type: string, description: 仅用于来源详情定位}
|
|
cabinetNo: {type: string}
|
|
containerNo: {type: string, nullable: true}
|
|
destinationPortName: {type: string, nullable: true}
|
|
destinationWarehouseCode: {type: string, nullable: true}
|
|
fleetSupplierName: {type: string, nullable: true}
|
|
pickupAppointmentAt: {type: string, nullable: true, description: 原业务当地预约时间,无时区偏移;仅有实际提柜事实时可为空}
|
|
actualPickupAt: {type: string, nullable: true}
|
|
'400': {description: 日期范围非法}
|
|
'403': {description: 非平台身份或权限不足}
|
|
'503': {description: 无法核对仓库范围}
|
|
/api/platform/v1/terminal-drayages:
|
|
get:
|
|
summary: 批量查询货柜码头拖车及服务端报空预警
|
|
x-permission: platform:firstleg:terminal-drayage:list
|
|
parameters:
|
|
- name: containerBookingIds
|
|
in: query
|
|
required: true
|
|
schema: {type: array, minItems: 1, maxItems: 200, items: {type: string, pattern: '^[1-9][0-9]*$'}}
|
|
responses: {'200': {$ref: '#/components/responses/ViewsResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}:
|
|
get:
|
|
summary: 查询单柜码头拖车详情
|
|
description: 已确认国内离仓的货柜即使船节点跟踪任务尚未建立也返回WAITING_FOR_ARRIVAL空详情;实际操作仍按到港、清关和卸柜节点校验
|
|
x-permission: platform:firstleg:terminal-drayage:list
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
|
|
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/history:
|
|
get:
|
|
summary: 查询单柜码头拖车操作历史
|
|
x-permission: platform:firstleg:terminal-drayage:list
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
|
|
responses: {'200': {$ref: '#/components/responses/HistoryResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/fleet:
|
|
post:
|
|
summary: 到港后选择或更换码头车队
|
|
x-permission: platform:firstleg:terminal-drayage:fleet:edit
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/FleetSelectionRequest'}}}}
|
|
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/pickup-appointment:
|
|
post:
|
|
summary: 预约目的港提柜时间
|
|
x-permission: platform:firstleg:terminal-drayage:pickup-appointment:edit
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/PickupAppointmentRequest'}}}}
|
|
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/empty-return:
|
|
post:
|
|
summary: 海外仓卸柜或全部直送目的仓实际卸货完成后确认实际还柜并推进EMPTY_RETURNED节点
|
|
description: 海外仓卸柜或全部直送目的仓实际卸货完成后开放还柜。无需已有车队或预约;海外仓卸柜可无实际提柜记录。无拖车记录时提交 expectedVersion=0,不补造提柜时间。保留原海外仓卸柜及已有船节点实际提柜的当地时间先后校验;直送目的仓时区不能套用于缺少时区的还柜时间,不比较不同地点的当地钟面值。
|
|
x-permission: platform:firstleg:terminal-drayage:empty-return:confirm
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ActualTimeRequest'}}}}
|
|
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/pickup-email:
|
|
post:
|
|
summary: 将当前车队提柜邮件加入发送队列
|
|
description: 初次选择车队不发信;此命令携带版本和幂等键,发送成功是任务已入队,不表示已送达。人工可使用最新版本重复发送提柜请求。更换车队时,原车队存在提柜请求邮件记录才原子入队取消邮件,并始终为新车队入队提柜请求;原车队从未下发时不发送取消邮件。同一车队重复选择不发信。
|
|
x-permission: platform:firstleg:terminal-drayage:fleet:edit
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody: {required: true, content: {application/json: {schema: {type: object, required: [expectedVersion], properties: {expectedVersion: {type: integer, minimum: 0}}}}}}
|
|
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/emails:
|
|
get:
|
|
summary: 查询最近100封车队邮件及发信开关
|
|
description: 已确认国内离仓的货柜允许读取空邮件列表,不以船节点跟踪任务是否已经建立作为货柜存在性条件
|
|
x-permission: platform:firstleg:terminal-drayage:list
|
|
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
|
|
responses:
|
|
'200':
|
|
description: 邮件记录;SENT表示SMTP已接受,不表示收件人已阅读
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code: {type: string}
|
|
data:
|
|
type: object
|
|
properties:
|
|
deliveryEnabled: {type: boolean}
|
|
records: {type: array, items: {$ref: '#/components/schemas/EmailTask'}}
|
|
/api/platform/v1/terminal-drayages/{containerBookingId}/emails/{mailId}/retry:
|
|
post:
|
|
summary: 核对失败邮件未收到后手动重试
|
|
description: 仅FAILED状态可重试,服务端校验mailId归属本柜;失败可能已经送达,须人工核对。同柜邮件依次发送,失败阻断后续邮件。
|
|
x-permission: platform:firstleg:terminal-drayage:fleet:edit
|
|
parameters:
|
|
- {$ref: '#/components/parameters/ContainerBookingId'}
|
|
- {name: mailId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
|
responses: {'200': {description: 已重新入队}}
|
|
components:
|
|
parameters:
|
|
ContainerBookingId: {name: containerBookingId, 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: 255}}
|
|
schemas:
|
|
EmailTask:
|
|
type: object
|
|
properties:
|
|
id: {type: string}
|
|
containerBookingId: {type: string}
|
|
fleetSupplierId: {type: string}
|
|
fleetName: {type: string}
|
|
recipient: {type: string, format: email}
|
|
kind: {type: string, enum: [REQUEST_PICKUP, CANCEL_PICKUP]}
|
|
subject: {type: string}
|
|
body: {type: string}
|
|
status: {type: string, enum: [PENDING, SENDING, SENT, FAILED]}
|
|
attempts: {type: integer}
|
|
failureReason: {type: string, nullable: true}
|
|
createdAt: {type: string, format: date-time}
|
|
sentAt: {type: string, format: date-time, nullable: true}
|
|
FleetSelectionRequest:
|
|
type: object
|
|
required: [expectedVersion, fleetSupplierId]
|
|
properties:
|
|
expectedVersion: {type: integer, minimum: 0}
|
|
fleetSupplierId: {type: string, pattern: '^[1-9][0-9]*$', description: Warehouse ACTIVE/TRUCKING且truckingScope=OVERSEAS的海外车队供应商ID}
|
|
fleetSupplierName: {type: string, maxLength: 128, nullable: true, description: 可选一致性提示,持久化名称以服务端快照为准}
|
|
reason: {type: string, maxLength: 500, nullable: true}
|
|
PickupAppointmentRequest:
|
|
type: object
|
|
required: [expectedVersion, pickupAppointmentAt]
|
|
properties:
|
|
expectedVersion: {type: integer, minimum: 0}
|
|
pickupAppointmentAt: {type: string, format: date-time}
|
|
reason: {type: string, maxLength: 500, nullable: true}
|
|
ActualTimeRequest:
|
|
type: object
|
|
required: [expectedVersion, actualAt]
|
|
properties:
|
|
expectedVersion: {type: integer, minimum: 0}
|
|
actualAt: {type: string, format: date-time}
|
|
remark: {type: string, maxLength: 500, nullable: true}
|
|
Warning:
|
|
type: object
|
|
required: [status, overdueHours, overdueDays]
|
|
properties:
|
|
status: {type: string, enum: [NOT_APPLICABLE, PENDING, OVERDUE, RESOLVED]}
|
|
deadlineAt: {type: string, format: date-time, nullable: true, description: 原海外仓卸柜时间加72小时;直送按最晚真实卸货Instant加72小时后保留该目的地当地时间}
|
|
overdueHours: {type: integer, format: int64, minimum: 0}
|
|
overdueDays: {type: integer, format: int64, minimum: 0}
|
|
TerminalDrayageView:
|
|
type: object
|
|
required: [containerBookingId, status, version, emptyReturnWarning, allowedActions, actualFacts]
|
|
properties:
|
|
containerBookingId: {type: string, pattern: '^[1-9][0-9]*$'}
|
|
containerNo: {type: string, nullable: true}
|
|
oceanBookingId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
|
|
status: {type: string, enum: [WAITING_FOR_ARRIVAL, ARRIVED, PICKUP_SCHEDULED, PICKED_UP, UNLOADED, EMPTY_RETURNED]}
|
|
version: {type: integer, minimum: 0}
|
|
fleetSupplierId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
|
|
fleetSupplierName: {type: string, nullable: true}
|
|
pickupAppointmentAt: {type: string, format: date-time, nullable: true}
|
|
actualPickupAt: {type: string, format: date-time, nullable: true, description: 优先使用实际船节点提柜时间;缺失时在海外PDA确认整柜拆柜完成后使用卸柜完成时间}
|
|
estimatedEmptyReturnAt: {type: string, format: date-time, nullable: true, description: 服务端权威值;直送72小时按绝对时长计算,时区不明的原海外仓事实保留原规则}
|
|
actualEmptyReturnAt: {type: string, format: date-time, nullable: true}
|
|
unloadingCompletedAt: {type: string, format: date-time, nullable: true}
|
|
emptyReturnWarning: {$ref: '#/components/schemas/Warning'}
|
|
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}}
|
|
actualFacts: {$ref: '#/components/schemas/ContainerActualFacts'}
|
|
updatedAt: {type: string, format: date-time, nullable: true}
|
|
ContainerActualFacts:
|
|
type: object
|
|
required: [containerBookingId, queryId, queryVersion, queryStatus]
|
|
properties:
|
|
containerBookingId: {type: string, pattern: '^[1-9][0-9]*$'}
|
|
queryId: {type: string, pattern: '^[1-9][0-9]*$'}
|
|
queryVersion: {type: integer, minimum: 0}
|
|
queryStatus: {type: string}
|
|
latestActualNode: {type: string, nullable: true}
|
|
latestActualAt: {type: string, format: date-time, nullable: true}
|
|
departedWarehouseAt: {type: string, format: date-time, nullable: true}
|
|
departedOriginPortAt: {type: string, format: date-time, nullable: true}
|
|
arrivedDestinationPortAt: {type: string, format: date-time, nullable: true}
|
|
pickupReadyAt: {type: string, format: date-time, nullable: true}
|
|
pickedUpAt: {type: string, format: date-time, nullable: true}
|
|
emptyReturnedAt: {type: string, format: date-time, nullable: true}
|
|
History:
|
|
type: object
|
|
required: [action, fromStatus, toStatus, fromVersion, toVersion, operatorId, createdAt]
|
|
properties:
|
|
action: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}
|
|
fromStatus: {type: string}
|
|
toStatus: {type: string}
|
|
fromVersion: {type: integer, minimum: 0}
|
|
toVersion: {type: integer, minimum: 1}
|
|
reason: {type: string, nullable: true}
|
|
operatorId: {type: string, pattern: '^[1-9][0-9]*$'}
|
|
operatorName: {type: string, nullable: true}
|
|
createdAt: {type: string, format: date-time}
|
|
ApiView: {type: object, required: [code, data], properties: {code: {type: string}, message: {type: string}, data: {$ref: '#/components/schemas/TerminalDrayageView'}}}
|
|
ApiViews: {type: object, required: [code, data], properties: {code: {type: string}, message: {type: string}, data: {type: array, items: {$ref: '#/components/schemas/TerminalDrayageView'}}}}
|
|
ApiHistory: {type: object, required: [code, data], properties: {code: {type: string}, message: {type: string}, data: {type: array, items: {$ref: '#/components/schemas/History'}}}}
|
|
responses:
|
|
ViewResponse: {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ApiView'}}}}
|
|
ViewsResponse: {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ApiViews'}}}}
|
|
HistoryResponse: {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ApiHistory'}}}}
|