Files
baiyue-firstleg/lastleg-service/src/main/resources/openapi/storage-rent-v1.yaml
T
2026-10-26 13:41:43 +08:00

228 lines
11 KiB
YAML

openapi: 3.0.3
info:
title: 海外仓租与出库资金预校验
version: 1.0.0
description: |
仅仓租自动计费。中转按CBM/天、退货按原托份额/天累进,首次或重建预校验读取客户当前仓租配置。
未配置客户使用仓库服务明确返回的两张默认报价表;网络、无效配置或不支持币种均阻断出库,不降级免费。
PlanJson保存配置ID、版本、币种和完整阶梯。有效预占重放与consume使用原快照及冻结金额,不受期间改价影响。
后续部分出库采用客户最新配置,原入库时间与原托份额保持不变。原币支持USD/CNY,结算币为CNY。
实际PDA入库开始计租,实际出库按本次数量生成待审核费用,审核通过后按确认金额扣款;所有海外仓租从余额及有效授信扣除。
头程同单同仓多次入库合并计租,统一沿用首次实际入库时间;其他业务按各批实际入库时间分别计龄。
每满24小时一天,不足24小时向上取整。公开时间均为ISO8601 UTC时间,携带Z,客户端按本地时区显示。
普通业务错误沿用HTTP 200及非200业务code。平台接口要求平台tenant_id=0。
security:
- bearerAuth: []
paths:
/api/platform/v1/last-leg/storage-rent:
get:
summary: 原计租批次分页
description: 权限platform:overseas-fee:list。一个原始实收批次一行。
parameters:
- {in: query, name: customerId, schema: {type: string}}
- {in: query, name: businessNo, schema: {type: string}}
- {in: query, name: warehouseId, schema: {type: string}}
- {in: query, name: businessType, schema: {type: string, enum: [LASTLEG_ORDER, WAREHOUSE_TRANSFER, RETURN_ORDER]}}
- {in: query, name: status, schema: {type: string, enum: [IN_STOCK, CLEARED]}}
- {in: query, name: page, schema: {type: integer, minimum: 1, default: 1}}
- {in: query, name: size, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
responses:
'200':
description: 统一响应data包含records、page、size、total、pages
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/Lot'}}
page: {type: integer}
size: {type: integer}
total: {type: integer}
pages: {type: integer}
/api/platform/v1/last-leg/storage-rent/warehouse-options:
get:
summary: 计租仓库选项
description: 权限platform:overseas-fee:list,只读取已有仓库快照。
responses:
'200':
description: data为id、warehouseName对象数组
/api/platform/v1/last-leg/storage-rent/{id}:
get:
summary: 原批次及逐次出库仓租
description: 权限platform:overseas-fee:list;只返回已实际出库的收费记录,免费出库保留零金额。
parameters:
- {$ref: '#/components/parameters/id'}
responses:
'200':
description: 统一响应
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data:
type: object
properties:
lot: {$ref: '#/components/schemas/Lot'}
charges: {type: array, items: {$ref: '#/components/schemas/Charge'}}
/api/platform/v1/last-leg/storage-rent/fees/{sourceFeeId}/adjust:
post:
summary: 审核前调整仓租金额并保存说明
description: 权限platform:finance:fee-source:edit。仅当前待审核且资金已锁定版本可改;金额按原币填写,保留冻结汇率与原计算快照。生成新费用版本。原零元改为非零须先补冻结;原非零费用调高在审核结算时由Finance原子检查差额,余额不足保留原冻结,不登记实扣。
parameters:
- {in: path, name: sourceFeeId, required: true, schema: {type: string}}
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [expectedVersion, amount, reason, idempotencyKey]
properties:
expectedVersion: {type: integer, minimum: 1}
amount: {type: number, minimum: 0, maximum: 999999999999.99, multipleOf: 0.01}
reason: {type: string, minLength: 1, maxLength: 500}
idempotencyKey: {type: string, minLength: 1, maxLength: 128}
responses:
'200': {description: 统一响应,data为调整后的费用版本;状态冲突或缺少说明返回非200业务code}
/api/pda/v1/last-leg/storage-rent/preparations:
post:
summary: 出库前计算仓租并提交余额授信冻结
description: |
权限lastleg:pda:operate及ROLE_OVERSEAS_WAREHOUSE_PDA_OPERATOR。客户与仓库从绑定身份及真实业务来源解析。
ready=false必须等待资金回执;仅ready=true可提交原扫码。先冻结后扣库存,实际扫码后生成待审核仓租,审核通过后实际扣款。
同一原扫码复用idempotencyKey与全部明细;更改货物或数量必须新键。冻结15分钟有效,变更计费天数或汇率月份需重算。
已实际出库的原键返回CONSUMED,调用原扫码接口恢复其幂等结果。零费用无需汇率及资金指令。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/PrepareRequest'}
responses:
'200':
description: 统一响应data为预校验状态
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/Envelope'}
- properties:
data: {$ref: '#/components/schemas/Preparation'}
/api/pda/v1/last-leg/storage-rent/preparations/{id}:
parameters:
- {$ref: '#/components/parameters/id'}
get:
summary: 查询原冻结真实回执
description: PDA权限及绑定仓校验同创建。
responses:
'200': {description: 统一响应data为Preparation}
delete:
summary: 取消未使用预占并解冻
description: 已出库不能取消;冻结处理中取消将于迟到成功回执后补解冻。PDA权限及绑定仓校验同创建。
responses:
'200': {description: 统一响应data为Preparation}
components:
securitySchemes:
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
parameters:
id: {in: path, name: id, required: true, schema: {type: string}}
schemas:
Envelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: object}
Lot:
type: object
properties:
id: {type: string}
customerId: {type: string}
customerName: {type: string}
businessType: {type: string}
businessNo: {type: string, description: 原计租来源单号,头程为对应尾程订单号,退货为退货单号}
warehouseId: {type: string}
warehouseName: {type: string}
batchNo: {type: string}
inboundAt: {type: string, format: date-time, description: 实际入库UTC时间,带Z}
storageDays: {type: integer, description: 已清仓按最后实际出库停止}
originalQuantity: {type: number}
remainingQuantity: {type: number}
quantityUnit: {type: string, enum: [PACKAGE, PIECE]}
billingQuantity: {type: number}
billingUnit: {type: string, enum: [CBM, PALLET]}
ruleCode: {type: string, enum: [TRANSIT_V1, RETURN_V1]}
status: {type: string, enum: [IN_STOCK, CLEARED]}
settledAmount: {type: number, description: 本原批次已成功扣款的CNY合计,不含处理中及失败记录}
chargeCount: {type: integer, description: 本原批次实际出库仓租记录数,包含免租记录}
settledChargeCount: {type: integer, description: 已完成结算的仓租记录数,包含免租记录}
generatedAmount: {type: number, nullable: true, description: 单币种合计;无记录为0,多币种为null}
generatedCurrency: {type: string, nullable: true, enum: [USD, CNY], description: 无记录或多币种为null}
generatedAmounts:
type: array
description: 按原币分别汇总,禁止跨币相加;无记录为空数组
items:
type: object
properties:
currency: {type: string, enum: [USD, CNY]}
amount: {type: number}
Charge:
type: object
properties:
id: {type: string}
outboundNo: {type: string}
businessNo: {type: string}
quantity: {type: number}
storageDays: {type: integer}
originalAmount: {type: number}
currency: {type: string, enum: [USD, CNY]}
settlementAmount: {type: number, description: CNY结算金额}
currencyRate: {type: number, nullable: true}
status: {type: string, enum: [PENDING_REVIEW, REVIEW_FREEZE_PENDING, REVIEW_FREEZE_FAILED, REJECTED, CONSUMED, SETTLE_FAILED, SETTLED]}
createdAt: {type: string, format: date-time}
outboundAt: {type: string, format: date-time}
PrepareRequest:
type: object
required: [mode, businessNo, idempotencyKey]
properties:
mode: {type: string, enum: [DISPATCH, OUTBOUND, OUTBOUND_PALLET, DISCARD]}
businessNo: {type: string, maxLength: 128}
itemId: {type: string}
positionId: {type: string}
packages: {type: integer, minimum: 1}
cartonMark: {type: string}
palletNo: {type: string}
idempotencyKey: {type: string, maxLength: 255}
cartonMarks: {type: array, items: {type: string}}
skuCode: {type: string}
productQuantity: {type: integer, minimum: 0}
lines:
type: array
items:
type: object
required: [itemId, actualPackages]
properties:
itemId: {type: string}
actualPackages: {type: integer, minimum: 0}
photoFileIds: {type: array, items: {type: string}}
scannedCartonMarks: {type: array, items: {type: string}}
confirmAllCartons: {type: boolean}
Preparation:
type: object
properties:
preparationId: {type: string, nullable: true}
status: {type: string, enum: [NOT_REQUIRED, FREEZE_PENDING, READY, FAILED, EXPIRED, CANCELLED, CONSUMED]}
ready: {type: boolean}
amount: {type: number}
currency: {type: string, enum: [CNY]}
originalAmount: {type: number, nullable: true, description: 整托包含多种原币时为null,CNY amount始终可合计}
originalCurrency: {type: string, nullable: true, enum: [USD, CNY]}
exchangeRate: {type: number, nullable: true}
exchangeRateMonth: {type: string, nullable: true}
message: {type: string, nullable: true}