This commit is contained in:
2026-08-07 14:46:55 +08:00
parent 830575cc92
commit b0ea1a0c5c
109 changed files with 5774 additions and 339 deletions
@@ -13,7 +13,13 @@ paths:
parameters:
- {$ref: '#/components/parameters/OptionalTenantId'}
- {name: ruleCode, in: query, schema: {type: string, maxLength: 50}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
responses:
'200':
description: 成功或业务失败
content:
application/json:
schema: {$ref: '#/components/schemas/CustomerRuleVersionSummary'}
'403': {description: 无权限}
/api/platform/v1/fba-pricing/customer-rules/versions:
post:
summary: 新建客户计费规则版本
@@ -51,10 +57,80 @@ paths:
summary: 停用船司 FBA 价格版本
parameters: [{$ref: '#/components/parameters/Id'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates/price-books:
get:
summary: 查询船期价格表版本
description: 需要 firstleg:fba-pricing:rate:view 权限;返回待确认上传、当前生效和历史替换版本。
parameters:
- {name: status, in: query, schema: {$ref: '#/components/schemas/PriceBookStatus'}}
responses:
'200':
description: 成功或业务失败
content:
application/json:
schema:
type: array
items: {$ref: '#/components/schemas/PriceBookVersionSummary'}
'403': {description: 无权限}
post:
summary: 上传船期价格表并生成待确认记录
description: 仅上传和解析,生成待确认上传记录,不改变当前生效版本;需要 firstleg:fba-pricing:rate:edit 权限。
requestBody:
required: true
content:
multipart/form-data:
schema: {$ref: '#/components/schemas/PriceBookUploadRequest'}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates/price-books/{versionId}:
get:
summary: 查询船期价格表版本详情和解析结果
parameters: [{$ref: '#/components/parameters/VersionId'}]
responses:
'200':
description: 成功或业务失败
content:
application/json:
schema: {$ref: '#/components/schemas/PriceBookVersionDetail'}
'403': {description: 无权限}
/api/platform/v1/fba-pricing/carrier-rates/price-books/{versionId}/publish:
post:
summary: 确认并立即生效船期价格表版本
description: 只确认上传表中的仓库映射,不允许在线改价;阻断错误必须为零。发布事务将上一 ACTIVE 版本标记为 SUPERSEDED,始终只保留一份 ACTIVE。
parameters: [{$ref: '#/components/parameters/VersionId'}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/PriceBookConfirmationRequest'}}}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates/price-books/{versionId}/source:
get:
summary: 下载船期价格表原始文件
description: 需要 firstleg:fba-pricing:rate:view 权限;由 Firstleg 代理 File 服务内部下载。
parameters: [{$ref: '#/components/parameters/VersionId'}]
responses:
'200': {description: 原始 XLSX 附件, content: {application/octet-stream: {schema: {type: string, format: binary}}}}
'403': {description: 无权限}
/api/merchant/v1/first-leg/pricing/channels:
get:
summary: 查询当前起运仓可选船期渠道
description: 客户只看到当前 ACTIVE 版本;不存在于当前版本的渠道不可选择。pricingTaxModes 来自当前起运仓下的生效价格行,前端不得写死包税选项。
parameters:
- {name: originWarehouseId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200':
description: 成功或业务失败
content:
application/json:
schema:
type: array
items: {$ref: '#/components/schemas/MerchantPricingChannel'}
/api/merchant/v1/first-leg/pricing/estimate:
post:
summary: 计算头程参考费用
description: 只返回基础参考费用,不包含复杂附加费和最终结算调整;pricingTaxMode 不复用订单 taxMode。
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/PriceEstimateRequest'}}}}
responses: {'200': {description: 成功或业务失败}}
/api/platform/v1/inbounds/{inboundId}/fees/calculate:
post:
summary: 按审核通过测量快照试算 FBA 费用
description: 精确匹配唯一客户规则和唯一船司价格;测量审核后即使主流程已到 WAIT_SPLIT,也可独立试算且不回退主流程状态;需要 firstleg:fba-pricing:calculate 权限。
description: 仅匹配当前唯一 ACTIVE 船期价格表中的 ACTIVE 价格行,按起运仓、渠道、目的仓、pricingTaxMode 和计费单位估价;不再以 carrierId 或客户计费规则作为前置。海派还需按FBA区域和重量阶梯匹配;测量审核后即使主流程已到 WAIT_SPLIT,也可独立试算且不回退主流程状态;需要 firstleg:fba-pricing:calculate 权限。
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
requestBody: {content: {application/json: {schema: {$ref: '#/components/schemas/CalculateRequest'}}}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
@@ -94,6 +170,7 @@ components:
TenantId: {name: tenantId, in: query, required: true, description: 目标客户 ID;参数名为历史兼容, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
Id: {name: id, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
InboundId: {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
VersionId: {name: versionId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
IdempotencyKey: {name: Idempotency-Key, in: header, required: true, schema: {type: string, maxLength: 128}}
schemas:
AdjustFeeRequest:
@@ -124,7 +201,7 @@ components:
effectiveTo: {type: string, format: date-time, nullable: true}
CarrierRateVersionRequest:
type: object
required: [rateCode, originWarehouseId, originWarehouseName, businessType, channelCode, carrierId, carrierName, destinationCode, chargeUnit, unitPrice, currency, additionalFee, effectiveFrom]
required: [rateCode, originWarehouseId, originWarehouseName, businessType, channelCode, carrierId, carrierName, destinationType, chargeUnit, unitPrice, currency, additionalFee, effectiveFrom]
properties:
rateCode: {type: string, maxLength: 50}
originWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
@@ -133,10 +210,170 @@ components:
channelCode: {type: string}
carrierId: {type: string, pattern: '^[1-9][0-9]*$'}
carrierName: {type: string}
destinationCode: {type: string}
destinationType: {$ref: '#/components/schemas/PricingDestinationType'}
destinationCode: {type: string, nullable: true}
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
destinationName: {type: string, maxLength: 128, nullable: true}
chargeUnit: {type: string, enum: [KG, CBM]}
unitPrice: {type: number, exclusiveMinimum: 0}
currency: {type: string, pattern: '^[A-Z]{3}$'}
additionalFee: {type: number, minimum: 0}
effectiveFrom: {type: string, format: date-time}
effectiveTo: {type: string, format: date-time, nullable: true}
PriceBookStatus:
type: string
enum: [PENDING_CONFIRMATION, ACTIVE, SUPERSEDED, FAILED]
PriceModel:
type: string
enum: [FBA_WAREHOUSE_RATE, REGION_WEIGHT_TIER]
PricingTaxMode:
type: string
enum: [TAX_INCLUDED, TAX_EXCLUDED]
PricingDestinationType:
type: string
description: 价格明细支持的目的地类型;PRIVATE 本期不参与自动估价
enum: [FBA, OVERSEAS]
PriceBookUploadRequest:
type: object
required: [file]
properties:
file: {type: string, format: binary, description: 原始 XLSX 文件}
PriceBookVersionSummary:
type: object
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
versionNo: {type: integer}
originalFileName: {type: string, maxLength: 255}
sourceFileId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
sourceSha256: {type: string, maxLength: 64, nullable: true}
status: {$ref: '#/components/schemas/PriceBookStatus'}
channelCount: {type: integer, minimum: 0}
rateCount: {type: integer, minimum: 0}
blockingErrorCount: {type: integer, minimum: 0}
warningCount: {type: integer, minimum: 0}
parseIssuesJson: {type: string, nullable: true, description: 上传解析问题及待确认重新校验结果JSON}
createdBy: {type: string, pattern: '^[1-9][0-9]*$'}
createdAt: {type: string, format: date-time}
publishedBy: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
publishedAt: {type: string, format: date-time, nullable: true}
supersededAt: {type: string, format: date-time, nullable: true}
PriceBookVersionDetail:
type: object
required: [version, channels, rates, issues]
properties:
version: {$ref: '#/components/schemas/PriceBookVersionSummary'}
channels:
type: array
items: {$ref: '#/components/schemas/PriceBookParsedChannel'}
rates:
type: array
items: {$ref: '#/components/schemas/PriceBookParsedRate'}
issues:
type: array
items: {$ref: '#/components/schemas/PriceBookParseIssue'}
PriceBookParseIssue:
type: object
properties:
severity: {type: string}
issueCode: {type: string}
message: {type: string}
sourceSheetName: {type: string, nullable: true}
sourceRowNumber: {type: integer, minimum: 1, nullable: true}
sourceCell: {type: string, nullable: true}
PriceBookConfirmationRequest:
type: object
required: [originMappings]
properties:
originMappings:
type: array
minItems: 1
maxItems: 2
items: {$ref: '#/components/schemas/PriceBookOriginMapping'}
overseasMappings:
type: array
maxItems: 2
items: {$ref: '#/components/schemas/PriceBookOverseasMapping'}
PriceBookOriginMapping:
type: object
required: [originWarehouseCode, warehouseId]
properties:
originWarehouseCode: {type: string, maxLength: 64, description: 上传表识别出的起运仓稳定编码}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$', description: 平台公共国内仓稳定ID}
PriceBookOverseasMapping:
type: object
required: [sourceDestinationName, warehouseId]
properties:
sourceDestinationName: {type: string, maxLength: 128, description: 上传表中的海外仓名称}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$', description: 平台公共海外仓稳定ID}
PriceBookParsedChannel:
type: object
required: [channelCode, channelName, priceModel, sourceSheetName]
properties:
channelCode: {type: string, maxLength: 64}
channelName: {type: string, maxLength: 128}
priceModel: {$ref: '#/components/schemas/PriceModel'}
sourceSheetName: {type: string, maxLength: 128}
estimatedDepartureDate: {type: string, format: date}
estimatedDepartureText: {type: string, maxLength: 128}
latestWarehouseEntry: {type: string, maxLength: 128}
vesselName: {type: string, maxLength: 128}
voyageNo: {type: string, maxLength: 64}
referenceTransit: {type: string, maxLength: 128}
surchargeDescription: {type: string, maxLength: 2000}
remark: {type: string, maxLength: 2000}
PriceBookParsedRate:
type: object
required: [channelCode, priceModel, originWarehouseCode, originWarehouseName, chargeUnit, unitPrice, currency, sourceSheetName, sourceRowNumber]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
channelCode: {type: string, maxLength: 64}
priceModel: {$ref: '#/components/schemas/PriceModel'}
originWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 确认时绑定的平台公共国内仓稳定ID}
originWarehouseCode: {type: string, maxLength: 64}
originWarehouseName: {type: string, maxLength: 128}
destinationType: {$ref: '#/components/schemas/PricingDestinationType', nullable: true, description: FBA_WAREHOUSE_RATE 必填;REGION_WEIGHT_TIER 为空}
destinationCode: {type: string, maxLength: 32, nullable: true}
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 确认时绑定的平台海外仓稳定ID}
destinationName: {type: string, maxLength: 128, nullable: true, description: 目的仓名称快照}
regionCode: {type: string, maxLength: 16, nullable: true}
pricingTaxMode: {$ref: '#/components/schemas/PricingTaxMode'}
chargeUnit: {type: string, enum: [KG, CBM]}
weightFromKg: {type: number, minimum: 0, nullable: true}
unitPrice: {type: number, exclusiveMinimum: 0}
currency: {type: string, pattern: '^[A-Z]{3}$'}
sourceSheetName: {type: string, maxLength: 128}
sourceRowNumber: {type: integer, minimum: 1}
sourceDestinationText: {type: string, maxLength: 1000}
remark: {type: string, maxLength: 500}
MerchantPricingChannel:
type: object
required: [priceBookVersionId, channelCode, channelName, priceModel, pricingTaxModes]
properties:
priceBookVersionId: {type: string, pattern: '^[1-9][0-9]*$'}
channelCode: {type: string, maxLength: 64}
channelName: {type: string, maxLength: 128}
priceModel: {$ref: '#/components/schemas/PriceModel'}
pricingTaxModes:
type: array
description: 当前起运仓、当前渠道的生效价格行支持的报价税模式;可能只包含包税或不包税其中一种。
items: {$ref: '#/components/schemas/PricingTaxMode'}
estimatedDepartureDate: {type: string, format: date, nullable: true}
estimatedDepartureText: {type: string, maxLength: 128, nullable: true}
latestWarehouseEntry: {type: string, maxLength: 128, nullable: true}
referenceTransit: {type: string, maxLength: 128, nullable: true}
surchargeDescription: {type: string, maxLength: 2000, nullable: true}
remark: {type: string, maxLength: 2000, nullable: true}
PriceEstimateRequest:
type: object
required: [originWarehouseId, channelCode, destinationType]
properties:
originWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
channelCode: {type: string, maxLength: 64}
destinationType: {$ref: '#/components/schemas/PricingDestinationType'}
destinationCode: {type: string, maxLength: 32}
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
destinationName: {type: string, maxLength: 128, nullable: true}
destinationRegion: {type: string, enum: [WEST, CENTRAL, EAST]}
pricingTaxMode: {$ref: '#/components/schemas/PricingTaxMode'}
actualWeightKg: {type: number, minimum: 0}
actualVolumeCbm: {type: number, minimum: 0}
@@ -9,7 +9,7 @@ paths:
/internal/firstleg/v1/inbounds/order-approved:
post:
summary: 订单审核通过后幂等创建入库单
description: 仅供订单服务调用;入仓码由订单提交时生成,Firstleg 必须原样沿用。承运商可在后续履约或计费前补充。
description: 仅供订单服务调用;入仓码由订单提交时生成,Firstleg 必须原样沿用。
security:
- internalServiceToken: []
requestBody:
@@ -90,7 +90,9 @@ paths:
签名body的 SHA-256 小写十六进制,六部分使用 LF(\n)连接且末尾不追加换行。
签名body = data原始UTF-8文本 + LF + image文件内容SHA-256小写十六进制。
三层语义:Nonce 防短时重放;Idempotency-Key 标识一次 HTTP 写操作;
appKey + eventNo 标识第三方业务事件。
appKey + eventNo 标识第三方业务事件。多台设备可共用同一 appKey/secret,
但 deviceCode、eventNo 和 Idempotency-Key 必须由调用方生成全局唯一值,
不得仅在单台设备内从 1 开始递增。
security:
- measurementAppKey: []
measurementTimestamp: []
@@ -294,9 +296,10 @@ components:
businessType: {type: string, nullable: true}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
carrierId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 可选,可在后续履约或计费前补充}
carrierId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 历史兼容的内部运输供应商快照}
carrierName: {type: string, nullable: true}
taxMode: {type: string, nullable: true}
pricingTaxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED], nullable: true, description: 报价包税维度;独立于订单taxMode}
containerMode: {type: string, nullable: true}
customsInspection: {type: boolean, nullable: true}
destinationType: {type: string, nullable: true}
@@ -391,6 +394,8 @@ components:
processStatus: {type: string}
customerId: {type: string, nullable: true}
companyId: {type: string, nullable: true}
taxMode: {type: string, nullable: true, description: 订单报关方式快照}
pricingTaxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED], nullable: true, description: 下单时选择的报价包税维度快照}
InboundMeasurementCallbackRequest:
type: object
required: [eventNo, externalDetailNo, warehouseCode, inboundCode, inboundDetailId, deviceCode, measuredAt, boxSpecification, packageCount, lengthCm, widthCm, heightCm]