Files
docs/财务管理/openapi/finance-phase1-five-pages-v1.yaml
T

1724 lines
77 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: Finance Phase 1 Five-page Acceptance API
version: 1.0.0-draft
description: >-
一期领导验收 5 页目标契约:客户账户、客户应收应付、客户对账单、结算单应收、
结算单应付。只支持 CNY。费用分析、利润表、钱包、预收和充值不属于本契约。
本文件冻结一期目标契约及后续确认的费用编辑审核、客户确认和应收统计扩展。实现与
Admin 接入证据单独维护在财务一期P0实现证据矩阵.md,不得因代码文件出现反复修改本契约。
servers:
- url: /api
x-product-scope:
included:
- CUSTOMER_ACCOUNT_DERIVED_VIEW
- CUSTOMER_ARAP_FEE_SOURCE_POOL
- CUSTOMER_RECONCILIATION_STATEMENT
- RECEIVABLE_SETTLEMENT
- PAYABLE_SETTLEMENT
excluded:
- WALLET
- PREPAYMENT
- MANUAL_RECHARGE
- COST_ANALYSIS
- PROFIT_REPORT
- FOREIGN_CURRENCY
- EXCHANGE_RATE
x-source-gate:
eligible: APPROVED + PUBLISHED + AVAILABLE + CNY + amount>0
currentStatus: 审核通过后自动发布并进入结算候选;Finance 不再维护人工“是否结算”开关,并继续校验客户、版本、方向和来源归属。
x-payable-cost-contract:
settlementModes: [ON_ACCOUNT, DIRECT_PAID]
paymentMethods: [ONLINE, BANK_TRANSFER, CASH, OTHER]
onAccount: 可进入正式 PAYABLE settlement;paidAt/paymentMethod/paymentReferenceNo/paymentVoucherFileIds 必须为空
directPaid: 必填 paidAt/paymentMethod,paymentReferenceNo 与 paymentVoucherFileIds 至少一项;只计成本,禁止进入 AP 和 outstandingPayable
totals: 总成本=有效ON_ACCOUNT来源+有效DIRECT_PAID成本事实;待付=正式AP outstanding;已付=AP paid+DIRECT_PAID
uniqueness: DIRECT_PAID 按 sourceSystem+sourceType+sourceFeeId+sourceVersion 唯一物化到 fin_cost,禁止与来源重复累计
x-phase1-p0-contract:
status: FROZEN
rule: 所有已列 operation 均为当前目标契约;实现状态不得写入本文件。
contract: ../财务一期P0操作契约与验收用例.md
evidenceMatrix: ../财务一期P0实现证据矩阵.md
x-idempotency-contract:
scope: method + normalizedPath + resolvedCustomerId + completeQueryAndBody
sameKeySameRequest: replay original result
sameKeyDifferentRequest: FIN_409
processing: FIN_409;超时后按现有 Finance 抢占恢复规则执行
failed: 按现有 Finance FAILED 恢复规则执行
x-error-contract:
FIN_400: 参数、日期、CNY 或正金额校验失败
FIN_404: 对象不存在或跨客户对象隐藏
FIN_409: 非法状态、乐观锁、重复占用或幂等冲突
FIN_503: File 或内部依赖不可用且 fail-closed
FIN_001: 未分类服务端错误
authentication: HTTP 401
permission: HTTP 403
paths:
/internal/finance/v1/fee-source-events:
post:
servers:
- url: /
operationId: consumeFirstlegFeeSourceEvent
summary: 消费 Firstleg 不可变费用来源事件
description: >-
使用内部服务令牌鉴权;按 eventId 和完整事件请求哈希幂等消费,回查 Firstleg
入库或柜子费用快照,校验客户、版本、审核、发布、CNY、方向和来源类型后,
写入 fin_inbox_event 与 fin_fee_source。调整新增版本并替代旧 AVAILABLE 版本,作废只改状态不删除历史。
x-authentication: X-Internal-Service-Token
x-error-codes:
- FIN-EVT-001
- FIN-EVT-002
- FIN-EVT-003
- FIN-EVT-004
- FIN-EVT-005
- FIN-EVT-006
- FIN-EVT-007
- FIN-EVT-008
- FIN-EVT-009
- FIN-EVT-010
- FIN-EVT-011
- FIN-EVT-012
- FIN-EVT-013
- FIN-EVT-014
- FIN-EVT-015
- FIN-EVT-401
parameters:
- $ref: '#/components/parameters/InternalServiceToken'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/FinanceFeeSourceEvent'}
responses:
'200':
description: 成功消费、同参重放结果或稳定业务错误。
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/FeeSourceEventResultEnvelope'
- $ref: '#/components/schemas/ErrorEnvelope'
/internal/exports/v1/{exportType}/batches:
post:
servers:
- url: /
operationId: provideFinanceExportBatch
summary: 向 File 下载中心提供 Finance 导出批次
description: >-
仅供 File Service 使用;按任务、申请人、完整筛选参数签名并校验 snapshotToken。
exportType 固定业务方向,参数不得包含 page、pageSize 或 direction(费用来源列表除外)。
x-authentication: X-Internal-Service-Token
parameters:
- $ref: '#/components/parameters/InternalServiceToken'
- name: exportType
in: path
required: true
schema:
type: string
enum:
- FINANCE_CUSTOMER_ACCOUNT_LIST
- FINANCE_CUSTOMER_ACCOUNT_LEDGER
- FINANCE_FEE_SOURCE_LIST
- FINANCE_RECONCILIATION_STATEMENT_LIST
- FINANCE_RECEIVABLE_SETTLEMENT_LIST
- FINANCE_RECEIVABLE_SETTLEMENT_DETAIL
- FINANCE_PAYABLE_SETTLEMENT_LIST
- FINANCE_PAYABLE_SETTLEMENT_DETAIL
- FINANCE_RECEIVABLE_STATISTICS
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/FinanceExportBatchRequest'}
responses:
'200':
description: 版本化导出批次;首批返回 columns、totalRows 和 snapshotToken。
content:
application/json:
schema: {$ref: '#/components/schemas/FinanceExportBatchEnvelope'}
'403': {description: 内部服务令牌无效。}
/platform/finance/v1/accounts:
get:
operationId: listDerivedCustomerAccounts
summary: 查询客户财务账户派生汇总
description: 只读聚合,不返回钱包余额,不提供充值或余额调整动作。
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: AccountListQuery
x-response-dto: AccountPageEnvelope
x-idempotency: READ_ONLY_NOT_APPLICABLE
x-customer-isolation: 平台权限下按真实客户主体聚合;不得返回 tenantId,不得产生可写余额。
x-state-machine: READ_ONLY_DERIVED_VIEW
x-error-codes: [FIN_400, FIN_001]
x-acceptance-cases: [AC-01, AC-02]
x-permission: platform:finance:customer-account:list
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PageSize'
- name: customerName
in: query
description: 按客户名称模糊查询,不支持客户编号或联系人搜索。
schema: {type: string}
- name: status
in: query
schema: {type: string, enum: [ACTIVE, DISABLED]}
responses:
'200': {$ref: '#/components/responses/AccountPageResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/customer-accounts/{customerId}:
get:
operationId: getDerivedCustomerAccount
summary: 查询客户财务账户详情
x-permission: platform:finance:customer-account:list
parameters:
- $ref: '#/components/parameters/CustomerId'
responses:
'200': {$ref: '#/components/responses/CustomerAccountReadResponse'}
'404': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/customer-accounts/{customerId}/summary:
get:
operationId: getCustomerAccountSummary
summary: 查询客户正式结算口径财务汇总
description: >-
固定 CNY。累计应收、已收和未结清仅聚合本客户非 VOIDED 的正式 RECEIVABLE
fin_settlement;待出账仅聚合合格且尚未进入非 VOIDED 对账单的应收费用来源;
未结应付仅聚合本客户非 VOIDED 的正式 PAYABLE fin_settlement。
x-permission: platform:finance:customer-account:list
x-customer-isolation: 所有聚合子查询都必须使用 customerId 约束,空客户返回零值。
parameters:
- $ref: '#/components/parameters/CustomerId'
responses:
'200': {$ref: '#/components/responses/CustomerAccountSummaryResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/accounts/{customerId}/ledger:
get:
operationId: listDerivedCustomerAccountLedger
summary: 查询客户财务派生流水
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: AccountLedgerQuery
x-response-dto: LedgerPageEnvelope
x-idempotency: READ_ONLY_NOT_APPLICABLE
x-customer-isolation: customerId 必须解析为真实客户,流水只聚合该客户数据;跨客户对象不得出现。
x-state-machine: READ_ONLY_DERIVED_VIEW
x-error-codes: [FIN_400, FIN_404, FIN_001]
x-acceptance-cases: [AC-03, AC-04]
x-permission: platform:finance:customer-account:list
parameters:
- $ref: '#/components/parameters/CustomerId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PageSize'
- name: businessType
in: query
schema: {$ref: '#/components/schemas/LedgerBusinessType'}
- name: startDate
in: query
schema: {type: string, format: date}
- name: endDate
in: query
schema: {type: string, format: date}
responses:
'200': {$ref: '#/components/responses/LedgerPageResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-sources:
get:
operationId: listFinanceFeeSources
summary: 分页查询客户应收应付费用来源
x-permission: platform:finance:customer-arap:list
parameters:
- name: page
in: query
schema: {type: integer, minimum: 1, default: 1}
- name: pageSize
in: query
schema: {type: integer, minimum: 1, maximum: 200, default: 20}
- name: customerId
in: query
schema: {$ref: '#/components/schemas/Id'}
- name: direction
in: query
schema: {$ref: '#/components/schemas/FeeDirection'}
- name: status
in: query
schema: {type: string, enum: [AVAILABLE, LOCKED, BILLED, VOIDED, SUPERSEDED]}
- name: reviewStatus
in: query
schema: {$ref: '#/components/schemas/ReviewStatus'}
- name: statementGenerated
in: query
schema: {type: boolean}
- name: businessDateFrom
in: query
schema: {type: string, format: date}
- name: businessDateTo
in: query
schema: {type: string, format: date}
- name: keyword
in: query
schema: {type: string, maxLength: 200}
responses:
'200': {$ref: '#/components/responses/FeeSourcePageResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-pool:
get:
operationId: listLegacyFinanceFeePool
summary: 查询旧版费用池(非五页事实源)
deprecated: true
x-permission: platform:finance:customer-arap:list
parameters:
- name: customerId
in: query
schema: {$ref: '#/components/schemas/Id'}
- name: direction
in: query
schema: {$ref: '#/components/schemas/FeeDirection'}
responses:
'200': {$ref: '#/components/responses/FeePoolReadResponse'}
/platform/finance/v1/fee-sources/{feeSourceId}:
get:
operationId: getFinanceFeeSource
summary: 查询费用来源详情、业务关联和操作记录
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: FeeSourceIdPath
x-response-dto: FeeSourceDetailEnvelope
x-idempotency: READ_ONLY_NOT_APPLICABLE
x-customer-isolation: 按费用来源真实 customerId 返回;跨客户关联按 FIN_404 隐藏。
x-state-machine: READ_ONLY_ALL_SOURCE_STATES
x-error-codes: [FIN_404, FIN_001]
x-acceptance-cases: [AC-05]
x-permission: platform:finance:customer-arap:list
parameters:
- $ref: '#/components/parameters/FeeSourceId'
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
put:
operationId: editFinanceFeeSource
summary: 编辑草稿或驳回的费用来源
description: sourceSystem=FIRSTLEG 时拒绝本地金额编辑,必须回入库费用或柜次费用业务明细修改并由 Firstleg 发布新版本。
x-permission: platform:finance:fee-source:edit
parameters:
- $ref: '#/components/parameters/FeeSourceId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/FeeSourceEditRequest'}}}
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-sources/{feeSourceId}/review:
post:
operationId: reviewFinanceFeeSource
summary: 审核费用来源
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: ReviewRequest
x-response-dto: FeeSourceDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: 只按 feeSourceId 解析其真实客户;请求不得覆盖 customerId 或金额。
x-state-machine: PENDING -> APPROVED | REJECTED
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_001]
x-acceptance-cases: [AC-06, AC-07, AC-29]
x-permission: platform:finance:fee-source:review
parameters:
- $ref: '#/components/parameters/FeeSourceId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ReviewRequest'}
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-sources/{feeSourceId}/submit:
post:
operationId: submitFinanceFeeSource
summary: 提交费用来源审核
x-permission: platform:finance:fee-source:edit
parameters:
- $ref: '#/components/parameters/FeeSourceId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/FeeSourceActionRequest'}
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-sources/{feeSourceId}/adjust:
post:
operationId: adjustFinanceFeeSource
summary: 将已审核费用调整为新草稿版本
description: sourceSystem=FIRSTLEG 时拒绝本地金额调整,必须由 Firstleg 业务明细形成新版本并发布 FIRSTLEG_FEE_ADJUSTED。
x-permission: platform:finance:fee-source:edit
parameters:
- $ref: '#/components/parameters/FeeSourceId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/FeeSourceEditRequest'}}}
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/fee-sources/{feeSourceId}/void:
post:
operationId: voidFinanceFeeSource
summary: 作废费用来源
description: sourceSystem=FIRSTLEG 时 Finance 仅发起幂等内部命令;Firstleg 原子作废业务费用并发布 FIRSTLEG_FEE_VOIDED,Finance 消费事件后同步本地状态,不执行本地先写或伪造事件。
x-permission: platform:finance:fee-source:edit
parameters:
- $ref: '#/components/parameters/FeeSourceId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/FeeSourceActionRequest'}}}
responses:
'200': {$ref: '#/components/responses/FeeSourceDetailResponse'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/statements:
get:
operationId: listReconciliationStatements
summary: 查询客户对账单
x-permission: platform:finance:customer-statement:list
parameters:
- name: customerId
in: query
required: false
schema: {$ref: '#/components/schemas/Id'}
responses:
'200': {$ref: '#/components/responses/StatementListReadResponse'}
post:
operationId: createReconciliationStatement
summary: 按截止时间或勾选来源生成客户对账单草稿
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: CreateReconciliationRequest
x-response-dto: ReconciliationDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: 所有来源必须属于 request.customerId;跨客户来源按 FIN_404,禁止部分落库。
x-state-machine: 合格且未占用来源 -> DRAFT;创建时锁定所选来源
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_001]
x-acceptance-cases: [AC-10, AC-11, AC-12, AC-29]
x-permission: platform:finance:reconciliation:create
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateReconciliationRequest'}
responses:
'200': {$ref: '#/components/responses/ReconciliationDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/bills/{billId}:
get:
operationId: getReconciliationStatement
summary: 查询客户对账单详情、费用明细和支付历史
x-permission: platform:finance:customer-statement:list
parameters:
- $ref: '#/components/parameters/BillId'
responses:
'200': {$ref: '#/components/responses/StatementDetailReadResponse'}
'404': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/reconciliation-statements/{statementId}/actions:
post:
operationId: actionReconciliationStatement
summary: 提交、审核、出账、调整、作废或重开客户对账单
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: ReconciliationActionRequest
x-response-dto: ReconciliationDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: statementId 决定客户;调整行必须全部属于该对账单,跨客户按 FIN_404。
x-state-machine: DRAFT->PENDING_REVIEW->APPROVED->ISSUED;REJECTED/VOIDED 可 REOPEN 新 revision;ISSUED 仅 ADJUST 新 revision
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_001]
x-acceptance-cases: [AC-13, AC-14, AC-15, AC-16, AC-17, AC-29]
x-permission-by-action:
SUBMIT: platform:finance:reconciliation:create
APPROVE: platform:finance:reconciliation:review
REJECT: platform:finance:reconciliation:review
ISSUE: platform:finance:reconciliation:issue
ADJUST: platform:finance:reconciliation:adjust
VOID: platform:finance:reconciliation:void
REOPEN: platform:finance:reconciliation:void
parameters:
- $ref: '#/components/parameters/StatementId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ReconciliationActionRequest'}
responses:
'200': {$ref: '#/components/responses/ReconciliationDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/receivable-settlements:
get:
operationId: listReceivableSettlements
summary: 查询结算单应收
x-permission: platform:finance:settlement-ar:list
parameters:
- name: customerId
in: query
required: true
schema: {$ref: '#/components/schemas/Id'}
responses:
'200': {$ref: '#/components/responses/ReceivableSettlementListReadResponse'}
post:
operationId: createReceivableSettlement
summary: 从审核通过的客户对账单生成应收结算单
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: CreateReceivableSettlementRequest
x-response-dto: SettlementDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: 客户从对账单派生,不接受前端覆盖;跨客户关联按 FIN_404。
x-state-machine: ISSUED reconciliation -> ISSUED RECEIVABLE settlement;一张对账单只允许一个有效 AR
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_001]
x-acceptance-cases: [AC-18, AC-19, AC-29]
x-permission: platform:finance:settlement-ar:create
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateReceivableSettlementRequest'}
responses:
'200': {$ref: '#/components/responses/SettlementDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/payable-settlements:
get:
operationId: listPayableSettlements
summary: 查询结算单应付
x-permission: platform:finance:settlement-ap:list
parameters:
- name: customerId
in: query
required: true
schema: {$ref: '#/components/schemas/Id'}
responses:
'200': {$ref: '#/components/responses/PayableSettlementListReadResponse'}
post:
operationId: createPayableSettlement
summary: 从审核通过且已发布的应付来源生成应付结算单
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: CreatePayableSettlementRequest
x-response-dto: SettlementDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: 所有 PAYABLE 来源必须同 customerId、同 supplierId;supplierId 必须来自 Warehouse ACTIVE 供应商主数据。费用项目 supplierCategory 非空时必须匹配,空时允许任意 ACTIVE 供应商;跨客户来源按 FIN_404。
x-state-machine: 合格未占用 PAYABLE 来源 -> ISSUED PAYABLE settlement
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_503, FIN_001]
x-acceptance-cases: [AC-20, AC-21, AC-29]
x-permission: platform:finance:settlement-ap:create
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreatePayableSettlementRequest'}
responses:
'200': {$ref: '#/components/responses/SettlementDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/receipts:
get:
operationId: listPlatformReceipts
summary: 平台按客户查询人工收款记录
x-permission: platform:finance:receipt:view
parameters:
- name: customerId
in: query
required: true
schema: {$ref: '#/components/schemas/Id'}
responses:
'200': {$ref: '#/components/responses/PlatformReceiptListReadResponse'}
post:
operationId: createReceiptWithAllocations
summary: 人工登记一笔收款并分配到一张或多张应收结算单
description: >-
收款总额必须等于 allocations 金额之和;所有结算单必须属于同一客户且为 CNY,
每笔分配不得超过对应未收余额。示例:收款 300 元可分配到 3 张结算单各 100 元,
共用同一组收款凭证图片。File 校验失败或不可用时必须 fail-closed,不得落库。
x-permission: platform:finance:receipt:create
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateReceiptRequest'}
responses:
'200': {$ref: '#/components/responses/ResourceResultResponse'}
'409': {$ref: '#/components/responses/BusinessError'}
/client/finance/v1/receipts:
get:
operationId: listClientVisibleReceipts
summary: 客户只读查询已确认收款和账单分配
description: 使用登录客户身份隔离,不接收 customerId;不返回凭证、操作人、内部备注或 tenantId。
x-permission: merchant:finance:statement:view
responses:
'200': {$ref: '#/components/responses/ClientReceiptListReadResponse'}
/client/finance/v1/statements/{statementId}/confirm:
post:
operationId: confirmClientReconciliationStatement
summary: 当前登录客户确认本人已出账对账单
description: 不接收 customerId;客户范围和确认人均取自登录态。重复请求按 Idempotency-Key 幂等处理。
x-permission: merchant:finance:statement:confirm
parameters:
- $ref: '#/components/parameters/StatementId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/CustomerConfirmationRequest'}}}
responses:
'200': {description: 已确认或幂等返回原确认结果}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/receivable-statistics:
get:
operationId: getReceivableStatistics
summary: 按结算单生成月份和客户统计 CNY 应收款
description: 只统计 direction=RECEIVABLE、status!=VOIDED 的 fin_settlement;按客户汇总应收、已收和余额未收。
x-permission: platform:finance:receivable-statistics:list
parameters:
- name: month
in: query
required: true
schema: {type: string, pattern: '^\d{4}-\d{2}$', example: '2026-08'}
- name: customerId
in: query
schema: {$ref: '#/components/schemas/Id'}
- name: page
in: query
schema: {type: integer, minimum: 1, default: 1}
- name: pageSize
in: query
schema: {type: integer, minimum: 1, maximum: 200, default: 20}
responses:
'200': {description: CNY 应收款统计结果}
'400': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/settlements/{settlementId}:
get:
operationId: getSettlement
summary: 查询应收或应付结算单详情
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: SettlementIdPath
x-response-dto: SettlementDetailEnvelope
x-idempotency: READ_ONLY_NOT_APPLICABLE
x-customer-isolation: 按结算单真实客户返回;不得返回其他客户数据,客户侧仍使用独立脱敏接口。
x-state-machine: READ_ONLY_ALL_SETTLEMENT_STATES
x-error-codes: [FIN_404, FIN_001]
x-acceptance-cases: [AC-22, AC-23]
x-permission-any-of:
- platform:finance:settlement-ar:list
- platform:finance:settlement-ap:list
parameters:
- $ref: '#/components/parameters/SettlementId'
responses:
'200': {$ref: '#/components/responses/SettlementDetailResponse'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/settlements/{settlementId}/transactions:
post:
operationId: createSettlementPayment
summary: 人工登记应付结算单付款并上传凭证
x-contract-status: FROZEN
x-delivery-priority: PHASE1_P0
x-request-dto: CreateSettlementPaymentRequest
x-response-dto: SettlementDetailEnvelope
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-customer-isolation: settlementId 决定客户和供应商;凭证必须属于同一客户的 FINANCE_VOUCHER。
x-state-machine: PAYABLE ISSUED -> PARTIALLY_PAID -> PAID;金额不得超过 outstandingAmount
x-error-codes: [FIN_400, FIN_404, FIN_409, FIN_503, FIN_001]
x-acceptance-cases: [AC-24, AC-25, AC-26, AC-29]
x-permission: platform:finance:payment:create
parameters:
- $ref: '#/components/parameters/SettlementId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateSettlementPaymentRequest'}
responses:
'200': {$ref: '#/components/responses/SettlementDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
'503': {$ref: '#/components/responses/BusinessError'}
/platform/finance/v1/settlements/{settlementId}/actions:
post:
operationId: actionSettlement
summary: 作废或重开未发生收付款的结算单
x-contract-status: FROZEN
x-idempotency: FULL_REQUEST_HASH_SAME_REPLAY_DIFFERENT_CONFLICT
x-state-machine: ISSUED -> VOIDED -> ISSUED;paidAmount 必须为 0
x-permission: platform:finance:settlement:void
parameters:
- $ref: '#/components/parameters/SettlementId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/SettlementActionRequest'}
responses:
'200': {$ref: '#/components/responses/SettlementDetailResponse'}
'400': {$ref: '#/components/responses/BusinessError'}
'403': {$ref: '#/components/responses/BusinessError'}
'404': {$ref: '#/components/responses/BusinessError'}
'409': {$ref: '#/components/responses/BusinessError'}
components:
parameters:
InternalServiceToken:
name: X-Internal-Service-Token
in: header
required: true
schema: {type: string, minLength: 1}
CustomerId:
name: customerId
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
FeeSourceId:
name: feeSourceId
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
StatementId:
name: statementId
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
BillId:
name: billId
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
SettlementId:
name: settlementId
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
Page:
name: page
in: query
required: false
schema: {type: integer, minimum: 1, default: 1}
PageSize:
name: pageSize
in: query
required: false
schema: {type: integer, minimum: 1, maximum: 200, default: 20}
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema: {type: string, minLength: 1, maxLength: 128}
description: 完整规范化 method/path/customer/body 哈希;同参重放,异参冲突。
schemas:
FinanceExportBatchRequest:
type: object
required: [taskId, tenantId, appCode, requestedBy, dispatchVersion, parameters, limit]
properties:
taskId: {type: string, pattern: '^[1-9][0-9]*$'}
tenantId: {type: string, enum: ['0']}
appCode: {type: string, enum: [PLATFORM]}
requestedBy: {type: string, pattern: '^[1-9][0-9]*$'}
dispatchVersion: {type: integer, minimum: 1}
parameters:
type: object
description: >-
ACCOUNT_LIST: customerId?, status?;ACCOUNT_LEDGER: customerId, businessType?, startDate?, endDate?;
FEE_SOURCE_LIST: customerId?, direction?, status?, reviewStatus?, statementGenerated?,
businessDateFrom?, businessDateTo?, keyword?;RECONCILIATION_STATEMENT_LIST: customerId?, status?, billNo?,
containerNo?, periodStartFrom?, periodStartTo?, periodEndFrom?, periodEndTo?, settled?, lastPaymentFrom?,
lastPaymentTo?, createdFrom?, createdTo?;AR_LIST: customerId?, status?, settlementNo?;AP_LIST 另含
supplierName?;所有 DETAIL 仅 settlementId。业务 ID 为十进制字符串,日期为 YYYY-MM-DD。
additionalProperties: true
cursor: {type: string, nullable: true, description: 非负十进制偏移量。}
snapshotToken: {type: string, nullable: true, description: 首批为空,后续批次必须原样回传。}
limit: {type: integer, minimum: 1, maximum: 500}
FinanceExportColumn:
type: object
required: [key, title, type]
properties:
key: {type: string}
title: {type: string}
type: {type: string, enum: [STRING, INTEGER, DECIMAL, BOOLEAN, DATE, DATETIME]}
width: {type: integer, nullable: true}
FinanceExportBatch:
type: object
required: [schemaVersion, schemaHash, snapshotToken, columns, rows, nextCursor, hasMore]
properties:
schemaVersion: {type: integer, enum: [1]}
schemaHash: {type: string}
snapshotToken: {type: string}
columns: {type: array, items: {$ref: '#/components/schemas/FinanceExportColumn'}}
rows: {type: array, items: {type: object, additionalProperties: true}}
nextCursor: {type: string}
hasMore: {type: boolean}
totalRows: {type: integer, format: int64, nullable: true}
FinanceExportBatchEnvelope:
type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/FinanceExportBatch'}
Id:
type: string
pattern: '^[1-9][0-9]*$'
FinanceFeeSourceEvent:
type: object
required: [eventId, eventType, eventVersion, producer, occurredAt, tenantId, aggregateType, aggregateId, sequence, idempotencyKey, payloadHash, payload]
properties:
eventId: {type: string, minLength: 1}
eventType:
type: string
enum: [FIRSTLEG_FEE_PUBLISHED, FIRSTLEG_FEE_ADJUSTED, FIRSTLEG_FEE_VOIDED]
eventVersion: {type: integer, minimum: 1}
producer: {type: string, enum: [firstleg-service]}
occurredAt: {type: string, format: date-time}
tenantId: {$ref: '#/components/schemas/Id'}
aggregateType: {type: string, enum: [INBOUND, CONTAINER]}
aggregateId: {$ref: '#/components/schemas/Id'}
sequence: {type: integer, minimum: 1}
idempotencyKey: {type: string, minLength: 1}
payloadHash: {type: string, pattern: '^[a-f0-9]{64}$'}
payload: {$ref: '#/components/schemas/FinanceFeeSourceEventPayload'}
FinanceFeeSourceEventPayload:
type: object
required: [feeId, feeVersion]
properties:
inboundId: {$ref: '#/components/schemas/Id'}
containerId: {$ref: '#/components/schemas/Id'}
feeId: {$ref: '#/components/schemas/Id'}
feeVersion: {type: integer, minimum: 1}
oneOf:
- required: [inboundId]
not: {required: [containerId]}
- required: [containerId]
not: {required: [inboundId]}
FeeSourceEventResult:
type: object
required: [feeSourceId]
properties:
feeSourceId: {type: integer, format: int64, minimum: 1}
Money:
type: string
pattern: '^(0|[1-9][0-9]*)(\.[0-9]{1,6})?$'
PositiveMoney:
type: string
pattern: '^(0\.(?=[0-9]{0,5}[1-9])[0-9]{1,6}|[1-9][0-9]*(\.[0-9]{1,6})?)$'
FeeDirection:
type: string
enum: [RECEIVABLE, PAYABLE]
SettlementMode:
type: string
enum: [ON_ACCOUNT, DIRECT_PAID]
description: 仅 PAYABLE 必填;RECEIVABLE 必须为空
CostPaymentMethod:
type: string
enum: [ONLINE, BANK_TRANSFER, CASH, OTHER]
FeeSourceType:
type: string
minLength: 1
description: 来源系统定义的费用来源类型;Finance 原样保留,当前已知 INBOUND_FEE、CONTAINER_FEE,后续可接入海外仓等来源类型
ReviewStatus:
type: string
enum: [PENDING, APPROVED, REJECTED]
ReconciliationStatus:
type: string
enum: [DRAFT, PENDING_REVIEW, APPROVED, ISSUED, REJECTED, VOIDED]
SettlementStatus:
type: string
enum: [DRAFT, PENDING_REVIEW, ISSUED, PARTIALLY_PAID, PAID, REJECTED, VOIDED]
PaymentStatus:
type: string
enum: [UNPAID, PARTIALLY_PAID, PAID, OVERDUE]
LedgerBusinessType:
type: string
enum: [RECONCILIATION_CREATED, SETTLEMENT_ISSUED, RECEIPT, PAYMENT, ADJUSTMENT, VOID]
TraceMeta:
type: object
required: [requestId, traceId, timestamp]
properties:
requestId: {type: string, minLength: 1}
traceId: {type: string, minLength: 1}
timestamp: {type: string, format: date-time}
PageMeta:
type: object
required: [page, pageSize, total]
properties:
page: {type: integer, minimum: 1}
pageSize: {type: integer, minimum: 1}
total: {type: integer, format: int64, minimum: 0}
AccountSummary:
type: object
required: [customerId, customerCode, customerName, outstandingReceivable, pendingBilling, receivedInPeriod, totalCost, paidCost, outstandingPayable, status, lastChangedAt]
properties:
customerId: {$ref: '#/components/schemas/Id'}
customerCode: {type: string}
customerName: {type: string}
contactName: {type: string}
contactPhone: {type: string}
outstandingReceivable: {$ref: '#/components/schemas/Money'}
pendingBilling: {$ref: '#/components/schemas/Money'}
receivedInPeriod: {$ref: '#/components/schemas/Money'}
totalCost: {$ref: '#/components/schemas/Money'}
paidCost: {$ref: '#/components/schemas/Money'}
outstandingPayable: {$ref: '#/components/schemas/Money'}
status: {type: string, enum: [ACTIVE, DISABLED]}
lastChangedAt: {type: string, format: date-time}
AccountDetail:
allOf:
- $ref: '#/components/schemas/AccountSummary'
- type: object
properties:
email: {type: string}
creditDays: {type: integer, minimum: 0}
CustomerAccountRead:
type: object
required: [customerId, currency, accountMode, totalReceivable, totalReceived, outstandingAmount, entries]
properties:
customerId: {$ref: '#/components/schemas/Id'}
currency: {type: string, enum: [CNY]}
accountMode: {type: string, enum: [MANUAL_RECEIVABLE_LEDGER]}
totalReceivable: {$ref: '#/components/schemas/Money'}
totalReceived: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
entries:
type: array
items: {$ref: '#/components/schemas/AccountEntryRead'}
CustomerAccountSummary:
type: object
required: [customerId, currency, totalReceivable, receivedAmount, outstandingReceivable, pendingBilling, totalCost, paidCost, outstandingPayable, asOf, lastChangedAt]
properties:
customerId: {$ref: '#/components/schemas/Id'}
currency: {type: string, enum: [CNY]}
totalReceivable: {$ref: '#/components/schemas/Money'}
receivedAmount: {$ref: '#/components/schemas/Money'}
outstandingReceivable: {$ref: '#/components/schemas/Money'}
pendingBilling: {$ref: '#/components/schemas/Money'}
totalCost: {$ref: '#/components/schemas/Money'}
paidCost: {$ref: '#/components/schemas/Money'}
outstandingPayable: {$ref: '#/components/schemas/Money'}
asOf: {type: string, format: date-time}
lastChangedAt: {type: string, format: date-time}
AccountEntryRead:
type: object
required: [entryType, resourceId, resourceNo, occurredAt, debitAmount, creditAmount, currency, status]
properties:
entryType: {type: string, enum: [RECEIVABLE, RECEIPT]}
resourceId: {$ref: '#/components/schemas/Id'}
resourceNo: {type: string}
occurredAt: {type: string, format: date-time}
debitAmount: {$ref: '#/components/schemas/Money'}
creditAmount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string}
LedgerEntry:
type: object
required: [ledgerId, occurredAt, businessType, documentType, documentId, receivableChange, payableChange, outstandingReceivableAfter, operatorName]
properties:
ledgerId: {$ref: '#/components/schemas/Id'}
occurredAt: {type: string, format: date-time}
businessType: {$ref: '#/components/schemas/LedgerBusinessType'}
documentType: {type: string}
documentId: {$ref: '#/components/schemas/Id'}
documentNo: {type: string}
receivableChange: {$ref: '#/components/schemas/Money'}
payableChange: {$ref: '#/components/schemas/Money'}
outstandingReceivableAfter: {$ref: '#/components/schemas/Money'}
operatorName: {type: string}
remark: {type: string}
FeeSource:
type: object
required: [feeSourceId, sourceSystem, sourceType, sourceFeeId, sourceVersion, direction, customerId, businessDate, feeItemName, amount, currency, reviewStatus, sourceStatus, statementGenerated]
properties:
feeSourceId: {$ref: '#/components/schemas/Id'}
sourceSystem: {type: string, minLength: 1}
sourceType: {$ref: '#/components/schemas/FeeSourceType'}
sourceBusinessId: {type: string, description: 来源系统内可展示的正式业务标识;不得用 Finance 技术主键替代}
sourceFeeId: {$ref: '#/components/schemas/Id'}
sourceVersion: {type: integer, minimum: 1}
direction: {$ref: '#/components/schemas/FeeDirection'}
settlementMode: {$ref: '#/components/schemas/SettlementMode'}
paidAt: {type: string, format: date-time}
paymentMethod: {$ref: '#/components/schemas/CostPaymentMethod'}
paymentReferenceNo: {type: string, maxLength: 128}
paymentVoucherFileIds:
type: array
items: {type: string, minLength: 1}
customerId: {$ref: '#/components/schemas/Id'}
customerName: {type: string}
supplierId: {$ref: '#/components/schemas/Id'}
supplierName: {type: string}
orderId: {$ref: '#/components/schemas/Id'}
inboundId: {$ref: '#/components/schemas/Id'}
inboundCode: {type: string}
containerId: {$ref: '#/components/schemas/Id'}
containerNo: {type: string}
businessDate: {type: string, format: date}
feeItemName: {type: string}
quantity: {$ref: '#/components/schemas/Money'}
unitPrice: {$ref: '#/components/schemas/Money'}
amount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
reviewStatus: {$ref: '#/components/schemas/ReviewStatus'}
sourceStatus: {type: string, enum: [AVAILABLE, LOCKED, BILLED, VOIDED, SUPERSEDED]}
statementGenerated: {type: boolean}
FeeSourceDetail:
allOf:
- $ref: '#/components/schemas/FeeSource'
- type: object
properties:
reviewReason: {type: string}
sourceHash: {type: string}
operationLogs:
type: array
items: {$ref: '#/components/schemas/OperationLog'}
FeePoolItemRead:
type: object
required: [poolItemId, direction, sourceType, sourceId, sourceVersion, feeItemName, amount, currency, status, createdAt]
properties:
poolItemId: {type: string}
direction: {$ref: '#/components/schemas/FeeDirection'}
sourceType: {type: string, enum: [FIRSTLEG_FEE, MANUAL_COST]}
sourceId: {$ref: '#/components/schemas/Id'}
sourceVersion: {type: integer, minimum: 1}
orderId: {$ref: '#/components/schemas/Id'}
inboundId: {$ref: '#/components/schemas/Id'}
containerId: {$ref: '#/components/schemas/Id'}
feeItemName: {type: string}
amount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string}
createdAt: {type: string, format: date-time}
OperationLog:
type: object
required: [occurredAt, action, operatorName, result]
properties:
occurredAt: {type: string, format: date-time}
action: {type: string}
operatorName: {type: string}
result: {type: string}
remark: {type: string}
ReviewRequest:
type: object
required: [action, expectedVersion]
properties:
action: {type: string, enum: [APPROVE, REJECT]}
reason: {type: string, maxLength: 500}
expectedVersion: {type: integer, minimum: 0}
FeeSourceEditRequest:
type: object
required: [amount, reason, expectedVersion]
properties:
amount: {$ref: '#/components/schemas/Money'}
reason: {type: string, minLength: 1, maxLength: 500}
expectedVersion: {type: integer, minimum: 0}
FeeSourceActionRequest:
type: object
required: [reason, expectedVersion]
properties:
reason: {type: string, minLength: 1, maxLength: 500}
expectedVersion: {type: integer, minimum: 0}
CustomerConfirmationRequest:
type: object
required: [expectedVersion]
properties:
expectedVersion: {type: integer, minimum: 0}
ReconciliationSummary:
type: object
required: [statementId, statementNo, customerId, customerName, periodStart, periodEnd, creditDays, currency, lineCount, sourceCount, sourceAmount, adjustmentAmount, totalReceivable, receivedAmount, outstandingAmount, settled, status, version, customerConfirmationStatus, createdBy, createdAt, updatedBy, updatedAt]
properties:
statementId: {$ref: '#/components/schemas/Id'}
statementNo: {type: string, pattern: '^REC-\d{6}-\d{4}$', example: REC-260818-0001}
customerId: {$ref: '#/components/schemas/Id'}
customerName: {type: string}
periodStart: {type: string, format: date}
periodEnd: {type: string, format: date}
creditDays: {type: integer, minimum: 0}
currency: {type: string, enum: [CNY]}
lineCount: {type: integer, minimum: 0, description: 对账单费用明细数量}
sourceCount: {type: integer, minimum: 0, description: 去重后的费用来源数量}
sourceAmount: {$ref: '#/components/schemas/Money'}
adjustmentAmount: {$ref: '#/components/schemas/Money'}
totalReceivable: {$ref: '#/components/schemas/Money'}
receivedAmount: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
lastReceiptAt: {type: string, format: date-time}
submittedAt: {type: string, format: date-time}
reviewedAt: {type: string, format: date-time}
issuedAt: {type: string, format: date-time}
settled: {type: boolean}
status: {$ref: '#/components/schemas/ReconciliationStatus'}
version: {type: integer, minimum: 0}
customerConfirmationStatus: {type: string, enum: [NOT_REQUIRED, PENDING_CONFIRMATION, CONFIRMED]}
customerConfirmedBy: {$ref: '#/components/schemas/Id'}
customerConfirmedByName: {type: string}
customerConfirmedAt: {type: string, format: date-time}
createdBy: {$ref: '#/components/schemas/Id'}
createdByName: {type: string, description: 创建时操作人名称快照;历史数据可能为空}
createdAt: {type: string, format: date-time}
updatedBy: {$ref: '#/components/schemas/Id'}
updatedByName: {type: string, description: 最后修改时操作人名称快照;历史数据可能为空}
updatedAt: {type: string, format: date-time}
remark: {type: string}
ReconciliationDetail:
allOf:
- $ref: '#/components/schemas/ReconciliationSummary'
- type: object
required: [lines, paymentHistory, revisions]
properties:
remark: {type: string}
lines:
type: array
items: {$ref: '#/components/schemas/ReconciliationLine'}
paymentHistory:
type: array
items: {$ref: '#/components/schemas/SettlementTransaction'}
revisions:
type: array
items: {$ref: '#/components/schemas/ReconciliationRevision'}
ReconciliationLine:
type: object
required: [statementLineId, feeSourceId, sourceVersion, direction, sourceType, feeItemName, sourceAmount, statementAmount, currency]
properties:
statementLineId: {$ref: '#/components/schemas/Id'}
feeSourceId: {$ref: '#/components/schemas/Id'}
sourceVersion: {type: integer, minimum: 1}
sourceHash: {type: string}
direction: {type: string, enum: [RECEIVABLE, PAYABLE]}
sourceType: {type: string, enum: [INBOUND_FEE, CONTAINER_FEE]}
sourceNo: {type: string}
orderId: {$ref: '#/components/schemas/Id'}
inboundId: {$ref: '#/components/schemas/Id'}
containerId: {$ref: '#/components/schemas/Id'}
inboundCode: {type: string}
containerNo: {type: string}
businessDate: {type: string, format: date}
quantity: {$ref: '#/components/schemas/Money'}
unitPrice: {$ref: '#/components/schemas/Money'}
feeItemName: {type: string}
sourceAmount: {$ref: '#/components/schemas/Money'}
statementAmount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
adjustmentReason: {type: string}
ReconciliationRevision:
type: object
required: [revisionNo, action, beforeAmount, afterAmount, operatorId, occurredAt]
properties:
revisionNo: {type: integer, minimum: 1}
action: {type: string, enum: [CREATE, SUBMIT, APPROVE, REJECT, ISSUE, ADJUST, VOID, REOPEN]}
beforeAmount: {$ref: '#/components/schemas/Money'}
afterAmount: {$ref: '#/components/schemas/Money'}
reason: {type: string}
operatorId: {$ref: '#/components/schemas/Id'}
operatorName: {type: string, description: 操作发生时的名称快照}
occurredAt: {type: string, format: date-time}
StatementRead:
type: object
required: [id, customerId, billNo, billDate, dueDate, totalAmount, receivedAmount, outstandingAmount, currency, status, version]
properties:
id: {$ref: '#/components/schemas/Id'}
customerId: {$ref: '#/components/schemas/Id'}
billNo: {type: string}
customerName: {type: string}
billDate: {type: string, format: date}
dueDate: {type: string, format: date}
totalAmount: {$ref: '#/components/schemas/Money'}
receivedAmount: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string, enum: [DRAFT, ISSUED, PARTIALLY_PAID, PAID, VOIDED]}
version: {type: integer, minimum: 0}
createdBy: {$ref: '#/components/schemas/Id'}
createdByName: {type: string, description: 创建时操作人名称快照;历史数据可能为空}
createdAt: {type: string, format: date-time}
updatedBy: {$ref: '#/components/schemas/Id'}
updatedByName: {type: string, description: 最后修改时操作人名称快照;历史数据可能为空}
updatedAt: {type: string, format: date-time}
StatementLineRead:
type: object
required: [id, sourceType, sourceId, sourceVersion, feeItemName, amount, currency]
properties:
id: {$ref: '#/components/schemas/Id'}
sourceType: {type: string}
sourceId: {$ref: '#/components/schemas/Id'}
sourceVersion: {type: integer, minimum: 1}
orderId: {$ref: '#/components/schemas/Id'}
inboundId: {$ref: '#/components/schemas/Id'}
feeItemCode: {type: string}
feeItemName: {type: string}
amount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
StatementDetailRead:
type: object
required: [statement, lines]
properties:
statement: {$ref: '#/components/schemas/StatementRead'}
lines:
type: array
items: {$ref: '#/components/schemas/StatementLineRead'}
ReceivableSettlementRead:
type: object
required: [id, customerId, settlementNo, billDate, dueDate, receivableAmount, receivedAmount, outstandingAmount, currency, status, version]
properties:
id: {$ref: '#/components/schemas/Id'}
customerId: {$ref: '#/components/schemas/Id'}
settlementNo: {type: string, pattern: '^AR-\d{6}-\d{4}$', example: AR-260818-0001}
billDate: {type: string, format: date}
dueDate: {type: string, format: date}
receivableAmount: {$ref: '#/components/schemas/Money'}
receivedAmount: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string}
version: {type: integer, minimum: 0}
PayableSettlementRead:
type: object
required: [id, customerId, settlementNo, costType, feeItemName, payableAmount, paidAmount, outstandingAmount, currency, status, createdAt, version]
properties:
id: {$ref: '#/components/schemas/Id'}
customerId: {$ref: '#/components/schemas/Id'}
settlementNo: {type: string, pattern: '^AP-\d{6}-\d{4}$', example: AP-260818-0001}
costType: {type: string, enum: [SINGLE_ORDER, CONTAINER_SHARED]}
orderId: {$ref: '#/components/schemas/Id'}
inboundId: {$ref: '#/components/schemas/Id'}
containerId: {$ref: '#/components/schemas/Id'}
supplierName: {type: string}
feeItemName: {type: string}
payableAmount: {$ref: '#/components/schemas/Money'}
paidAmount: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
currency: {type: string, enum: [CNY]}
status: {type: string}
createdAt: {type: string, format: date-time}
version: {type: integer, minimum: 0}
CreateReconciliationRequest:
type: object
required: [customerId, currency, generationMode, periodStart, periodEnd]
description: SELECTED 模式 feeSourceIds 至少一项;BY_CUTOFF 模式由服务端按 periodEnd 选取合格来源。来源金额只能取服务端快照。
properties:
customerId: {$ref: '#/components/schemas/Id'}
currency: {type: string, enum: [CNY]}
generationMode: {type: string, enum: [BY_CUTOFF, SELECTED]}
feeSourceIds:
type: array
minItems: 1
uniqueItems: true
items: {$ref: '#/components/schemas/Id'}
periodStart: {type: string, format: date}
periodEnd: {type: string, format: date}
remark: {type: string, maxLength: 500}
oneOf:
- properties:
generationMode: {type: string, enum: [BY_CUTOFF]}
not: {required: [feeSourceIds]}
- required: [feeSourceIds]
properties:
generationMode: {type: string, enum: [SELECTED]}
ReconciliationActionRequest:
type: object
required: [action, expectedVersion]
description: REJECT/ADJUST/VOID/REOPEN 必须填写 reason;ADJUST 必须提交至少一条 adjustmentLines,且调整后总额不得低于已收金额。
properties:
action: {type: string, enum: [SUBMIT, APPROVE, REJECT, ISSUE, ADJUST, VOID, REOPEN]}
reason: {type: string, maxLength: 500}
expectedVersion: {type: integer, minimum: 0}
adjustmentLines:
type: array
minItems: 1
items: {$ref: '#/components/schemas/StatementAdjustmentLineRequest'}
oneOf:
- properties:
action: {type: string, enum: [SUBMIT, APPROVE, ISSUE]}
- required: [reason]
properties:
action: {type: string, enum: [REJECT, VOID, REOPEN]}
reason: {type: string, minLength: 1, maxLength: 500}
- required: [reason, adjustmentLines]
properties:
action: {type: string, enum: [ADJUST]}
reason: {type: string, minLength: 1, maxLength: 500}
StatementAdjustmentLineRequest:
type: object
required: [statementLineId, adjustedAmount, reason]
properties:
statementLineId: {$ref: '#/components/schemas/Id'}
adjustedAmount: {$ref: '#/components/schemas/Money'}
reason: {type: string, minLength: 1, maxLength: 500}
SettlementSummary:
type: object
required: [settlementId, settlementNo, direction, currency, totalAmount, paidAmount, outstandingAmount, generatedDate, dueDate, paymentStatus, status, version]
properties:
settlementId: {$ref: '#/components/schemas/Id'}
settlementNo: {type: string, pattern: '^(AR|AP)-\d{6}-\d{4}$', example: AR-260818-0001}
direction: {$ref: '#/components/schemas/FeeDirection'}
customerId: {$ref: '#/components/schemas/Id'}
customerName: {type: string}
supplierId: {$ref: '#/components/schemas/Id'}
supplierName: {type: string}
reconciliationStatementId: {$ref: '#/components/schemas/Id'}
businessPeriod: {type: string}
currency: {type: string, enum: [CNY]}
totalAmount: {$ref: '#/components/schemas/Money'}
paidAmount: {$ref: '#/components/schemas/Money'}
outstandingAmount: {$ref: '#/components/schemas/Money'}
generatedDate: {type: string, format: date}
dueDate: {type: string, format: date}
paymentStatus: {$ref: '#/components/schemas/PaymentStatus'}
status: {$ref: '#/components/schemas/SettlementStatus'}
version: {type: integer, minimum: 0}
SettlementDetail:
allOf:
- $ref: '#/components/schemas/SettlementSummary'
- type: object
required: [lines, transactions, revisions]
properties:
lines:
type: array
items: {$ref: '#/components/schemas/FeeSource'}
transactions:
type: array
items: {$ref: '#/components/schemas/SettlementTransaction'}
revisions:
type: array
items: {$ref: '#/components/schemas/SettlementRevision'}
SettlementRevision:
type: object
required: [revisionNo, action, beforeAmount, afterAmount, operatorId, occurredAt]
properties:
revisionNo: {type: integer, minimum: 1}
action: {type: string, enum: [CREATE, ISSUE, RECEIPT, PAYMENT, ADJUST, VOID, REOPEN]}
beforeAmount: {$ref: '#/components/schemas/Money'}
afterAmount: {$ref: '#/components/schemas/Money'}
reason: {type: string}
operatorId: {$ref: '#/components/schemas/Id'}
operatorName: {type: string, description: 操作发生时的名称快照}
occurredAt: {type: string, format: date-time}
CreateReceivableSettlementRequest:
type: object
required: [reconciliationStatementId, currency]
description: 客户、金额、期间和默认 30 天到期日均从已出账对账单与客户账期派生,不接受前端覆盖。
properties:
reconciliationStatementId: {$ref: '#/components/schemas/Id'}
currency: {type: string, enum: [CNY]}
CreatePayableSettlementRequest:
type: object
required: [customerId, supplierId, feeSourceIds, dueDate, currency]
properties:
customerId: {$ref: '#/components/schemas/Id'}
supplierId:
allOf: [{$ref: '#/components/schemas/Id'}]
description: Warehouse ACTIVE 供应商 ID;必须与全部费用来源解析出的唯一类别匹配。
feeSourceIds:
type: array
minItems: 1
uniqueItems: true
items: {$ref: '#/components/schemas/Id'}
dueDate: {type: string, format: date}
currency: {type: string, enum: [CNY]}
SettlementTransaction:
type: object
required: [transactionId, transactionType, transactionDate, amount, method, createdBy, createdAt]
properties:
transactionId: {$ref: '#/components/schemas/Id'}
transactionType: {type: string, enum: [RECEIPT, PAYMENT]}
transactionDate: {type: string, format: date}
amount: {$ref: '#/components/schemas/PositiveMoney'}
method: {type: string, enum: [BANK_TRANSFER, CASH, OTHER]}
referenceNo: {type: string}
voucherFileIds:
type: array
items: {$ref: '#/components/schemas/Id'}
createdBy: {$ref: '#/components/schemas/Id'}
createdByName: {type: string, description: 登记时操作人名称快照;历史数据可能为空}
createdAt: {type: string, format: date-time}
remark: {type: string}
ReceiptAllocationRequest:
type: object
required: [settlementId, amount]
properties:
settlementId: {$ref: '#/components/schemas/Id'}
amount: {$ref: '#/components/schemas/PositiveMoney'}
CreateReceiptRequest:
type: object
required: [customerId, receivedDate, amount, paymentMethod, voucherFileIds, allocations]
properties:
customerId: {$ref: '#/components/schemas/Id'}
receivedDate: {type: string, format: date}
amount: {$ref: '#/components/schemas/PositiveMoney'}
currency: {type: string, enum: [CNY], default: CNY}
paymentMethod: {type: string, enum: [BANK_TRANSFER, CASH, OTHER]}
voucherFileIds:
type: array
minItems: 1
uniqueItems: true
items: {$ref: '#/components/schemas/Id'}
allocations:
type: array
minItems: 1
items: {$ref: '#/components/schemas/ReceiptAllocationRequest'}
remark: {type: string, maxLength: 500}
ClientReceiptRead:
type: object
required: [id, receiptNo, receivedAmount, receivedAt, paymentMethod, currency, status, allocations]
properties:
id: {$ref: '#/components/schemas/Id'}
receiptNo: {type: string}
receivedAmount: {$ref: '#/components/schemas/Money'}
receivedAt: {type: string, format: date-time}
paymentMethod: {type: string, enum: [BANK_TRANSFER, CASH, OTHER]}
currency: {type: string, enum: [CNY]}
status: {type: string, enum: [CONFIRMED]}
allocations:
type: array
items: {$ref: '#/components/schemas/ClientReceiptAllocationRead'}
PlatformReceiptRead:
type: object
required: [id, customerId, receiptNo, receivedAmount, receivedAt, paymentMethod, voucherFileIds, currency, status, version, allocations]
properties:
id: {$ref: '#/components/schemas/Id'}
customerId: {$ref: '#/components/schemas/Id'}
receiptNo: {type: string}
receivedAmount: {$ref: '#/components/schemas/Money'}
receivedAt: {type: string, format: date-time}
paymentMethod: {type: string, enum: [BANK_TRANSFER, CASH, OTHER]}
voucherNo: {type: string}
voucherFileIds:
type: array
items: {type: string}
currency: {type: string, enum: [CNY]}
status: {type: string}
remark: {type: string}
version: {type: integer, minimum: 0}
allocations:
type: array
items: {$ref: '#/components/schemas/ClientReceiptAllocationRead'}
ClientReceiptAllocationRead:
type: object
required: [billId, billNo, appliedAmount]
properties:
billId: {$ref: '#/components/schemas/Id'}
billNo: {type: string}
appliedAmount: {$ref: '#/components/schemas/Money'}
ResourceResult:
type: object
required: [id, resourceNo, status]
properties:
id: {$ref: '#/components/schemas/Id'}
resourceNo: {type: string}
status: {type: string}
version: {type: integer, minimum: 0}
CreateSettlementPaymentRequest:
type: object
required: [transactionDate, amount, currency, method, voucherFileIds, expectedVersion]
description: 仅用于 PAYABLE 结算单人工付款;amount 必须大于 0 且不得超过未付余额,File 校验必须 fail-closed。
properties:
transactionDate: {type: string, format: date}
amount: {$ref: '#/components/schemas/PositiveMoney'}
currency: {type: string, enum: [CNY]}
method: {type: string, enum: [BANK_TRANSFER, CASH, OTHER]}
referenceNo: {type: string}
voucherFileIds:
type: array
minItems: 1
uniqueItems: true
items: {$ref: '#/components/schemas/Id'}
expectedVersion: {type: integer, minimum: 0}
remark: {type: string, maxLength: 500}
SettlementActionRequest:
type: object
additionalProperties: false
properties:
action: {type: string, enum: [VOID, REOPEN]}
reason: {type: string, minLength: 1, maxLength: 500}
expectedVersion: {type: integer, minimum: 0}
required: [action, reason, expectedVersion]
ErrorEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message]
properties:
code: {type: string}
message: {type: string}
FeeSourceEventResultEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/FeeSourceEventResult'}
AccountPageEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data, page]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/AccountSummary'}}
page: {$ref: '#/components/schemas/PageMeta'}
AccountDetailEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/AccountDetail'}
LedgerPageEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data, page]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/LedgerEntry'}}
page: {$ref: '#/components/schemas/PageMeta'}
FeeSourcePageEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data, page]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/FeeSource'}}
page: {$ref: '#/components/schemas/PageMeta'}
FeeSourceDetailEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/FeeSourceDetail'}
ReconciliationPageEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data, page]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/ReconciliationSummary'}}
page: {$ref: '#/components/schemas/PageMeta'}
ReconciliationDetailEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/ReconciliationDetail'}
SettlementPageEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data, page]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/SettlementSummary'}}
page: {$ref: '#/components/schemas/PageMeta'}
SettlementDetailEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/SettlementDetail'}
CustomerAccountReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/CustomerAccountRead'}
CustomerAccountSummaryEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/CustomerAccountSummary'}
FeePoolReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/FeePoolItemRead'}}
StatementListReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/ReconciliationSummary'}}
StatementDetailReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/StatementDetailRead'}
ReceivableSettlementListReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/ReceivableSettlementRead'}}
PayableSettlementListReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/PayableSettlementRead'}}
ClientReceiptListReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/ClientReceiptRead'}}
PlatformReceiptListReadEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/PlatformReceiptRead'}}
ResourceResultEnvelope:
allOf:
- $ref: '#/components/schemas/TraceMeta'
- type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/ResourceResult'}
responses:
AccountPageResponse:
description: 客户账户派生汇总分页。
content: {application/json: {schema: {$ref: '#/components/schemas/AccountPageEnvelope'}}}
AccountDetailResponse:
description: 客户账户派生详情。
content: {application/json: {schema: {$ref: '#/components/schemas/AccountDetailEnvelope'}}}
LedgerPageResponse:
description: 客户财务派生流水分页。
content: {application/json: {schema: {$ref: '#/components/schemas/LedgerPageEnvelope'}}}
FeeSourcePageResponse:
description: 费用来源分页。
content: {application/json: {schema: {$ref: '#/components/schemas/FeeSourcePageEnvelope'}}}
FeeSourceDetailResponse:
description: 费用来源详情。
content: {application/json: {schema: {$ref: '#/components/schemas/FeeSourceDetailEnvelope'}}}
ReconciliationPageResponse:
description: 客户对账单分页。
content: {application/json: {schema: {$ref: '#/components/schemas/ReconciliationPageEnvelope'}}}
ReconciliationDetailResponse:
description: 客户对账单详情。
content: {application/json: {schema: {$ref: '#/components/schemas/ReconciliationDetailEnvelope'}}}
SettlementPageResponse:
description: 结算单分页。
content: {application/json: {schema: {$ref: '#/components/schemas/SettlementPageEnvelope'}}}
SettlementDetailResponse:
description: 结算单详情。
content: {application/json: {schema: {$ref: '#/components/schemas/SettlementDetailEnvelope'}}}
CustomerAccountReadResponse:
description: 当前固定 DTO 客户账户及流水。
content: {application/json: {schema: {$ref: '#/components/schemas/CustomerAccountReadEnvelope'}}}
CustomerAccountSummaryResponse:
description: 客户正式结算口径财务汇总。
content: {application/json: {schema: {$ref: '#/components/schemas/CustomerAccountSummaryEnvelope'}}}
FeePoolReadResponse:
description: 当前固定 DTO 客户应收应付费用池。
content: {application/json: {schema: {$ref: '#/components/schemas/FeePoolReadEnvelope'}}}
StatementListReadResponse:
description: 客户对账单业务摘要列表,包含期间、金额、来源数量和流程时间。
content: {application/json: {schema: {$ref: '#/components/schemas/StatementListReadEnvelope'}}}
StatementDetailReadResponse:
description: 当前固定 DTO 客户对账单详情。
content: {application/json: {schema: {$ref: '#/components/schemas/StatementDetailReadEnvelope'}}}
ReceivableSettlementListReadResponse:
description: 当前固定 DTO 应收结算单列表。
content: {application/json: {schema: {$ref: '#/components/schemas/ReceivableSettlementListReadEnvelope'}}}
PayableSettlementListReadResponse:
description: 当前固定 DTO 应付结算单列表。
content: {application/json: {schema: {$ref: '#/components/schemas/PayableSettlementListReadEnvelope'}}}
ClientReceiptListReadResponse:
description: 客户专用收款 DTO 列表,不含凭证和内部字段。
content: {application/json: {schema: {$ref: '#/components/schemas/ClientReceiptListReadEnvelope'}}}
PlatformReceiptListReadResponse:
description: 平台专用收款 DTO 列表,包含凭证引用和账单分配。
content: {application/json: {schema: {$ref: '#/components/schemas/PlatformReceiptListReadEnvelope'}}}
ResourceResultResponse:
description: 写操作资源结果。
content: {application/json: {schema: {$ref: '#/components/schemas/ResourceResultEnvelope'}}}
BusinessError:
description: 稳定业务错误。
content: {application/json: {schema: {$ref: '#/components/schemas/ErrorEnvelope'}}}