openapi: 3.0.3 info: title: 平台运输车次与资源分配 version: 1.0.0 description: >- 排车列表是一趟整车作业的唯一主入口,一张排车单对应唯一车次资源记录;同一起运仓允许多个客户和目的地。 整车主单与任务不属于单一客户,货物明细、扫码归属、出库和派送单分别保留真实客户边界。 本文件保留资源占用查询、历史详情、计划容量、外接预订、结案及车辆/司机任务结束等附加能力。 不提供独立派送车次创建、多排车单手工绑定、旧调度/理货审核或装车写入口;审核和装发使用排车主单接口。 已绑定排车主单的资源与路线调整由排车主单执行;零真实扫码时显式退回装车前,修改后重新两级审核。 车辆和司机资格、容量与实际占用由服务端复验;候选可用不表示已预留,临时外配证据依排车主单规则核验。 调度审核后经理货审核才可真实扫码;PDA拣货核平后,平台和PDA均可确认装车完成及实际发车。 发车前整车派送安排须完整,正常签收汇总推进排车派送完成;既有异常业务和附加资源能力保留。 货物结案不自动释放车辆或司机;各资源任务分别提交实际结束时间、地点和原因,车辆另确认结束状态。 版本、幂等、客户隔离及事务要求以各实际端点及排车公共契约为准;历史数量不授权当前分配。 security: - bearerAuth: [] paths: /api/platform/v1/last-leg/fleet/trips/{tripNo}/resource-occupancy: get: summary: 批量读取当前下拉候选的实际车辆或司机占用 description: 仅平台且须platform:fleet:trip:list。本车已占用仍可保留;别车占用不可选。只反映占用,不代表证照或容量合格,不产生资源预留,保存分配时再次复验。 parameters: - {in: path, name: tripNo, required: true, schema: {type: string}} - {in: query, name: kind, required: true, schema: {type: string, enum: [VEHICLE, DRIVER]}} - in: query name: resourceIds required: true style: form explode: false schema: {type: array, minItems: 1, maxItems: 100, items: {type: string, pattern: '^[1-9][0-9]*$'}} responses: '200': description: 标准业务响应;data为候选占用数组,HTTP200亦需检查code。业务无权限、参数错误及资源不存在沿统一错误码。 content: application/json: schema: type: object properties: code: {type: string} data: type: array items: type: object properties: resourceId: {type: string} occupiedTripNo: {type: string, nullable: true} available: {type: boolean} /api/platform/v1/last-leg/fleet/trips/calendar: get: summary: 读取美国真实整车排车日历来源 description: >- 仅PLATFORM且平台公共主体(tenantId=0),权限 platform:overseas-warehouse:dispatch:list,与排车列表及详情一致。from/to 是明确UTC时间点,已发车按实际发车时间、尚未发车按计划发车时间读取半开区间,最多44天; 该保护性窗口供界面最多42个当地日历日加时区边界使用,不扩大界面范围。 仅出库派送用途(DELIVERY);上门取货入仓用途(PICKUP)不属于此日历排车来源。 最多2000条候选,超限明确拒绝并要求缩小日期范围,不分页扫描、不静默截断。 仅关联ll_dispatch_order中ACTIVE真实主单,返回dispatchNo;独立旧车次和取消排车主单排除,一张排车主单一条。 保留原计划与实际时间,已执行事实不随计划改期移动,不表示收货预约已确认;日历跳排车详情,不使用内部车次号拼排车路径。 已知非美国仓排除;未知仓库/国家/地理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} /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;CONFIRMED或尚未绑定排车的RECEIVED可核对。实际来货已完成测量,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}/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}/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'}}}} /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'}} previousDispatches: type: array description: 原绑定历史中已不在当前绑定的批次及其客户、来源引用,按最新有效证据去重;历史数量不作为当前装载或可分配数量 items: {$ref: '#/components/schemas/PreviousDispatch'} appointmentHistoryUnavailableReason: type: string nullable: true description: 原绑定历史缺少引用证据或超过1000条读取上限时的明确原因;仅历史引用不可完整使用,当前车次和绑定仍可读 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, dispatchNo, status, plannedDepartureAt, expectedDriverEndAt, stops, incompleteReasons] properties: sourceType: {type: string, enum: [DISPATCH]} dispatchNo: {type: string, description: 真实整车主单排车号,用于排车详情路由} 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} weightKg: {type: number, nullable: true, minimum: 0.001, description: 当前组成缺少可信测量时必填,为该票外接货实测毛重,不填整托其他来源重量} volumeCbm: {type: number, nullable: true, minimum: 0.001, description: 当前组成变化后重新实测的该票货体积;不沿用旧托盘或计费材积重} 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} 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 required: [appointmentBatches] properties: appointmentBatches: {type: array, items: {$ref: 'overseas-business-v1.yaml#/components/schemas/DispatchBatchReference'}} dispatchNo: {type: string} packageCount: {type: integer, description: 关联时待发运箱数,不是实物托位数} boundBy: {type: string} boundAt: {type: string, format: date-time} review: {$ref: '#/components/schemas/ReviewState'} PreviousDispatch: type: object required: [dispatchNo, recordVersion, recordedAt, appointmentBatches] properties: dispatchNo: {type: string} recordVersion: {type: integer, format: int64, description: 原绑定历史的车次版本} recordedAt: {type: string, format: date-time} appointmentBatches: {type: array, items: {$ref: 'overseas-business-v1.yaml#/components/schemas/DispatchBatchReference'}} 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;未配置时可以保存计划但不能确认装载} 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} tripPurpose: {type: string, enum: [DELIVERY, PICKUP], description: 派送车次或入仓取货车次} 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'}