Files
baiyue-firstleg/firstleg/src/main/resources/openapi/fba-pricing-v1.yaml
T
2026-08-14 14:26:56 +08:00

382 lines
21 KiB
YAML

openapi: 3.0.3
info:
title: 柏悦二期 FBA 计费 API
version: 2.0.0
description: 业务成功和失败均使用 HTTP 200;仅响应体 code 为字符串 "200" 时表示成功。
security:
- bearerAuth: []
paths:
/api/platform/v1/fba-pricing/customer-rules:
get:
summary: 查询客户计费规则版本
description: 需要 firstleg:fba-pricing:rule:view 权限
parameters:
- {$ref: '#/components/parameters/OptionalTenantId'}
- {name: ruleCode, in: query, schema: {type: string, maxLength: 50}}
responses:
'200':
description: 成功或业务失败
content:
application/json:
schema: {$ref: '#/components/schemas/CustomerRuleVersionSummary'}
'403': {description: 无权限}
/api/platform/v1/fba-pricing/customer-rules/versions:
post:
summary: 新建客户计费规则版本
description: 版本内容不可原地修改;有效期使用 [effectiveFrom,effectiveTo) 半开区间。
parameters: [{$ref: '#/components/parameters/TenantId'}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/CustomerRuleVersionRequest'}}}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/customer-rules/{id}:
get:
summary: 查询客户计费规则版本详情
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/Id'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
delete:
summary: 停用客户计费规则版本
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/Id'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates:
get:
summary: 查询平台公共船司 FBA 价格版本
description: 需要 firstleg:fba-pricing:rate:view 权限
parameters:
- {name: rateCode, in: query, schema: {type: string, maxLength: 50}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates/versions:
post:
summary: 新建平台公共船司 FBA 价格版本
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/CarrierRateVersionRequest'}}}}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/fba-pricing/carrier-rates/{id}:
get:
summary: 查询船司 FBA 价格版本详情
parameters: [{$ref: '#/components/parameters/Id'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
delete:
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: 仅匹配当前唯一 ACTIVE 船期价格表中的 ACTIVE 价格行,按起运仓、渠道、目的仓、pricingTaxMode 和计费单位估价;不再以 carrierId、业务 customerId 或客户计费规则作为前置。区域阶梯渠道可按平台 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: 无权限}}
/api/platform/v1/inbounds/{inboundId}/fees/confirm:
post:
summary: 确认最新费用快照
description: 确认费用只更新费用状态;主流程已到 WAIT_SPLIT 时保持不变。
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/inbounds/{inboundId}/fees/send:
post:
summary: 发送已确认费用快照
description: 该动作涉及后续仓储流程,本轮二期验收不调用。
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/inbounds/{inboundId}/fees/latest:
get:
summary: 查询最新费用快照
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}]
responses: {'200': {description: 成功或业务失败}, '403': {description: 无权限}}
/api/platform/v1/inbounds/{inboundId}/fees/published:
put:
summary: 调整初算或已发布费用
description: 需要 firstleg:fba-pricing:adjust 权限;人工修改计费量、单价和附加费,小计与总额由服务端重算并生成新版本,不回退 WAIT_SPLIT 状态。调整 CALCULATED/CONFIRMED 时生成新的 CALCULATED 版本;调整 SENT 时生成新的 SENT 版本并发布调整事件。
parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AdjustFeeRequest'}
responses: {'200': {description: 成功或业务失败}, '403': {description: 无调整权限}}
components:
securitySchemes:
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
parameters:
OptionalTenantId: {name: tenantId, in: query, required: false, description: 可选目标客户 ID;参数名为历史兼容,不传时查询全部企业, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
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:
type: object
required: [expectedFeeVersion, chargeableQuantity, unitPrice, additionalAmount, reason]
properties:
expectedFeeVersion: {type: integer, minimum: 1}
chargeableQuantity: {type: number, exclusiveMinimum: 0, description: 计费量,单位沿用当前费用快照的 chargeUnit}
unitPrice: {type: number, minimum: 0, description: 人工确认单价}
additionalAmount: {type: number, minimum: 0, multipleOf: 0.01}
reason: {type: string, minLength: 1, maxLength: 500}
CalculateRequest:
type: object
properties: {pricingAt: {type: string, format: date-time, description: 缺省为服务端当前时间}}
CustomerRuleVersionRequest:
type: object
required: [ruleCode, customerId, customerName, businessType, chargeMode, taxMode, conversionFactor, roundingScale, roundingMode, currency, effectiveFrom]
properties:
ruleCode: {type: string, maxLength: 50}
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
customerName: {type: string, maxLength: 128}
businessType: {type: string, maxLength: 32}
chargeMode: {type: string, enum: [KG, CBM]}
taxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED]}
conversionFactor: {type: number, exclusiveMinimum: 0, example: 167}
roundingScale: {type: integer, minimum: 0, maximum: 4}
roundingMode: {type: string, enum: [UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN]}
currency: {type: string, pattern: '^[A-Z]{3}$'}
effectiveFrom: {type: string, format: date-time}
effectiveTo: {type: string, format: date-time, nullable: true}
CarrierRateVersionRequest:
type: object
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]*$'}
originWarehouseName: {type: string}
businessType: {type: string}
channelCode: {type: string}
carrierId: {type: string, pattern: '^[1-9][0-9]*$'}
carrierName: {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}