feat(finance): add container settlement aggregate

This commit is contained in:
2026-09-08 21:03:47 +08:00
parent fc079fcdc0
commit 2e2ca3bef4
11 changed files with 596 additions and 1 deletions
@@ -0,0 +1,109 @@
openapi: 3.0.3
info:
title: Finance Container Settlement Query API
version: 1.0.0
description: 柜级已结算费用来源与成本分摊的固定请求量只读聚合契约。
servers:
- url: /api
paths:
/platform/finance/v1/container-settlement-details:
get:
summary: 按客户和柜次查询已结算柜费及成本分摊
description: >-
customerId 与 containerId 必须在 Finance 的费用来源或成本快照中存在归属关系。
服务端固定执行三条集合 SQL,不按结算单或成本逐项查询;响应不包含整张结算单、
其他客户数据、付款凭证或内部备注。
x-permissions-all-of:
- platform:finance:cost:view
- platform:finance:settlement-ar:list
- platform:finance:settlement-ap:list
x-query-count: 3 fixed set-based SQL statements
security:
- bearerAuth: []
parameters:
- name: customerId
in: query
required: true
schema: {$ref: '#/components/schemas/Id'}
- name: containerId
in: query
required: true
description: Firstleg 装柜计划 ID。
schema: {$ref: '#/components/schemas/Id'}
responses:
'200':
description: 柜级财务聚合结果。
content:
application/json:
schema: {$ref: '#/components/schemas/ContainerSettlementDetailsEnvelope'}
'403': {description: 权限不足。}
'404': {description: 柜次不存在或不属于客户。}
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
schemas:
Id:
type: string
pattern: '^[1-9][0-9]*$'
Money:
type: number
format: decimal
minimum: 0
ContainerSettlementDetailsEnvelope:
type: object
required: [code, message, data, timestamp]
properties:
code: {type: string, example: '200'}
message: {type: string, example: success}
data: {$ref: '#/components/schemas/ContainerSettlementDetails'}
requestId: {type: string}
traceId: {type: string}
timestamp: {type: string, format: date-time}
ContainerSettlementDetails:
type: object
required: [customerId, containerId, settledSourceFeeIds, costs]
properties:
customerId: {$ref: '#/components/schemas/Id'}
containerId: {$ref: '#/components/schemas/Id'}
settledSourceFeeIds:
type: array
uniqueItems: true
items: {$ref: '#/components/schemas/Id'}
costs:
type: array
items: {$ref: '#/components/schemas/ContainerCostDetail'}
ContainerCostDetail:
type: object
required: [costId, costNo, costType, costOrigin, containerId, feeItemName, amount, currency, status, allocations]
properties:
costId: {$ref: '#/components/schemas/Id'}
costNo: {type: string}
costType: {type: string, enum: [SINGLE_ORDER, CONTAINER_SHARED, SOURCE_DIRECT_PAID]}
costOrigin: {type: string, enum: [MANUAL, FIRSTLEG_DIRECT_PAID, BUSINESS_DIRECT_PAID]}
sourceFeeId: {$ref: '#/components/schemas/Id'}
sourceFeeVersion: {type: integer, minimum: 1}
containerId: {$ref: '#/components/schemas/Id'}
supplierName: {type: string, nullable: true}
feeItemName: {type: string}
amount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string, enum: [DRAFT, CONFIRMED, VOIDED]}
allocations:
type: array
items: {$ref: '#/components/schemas/ContainerCostAllocation'}
ContainerCostAllocation:
type: object
required: [allocationId, orderId, volumeCbm, totalVolumeCbm, allocationRate, allocatedAmount, roundingAdjustment]
properties:
allocationId: {$ref: '#/components/schemas/Id'}
orderId: {$ref: '#/components/schemas/Id'}
inboundId:
allOf: [{$ref: '#/components/schemas/Id'}]
nullable: true
volumeCbm: {$ref: '#/components/schemas/Money'}
totalVolumeCbm: {$ref: '#/components/schemas/Money'}
allocationRate: {type: number, format: decimal, minimum: 0, maximum: 1}
allocatedAmount: {$ref: '#/components/schemas/Money'}
roundingAdjustment: {type: boolean}