费用提交

This commit is contained in:
2026-10-26 13:41:43 +08:00
parent 0fe1d10566
commit 761fe3686e
171 changed files with 8750 additions and 386 deletions
@@ -2378,8 +2378,10 @@ paths:
content: { application/json: { schema: { $ref: '#/components/schemas/CustomerOptionResponse' } } }
/api/platform/v1/last-leg/overseas-procurements/warehouse-options:
get:
summary: 查询有效公共海外收货仓候选
description: 权限 platform:overseas-business:purchase:list;固定国内权威公共 OVERSEAS、ACTIVE、RECEIVING 仓,浏览器不访问内部 API。
summary: 按采购方向查询有效公共起运收货仓候选
description: 权限 platform:overseas-business:purchase:list;海外采购取 OVERSEAS、ACTIVE、RECEIVING 公共仓,国内采购取 DOMESTIC、ACTIVE 公共仓,均以 Warehouse 为准。
parameters:
- { name: procurementDirection, in: query, schema: { $ref: '#/components/schemas/ProcurementDirection' } }
security: [{ bearerAuth: [] }]
responses:
'200':
@@ -3705,6 +3707,7 @@ components:
properties:
feeItemCode: { type: string, minLength: 1, maxLength: 64 }
feeItemName: { type: string, minLength: 1, maxLength: 128 }
feeRemark: { type: string, maxLength: 500, nullable: true, description: 费用说明;同单同方向已有相同项目时须填写补收或重复作业原因 }
direction: { type: string, enum: [RECEIVABLE, PAYABLE] }
currency: { type: string, enum: [CNY, USD] }
amount: { type: number, format: decimal, minimum: 0.01 }
@@ -3712,7 +3715,7 @@ components:
supplierId: { type: string, pattern: '^[1-9][0-9]*$' }
supplierName: { type: string, maxLength: 200 }
supplierCategory: { type: string, maxLength: 32 }
settlementMode: { type: string, enum: [ON_ACCOUNT, DIRECT_PAID] }
settlementMode: { type: string, enum: [BILL, WALLET, ON_ACCOUNT, DIRECT_PAID], nullable: true, description: 应收可选推送结算或余额扣费;应付使用账期或已付 }
chargeableQuantity: { type: number, minimum: 0, exclusiveMinimum: true }
quantityUnit: { type: string, maxLength: 32 }
unitPrice: { type: number, minimum: 0, exclusiveMinimum: true }
@@ -3729,6 +3732,7 @@ components:
orderId: { type: string, pattern: '^[1-9][0-9]*$' }
feeItemCode: { type: string }
feeItemName: { type: string }
feeRemark: { type: string, maxLength: 500, nullable: true, description: 业务费用说明,与审核原因分开保存 }
direction: { type: string, enum: [RECEIVABLE, PAYABLE] }
currency: { type: string, enum: [CNY] }
amount: { type: number, format: decimal }
@@ -4201,7 +4205,7 @@ components:
supplierId: { type: string, pattern: '^[1-9][0-9]*$' }
supplierName: { type: string, maxLength: 200 }
supplierCategory: { type: string, maxLength: 32 }
settlementMode: { type: string, enum: [ON_ACCOUNT, DIRECT_PAID] }
settlementMode: { type: string, enum: [BILL, WALLET, ON_ACCOUNT, DIRECT_PAID], nullable: true, description: 应收可选推送结算或余额扣费;应付使用账期或已付 }
chargeableQuantity: { type: number, minimum: 0, exclusiveMinimum: true }
quantityUnit: { type: string, maxLength: 32 }
unitPrice: { type: number, minimum: 0, exclusiveMinimum: true }
@@ -4507,7 +4511,7 @@ components:
labelDeadline: { type: string, format: date-time }
contactName: { type: string, maxLength: 128 }
contactPhone: { type: string, maxLength: 64 }
chargeAmount: { type: number, nullable: true, minimum: 0.01, description: 本次贴标费用(CNY);未传时不冻结或结算资金 }
chargeAmount: { type: number, nullable: true, minimum: 0.01, description: 换标报价快照(CNY);不自动冻结或收费,应收由海外费用登记审核 }
remark: { type: string, nullable: true, maxLength: 1000 }
idempotencyKey: { type: string, maxLength: 255 }
deliveryMethod: { type: string, nullable: true, enum: [TRUCK, EXPRESS, AMAZON_PICKUP, CUSTOMER_PICKUP, PICKUP], description: 只换箱唛或SKU与箱唛同时换时必填;只换SKU时不传;仅TRUCK进入平台预排车,其余方式直接创建出库任务 }
@@ -4674,10 +4678,16 @@ components:
- type: object
required: [records]
properties: { records: { type: array, items: { $ref: '#/components/schemas/ProcurementSummary' } } }
ProcurementDirection:
type: string
enum: [OVERSEAS_TO_DOMESTIC, DOMESTIC_TO_OVERSEAS]
default: OVERSEAS_TO_DOMESTIC
description: 海外采购回国内或国内采购发海外;创建可选,待审核时可核定,通过后锁定。历史运输段编码保持不变,区域文案按方向展示。
ProcurementSummary:
type: object
required: [id, orderNo, customerId, purchaseCategory, productName, purchaseQuantity, status, version, createdAt, updatedAt]
properties:
procurementDirection: { $ref: '#/components/schemas/ProcurementDirection' }
id: { type: string, pattern: '^[0-9]+$' }
orderNo: { type: string }
customerId: { type: string }
@@ -5041,12 +5051,13 @@ components:
actualVolumeCbm: { type: number, nullable: true }
status: { type: string }
version: { type: integer }
ProcurementStatus: { type: string, enum: [PENDING_REVIEW, WAIT_PURCHASE, WAIT_OVERSEAS_RECEIPT, OVERSEAS_RECEIVING, WAIT_PACKING, WAIT_LABELS, WAIT_OVERSEAS_DISPATCH, INTERNATIONAL_TRANSIT, DOMESTIC_RECEIVING, WAIT_CHARGES, WAIT_CUSTOMER_DISPATCH, SHIPPED_TO_CUSTOMER, REJECTED, CANCELLED, EXCEPTION_CLOSED] }
ProcurementStatus: { type: string, enum: [PENDING_REVIEW, WAIT_PURCHASE, WAIT_OVERSEAS_RECEIPT, OVERSEAS_RECEIVING, WAIT_PACKING, WAIT_LABELS, WAIT_OVERSEAS_DISPATCH, WAIT_OVERSEAS_SHIPMENT, INTERNATIONAL_TRANSIT, DOMESTIC_RECEIVING, WAIT_CHARGES, WAIT_CUSTOMER_DISPATCH, WAIT_CUSTOMER_SHIPMENT, SHIPPED_TO_CUSTOMER, REJECTED, CANCELLED, EXCEPTION_CLOSED] }
ProcurementReview:
type: object
required: [version, decision, idempotencyKey]
description: 审核通过必须选择有效公共海外收货仓;拒绝不要求仓库。
description: 审核通过必须选择与采购方向匹配的有效公共收货仓;国内采购选择国内仓,海外采购选择海外收货仓;拒绝不要求仓库。已有购买或收货事实不得切换方向。
properties:
procurementDirection: { $ref: '#/components/schemas/ProcurementDirection' }
version: { type: integer, format: int64, minimum: 0 }
decision: { type: string, enum: [APPROVE, REJECT] }
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
@@ -5056,6 +5067,7 @@ components:
type: object
required: [productName, purchaseQuantity, budgetUnitPrice, currency, receivingAddress, contactName, contactPhone, idempotencyKey]
properties:
procurementDirection: { $ref: '#/components/schemas/ProcurementDirection' }
customerName: { type: string, nullable: true, maxLength: 255 }
purchaseCategory: { type: string, maxLength: 128 }
productName: { type: string, maxLength: 255 }
@@ -5064,7 +5076,7 @@ components:
purchaseQuantity: { type: integer, format: int64, minimum: 1 }
budgetUnitPrice: { type: number, minimum: 0, multipleOf: 0.01, description: 客户授权的货款预算单价;零表示仅授权免费样品 }
currency: { type: string, enum: [CNY, USD] }
receivingAddress: { type: string, minLength: 1, maxLength: 1000, description: 最终客户国内收件完整地址 }
receivingAddress: { type: string, minLength: 1, maxLength: 1000, description: 最终客户目的地完整地址;国内采购发海外时填写海外地址 }
contactName: { type: string, maxLength: 128 }
contactPhone: { type: string, maxLength: 64 }
remark: { type: string, nullable: true, maxLength: 1000 }
@@ -7683,6 +7695,7 @@ components:
nullable: true
DispatchFeeItem:
type: object
description: 派送应付费用。客户应收费用统一到海外费用登记并审核,派送完成不自动生成应收。
x-java-record: DispatchDeliveryModels.FeeItem
properties:
feeType:
@@ -7693,6 +7706,7 @@ components:
nullable: true
direction:
type: string
enum: [PAYABLE]
nullable: true
currency:
type: string
@@ -0,0 +1,21 @@
openapi: 3.0.3
info: { title: 海外录费公共费用项目, version: 1.0.0 }
security: [{ bearerAuth: [] }]
paths:
/api/platform/v1/last-leg/finance-fee-sources/fee-items:
get:
summary: 按收付方向选择当前启用的海外费用项目
description: '仅平台主体;需要platform:overseas-fee:list或platform:finance:customer-arap:list。复用Firstleg目录,不建立独立目录。录费时重新校验当前编码和名称。'
parameters:
- name: direction
in: query
required: false
schema: { type: string, enum: [RECEIVABLE, PAYABLE], default: RECEIVABLE }
responses:
'400': { description: 收付方向无效 }
'200': { description: '统一响应data为数组;每项code、name、defaultPrice。默认价仅CNY,USD录费不得直接套用。' }
'403': { description: 身份或查询权限不满足 }
'409': { description: 费用目录未就绪或响应无效 }
components:
securitySchemes:
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
@@ -1,6 +1,13 @@
openapi: 3.0.3
info: { title: Overseas Business Fee Source API, version: 1.0.0 }
info: { title: Overseas Business Fee Source API, version: 1.1.0, description: '首版除仓租外均人工登记审核;换标报价、外接运费及拆柜成本不自动收费;旧资金链同项目已锁款或收取时拒绝重复登记。' }
paths:
/api/platform/v1/last-leg/finance-fee-sources/{sourceFeeId}/retries:
get:
summary: 查询该费用每次人工重试的时间、操作人和实际结果
description: 与费用详情使用相同列表权限。按客户及稳定费用身份隔离,包含各版本的推送重试和资金重试。SUCCESS依据投递接收或实际资金成功回执;FAILED保留失败原因;SUBMITTED只代表请求已提交。多次重试分别保留,后一次成功不覆盖前一次失败。
security: [{ bearerAuth: [] }]
parameters: [{ in: path, name: sourceFeeId, required: true, schema: { type: string } }]
responses: { '200': { description: 'data为RetryRecord数组,按重试时间倒序' } }
/api/platform/v1/last-leg/finance-fee-sources:
get:
summary: 查询海外业务费用来源当前版本
@@ -12,12 +19,56 @@ paths:
- { in: query, name: containerBookingId, description: 精确查询真实来源柜下全部客户的费用;可再传customerId收窄到单个客户, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
responses: { '200': { description: '当前版本列表;voidStatus为NOT_REQUESTED、PENDING_FINANCE、FINANCE_ATTENTION或CONFIRMED,批量查询作废确认状态,不逐行读取。等待或拒绝时sourceStatus保留ACTIVE,只有Finance持久化确认后为VOIDED。' } }
post:
summary: 创建海外业务费用来源草稿
description: 采购费用仅由采购履约或财务节点实扣后自动发布,本入口拒绝采购来源或采购业务类型。客户和业务编号必填;入仓ID、入仓码均按业务事实选填,不得为补字段伪造。海外货柜费用必须以相同的businessId和containerBookingId引用真实来源柜,且businessNo与containerNo均为该柜真实集装箱号。
summary: 创建人工费用并锁定资金
description: 需platform:finance:fee-source:edit。创建即PENDING。应收仅当前LASTLEG_ORDER且orderType=FIRST_LEG采用BILL,其余业务(含ONE_CLICK_DROPSHIP、退货、转运、柜级费用)为WALLET,发送异步FREEZE,本土卡车、本土散板应收同采购一样使用客户余额及授信扣款;余额及授信不足显示FREEZE_FAILED,不可审核通过。原USD按业务月有效汇率固化为CNY后冻结;原币与汇率快照保留。采购来源仍只允许采购业务节点处理。业务ID、客户、单号与补充订单/入仓关联由服务端核对;真实柜要求businessId=containerBookingId且businessNo=containerNo。调用重放不重复冻结。
security: [{ bearerAuth: [] }]
parameters: [{ in: header, name: Idempotency-Key, required: true, schema: { type: string, maxLength: 128 } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/SaveRequest' } } } }
responses: { '200': { description: 草稿费用来源 }, '400': { description: 业务归属或付款事实无效 } }
responses: { '200': { description: 待审核费用,含collectionMode、walletStatus、allowedActions }, '400': { description: 业务归属或付款事实无效 } }
/api/platform/v1/last-leg/finance-fee-sources/page:
get:
summary: 分页查询海外费用
description: 需platform:overseas-fee:list或platform:finance:customer-arap:list。只返回各稳定来源最新版本,按创建时间及ID倒序;应收是默认方向。资金状态批量加载。
security: [{ bearerAuth: [] }]
parameters:
- { in: query, name: page, schema: { type: integer, minimum: 1, default: 1 } }
- { in: query, name: size, schema: { type: integer, minimum: 1, maximum: 200, default: 20 } }
- { in: query, name: customerId, schema: { type: string } }
- { in: query, name: businessType, schema: { $ref: '#/components/schemas/BusinessType' } }
- { in: query, name: businessNo, schema: { type: string } }
- { in: query, name: feeItemCode, schema: { type: string } }
- { in: query, name: storageRentOnly, description: 只查询已实际出库生成的仓租费用,分页总数使用相同口径, schema: { type: boolean, default: false } }
- { in: query, name: reviewStatus, schema: { type: string, enum: [DRAFT, PENDING, APPROVED, REJECTED] } }
- { in: query, name: walletStatus, schema: { type: string } }
- { in: query, name: processingStatus, description: 业务费用状态,按当前版本事件及资金状态统一筛选并统计分页, schema: { type: string, enum: [WAITING, PROCESSING, COMPLETED, FAILED, CLOSED] } }
- { in: query, name: direction, schema: { type: string, enum: [RECEIVABLE, PAYABLE], default: RECEIVABLE } }
responses:
'200':
description: data为PageResult,包含records、page、size、total、pages
/api/platform/v1/last-leg/finance-fee-sources/{sourceFeeId}:
get:
summary: 费用详情及服务端可执行动作
security: [{ bearerAuth: [] }]
parameters: [{ in: path, name: sourceFeeId, required: true, schema: { type: string } }]
responses: { '200': { description: 当前费用及资金、审核、作废确认状态 }, '404': { description: 费用不存在 } }
/api/platform/v1/last-leg/finance-fee-sources/customer-options:
get:
summary: 查询已有海外业务或费用的客户候选
security: [{ bearerAuth: [] }]
responses: { '200': { description: data为ContainerCustomerOption数组 } }
/api/platform/v1/last-leg/finance-fee-sources/business-options:
get:
summary: 查询真实服务业务单候选
description: 只查Lastleg自有实体,每次最多50条;LASTLEG_ORDER保留真实orderType,区分FIRST_LEG与ONE_CLICK_DROPSHIP等业务。
security: [{ bearerAuth: [] }]
parameters:
- { in: query, name: businessType, required: true, schema: { type: string, enum: [LASTLEG_ORDER, RELABEL_ORDER, WAREHOUSE_TRANSFER, RETURN_ORDER, US_TRUCK, LOCAL_LOOSEBOARD, DISCARD_ORDER, OVERSEAS_INBOUND, DELIVERY_ORDER] } }
- { in: query, name: customerId, schema: { type: string } }
- { in: query, name: keyword, schema: { type: string } }
responses:
'200':
description: 真实订单候选
content: { application/json: { schema: { type: object, properties: { data: { type: array, items: { $ref: '#/components/schemas/BusinessOption' } } } } } }
/api/platform/v1/last-leg/finance-fee-sources/container-customers:
get:
summary: 查询真实来源柜内客户选项
@@ -33,16 +84,132 @@ paths:
schema: { $ref: '#/components/schemas/ContainerCustomerListResponse' }
/api/platform/v1/last-leg/finance-fee-sources/{sourceFeeId}/{action}:
post:
summary: 提交、审核、调整或作废海外业务费用来源
description: 采购来源不接受通用提交、审核、调整或作废,须回到采购财务节点处理。审核通过与作废均事务性写入Outbox;此处作废仅指申请,直接可靠投递至独立Finance;action为submit、review、adjust、void。作废申请不立即更改sourceStatus,voidStatus为PENDING_FINANCE;等待原发布成功后才投递作废,收到匹配APPLIED/DUPLICATE确认时在投递审计事务内更新VOIDED。失败/结果未知仍保留原来源,拒绝或投递耗尽显示FINANCE_ATTENTION,禁止未决作废期间调整版本。
summary: 提交、审核、调整、作废或处理资金
x-headleg-delivery-review: 首版头程派送费由审核员核对原报价是否已包含;当前未实现自动识别。已含费用不应再建单或通过审核,另收费用人工添加后审核进入头程账单。
description: 编辑动作需platform:finance:fee-source:edit,review与void需platform:finance:fee-source:review。WALLET通过审核只发送SETTLE,实际匹配成功回执含冻结与账本引用后才PUBLISHED,此时仅本地费用完成、不推送财务账单;失败为SETTLE_FAILED,保持未收。驳回释放冻结,冻结在途时回执成功后自动释放。驳回后的费用只读,不能继续操作;如需重新收费应在业务单据中新增费用。头程BILL审核通过推送结算;已发布BILL作废等待Finance持久化确认才VOIDED。历史无资金记录的海外费用必须重新提交完成冻结,不允许审核绕过。采购来源仍由采购节点处理。
security: [{ bearerAuth: [] }]
parameters:
- { in: path, name: sourceFeeId, required: true, schema: { type: string } }
- { in: path, name: action, required: true, schema: { type: string, enum: [submit, review, adjust, void] } }
- { in: path, name: action, required: true, schema: { type: string, enum: [submit, review, adjust, void, retry-funding, retry-delivery] } }
requestBody:
required: true
content:
application/json:
schema:
description: 请求格式随路径action选择;submit、cancel、retry-funding用ActionRequest,其他动作使用同名请求。
anyOf:
- { $ref: '#/components/schemas/ActionRequest' }
- { $ref: '#/components/schemas/ReviewRequest' }
- { $ref: '#/components/schemas/AdjustRequest' }
- { $ref: '#/components/schemas/VoidRequest' }
- { $ref: '#/components/schemas/RetryDeliveryRequest' }
examples:
review: { value: { decision: APPROVE, idempotencyKey: review-unique-key } }
funding: { value: { idempotencyKey: retry-unique-key } }
responses: { '200': { description: 当前费用来源版本 }, '409': { description: 状态、版本或幂等冲突 } }
components:
schemas:
BusinessType: { type: string, enum: [OVERSEAS_INBOUND, OVERSEAS_PROCUREMENT, PROCUREMENT_FEE, US_TRUCK, LOCAL_LOOSEBOARD, WAREHOUSE_SERVICE, OVERSEAS_CONTAINER, LASTLEG_ORDER, DELIVERY_ORDER, RELABEL_ORDER] }
RetryRecord:
type: object
properties:
requestId: { type: string }
requestedAt: { type: string, format: date-time, description: 系统 UTC 时间,明确携带 Z 时区 }
operatorName: { type: string, description: 认证操作人名称及ID,非客户端提交 }
action: { type: string }
result: { type: string, enum: [SUBMITTED, SUCCESS, FAILED] }
errorMessage: { type: string, nullable: true }
RetryDeliveryRequest:
type: object
description: 需platform:finance:fee-source:edit。可重试当前费用对应的DEAD事件或已有失败原因的PENDING事件,校验费用版本、原事件ID及载荷摘要;沿用原事件及资金幂等身份,不创建费用或资金指令。同一请求UUID重复提交仅返回原操作,跨费用或事件复用拒绝。无失败原因的PENDING、PROCESSING和PUBLISHED不可新发起人工重试;每次重试失败后可再次提交新的请求UUID继续重推。写入既有event_delivery_retry_audit审计。
required: [expectedVersion, eventId, idempotencyKey]
properties:
expectedVersion: { type: integer, minimum: 1 }
eventId: { type: string, maxLength: 64 }
idempotencyKey: { type: string, format: uuid }
ActionRequest:
type: object
description: submit、cancel、retry-funding共用;标识需按费用及单次操作生成,重试原操作沿用。
required: [idempotencyKey]
properties:
idempotencyKey: { type: string, minLength: 1, maxLength: 128 }
ReviewRequest:
type: object
required: [decision, idempotencyKey]
properties:
decision: { type: string, enum: [APPROVE, REJECT] }
expectedVersion: { type: integer, minimum: 1, description: 仓租审核必填,必须为审核人看到的当前费用版本;调价后旧版审核被拒绝。 }
reason: { type: string, maxLength: 500, nullable: true }
idempotencyKey: { type: string, minLength: 1, maxLength: 128 }
AdjustRequest:
type: object
required: [expectedVersion, fee, idempotencyKey]
properties:
expectedVersion: { type: integer, minimum: 1 }
fee: { $ref: '#/components/schemas/SaveRequest' }
idempotencyKey: { type: string, minLength: 1, maxLength: 128 }
VoidRequest:
type: object
required: [expectedVersion, reason, idempotencyKey]
properties:
expectedVersion: { type: integer, minimum: 1 }
reason: { type: string, minLength: 1, maxLength: 500 }
idempotencyKey: { type: string, minLength: 1, maxLength: 128 }
BusinessType: { type: string, enum: [OVERSEAS_INBOUND, OVERSEAS_PROCUREMENT, PROCUREMENT_FEE, US_TRUCK, LOCAL_LOOSEBOARD, WAREHOUSE_SERVICE, OVERSEAS_CONTAINER, LASTLEG_ORDER, DELIVERY_ORDER, RELABEL_ORDER, WAREHOUSE_TRANSFER, RETURN_ORDER, DISCARD_ORDER] }
BusinessOption:
type: object
properties:
businessId: { type: string }
businessType: { $ref: '#/components/schemas/BusinessType' }
businessNo: { type: string }
customerId: { type: string }
customerName: { type: string, nullable: true, description: 查询显示按客户ID读取IAM当前名称;主档不可用时回退历史名称,查询不回写费用或结算快照。 }
warehouseId: { type: string, nullable: true }
orderId: { type: string, nullable: true }
orderType: { type: string, nullable: true }
FundingDescription:
type: object
description: 海外费用来源返回值的资金补充字段。amount及currency始终为CNY结算快照;originalAmount、originalCurrency、exchangeRate、exchangeRateMonth保留原币依据。
properties:
displayBusinessType:
allOf: [{ $ref: '#/components/schemas/BusinessType' }]
readOnly: true
description: 按真实业务事实解析的展示分类;分页业务类型筛选使用此分类。换标履约费用显示RELABEL_ORDER,原businessType/businessId保留收费凭据的关联身份。新登记换标履约费用以真实换标申请作为主业务关联。
storageRent:
type: object
nullable: true
readOnly: true
description: 自动仓租的原始计费与实际出入库明细;审核前可通过仓租adjust入口留说明调价。chargedAmount仅成功实扣或确认零元后返回。
properties:
outboundNo: {type: string}
outboundAt: {type: string, format: date-time}
calculatedAmount: {type: number, description: 原快照计算金额,币种为originalCurrency}
chargedAmount: {type: number, nullable: true, description: 实际扣费CNY,未成功时为null}
lines:
type: array
items:
type: object
properties:
lotId: {type: string}
sourceBusinessType: {type: string, nullable: true, description: 原计租入库来源类型,头程为LASTLEG_ORDER,退货为RETURN_ORDER}
sourceBusinessNo: {type: string, nullable: true, description: 原计租来源单号,头程展示对应尾程订单号,退货展示退货单号;不以换标出库单替代}
batchNo: {type: string, nullable: true, description: 原计租入库批次}
inboundAt: {type: string, format: date-time}
quantity: {type: number}
days: {type: integer}
calculatedAmount: {type: number, description: 本原批次原币计费依据}
collectionMode: { type: string, enum: [BILL, WALLET] }
walletStatus: { type: string, enum: [NOT_REQUIRED, FREEZE_PENDING, FROZEN, FREEZE_FAILED, SETTLE_PENDING, SETTLED, SETTLE_FAILED, RELEASE_PENDING, RELEASED, RELEASE_FAILED] }
walletErrorMessage: { type: string, nullable: true }
deliveryStatus: { type: string, nullable: true, enum: [PENDING, PROCESSING, PUBLISHED, DEAD], description: 当前版本原事件的实际投递状态;账单费用publicationStatus=PUBLISHED仅表示已入队,不代表Finance已接收;余额应收实扣成功即完成且deliveryStatus为空。 }
deliveryKind: { type: string, nullable: true, enum: [FEE, FUNDING] }
deliveryEventId: { type: string, nullable: true, description: 当前原事件ID,重试时必须原样提交 }
deliveryErrorMessage: { type: string, nullable: true }
allowedActions: { type: array, items: { type: string, enum: [SUBMIT, APPROVE, REJECT, ADJUST, ADJUST_RENT, VOID, RETRY_FREEZE, RETRY_SETTLE, RETRY_RELEASE, RETRY_PUBLISH, RETRY_FUNDING_DELIVERY] } }
reviewerId: { type: string, nullable: true, description: 审核人ID }
reviewerName: { type: string, nullable: true, description: 审核人名称快照 }
reviewedAt: { type: string, format: date-time, nullable: true, description: 审核时间,UTC 且携带 Z 时区 }
createdAt: { type: string, format: date-time, nullable: true, description: 创建时间,UTC 且携带 Z 时区 }
updatedAt: { type: string, format: date-time, nullable: true, description: 更新时间,UTC 且携带 Z 时区 }
OverseasContainerFeeItem:
type: string
description: 海外阶段柜级费用项目:港口费、堆存费、修箱费、吊机费、码头拖车费、其他。
@@ -67,12 +234,12 @@ components:
timestamp: { type: string, format: date-time }
SaveRequest:
type: object
required: [customerId, sourceType, businessType, businessNo, feeItemCode, feeItemName, direction, businessDate, currency, amount]
required: [customerId, sourceType, businessType, businessId, businessNo, feeItemCode, feeItemName, direction, businessDate, currency, amount]
properties:
customerId: { type: string }
sourceType: { type: string, enum: [OVERSEAS_INBOUND_FEE, OVERSEAS_TRUCK_FEE, OVERSEAS_LOOSEBOARD_FEE, OVERSEAS_WAREHOUSE_FEE, OVERSEAS_CONTAINER_FEE, OVERSEAS_ORDER_FEE, OVERSEAS_DELIVERY_FEE, OVERSEAS_RELABEL_FEE] }
businessType: { type: string, enum: [OVERSEAS_INBOUND, US_TRUCK, LOCAL_LOOSEBOARD, WAREHOUSE_SERVICE, OVERSEAS_CONTAINER, LASTLEG_ORDER, DELIVERY_ORDER, RELABEL_ORDER] }
businessId: { type: string, pattern: '^[1-9][0-9]*$', nullable: true }
businessType: { type: string, enum: [OVERSEAS_INBOUND, US_TRUCK, LOCAL_LOOSEBOARD, OVERSEAS_CONTAINER, LASTLEG_ORDER, DELIVERY_ORDER, RELABEL_ORDER, WAREHOUSE_TRANSFER, RETURN_ORDER, DISCARD_ORDER] }
businessId: { type: string, pattern: '^[1-9][0-9]*$' }
businessNo: { type: string, maxLength: 128 }
containerBookingId: { type: string, pattern: '^[1-9][0-9]*$', nullable: true }
containerNo: { type: string, maxLength: 64, nullable: true }
@@ -81,8 +248,9 @@ components:
inboundCode: { type: string, maxLength: 64, nullable: true }
feeItemCode:
type: string
description: OVERSEAS_CONTAINER时必须取OverseasContainerFeeItem枚举;其他业务类型沿用各自费用项目编码。
description: 必须选择共享费用目录的有效编码,人工录费禁止自动仓租项目FEE_TYPE_077。OVERSEAS_CONTAINER时同时符合OverseasContainerFeeItem枚举。
feeItemName: { type: string }
feeRemark: { type: string, maxLength: 500, nullable: true, description: 费用说明;同单同方向已有相同项目时必填,允许实际作业分次收费。已驳回原费用终结,只能重新新增。 }
direction: { type: string, enum: [RECEIVABLE, PAYABLE] }
businessDate: { type: string, format: date }
currency: { type: string, enum: [CNY, USD], description: 业务原币;USD由服务端按业务月份有效汇率折算为CNY入池 }
@@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: 采购样品履约节点 API
version: 1.0.0
description: 客户范围、节点资格、版本与幂等由服务端校验;购买事实与资金结果分开保存。
description: 客户范围、节点资格、版本与幂等由服务端校验;购买事实与资金结果分开保存。采购双方向复用两段技术编码:OVERSEAS 为起运段,DOMESTIC 为目的地段;按 procurementDirection 解释实际区域。
security:
- bearerAuth: []
paths:
@@ -2310,7 +2310,6 @@ components:
maxLength: 500
ChargeSelection:
type: object
required: []
properties:
feeId:
type: string
@@ -2977,6 +2976,8 @@ components:
- status
- version
properties:
procurementDirection:
$ref: 'overseas-business-v1.yaml#/components/schemas/ProcurementDirection'
orderNo:
type: string
nullable: true
@@ -0,0 +1,227 @@
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}