openapi: "3.0.3" info: title: "原排车外配车辆运营视图" version: "1.0.0" description: "仅ACTIVE且装车后/派送中/已完成。按原装车归属DISPATCHED及MASTER/EXTERNAL资源快照读取;无快照不回填。复用四张附加表,不推进排车、不触发库存/财务。承运金额CNY/USD显式登记;单价除以实际物理托数并HALF_UP两位。无里程、油耗及油耗照片。响应遵循NON_NULL:可空属性可省略,省略与null均表示空值,0仍是明确登记值;请求必填项仍以required及DTO校验为准。" security: - bearerAuth: [] paths: /api/platform/v1/last-leg/fleet/outsourced-business: get: operationId: listOutsourcedBusiness summary: "外配列表及同筛选四项完整统计" x-permission-code: "platform:fleet:outsourced-business: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: "原排车号、车牌或真实目的仓/FBA编码" } - { name: warehouseId, in: query, schema: { type: string, maxLength: 64 } } - { name: plannedDepartureFrom, in: query, schema: { type: string, format: date-time }, description: "原计划发车时间下界(含)" } - { name: plannedDepartureTo, in: query, schema: { type: string, format: date-time }, description: "原计划发车时间上界(不含)" } - { name: stage, in: query, schema: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Stage" } } responses: "200": description: "完整条件统计不带分页,不逐行GET;响应为统一ApiResponse。" content: application/json: schema: { "$ref": "#/components/schemas/ListResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}: parameters: [ { "$ref": "#/components/parameters/DispatchNo" } ] get: operationId: getOutsourcedBusiness summary: "外配原排车组合详情" x-permission-code: "platform:fleet:outsourced-business:list" responses: "200": { "$ref": "#/components/responses/DetailResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/history: parameters: [ { "$ref": "#/components/parameters/DispatchNo" } ] get: operationId: getOutsourcedBusinessHistory summary: "原排车与运营附加历史分页" x-permission-code: "platform:fleet:outsourced-business: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: "DISPATCH/OPERATIONS保留独立版本,原历史无虚构运营字段。" content: application/json: schema: { "$ref": "#/components/schemas/HistoryResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/operations: parameters: [ { "$ref": "#/components/parameters/DispatchNo" } ] put: operationId: saveOutsourcedBusinessOperations summary: "登记或清空整车承运金额和逐目的仓实际到达" x-permission-code: "platform:fleet:outsourced-business:edit" requestBody: required: true content: application/json: schema: { "$ref": "#/components/schemas/SaveOperations" } responses: "200": { "$ref": "#/components/responses/DetailResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/photos/{slot}/uploads: parameters: [ { "$ref": "#/components/parameters/DispatchNo" }, { "$ref": "#/components/parameters/Slot" } ] post: operationId: uploadOutsourcedBusinessPhoto summary: "准备五框照片文件,尚未绑定" x-permission-code: "platform:fleet:outsourced-business:upload" requestBody: required: true content: multipart/form-data: schema: type: object required: [file, idempotencyKey] properties: file: { type: string, format: binary, description: "非空JPG/PNG,签名校验,最大10MiB;固定装车File分类" } idempotencyKey: { type: string, minLength: 8, maxLength: 128 } responses: "200": description: "savedAt=null;未知结果保留原键查询,不重传。" content: application/json: schema: { "$ref": "#/components/schemas/PhotoResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/photos/{slot}: parameters: [ { "$ref": "#/components/parameters/DispatchNo" }, { "$ref": "#/components/parameters/Slot" } ] put: operationId: bindOutsourcedBusinessPhoto summary: "以独立稳定键绑定原File编号" x-permission-code: "platform:fleet:outsourced-business:upload" requestBody: required: true content: application/json: schema: { "$ref": "#/components/schemas/BindPhoto" } responses: "200": { "$ref": "#/components/responses/DetailResponse" } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/photos/{slot}/files/{fileId}/content: parameters: [ { "$ref": "#/components/parameters/DispatchNo" }, { "$ref": "#/components/parameters/Slot" } ] get: operationId: readOutsourcedBusinessPhotoContent summary: "读取当前或精确历史版本的同车照片引用" x-permission-code: "platform:fleet:outsourced-business:list" parameters: - { name: fileId, in: path, required: true, schema: { type: integer, format: int64, minimum: 1 } } - { name: revisionVersion, in: query, schema: { type: integer, format: int64, minimum: 1 } } responses: "200": description: "原始照片字节,Cache-Control=no-store,X-Content-Type-Options=nosniff;无引用不允许探测。" content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } /api/platform/v1/last-leg/fleet/outsourced-business/{dispatchNo}/commands/{idempotencyKey}: parameters: [ { "$ref": "#/components/parameters/DispatchNo" } ] get: operationId: getOutsourcedBusinessCommand summary: "仅原操作账号查询原命令结果" x-permission-code: "platform:fleet:outsourced-business:list" parameters: - { name: idempotencyKey, in: path, required: true, schema: { type: string, minLength: 8, maxLength: 128 } } responses: "200": description: "同dispatch唯一账本;相同键异内容/版本冲突,异账号拒绝,未知不自动重试。" content: application/json: schema: { "$ref": "#/components/schemas/CommandResponse" } components: securitySchemes: bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT } parameters: DispatchNo: { name: dispatchNo, in: path, required: true, schema: { type: string, minLength: 1, maxLength: 128 } } Slot: { name: slot, in: path, required: true, schema: { "$ref": "#/components/schemas/PhotoSlot" } } responses: DetailResponse: description: "统一ApiResponse;成功code=200,业务拒绝A0400/A0403/A0404/A0409,认证/网关可真实401/403/503;保留requestId/traceId。" content: application/json: schema: allOf: - { "$ref": "#/components/schemas/Envelope" } - { type: object, properties: { data: { allOf: [ { "$ref": "#/components/schemas/Detail" } ], nullable: true } } } schemas: Envelope: type: object properties: code: { type: string } message: { type: string } requestId: { type: string, nullable: true } traceId: { type: string, nullable: true } Operations: type: object additionalProperties: false x-java-record: OutsourcedBusinessModels.Operations required: [arrivals] properties: money: { allOf: [ { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Money" } ], nullable: true } arrivals: { type: array, items: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Arrival" }, description: "只接受原实际destinationKey,禁止重复或其他车辆目的地;省略目的地或null均不推定到达" } SaveOperations: type: object additionalProperties: false x-java-record: OutsourcedBusinessModels.SaveOperations required: [recordVersion, idempotencyKey, operations] properties: recordVersion: { type: string, pattern: "^(0|[1-9][0-9]*)$" } idempotencyKey: { type: string, minLength: 8, maxLength: 128 } operations: { "$ref": "#/components/schemas/Operations" } reason: { type: string, nullable: true, maxLength: 1000 } BindPhoto: type: object additionalProperties: false x-java-record: OutsourcedBusinessModels.BindPhoto required: [recordVersion, idempotencyKey, fileId] properties: recordVersion: { type: string, pattern: "^(0|[1-9][0-9]*)$" } idempotencyKey: { type: string, minLength: 8, maxLength: 128 } fileId: { type: string, pattern: "^[1-9][0-9]*$" } Vehicle: type: object x-java-record: OutsourcedBusinessModels.Vehicle required: [ownership] properties: vehicleId: { type: string, nullable: true, description: "原临时EXTERNAL车辆合法为空,档案MASTER核对原捕获ID" } plate: { type: string, nullable: true } ownership: { type: string, enum: [DISPATCHED] } carrierName: { type: string, nullable: true, description: "只取原车辆快照,缺失显示—;不查当前档案补值" } PhotoSlot: type: string enum: [LOADING_SCENE, LOADING_LIST, PRE_DEPARTURE_CHECK, DRIVER_LICENSE, RECEIPT] Photo: type: object x-java-record: OutsourcedBusinessModels.Photo required: [slot, category, fileId, fileName, contentType, sizeBytes, uploadedAt] properties: slot: { "$ref": "#/components/schemas/PhotoSlot" } category: { type: string, enum: [LOADING] } fileId: { type: string } fileName: { type: string } contentType: { type: string, enum: [image/png, image/jpeg] } sizeBytes: { type: string } uploadedAt: { type: string, format: date-time } savedAt: { type: string, format: date-time, nullable: true } PhotoSummary: type: object x-java-record: OutsourcedBusinessModels.PhotoSummary required: [loadingCount] properties: loadingCount: { type: integer, minimum: 0, maximum: 5 } Row: type: object x-java-record: OutsourcedBusinessModels.Row required: [dispatchNo, stage, plannedDepartureAt, loadingCompletedAt, origin, vehicle, driver, destinations, actualPalletCount, operations, recordVersion, dispatchRecordVersion, photoSummary, actions, sourceIssues] properties: dispatchNo: { type: string } stage: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Stage" } plannedDepartureAt: { type: string, format: date-time } loadingCompletedAt: { type: string, format: date-time } departedAt: { type: string, format: date-time, nullable: true } deliveryCompletedAt: { type: string, format: date-time, nullable: true } origin: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Origin" } vehicle: { "$ref": "#/components/schemas/Vehicle" } driver: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Driver" } destinations: { type: array, items: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Destination" } } actualPalletCount: { type: integer, minimum: 0, description: "原实载warehousePalletId去重;同客户/跨客户共托只计一次,不用标准托位作除数" } operations: { "$ref": "#/components/schemas/Operations" } unitPrice: { type: string, nullable: true, description: "整车金额除实际物理托数,HALF_UP两位;金额null或托数0时null" } recordVersion: { type: string, description: "本页附加版本,初始只读虚拟0;原主单版本独立" } dispatchRecordVersion: { type: string } photoSummary: { "$ref": "#/components/schemas/PhotoSummary" } actions: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Actions" } sourceIssues: { type: array, items: { type: string } } ListResult: type: object x-java-record: OutsourcedBusinessModels.ListResult required: [records, page, size, total, summary] properties: records: { type: array, items: { "$ref": "#/components/schemas/Row" } } page: { type: integer } size: { type: integer } total: { type: integer } summary: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Summary" } Detail: type: object x-java-record: OutsourcedBusinessModels.Detail required: [row, dispatch, cargo, photos] properties: row: { "$ref": "#/components/schemas/Row" } dispatch: { "$ref": "overseas-business-v1.yaml#/components/schemas/DispatchDetail" } cargo: { type: array, items: { "$ref": "fleet-owned-business-v1.yaml#/components/schemas/Cargo" } } photos: { type: array, items: { "$ref": "#/components/schemas/Photo" } } History: type: object x-java-record: OutsourcedBusinessModels.History required: [eventSource, action, occurredAt, photos] properties: eventSource: { type: string, enum: [DISPATCH, OPERATIONS] } recordVersion: { type: string, nullable: true } dispatchRecordVersion: { type: string, nullable: true } action: { type: string } operatorName: { type: string, nullable: true } occurredAt: { type: string, format: date-time } reason: { type: string, nullable: true } operations: { allOf: [ { "$ref": "#/components/schemas/Operations" } ], nullable: true } photos: { type: array, items: { "$ref": "#/components/schemas/Photo" } } HistoryPage: type: object x-java-record: OutsourcedBusinessModels.HistoryPage required: [records, page, size, total] properties: records: { type: array, items: { "$ref": "#/components/schemas/History" } } page: { type: integer } size: { type: integer } total: { type: integer } Command: type: object x-java-record: OutsourcedBusinessModels.Command description: "SAVE_OPERATIONS/BIND_PHOTO成功时recordVersion和result必须有值;UPLOAD_PHOTO成功时result必须含fileId,recordVersion可空。仅可空的未确定或拒绝结果字段允许省略,不放宽成功回执的关联要求。" required: [dispatchNo, action, idempotencyKey, state, replayed, retryAllowed] properties: dispatchNo: { type: string } action: { type: string, enum: [SAVE_OPERATIONS, UPLOAD_PHOTO, BIND_PHOTO] } idempotencyKey: { type: string } state: { type: string, enum: [SUCCEEDED, PENDING, UNKNOWN_RESULT, REJECTED] } recordVersion: { type: string, nullable: true } replayed: { type: boolean } result: { nullable: true, oneOf: [ { "$ref": "#/components/schemas/Detail" }, { "$ref": "#/components/schemas/Photo" } ] } errorCode: { type: string, nullable: true } retryAllowed: { type: boolean, enum: [false] } ListResponse: allOf: - { "$ref": "#/components/schemas/Envelope" } - { type: object, properties: { data: { allOf: [ { "$ref": "#/components/schemas/ListResult" } ], nullable: true } } } HistoryResponse: allOf: - { "$ref": "#/components/schemas/Envelope" } - { type: object, properties: { data: { allOf: [ { "$ref": "#/components/schemas/HistoryPage" } ], nullable: true } } } PhotoResponse: allOf: - { "$ref": "#/components/schemas/Envelope" } - { type: object, properties: { data: { allOf: [ { "$ref": "#/components/schemas/Photo" } ], nullable: true } } } CommandResponse: allOf: - { "$ref": "#/components/schemas/Envelope" } - { type: object, properties: { data: { allOf: [ { "$ref": "#/components/schemas/Command" } ], nullable: true } } }