feat(fleet): bind quote versions and reconcile actual return quantities

This commit is contained in:
2026-10-03 13:32:55 +08:00
parent cb6c54ffe5
commit a6fd0ba3c5
60 changed files with 1363 additions and 75 deletions
@@ -65,6 +65,37 @@ paths:
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:
@@ -379,6 +410,7 @@ components:
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:
@@ -387,7 +419,13 @@ components:
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]
@@ -406,6 +444,11 @@ components:
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}
@@ -421,8 +464,8 @@ components:
recordVersion: {type: integer, format: int64}
updatedAt: {type: string, format: date-time}
Outcome:
description: packages保留原实发量;signedPackages为不可变实签量,returnedPackages只计原运输实际退回,remainingPackages必须为零且三者守恒才可结案。签收后的另行退货不重开原运输。
type: object
description: 本车原运输的结案依据;已签收后另发起退货仍保留本次运输DELIVERED及原signedAt,不修改后续退货单据状态。
properties:
dispatchNo: {type: string}
deliveryNo: {type: string}
@@ -431,6 +474,9 @@ components:
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'}