Files
baiyue-firstleg/lastleg-service/src/main/resources/openapi/fleet-trips-v1.yaml
T

750 lines
46 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: 平台运输车次与资源分配
version: 1.0.0
description: >-
车次是一次实际运输的稳定业务编号,客户排车、库存和派送单继续保留各自客户归属。
本文件定义计划、资源分配及客户排车单关联命令;分配或关联不会扣库存或标记发车。
创建可暂不指定车与司机,幂等键按创建人隔离;相同键相同内容返回同一车次,不同内容拒绝。
正式分配要求在役海外车辆及已确认的托位/载重/容积,以及海外司机;司机按预计任务结束时间重新核验且验证证照文件。
发车预览与实际发车重新核对司机当前海外区域和身份;分配后档案变更不能沿用原分配时的资格结果。
一个车辆或司机同时只能占用一个未释放车次;当前不提供多个未来时段的并行预约。
改派先取得新资源,成功后释放旧资源;整次写入与历史处于同一事务。
司机预计结束包含承担的返程/转场;修改预计结束须重新核验司机,所有写命令使用recordVersion。
普通计划接口不提供修改发车或签收状态的入口;PDA统一发车,结案检查所有客户派送终态及实发数量。
货物结案不释放车辆或司机;结束各资源任务独立提交实际结束时间、地点和原因,车辆另确认可用/维修/停用/已归还状态。
结案和结束任务命令携带版本及幂等键;结束司机任务不要求其证照仍有效,也不自动恢复其派车资格。
关联要求已分配车和司机,客户排车单同起运仓且未开始拣货;可跨客户关联但不改变客户数据归属。
同一排车单唯一关联一个车次;关联、改派、解除及尚未执行的派送单车/司机快照同步使用同一事务。
关联后子排车不能独立编辑、取消或单独发车;取消车次前须解除关联,已开工不允许直接解除或变更路线。
发车前允许在车次统一换车、换司机或调整时间,保留全部拣货事实与客户归属;已确认装载须能容纳于替换车辆。
改派或调整计划使原装载确认失效,发车前须重新确认;不支持用计划接口处理在途换车或撤销已执行货物。
关联只建立执行单据关系,不代表实际装载量、容量核验或审核已完成。
每张客户排车单调度审核通过后允许新拣货;整车确认实际装载并通过理货审核后允许发车。
审核仅通过或打回,通过意见选填、打回原因必填;无需额外提交或不同审核人。
换车换司机、修改路线或时间使调度与理货审核待审;仅修改备注保留审核及装载。
关联变更、重新确认装载或重新审核客户排车单使理货审核待审;保留全部拣货事实及历史审核快照。
security:
- bearerAuth: []
paths:
/api/platform/v1/last-leg/fleet/trips/calendar:
get:
summary: 读取美国车次计划日历来源
description: >-
仅PLATFORM且平台公共主体(tenantId=0),权限 platform:fleet:trip:list。from/to 是明确UTC时间点,按计划发车时间读取半开区间,最多44天;
该保护性窗口供界面最多42个当地日历日加时区边界使用,不扩大界面范围。
最多2000条候选,超限明确拒绝并要求缩小日期范围,不分页扫描、不静默截断。
一车一条,保留取消及完成状态;记录只表示用车计划,不表示收货预约已确认。
已知非美国仓排除;未知仓库/国家/地理IANA时区进入unresolvedRecords,不落入美国当地日槽。
一次车次查询加一次仓库批量资料请求,包含停用仓历史资料,资料服务失败返回错误而非空日历。
parameters:
- {name: from, in: query, required: true, schema: {type: string, format: date-time}}
- {name: to, in: query, required: true, schema: {type: string, format: date-time}}
responses:
'200':
description: 统一业务响应;UTC事实保持原值,司机预计结束不是收货预约时间
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
required: [records, unresolvedRecords]
properties:
records: {type: array, items: {$ref: '#/components/schemas/TripCalendarEntry'}}
unresolvedRecords: {type: array, items: {$ref: '#/components/schemas/TripCalendarEntry'}}
'400': {description: 时间范围无效或候选车次超过2000条}
'403': {description: 缺少车次查看权限}
'503': {description: 仓库元数据无法可靠读取}
/api/platform/v1/last-leg/fleet/trips:
get:
summary: 分页查询车次
description: '权限:platform:fleet:trip:list'
parameters:
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
- {name: keyword, in: query, schema: {type: string, maxLength: 128}, description: 车次号/车牌/司机}
- {name: status, in: query, schema: {type: string, enum: [PLANNED, IN_TRANSIT, COMPLETED, CANCELLED]}}
- {name: warehouseId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200':
description: 统一业务响应,data包含records/page/size/total/pages;不逐行请求司机详情
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/Trip'}}
page: {type: integer}
size: {type: integer}
total: {type: integer}
pages: {type: integer}
post:
summary: 幂等创建车次计划
description: '权限:platform:fleet:trip:create;起运仓使用公共有效海外仓目录;不推断GPS路线。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Create'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/customer-options:
get:
summary: 查询有效委托客户候选
description: '权限:platform:fleet:trip:list;读取IAM当前客户主档;不使用采购历史或允许输入不存在的客户。'
parameters: [{name: keyword, in: query, schema: {type: string}}]
responses: {'200': {description: 统一响应data为客户id/code/name/contactName/contactPhone数组}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/quote-candidates:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 按本车真实起运仓及当地计划日期查询客户销售报价
description: '同时要求platform:fleet:trip:list与platform:fleet:quote:list。城市来自有效公共海外仓的唯一明确地址城市,日期为计划起运UTC时间转换到仓库明确时区;不接收浏览器城市或日期。目的地须为本车既有FBA卸货站;私人地址、缺失或歧义城市/时区明确拒绝查询,仍可手工询价。'
parameters:
- {name: customerId, in: query, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: destinationKey, in: query, required: true, schema: {type: string, maxLength: 160}}
- {name: currency, in: query, required: true, schema: {type: string, enum: [CNY, USD]}}
- {name: priceBasis, in: query, required: true, schema: {type: string, enum: [PALLET, ORDER]}}
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
responses:
'200':
description: 统一业务响应,data为报价来源候选分页;无价不列入,零价保留
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
records: {type: array, items: {$ref: 'fleet-quote-candidates-v1.yaml#/components/schemas/SourceSnapshot'}}
page: {type: integer}
size: {type: integer}
total: {type: integer}
pages: {type: integer}
'403': {description: 缺少任一读取权限}
'409': {description: 无法确定本车报价查询上下文}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 查询本车外接询价与承运预订
description: '权限:platform:fleet:trip:list;返回tripRecordVersion及records;约定金额不是应收或实收。'
responses: {'200': {description: 统一响应data为版本及Booking数组}}
post:
summary: 登记外接询价
description: '权限:platform:fleet:trip:booking-create;DRAFT不占位。客户由IAM校验,报价和预计载荷可待确认再补;起点固定本起运仓,卸货站为既有路线站点。相同创建键与内容重放原预订。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingCreate'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
put:
summary: 编辑尚未确认的外接询价
description: '权限:platform:fleet:trip:booking-edit;仅DRAFT;客户与预订业务编号不变,更新前核对车次及预订版本。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingUpdate'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}/confirm:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
post:
summary: 确认外接承运并占用计划容量
description: '权限:platform:fleet:trip:booking-confirm;父车次锁内核对来源仍有效的自有货容量计划及全部已确认预订;报价/币种/预计托位重量体积完整。幂等重放返回当前预订事实,不重复占位;确认不代表已收货、已发运或已入财务。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingCommand'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}, '409': {description: 版本、资格或容量不满足}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}/incoming:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
get:
summary: 查询外接来货及实际测量依据
description: '权限:platform:fleet:trip:list;固定预订客户范围,返回tripRecordVersion、recordVersion与incoming;尚未登记时incoming为null,不逐行预取。'
responses: {'200': {description: 统一响应data为版本及IncomingEvidence}}
post:
summary: 为已确认承运生成真实来货单
description: '权限:platform:fleet:trip:booking-edit;复用仓储转运创建/审核,在同一事务建立客户自送来货并关联预订;不写库存,不冒充实收;已有来货拒绝重复创建,同键同内容重放。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingIncoming'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}/receipt-confirmation:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
post:
summary: 运营确认委托方实收货量与运费
description: '权限:platform:fleet:trip:booking-confirm;实际来货已完成测量,receiptHash和实托集合一致,重新核算容量和约定金额,引用真实收货证据并确认原来货流程;不重复入库。差异必须显式确认,超容量回滚。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingAcceptReceipt'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}/dispatch:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
post:
summary: 将外接实收货物关联客户排车
description: '权限:同时要求platform:fleet:trip:booking-edit和platform:fleet:trip:edit;排车必须同客户同仓,完整包含预订来货的实收托盘与数量且目的地一致;原子绑定共享车次,防止绕过预订挂到其他车次。解除未开工关联后回到RECEIVED并重新预留容量,已拣货不允许直接解除。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingBindDispatch'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/bookings/{bookingNo}/cancel:
parameters: [{$ref: '#/components/parameters/TripNo'}, {$ref: '#/components/parameters/BookingNo'}]
post:
summary: 取消未执行的外接预订并释放容量
description: '权限:platform:fleet:trip:booking-cancel;仅计划中车次的DRAFT/CONFIRMED/RECEIVED;只释放承运预留,不删除来货或库存;同键同内容重放不重复释放,历史保留报价及承运确认。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BookingCommand'}}}}
responses: {'200': {$ref: '#/components/responses/BookingResult'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 查询车次详情和当前司机资格
description: '权限:platform:fleet:trip:list;司机资格仅是详情预览,实际命令必须重新核验。'
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/dispatches/{dispatchNo}/review:
parameters:
- {$ref: '#/components/parameters/TripNo'}
- {name: dispatchNo, in: path, required: true, schema: {type: string}}
post:
summary: 通过或打回单张客户排车调度审核
description: '权限:platform:fleet:trip:dispatch-review;仅PLANNED;审核所属车次内的排车单,成功后理货审核待审;审批不扣库存。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Review'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}, '409': {description: 版本、关联或资格冲突}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/loading-review:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 通过或打回整车理货审核
description: '权限:platform:fleet:trip:loading-review;仅PLANNED;通过要求全部调度审核、拣货和实际装载确认已完成,当前司机资格有效。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Review'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}, '409': {description: 版本、调度审核、装载或资格冲突}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/plan:
parameters: [{$ref: '#/components/parameters/TripNo'}]
put:
summary: 修改计划时间和路线
description: '权限:platform:fleet:trip:edit;仅PLANNED;司机预计结束变更重新核验;原因必填。已开始拣货时路线须完全一致,仅可调整时间和备注;调整时间使审核及装载确认失效,仅修改备注保留。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Plan'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/assignment:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 分配或更换车辆与司机
description: '权限:platform:fleet:trip:assign;仅PLANNED且全部关联单未发车、未出库;允许已拣货时统一改派并同步派送快照,保留拣货和到达时间。替换车辆须满足已确认装载容量,成功后清除原装载确认并重新核验;行锁和唯一占用键防重复派车,资格校验不得通过人工审核绕过。'
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [recordVersion, vehicleId, driverId, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
vehicleId: {type: string, pattern: '^[1-9][0-9]*$'}
driverId: {type: string, pattern: '^[1-9][0-9]*$'}
reason: {type: string, minLength: 1, maxLength: 1000}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/cancel:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 取消计划并释放车和司机
description: '权限:platform:fleet:trip:cancel;仅PLANNED;保留车次快照和历史。已执行货物后续须按实际执行状态校验,不允许取消抹除作业事实。'
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [recordVersion, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
reason: {type: string, minLength: 1, maxLength: 1000}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/dispatches/bind:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 将客户排车单关联到车次
description: '权限:platform:fleet:trip:edit;按业务单号解析客户归属,同仓且未开工;关联、车/司机快照同步及按真实货物目的地标识补齐卸货站原子提交;目的地缺失拒绝关联,已有有效站点顺序与索引保留,初始默认占位站替换为真实目的地。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BindingCommand'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/dispatches/unbind:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 解除尚未执行的客户排车单关联
description: '权限:platform:fleet:trip:edit;清除排车及派送单当前车辆司机快照,历史保留;已拣货禁止直接解除。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BindingCommand'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/history:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 分页读取车次操作历史
description: '权限:platform:fleet:trip:list;版本倒序;不将历史快照当作当前资格。'
parameters:
- {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: 统一响应;data为PageResult,records项包含recordVersion/action/reason/operatorId/occurredAt/snapshot,snapshot包含trip、带review的dispatches、capacityPlan、confirmedLoad、completion及loadingReview、externalBookings不可变快照
/api/platform/v1/last-leg/fleet/trips/{tripNo}/capacity-plan:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 读取拣货前计划载荷和逐段余位
description: '权限:platform:fleet:trip:list;按当前关联货物返回manifestHash;planValid为false表示尚未核对或来源已经变化,不能据旧计划承诺外接运力。'
responses:
'200': {description: 统一响应data为Planning, content: {application/json: {schema: {$ref: '#/components/schemas/PlanningEnvelope'}}}}
post:
summary: 核对本车货物计划载荷
description: '权限:platform:fleet:trip:edit;仅PLANNED;允许尚未拣货或审核,通过实托去重及逐段容量检查。保存计划不推进审核、库存或发车,不代替实际装载确认;调整计划/资源/关联使容量计划失效,纯备注保留。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ConfirmLoad'}}}}
responses:
'200': {description: 已保存容量计划, content: {application/json: {schema: {$ref: '#/components/schemas/PlanningEnvelope'}}}}
'409': {description: 版本、来源变化或容量超限}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/loading:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 读取整车实物装载核对依据
description: '权限:platform:fleet:trip:list;返回各客户货物组成、manifestHash和当前装载确认,实际重量不得使用计费材积重。'
responses:
'200': {description: 统一响应data为Loading, content: {application/json: {schema: {$ref: '#/components/schemas/LoadingEnvelope'}}}}
post:
summary: 确认整车实际装载及逐段容量
description: '权限:platform:fleet:trip:edit;全部客户拣货核平且转派送后确认;同一实物托盘只计量一次。货物hash或车次版本变化拒绝,托盘卸货站须匹配原货物目的地。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ConfirmLoad'}}}}
responses:
'200': {description: 已确认装载快照,统一响应data为Loading, content: {application/json: {schema: {$ref: '#/components/schemas/LoadingEnvelope'}}}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/completion:
parameters: [{$ref: '#/components/parameters/TripNo'}]
get:
summary: 核对各客户货物是否全部结束履约
description: '权限:platform:fleet:trip:list;返回tripNo、recordVersion、canComplete、blockReason、outcomes。签收以signedAt为准,退回须有RETURN_COMPLETED操作事实,不以updatedAt代替实际终态时间。'
responses:
'200': {description: 统一响应data包含结案检查结果与逐张派送Outcome, content: {application/json: {schema: {$ref: '#/components/schemas/CompletionEnvelope'}}}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/complete:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 核对全部货物并结案车次
description: '权限:platform:fleet:trip:complete;仅IN_TRANSIT,实发数量由全部已签收或已真实退回派送单覆盖;拒收、待退回、取消不算终态完成。不改写客户单、不新增收费、不释放资源;同键同内容重放,旧版本或不同内容拒绝。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Complete'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
/api/platform/v1/last-leg/fleet/trips/{tripNo}/resources/release:
parameters: [{$ref: '#/components/parameters/TripNo'}]
post:
summary: 单独结束车辆或司机本次任务并释放占用
description: '权限:platform:fleet:trip:release;货物结案后才允许;实际结束时间不早于货物完成且不晚于当前时间,地点及原因必填。车辆状态与释放同事务更新;司机可继续返程而保持占用。原请求重放不释放后来另一个车次的占用。'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Release'}}}}
responses: {'200': {$ref: '#/components/responses/Detail'}}
components:
securitySchemes:
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
parameters:
BookingNo:
name: bookingNo
in: path
required: true
schema: {type: string}
TripNo: {name: tripNo, in: path, required: true, schema: {type: string}}
responses:
BookingResult:
description: 统一响应data含tripRecordVersion、booking及replayed;客户端使用当前状态,重放不覆盖后续已发生的取消
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
tripRecordVersion: {type: integer, format: int64}
booking: {$ref: '#/components/schemas/Booking'}
replayed: {type: boolean}
Detail:
description: 统一响应,code为200代表成功,data为车次详情;业务冲突使用业务错误,不降级为成功
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
trip: {$ref: '#/components/schemas/Trip'}
dispatches: {type: array, items: {$ref: '#/components/schemas/DispatchBinding'}}
loadingReview: {$ref: '#/components/schemas/ReviewState'}
driverQualification:
type: object
nullable: true
description: 未分配司机为null;字段与fleet-drivers-v1的Qualification一致
properties:
canDispatch: {type: boolean}
expiringSoon: {type: boolean}
reason: {type: string}
licenseExpiresOn: {type: string, format: date, nullable: true}
schemas:
TripCalendarEntry:
type: object
required: [sourceType, tripNo, status, plannedDepartureAt, expectedDriverEndAt, stops, incompleteReasons]
properties:
sourceType: {type: string, enum: [TRIP_PLAN]}
tripNo: {type: string}
status: {type: string, enum: [PLANNED, IN_TRANSIT, COMPLETED, CANCELLED]}
originWarehouseId: {type: string, nullable: true}
originWarehouseCode: {type: string, nullable: true}
originWarehouseName: {type: string, nullable: true}
originCountryCode: {type: string, nullable: true}
originTimezone: {type: string, nullable: true, description: 地理IANA时区;未知、固定偏移、Etc及SystemV标记为空,不猜UTC}
originWarehouseStatus: {type: string, nullable: true}
plannedDepartureAt: {type: string, format: date-time}
expectedDriverEndAt: {type: string, format: date-time, description: 司机任务预计结束,不是收货预约时间}
departedAt: {type: string, format: date-time, nullable: true}
completedAt: {type: string, format: date-time, nullable: true}
stops: {type: array, items: {$ref: '#/components/schemas/Stop'}}
incompleteReasons:
type: array
items: {type: string, enum: [ORIGIN_WAREHOUSE_UNKNOWN, ORIGIN_COUNTRY_UNKNOWN, ORIGIN_TIMEZONE_UNKNOWN, ROUTE_INCOMPLETE]}
BookingCargo:
type: object
required: [destinationKey]
properties:
destinationKey: {type: string, maxLength: 160}
cargoName: {type: string, nullable: true, maxLength: 255}
packageCount: {type: integer, nullable: true, minimum: 1, description: 询价未知可为空,确认承运前必须补齐正数箱数}
palletSpaces: {type: integer, nullable: true, minimum: 1}
weightKg: {type: number, nullable: true, minimum: 0.001}
volumeCbm: {type: number, nullable: true, minimum: 0.001}
priceBasis: {type: string, nullable: true, enum: [PALLET, ORDER], description: 为空时默认PALLET}
unitPrice: {type: number, nullable: true, minimum: 0, multipleOf: 0.01}
currency: {type: string, nullable: true, maxLength: 3}
contactName: {type: string, nullable: true, maxLength: 128}
contactPhone: {type: string, nullable: true, maxLength: 128}
remark: {type: string, nullable: true, maxLength: 1000}
IncomingEvidence:
type: object
properties:
incomingNo: {type: string}
inboundCode: {type: string}
warehouseId: {type: string}
destinationKey: {type: string}
status: {type: string}
receiptHash: {type: string, description: 实托、数量、实测值及来源匹配摘要,不包含可变作业状态}
receivedPackages: {type: integer}
pallets:
type: array
items:
type: object
properties:
warehousePalletId: {type: string}
palletNo: {type: string}
packages: {type: integer}
weightKg: {type: number, nullable: true}
volumeCbm: {type: number, nullable: true}
BookingIncoming:
allOf:
- {$ref: '#/components/schemas/BookingCommand'}
- properties:
estimatedArrivalAt: {type: string, format: date-time, nullable: true, description: 缺省为计划发车前2小时的预计值}
deliveryInstructions: {type: string, nullable: true, maxLength: 1000}
privateAddress: {type: string, nullable: true, maxLength: 1000}
postalCode: {type: string, nullable: true, maxLength: 32}
recipientName: {type: string, nullable: true, maxLength: 128}
recipientPhone: {type: string, nullable: true, maxLength: 64}
BookingPalletSpaces:
type: object
required: [warehousePalletId, palletSpaces]
properties:
warehousePalletId: {type: string}
palletSpaces: {type: integer, minimum: 1}
BookingAcceptReceipt:
allOf:
- {$ref: '#/components/schemas/BookingCommand'}
- required: [receiptHash, pallets, unitPrice]
properties:
receiptHash: {type: string}
pallets: {type: array, minItems: 1, items: {$ref: '#/components/schemas/BookingPalletSpaces'}}
unitPrice: {type: number, minimum: 0, multipleOf: 0.01}
BookingBindDispatch:
allOf:
- {$ref: '#/components/schemas/BookingCommand'}
- required: [dispatchNo]
properties:
dispatchNo: {type: string, maxLength: 64}
BookingCreate:
type: object
required: [tripRecordVersion, customerId, cargo, idempotencyKey]
properties:
tripRecordVersion: {type: integer, format: int64, minimum: 0}
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
quoteRef: {$ref: '#/components/schemas/BookingQuoteRef'}
cargo: {$ref: '#/components/schemas/BookingCargo'}
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
BookingUpdate:
type: object
required: [tripRecordVersion, recordVersion, cargo]
properties:
tripRecordVersion: {type: integer, format: int64, minimum: 0}
recordVersion: {type: integer, format: int64, minimum: 0}
quoteRef: {$ref: '#/components/schemas/BookingQuoteRef'}
cargo: {$ref: '#/components/schemas/BookingCargo'}
BookingQuoteRef:
type: object
nullable: true
description: '选填;null或省略为手工询价。引用或清除已有来源另要求platform:fleet:quote:list。服务端在承运写事务内锁定并核对精确版本、SALE/ACTIVE、客户、路线、币种、仓库当地计划日期及价项;只保存可信来源,不接收浏览器快照。PALLET选LOOSE_DELIVERY,ORDER选FULL_DELIVERY。'
allOf: [{$ref: 'fleet-quote-candidates-v1.yaml#/components/schemas/QuoteRef'}]
BookingCommand:
type: object
required: [tripRecordVersion, recordVersion, idempotencyKey]
properties:
tripRecordVersion: {type: integer, format: int64, minimum: 0}
recordVersion: {type: integer, format: int64, minimum: 0}
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
reason: {type: string, nullable: true, maxLength: 1000}
Booking:
type: object
properties:
offerNo: {type: string, nullable: true, description: 来源拼车发布号,池来源的成交和取消必须经专用接口}
expectedPalletCount: {type: integer, nullable: true, minimum: 1, description: 预计实托数,不等同托位}
bookingNo: {type: string}
tripNo: {type: string}
customerId: {type: string}
customerCode: {type: string}
customerName: {type: string}
status: {type: string, enum: [DRAFT, CONFIRMED, RECEIVED, BOUND, CANCELLED]}
cargo: {$ref: '#/components/schemas/BookingCargo'}
quoteSource:
type: object
nullable: true
description: '可信报价来源,独立于cargo.unitPrice及agreedAmount。确认承运重新核对报价及当前计划日期;确认后的报价变更或实收议价不覆盖已保存来源。'
allOf: [{$ref: 'fleet-quote-candidates-v1.yaml#/components/schemas/SourceSnapshot'}]
destinationLabel: {type: string}
agreedAmount: {type: number, nullable: true, description: 约定运费,非财务应收或实收}
incomingNo: {type: string, nullable: true}
dispatchNo: {type: string, nullable: true}
receipt:
type: object
nullable: true
properties:
source: {$ref: '#/components/schemas/IncomingEvidence'}
pallets: {type: array, items: {$ref: '#/components/schemas/BookingPalletSpaces'}}
operatorId: {type: string}
confirmedAt: {type: string, format: date-time}
recordVersion: {type: integer, format: int64}
updatedAt: {type: string, format: date-time}
Outcome:
description: packages保留原实发量;signedPackages为不可变实签量,returnedPackages只计原运输实际退回,remainingPackages必须为零且三者守恒才可结案。签收后的另行退货不重开原运输。
type: object
properties:
dispatchNo: {type: string}
deliveryNo: {type: string}
customerId: {type: string}
destination: {type: string, nullable: true}
status: {type: string}
packages: {type: integer}
terminalAt: {type: string, format: date-time, nullable: true}
signedPackages: {type: integer, minimum: 0}
returnedPackages: {type: integer, minimum: 0}
remainingPackages: {type: integer, minimum: 0}
CompletionEnvelope:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
tripNo: {type: string}
recordVersion: {type: integer, format: int64}
canComplete: {type: boolean}
blockReason: {type: string, nullable: true}
outcomes: {type: array, items: {$ref: '#/components/schemas/Outcome'}}
Complete:
type: object
required: [recordVersion, idempotencyKey, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
reason: {type: string, minLength: 1, maxLength: 1000}
Release:
type: object
required: [recordVersion, resourceKind, actualEndAt, endLocation, idempotencyKey, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
resourceKind: {type: string, enum: [VEHICLE, DRIVER]}
actualEndAt: {type: string, format: date-time}
endLocation: {type: string, minLength: 1, maxLength: 500}
vehicleStatus: {type: string, nullable: true, enum: [IN_SERVICE, MAINTENANCE, INACTIVE, RETURNED], description: 结束车辆任务必填,结束司机任务必须为空}
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
reason: {type: string, minLength: 1, maxLength: 1000}
ReleaseInfo:
type: object
nullable: true
properties:
actualEndAt: {type: string, format: date-time}
endLocation: {type: string}
vehicleStatus: {type: string, nullable: true, description: 结束本次车辆任务时的状态快照,不代表车辆此后的实时可派状态}
LoadingEnvelope:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
tripNo: {type: string}
recordVersion: {type: integer, format: int64}
manifestHash: {type: string}
cargo: {type: array, items: {$ref: '#/components/schemas/Cargo'}}
blockReason: {type: string, nullable: true}
confirmedLoad:
type: object
nullable: true
properties:
manifestHash: {type: string}
cargo: {type: array, items: {$ref: '#/components/schemas/Cargo'}}
pallets: {type: array, items: {$ref: '#/components/schemas/Measurement'}}
segments: {type: array, items: {type: object}, description: 逐段fromIndex/toIndex及occupied/remaining托位、weightKg、volumeCbm}
operatorId: {type: string}
confirmedAt: {type: string, format: date-time}
Cargo:
type: object
properties:
dispatchNo: {type: string}
customerId: {type: string}
dispatchItemId: {type: string}
warehousePalletId: {type: string, nullable: true}
palletNo: {type: string, nullable: true}
packages: {type: integer}
destinationKey: {type: string, nullable: true, description: 原货物目的地稳定匹配键,选择路线站点时透传}
destinationLabel: {type: string, nullable: true}
Measurement:
type: object
required: [warehousePalletId, palletSpaces, weightKg, volumeCbm, deliveryIndex]
properties:
warehousePalletId: {type: string}
palletSpaces: {type: integer, minimum: 1}
weightKg: {type: number, minimum: 0.001, multipleOf: 0.001, maximum: 999999999.999}
volumeCbm: {type: number, minimum: 0.001, multipleOf: 0.001, maximum: 999999999.999}
deliveryIndex: {type: integer, minimum: 1, description: 卸货站索引,起运仓固定为0}
PlanningEnvelope:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
tripNo: {type: string}
recordVersion: {type: integer, format: int64}
cargo: {type: array, items: {$ref: '#/components/schemas/Cargo'}}
manifestHash: {type: string}
planValid: {type: boolean, description: 计划已经核对且来源hash仍一致}
availableSegments: {type: array, items: {$ref: '#/components/schemas/Segment'}, description: 当前自有货计划加已确认外接预订后的逐段占用与余位;计划失效返回空数组}
blockReason: {type: string, nullable: true}
capacityPlan:
type: object
nullable: true
description: 计划值,不能作为实际装载确认
properties:
manifestHash: {type: string}
cargo: {type: array, items: {$ref: '#/components/schemas/Cargo'}}
pallets: {type: array, items: {$ref: '#/components/schemas/Measurement'}}
segments: {type: array, items: {$ref: '#/components/schemas/Segment'}}
operatorId: {type: string}
confirmedAt: {type: string, format: date-time}
Segment:
type: object
properties:
fromIndex: {type: integer}
toIndex: {type: integer}
occupied: {$ref: '#/components/schemas/CapacityLoad'}
remaining: {$ref: '#/components/schemas/CapacityLoad'}
CapacityLoad:
type: object
properties:
palletSpaces: {type: integer}
weightKg: {type: number}
volumeCbm: {type: number}
ConfirmLoad:
type: object
required: [recordVersion, manifestHash, pallets, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
manifestHash: {type: string, pattern: '^[0-9a-f]{64}$'}
pallets: {type: array, minItems: 1, maxItems: 1000, items: {$ref: '#/components/schemas/Measurement'}}
reason: {type: string, minLength: 1, maxLength: 1000}
BindingCommand:
type: object
required: [recordVersion, dispatchNo, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
dispatchNo: {type: string, minLength: 1, maxLength: 64}
reason: {type: string, minLength: 1, maxLength: 1000}
Review:
type: object
required: [recordVersion, decision]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
decision: {type: string, enum: [APPROVED, REJECTED]}
reason: {type: string, nullable: true, maxLength: 1000, description: 通过选填;打回必填}
ReviewState:
type: object
required: [status]
properties:
status: {type: string, enum: [PENDING, APPROVED, REJECTED]}
reason: {type: string, nullable: true}
reviewerId: {type: string, nullable: true}
reviewedAt: {type: string, format: date-time, nullable: true}
recordVersion: {type: integer, format: int64, nullable: true, description: 本次审核所核对的车次版本}
DispatchBinding:
type: object
properties:
dispatchNo: {type: string}
customerId: {type: string, description: 排车单自身客户归属,由服务端解析}
packageCount: {type: integer, description: 关联时待发运箱数,不是实物托位数}
boundBy: {type: string}
boundAt: {type: string, format: date-time}
review: {$ref: '#/components/schemas/ReviewState'}
Envelope:
type: object
properties:
code: {type: string}
message: {type: string, nullable: true}
data: {type: object, nullable: true}
Stop:
type: object
required: [name]
properties:
name: {type: string, minLength: 1, maxLength: 128}
address: {type: string, nullable: true, maxLength: 500}
destinationKey: {type: string, nullable: true, maxLength: 160, description: 卸货站匹配Loading货物的destinationKey;未配置时可以保存计划但不能确认装载}
Create:
type: object
required: [warehouseId, plannedDepartureAt, expectedDriverEndAt, stops, idempotencyKey]
properties:
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
plannedDepartureAt: {type: string, format: date-time}
expectedDriverEndAt: {type: string, format: date-time}
stops: {type: array, minItems: 2, maxItems: 200, items: {$ref: '#/components/schemas/Stop'}}
remark: {type: string, nullable: true, maxLength: 1000}
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
Plan:
type: object
required: [recordVersion, plannedDepartureAt, expectedDriverEndAt, stops, reason]
properties:
recordVersion: {type: integer, format: int64, minimum: 0}
plannedDepartureAt: {type: string, format: date-time}
expectedDriverEndAt: {type: string, format: date-time}
stops: {type: array, minItems: 2, maxItems: 200, items: {$ref: '#/components/schemas/Stop'}}
remark: {type: string, nullable: true, maxLength: 1000}
reason: {type: string, minLength: 1, maxLength: 1000}
Trip:
type: object
properties:
tripNo: {type: string}
status: {type: string, enum: [PLANNED, IN_TRANSIT, COMPLETED, CANCELLED]}
warehouseId: {type: string}
warehouseCode: {type: string}
warehouseName: {type: string}
vehicleId: {type: string, nullable: true}
vehiclePlate: {type: string, nullable: true}
driverId: {type: string, nullable: true}
driverName: {type: string, nullable: true}
driverPhone: {type: string, nullable: true}
maxPalletSpaces: {type: integer, nullable: true}
maxLoadKg: {type: number, nullable: true}
maxVolumeCbm: {type: number, nullable: true}
plannedDepartureAt: {type: string, format: date-time}
expectedDriverEndAt: {type: string, format: date-time}
departedAt: {type: string, format: date-time, nullable: true}
completedAt: {type: string, format: date-time, nullable: true}
stops: {type: array, items: {$ref: '#/components/schemas/Stop'}}
remark: {type: string, nullable: true}
recordVersion: {type: integer, format: int64}
updatedAt: {type: string, format: date-time}
vehicleRelease: {$ref: '#/components/schemas/ReleaseInfo'}
driverRelease: {$ref: '#/components/schemas/ReleaseInfo'}