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: customerId in: query required: false schema: {type: string, pattern: '^[1-9][0-9]*$'} - {name: ruleCode, in: query, schema: {type: string, maxLength: 50}} responses: '200': description: 成功或业务失败 content: application/json: schema: {$ref: '#/components/schemas/CustomerRuleVersionListApiResponse'} '403': {description: 无权限} /api/platform/v1/fba-pricing/customer-rules/versions: post: summary: 新建客户计费规则版本 description: 新增配置固定为未启用,可保存有效期重叠的多条配置;保存后通过设置默认规则接口启用其中一条。 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}/default: put: summary: 启用客户计费规则 description: 将指定配置设为当前客户唯一默认生效规则,并取消原默认规则。 parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/Id'}] 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: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/FeeSnapshotApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fees/confirm: post: summary: 确认最新费用快照 description: 需要 firstleg:inbound:confirm-send-fee 或兼容权限 firstleg:fba-pricing:confirm。确认费用只更新费用状态;主流程已到 WAIT_SPLIT 时保持不变。 parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}] responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/FeeSnapshotApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fees/send: post: summary: 发送已确认费用快照 description: 需要 firstleg:inbound:confirm-send-fee 或兼容权限 firstleg:inbound:send-fee。人工发布当前已确认版本;仅此动作将费用置为 SENT、生成 PUBLISHED 的 FBA_PRICING 只读派生明细并写入 Finance Outbox。入库单已到 WAIT_SPLIT 时不得回退或阻塞主流程。 parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/IdempotencyKey'}] responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/FeeSnapshotApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fees/latest: get: summary: 查询 fl_inbound_fee 最新费用快照 description: fl_inbound_fee 是头程运费唯一事实源;fee-details 中 sourceType=FBA_PRICING 的记录仅为最新版本只读派生。 parameters: [{$ref: '#/components/parameters/TenantId'}, {$ref: '#/components/parameters/InboundId'}] responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/FeeSnapshotApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fees/published: put: summary: 调整初算或已发布费用 description: 需要 firstleg:fba-pricing:adjust 权限;计费量只能在系统原计费量上下10%范围内(含边界),请求必须携带当前费用版本、必填原因及二次确认标志,越界或并发冲突返回A0409。小计与总额由服务端重算并生成新版本,不回退 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: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/FeeSnapshotApiResponse'}}}}, '403': {description: 无调整权限}} /api/platform/v1/inbounds/{inboundId}/fee-details: get: summary: 查询入仓费用明细 description: 默认隐藏 publicationStatus=SUPERSEDED 的历史版本。FBA_PRICING 是 fl_inbound_fee 最新版本的只读派生;MANUAL 是独立新增、审核和版本调整的其他应收/应付。 parameters: - {$ref: '#/components/parameters/AccountId'} - {$ref: '#/components/parameters/InboundId'} - {name: includeHistory, in: query, required: false, schema: {type: boolean, default: false}, description: true 时包含 SUPERSEDED 历史版本} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailListApiResponse'}}}}, '403': {description: 无权限}} post: summary: 新增 MANUAL 其他费用 description: 只允许创建 MANUAL 来源;FBA_PRICING 由系统从 fl_inbound_fee 派生。 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailSaveRequest'}}}} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}: put: summary: 编辑待审核 MANUAL 费用 description: FBA_PRICING 只读派生禁止通过通用费用接口修改。 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/DetailId'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailSaveRequest'}}}} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailApiResponse'}}}}, '403': {description: 无权限}} delete: summary: 删除待审核 MANUAL 费用 description: FBA_PRICING 只读派生禁止删除。 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/DetailId'}] responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/VoidApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/approve: post: summary: 审核通过 MANUAL 费用当前版本 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/DetailId'}] responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/VoidApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/reject: post: summary: 驳回 MANUAL 费用当前版本 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/DetailId'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailRejectRequest'}}}} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/VoidApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/adjust: post: summary: 调整已审核 MANUAL 费用并创建新版本 description: 原版本置为 SUPERSEDED,新记录使用相同 sourceFeeId、sourceFeeVersion+1 并重新进入 PENDING/DRAFT;FBA_PRICING 必须通过头程费用调整接口处理。 parameters: - {$ref: '#/components/parameters/AccountId'} - {$ref: '#/components/parameters/InboundId'} - {$ref: '#/components/parameters/DetailId'} - {name: expectedSourceVersion, in: query, required: true, schema: {type: integer, minimum: 1}} requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailSaveRequest'}}}} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailApiResponse'}}}}, '403': {description: 无权限}} /api/platform/v1/inbounds/{inboundId}/fee-details/{detailId}/void: post: summary: 作废已审核 MANUAL 费用当前版本 parameters: [{$ref: '#/components/parameters/AccountId'}, {$ref: '#/components/parameters/InboundId'}, {$ref: '#/components/parameters/DetailId'}] requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/InboundFeeDetailVersionRequest'}}}} responses: {'200': {description: 成功或业务失败, content: {application/json: {schema: {$ref: '#/components/schemas/VoidApiResponse'}}}}, '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]*$'}} DetailId: {name: detailId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}} AccountId: {name: accountId, in: query, required: true, description: 目标客户 ID, 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: CustomerRuleVersionListApiResponse: type: object required: [code, message, data, timestamp] properties: code: {type: string, example: '200'} message: {type: string} data: type: array items: {$ref: '#/components/schemas/CustomerRuleVersionResource'} requestId: {type: string, nullable: true} traceId: {type: string, nullable: true} timestamp: {type: string, format: date-time} CustomerRuleVersionResource: type: object properties: id: {type: string, pattern: '^[1-9][0-9]*$'} tenantId: {type: string, pattern: '^[1-9][0-9]*$'} ruleCode: {type: string} ruleVersion: {type: integer} customerId: {type: string, pattern: '^[1-9][0-9]*$'} customerName: {type: string} businessType: {type: string} chargeMode: {type: string} taxMode: {type: string} conversionFactor: {type: number} roundingScale: {type: integer} roundingMode: {type: string} currency: {type: string} effectiveFrom: {type: string, format: date-time} effectiveTo: {type: string, format: date-time, nullable: true} status: {type: string} remark: {type: string, nullable: true} createdBy: {type: string, nullable: true} createdAt: {type: string, format: date-time, nullable: true} updatedBy: {type: string, nullable: true} updatedAt: {type: string, format: date-time, nullable: true} deleted: {type: boolean, nullable: true} version: {type: integer, nullable: true} FeeSnapshotApiResponse: type: object required: [code, message, data] properties: code: {type: string} message: {type: string} data: {$ref: '#/components/schemas/FeeSnapshotResponse'} requestId: {type: string, nullable: true} traceId: {type: string, nullable: true} timestamp: {type: string, format: date-time, nullable: true} FeeSnapshotResponse: type: object description: fl_inbound_fee 当前版本快照;自动初算为 CALCULATED,人工确认后为 CONFIRMED,只有人工发布后为 SENT。 required: [feeId, feeNo, feeVersion, feeStatus, inboundId, conversionFactor, roundingScale, roundingMode, totalAmount, currency] properties: feeId: {type: string, pattern: '^[1-9][0-9]*$'} feeNo: {type: string} feeVersion: {type: integer, minimum: 1} feeStatus: {type: string, enum: [CALCULATED, CONFIRMED, SENT, SUPERSEDED]} inboundId: {type: string, pattern: '^[1-9][0-9]*$'} inboundCode: {type: string, nullable: true} measurementId: {type: string, nullable: true} measurementSource: {type: string, nullable: true} chargeRuleId: {type: string, nullable: true} ruleCode: {type: string, nullable: true} chargeRuleVersion: {type: integer, nullable: true} carrierRateId: {type: string, nullable: true} rateCode: {type: string, nullable: true} carrierRateVersion: {type: integer, nullable: true} priceBookVersionId: {type: string, nullable: true} customerId: {type: string, nullable: true} customerName: {type: string, nullable: true} originWarehouseId: {type: string, nullable: true} originWarehouseName: {type: string, nullable: true} businessType: {type: string, nullable: true} channelCode: {type: string, nullable: true} carrierId: {type: string, nullable: true} carrierName: {type: string, nullable: true} destinationType: {type: string, nullable: true} destinationWarehouseId: {type: string, nullable: true} destinationName: {type: string, nullable: true} destinationCode: {type: string, nullable: true} taxMode: {type: string, nullable: true} pricingTaxMode: {type: string, nullable: true} chargeMode: {type: string, nullable: true} conversionFactor: {type: number, description: 本费用版本实际使用的重量体积换算系数;FBA/区域重量阶梯按KG为167,FBA按CBM为363} roundingScale: {type: integer, enum: [6], description: 本费用版本最终计费量实际保留的小数位数} roundingMode: {type: string, enum: [HALF_UP], description: 本费用版本最终计费量实际使用的舍入方式} actualWeightKg: {type: number, nullable: true} actualVolumeCbm: {type: number, nullable: true} convertedQuantity: {type: number, nullable: true} baselineChargeableQuantity: {type: number, description: 系统按权威测量与生效报价计算的原计费量,人工调整后保持不变} lowerChargeableQuantity: {type: number, description: 允许人工调整的计费量下界,包含边界} upperChargeableQuantity: {type: number, description: 允许人工调整的计费量上界,包含边界} tolerancePercent: {type: number, enum: [10.00], description: 相对系统原计费量允许的上下偏差百分比} chargeableQuantity: {type: number, nullable: true} chargeUnit: {type: string, nullable: true} unitPrice: {type: number, nullable: true} subtotalAmount: {type: number, nullable: true} additionalAmount: {type: number, nullable: true} totalAmount: {type: number} currency: {type: string, pattern: '^[A-Z]{3}$'} rateEffectiveFrom: {type: string, format: date-time, nullable: true} rateEffectiveTo: {type: string, format: date-time, nullable: true} calculatedAt: {type: string, format: date-time, nullable: true} confirmedAt: {type: string, format: date-time, nullable: true} sentAt: {type: string, format: date-time, nullable: true} nextProcessStatus: {type: string, nullable: true, description: 费用动作后的入库主流程状态;审核完成后保持 WAIT_SPLIT} customerConfirmationStatus: {type: string, enum: [PENDING_CONFIRMATION, CONFIRMED], description: 客户对当前费用版本的确认状态} customerConfirmedBy: {type: string, nullable: true, description: 客户确认人用户ID} customerConfirmedByName: {type: string, nullable: true, description: 客户确认人名称快照} customerConfirmedAt: {type: string, format: date-time, nullable: true, description: 客户确认时间;非空后当前版本不可修改} InboundFeeDetailSaveRequest: type: object required: [feeItemId, direction, businessDate, unitPrice, currency, amount] properties: feeItemId: {type: string, pattern: '^[1-9][0-9]*$'} direction: {type: string, enum: [RECEIVABLE, PAYABLE]} businessDate: {type: string, format: date} unitPrice: {type: number, minimum: 0} currency: {type: string, pattern: '^[A-Z]{3}$'} amount: {type: number, minimum: 0} supplierId: {type: string, nullable: true} settlementMode: {type: string, enum: [ON_ACCOUNT, DIRECT_PAID], nullable: true, description: 仅PAYABLE必填;ON_ACCOUNT账期应付,DIRECT_PAID业务已付} paidAt: {type: string, format: date-time, nullable: true, description: DIRECT_PAID必填;ON_ACCOUNT与RECEIVABLE为空} paymentMethod: {type: string, enum: [ONLINE, BANK_TRANSFER, CASH, OTHER], nullable: true, description: DIRECT_PAID必填} paymentReferenceNo: {type: string, maxLength: 128, nullable: true} paymentVoucherFileIds: {type: array, maxItems: 20, nullable: true, items: {type: string, pattern: '^[1-9][0-9]*$'}, description: DIRECT_PAID时与paymentReferenceNo至少一项;File按当前客户失败关闭校验} remark: {type: string, maxLength: 500, nullable: true} InboundFeeDetailVersionRequest: type: object required: [expectedSourceVersion] properties: {expectedSourceVersion: {type: integer, minimum: 1}} InboundFeeDetailRejectRequest: type: object required: [reason] properties: {reason: {type: string, minLength: 1, maxLength: 500}} InboundFeeDetailResource: type: object description: 入仓费用展示记录。sourceType=FBA_PRICING 时是只读派生;sourceType=MANUAL 时按 sourceFeeId/sourceFeeVersion 独立版本化。 required: [id, tenantId, inboundId, feeItemId, sourceType, sourceFeeVersion, direction, businessDate, unitPrice, currency, amount, reviewStatus, publicationStatus] properties: id: {type: string, pattern: '^[1-9][0-9]*$'} tenantId: {type: string, pattern: '^[1-9][0-9]*$'} inboundId: {type: string, pattern: '^[1-9][0-9]*$'} feeItemId: {type: string, pattern: '^[1-9][0-9]*$'} sourceType: {type: string, enum: [MANUAL, FBA_PRICING]} sourceFeeId: {type: string, nullable: true, description: FBA_PRICING 对应 fl_inbound_fee.id;MANUAL V2+ 指向稳定的首版本来源 ID} sourceFeeVersion: {type: integer, minimum: 1} sourceFeeNo: {type: string, nullable: true} inboundCode: {type: string, nullable: true} direction: {type: string, enum: [RECEIVABLE, PAYABLE]} supplierId: {type: string, nullable: true} supplierName: {type: string, nullable: true, readOnly: true} supplierCategory: {type: string, enum: [BOOKING, CUSTOMS, TRUCKING, CERTIFICATE], nullable: true, description: 费用项目供应商类别约束快照;为空表示仅要求供应商ACTIVE} settlementMode: {type: string, enum: [ON_ACCOUNT, DIRECT_PAID], nullable: true} paidAt: {type: string, format: date-time, nullable: true} paymentMethod: {type: string, enum: [ONLINE, BANK_TRANSFER, CASH, OTHER], nullable: true} paymentReferenceNo: {type: string, nullable: true} paymentVoucherFileIds: {type: array, nullable: true, items: {type: string}} businessDate: {type: string, format: date} customerId: {type: string, nullable: true} customerName: {type: string, nullable: true} invoiceTitle: {type: string, nullable: true} feeCategorySnapshot: {type: string, nullable: true} tradeScopeSnapshot: {type: string, nullable: true} feeTypeNameSnapshot: {type: string, nullable: true} channelCode: {type: string, nullable: true} channelName: {type: string, nullable: true} destinationCode: {type: string, nullable: true} destinationName: {type: string, nullable: true} packageCount: {type: integer, nullable: true} actualGrossWeightKg: {type: number, nullable: true} actualVolumeCbm: {type: number, nullable: true} volumeWeightKg: {type: number, nullable: true} chargeableWeightKg: {type: number, nullable: true} chargeableVolumeCbm: {type: number, nullable: true} chargeableQuantity: {type: number, nullable: true} chargeUnit: {type: string, nullable: true} unitPrice: {type: number} currency: {type: string, pattern: '^[A-Z]{3}$'} amount: {type: number} remark: {type: string, nullable: true} reviewStatus: {type: string, enum: [PENDING, APPROVED, REJECTED]} reviewerId: {type: string, nullable: true} reviewerName: {type: string, nullable: true} reviewedAt: {type: string, format: date-time, nullable: true} reviewReason: {type: string, nullable: true} publicationStatus: {type: string, enum: [DRAFT, PUBLISHED, SUPERSEDED, VOIDED]} publishedBy: {type: string, nullable: true} publishedByName: {type: string, nullable: true} publishedAt: {type: string, format: date-time, nullable: true} inboundedAt: {type: string, format: date-time, nullable: true} createdBy: {type: string, nullable: true} createdAt: {type: string, format: date-time, nullable: true} updatedBy: {type: string, nullable: true} updatedAt: {type: string, format: date-time, nullable: true} deleted: {type: boolean, nullable: true} version: {type: integer, nullable: true} InboundFeeDetailApiResponse: type: object required: [code, message, data] properties: code: {type: string} message: {type: string} data: {$ref: '#/components/schemas/InboundFeeDetailResource'} requestId: {type: string, nullable: true} traceId: {type: string, nullable: true} timestamp: {type: string, format: date-time, nullable: true} InboundFeeDetailListApiResponse: type: object required: [code, message, data] properties: code: {type: string} message: {type: string} data: {type: array, items: {$ref: '#/components/schemas/InboundFeeDetailResource'}} requestId: {type: string, nullable: true} traceId: {type: string, nullable: true} timestamp: {type: string, format: date-time, nullable: true} VoidApiResponse: type: object required: [code, message] properties: code: {type: string} message: {type: string} data: {nullable: true} requestId: {type: string, nullable: true} traceId: {type: string, nullable: true} timestamp: {type: string, format: date-time, nullable: true} AdjustFeeRequest: type: object required: [expectedFeeVersion, chargeableQuantity, unitPrice, additionalAmount, reason, toleranceConfirmed] properties: expectedFeeVersion: {type: integer, minimum: 1} chargeableQuantity: {type: number, minimum: 0, exclusiveMinimum: true, description: 计费量,单位沿用当前费用快照的 chargeUnit} unitPrice: {type: number, minimum: 0, description: 人工确认单价} additionalAmount: {type: number, minimum: 0, multipleOf: 0.01} reason: {type: string, minLength: 1, maxLength: 500} toleranceConfirmed: {type: boolean, enum: [true], description: 前端展示上下界并由操作员二次确认后固定传true;服务端仍会重新校验范围与版本} CalculateRequest: type: object properties: pricingAt: {type: string, format: date-time, description: 缺省为服务端当前时间} selectedWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, nullable: true, description: 选定的权威重量快照} selectedVolumeCbm: {type: number, exclusiveMinimum: true, minimum: 0, nullable: true, description: 选定的权威体积快照} weightSource: {type: string, maxLength: 32, nullable: true} volumeSource: {type: string, maxLength: 32, nullable: true} 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, minimum: 0, exclusiveMinimum: true, 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, minimum: 0, exclusiveMinimum: true} 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, minimum: 0, exclusiveMinimum: true} 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'} chargeMode: {type: string, enum: [KG, CBM], description: 包税报价固定为KG;不包税报价必须与客户当前计费规则一致} actualWeightKg: {type: number, minimum: 0} actualVolumeCbm: {type: number, minimum: 0}