文件
hl-api-changelog/changelogs-v2/2026-09/17_7883_往来账供应商往来-新增接口-管理后台.md
T
2026-09-17 19:20:15 +08:00

19 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 statement-supplier-ledger-query 往来账·供应商往来最小闭环——账页分页 + 流水明细分页(2 个查询端点) admin yst(GIT) 新增接口 deployed verified verified mmg a975f40b05cac17ac7d8523ddc2fe46437f307f1 2026-09-17 财务域往来账首次交付查询侧:供应商往来账页分页(期初现算 + 增减合计 + 净余额)+ 往来流水明细分页 2 个新端点。本期仅开放 SUPPLIER 账套;direction 去借贷化(INCREASE/DECREASE),金额恒正;sourceType 本期接通 PAYMENT 应付款 / PREPAY 预付款两路。后端已合并 dev-v3 并部署测试服,E2E 已真实跑通(供应商 2096854417461403650 全链路:批准+5000 → 付讫 → 撤销红冲-3000 → 预付付讫-1000,净额 -1000)。前端此前无往来账页面,按本文一次对接即可。[mmg 2026-09-17 交付] ①api/finance/statement.js 2 只读端点(ledgerType 函数内强制覆写 SUPPLIER;negativeOnly 仅 true 上送;direction/sourceType 前端字典渲染契约无 xxxName;596005/596009 拦截器透 message);②finance/current-account/supplier 页(菜单路径保持):页内两视图——账页列表(refName 模糊+negativeOnly 复选框「只看多付(净额为负)」契约语义,七列全渲含恒 0 核销/调账,净往来三态语义正我欠他/负多付他/0 已结清)→ 流水明细(带 refId 自管分页,日期区间/方向/来源/团号筛选,金额恒正不取负,PREPAY 行 teamNo 显 —)。原型有契约无缺口不造数留痕:类别/联系人/流水余额列/往来单据明细卡/原型类型选项;原型复选框「未结清」文案与契约语义不符按契约写。api spec 5 例+页面 spec 6 例,scoped checkpoint 13 项全绿。 2026-09-17 dev-v3

往来账·供应商往来最小闭环(管理后台)

服务: hl-order-service-v3(hl-finance 模块) 类型: 🆕 新增(本期首次交付,前端首次对接) 日期: 2026-09-17 影响范围: 管理后台财务域「往来账-供应商往来」页面 覆盖 Epic: #7883(PR-1 #7884 建表+流水写入护栏 / 文档 PR #7893)


一、接口背景

往来账 = 公司与往来对象(本期仅供应商)之间的资金往来台账。本次交付查询侧最小闭环,两个端点:

  • 账页分页:一本账一页——按供应商聚合「期初净额 + 本期净额增 − 本期净额减」现算净往来余额(余额不存列,每次查询实时算)
  • 流水明细分页:按供应商/方向/来源/团号/入账日期区间逐行查看往来流水,可溯源到来源单据

业务语义(去借贷化,没有 DEBIT/CREDIT):

  • INCREASE 净额增:我欠他变多(典型:应付款批准,该付增加)
  • DECREASE 净额减:我欠他变少 / 多付(典型:付讫、撤销批准红冲、预付付讫)
  • 金额恒正,方向由 direction 单列表达
  • 净往来余额 netAmount:正 = 我方欠对方;负 = 多付对方(对方欠我方)

流水来源本期接通两路:PAYMENT 应付款(批准/付讫/撤销批准)、PREPAY 预付款(预付付讫)。核销 / 调账未做,账页 writeoffTotal / adjustTotal 恒 0 占位对齐契约。


二、变更清单

# 变更 类型 说明
1 GET /admin/finance/statements/page ✨ 新增 供应商往来账页分页(按供应商聚合:期初现算 + 增 − 减 = 净余额,支持名称模糊 / 只看负数)
2 GET /admin/finance/statements/entries/page ✨ 新增 往来流水明细分页(供应商 / 方向 / 来源类型 / 入账日期区间 / 团号筛选)
3 错误码段位 596000-596099 ✨ 新增 596 段首次落码(hl-finance),本期启用 596005 / 596009,596006-596008 为流水写入护栏

三、接口详情

项 说明
使用场景 管理后台财务域「往来账-供应商往来」:账页(按供应商看净余额)+ 流水明细(逐行溯源)
认证 管理后台 JWT(网关统一鉴权),需财务域菜单权限
幂等性 两个端点均为只读查询,天然幂等,可安全重试
限流 走网关统一限流,无模块特殊限流
ID 序列化 流水明细的 Long 型 ID(id / refId / sourceId)序列化为 String,防 JS 精度丢失;账页 refId 本身即为 String
账套约束 本期仅开放 SUPPLIER 供应商往来账套,ledgerType 传其他值(含大小写不匹配的垃圾值)→ 596005

四、接口入参

两个端点均为 GET,参数全走 Query。分页参数继承统一分页基类:

参数 类型 必填 说明
page Integer 否 页码,默认 1,最小 1(兼容别名 pageNo,非法值 0/负数 → 400)
pageSize Integer 否 每页条数,默认 20,范围 1-100

4.1 GET /admin/finance/statements/page 账页分页 Query 入参

参数 类型 必填 说明
ledgerType String ✅ 账套:本期仅 SUPPLIER 供应商往来(其他值 → 596005;为空 → 400 参数校验)
refName String 否 往来对象名(模糊匹配,自动 trim);空 = 不限
negativeOnly Boolean 否 仅看负余额:true = 只返回净额 netAmount < 0 的行(结存为负 = 多付 / 对方欠我方);空或 false = 全部

4.2 GET /admin/finance/statements/entries/page 流水明细分页 Query 入参

参数 类型 必填 说明
ledgerType String ✅ 账套:本期仅 SUPPLIER(其他值 → 596005;为空 → 400 参数校验)
refId Long 否 往来对象ID(供应商主键)精确;空 = 不限
direction String 否 增减方向:INCREASE / DECREASE;空 = 不限。非法值不报错:列只存枚举值,垃圾值查不出行返回空页
sourceType String 否 来源类型:PAYMENT 应付款 / PREPAY 预付款;空 = 不限。非法值不报错:同上返回空页
entryDateStart Date 否 入账日期起,格式 yyyy-MM-dd;晚于 entryDateEnd → 596009
entryDateEnd Date 否 入账日期止,格式 yyyy-MM-dd(含当日)
teamNo String 否 团号(精确匹配,自动 trim);空 = 不限

五、出参字段

两个端点统一返回 Result<PageResult<T>>,外层结构:

字段 类型 说明
code Integer 0 = 成功;业务失败为错误码(596005 / 596009 等)
message String 错误描述(成功时为空或 success)
data.records Array 当前页数据行
data.total Integer 总记录数
data.page Integer 当前页码
data.pageSize Integer 每页条数

5.1 账页行 StatementRowRespVO(/statements/page 的 records 元素)

字段 类型 说明
ledgerType String 账套:SUPPLIER
refId String 往来对象ID(供应商主键,String 输出)
refName String 往来对象名(流水名优先,供应商改名后取新;无流水时回退期初名)
openingAmount BigDecimal 期初净额 = 期初应付 − 期初应收(来自 fin_opening_balance 现算,不存列;无期初记录按 0)
increaseTotal BigDecimal 本期净额增合计(如应付款批准该付增加;无流水按 0)
decreaseTotal BigDecimal 本期净额减合计(如付讫 / 撤销批准冲减 / 预付付讫;无流水按 0)
writeoffTotal BigDecimal 本期核销合计(本期恒 0,核销 Epic 开放后有值)
adjustTotal BigDecimal 本期调账合计(本期恒 0,调账标二期)
netAmount BigDecimal 净往来余额 = openingAmount + increaseTotal − decreaseTotal(正 = 我欠他 / 负 = 多付他)

排序:refId 升序。聚合方式为「全量两表按 refId 分组 → 内存合并过滤 → 内存分页」(业务量日百级流水,性能无虞)。

5.2 流水行 StatementEntryRowRespVO(/statements/entries/page 的 records 元素)

字段 类型 说明
id String 流水行ID(Long → String)
ledgerType String 账套:SUPPLIER
refId String 往来对象ID(供应商主键,Long → String)
refName String 往来对象名快照(写入时快照,不随后续改名变化)
entryDate Date 入账日期(业务发生日,yyyy-MM-dd)
sourceType String 来源类型:PAYMENT 应付款 / PREPAY 预付款
sourceId String 来源单据ID(Long → String;可按 sourceType + sourceId 溯源到应付款单 / 预付款单)
sourceNo String 来源单号快照
direction String 增减方向:INCREASE 净额增 / DECREASE 净额减
amount BigDecimal 金额(恒正,方向由 direction 表达)
teamNo String 团号(可空:预付款无团号为 null)
summary String 摘要(白话业务词,如「应付款批准,该付增加」「应付款付讫」「冲减:撤销批准」「预付款付讫」)

排序:流水行ID 降序(最新流水在前)。


六、枚举 / 数据字典

ledgerType 账套

值 含义 本期状态
SUPPLIER 供应商往来 ✅ 本期唯一开放;其他值 → 596005

direction 增减方向(去借贷化,无 DEBIT/CREDIT)

值 含义 典型场景
INCREASE 净额增(我欠他变多) 应付款批准,该付增加
DECREASE 净额减(我欠他变少 / 多付) 应付款付讫、撤销批准红冲、预付款付讫

sourceType 来源类型

值 含义 本期状态
PAYMENT 应付款 ✅ 已接通(批准 / 付讫 / 撤销批准三路流水)
PREPAY 预付款 ✅ 已接通(预付付讫流水)

sourceType 不给 xxxName 出参,名称由前端字典渲染。


七、错误码

596 段首次落码(owner = hl-finance,段位 596000-596099):

错误码 含义 触发场景 本批两个查询端点是否可达
596005 账套非法或本期未开放 ledgerType 非 SUPPLIER(含大小写不匹配 / 未来账套值) ✅ 可达
596006 流水金额必须为正 流水写入侧护栏(金额恒正约束) ❌ 查询端点不可达
596007 往来对象缺失 流水写入侧护栏(refId/refName 空) ❌ 查询端点不可达
596008 来源单据缺失 流水写入侧护栏(sourceType/sourceId 空) ❌ 查询端点不可达
596009 入账日期区间倒置 entryDateStart 晚于 entryDateEnd ✅ 可达(仅流水明细分页)

596001-596004 为核销/调账设计稿预留号,本期不启用。 ledgerType 为空串 / 不传 → Spring 参数校验 400(@NotBlank),不走 596005。 direction / sourceType 垃圾值不报错,查不出行返回空页(对齐 OpeningBalance 先例)。


八、示例

以下示例数据来自测试服真实 E2E:供应商 2096854417461403650 全链路(应付款批准 +5000 → 付讫 -5000 → 撤销批准红冲 -3000 → 预付款付讫 -1000,期初 3000,最终净额 -1000)。

8.1 典型成功:账页分页(含负余额行)

请求:

GET /admin/finance/statements/page?ledgerType=SUPPLIER&page=1&pageSize=20

响应(code=0,节选 data):

{
  "code": 0,
  "data": {
    "records": [
      {
        "ledgerType": "SUPPLIER",
        "refId": "2096854417461403650",
        "refName": "示例供应商A",
        "openingAmount": 3000.00,
        "increaseTotal": 5000.00,
        "decreaseTotal": 9000.00,
        "writeoffTotal": 0,
        "adjustTotal": 0,
        "netAmount": -1000.00
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20
  }
}

8.2 边界情况

8.2.1 只看负余额(negativeOnly 命中)——净额 ≥ 0 的行被过滤:

GET /admin/finance/statements/page?ledgerType=SUPPLIER&negativeOnly=true

上行示例供应商 netAmount=-1000.00 命中返回;净额为 0 或正的供应商行不出现在 records。

8.2.2 流水明细:预付款行 teamNo 为 null + 垃圾值筛选返回空页:

GET /admin/finance/statements/entries/page?ledgerType=SUPPLIER&refId=2096854417461403650&sourceType=PREPAY

响应(预付付讫行,teamNo=null):

{
  "code": 0,
  "data": {
    "records": [
      {
        "id": "2100178456789012481",
        "ledgerType": "SUPPLIER",
        "refId": "2096854417461403650",
        "refName": "示例供应商A",
        "entryDate": "2026-09-16",
        "sourceType": "PREPAY",
        "sourceId": "2100178000111222333",
        "sourceNo": "YF20260916001",
        "direction": "DECREASE",
        "amount": 1000.00,
        "teamNo": null,
        "summary": "预付款付讫"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20
  }
}

垃圾值不报错返回空页:

GET /admin/finance/statements/entries/page?ledgerType=SUPPLIER&direction=FOO
{ "code": 0, "data": { "records": [], "total": 0, "page": 1, "pageSize": 20 } }

8.2.3 流水明细:来源 + 日期区间组合筛选(应付款三路流水):

GET /admin/finance/statements/entries/page?ledgerType=SUPPLIER&refId=2096854417461403650&sourceType=PAYMENT&entryDateStart=2026-09-01&entryDateEnd=2026-09-30

响应节选(按流水ID降序,最新在前):

{
  "code": 0,
  "data": {
    "records": [
      {
        "id": "2100160000000000003",
        "ledgerType": "SUPPLIER",
        "refId": "2096854417461403650",
        "refName": "示例供应商A",
        "entryDate": "2026-09-16",
        "sourceType": "PAYMENT",
        "sourceId": "2100159999888777666",
        "sourceNo": "FK20260916003",
        "direction": "DECREASE",
        "amount": 3000.00,
        "teamNo": "T20260912001",
        "summary": "冲减:撤销批准"
      },
      {
        "id": "2100160000000000002",
        "ledgerType": "SUPPLIER",
        "refId": "2096854417461403650",
        "refName": "示例供应商A",
        "entryDate": "2026-09-16",
        "sourceType": "PAYMENT",
        "sourceId": "2100159999888777666",
        "sourceNo": "FK20260916003",
        "direction": "DECREASE",
        "amount": 5000.00,
        "teamNo": "T20260912001",
        "summary": "应付款付讫"
      },
      {
        "id": "2100160000000000001",
        "ledgerType": "SUPPLIER",
        "refId": "2096854417461403650",
        "refName": "示例供应商A",
        "entryDate": "2026-09-15",
        "sourceType": "PAYMENT",
        "sourceId": "2100159999888777666",
        "sourceNo": "FK20260916003",
        "direction": "INCREASE",
        "amount": 5000.00,
        "teamNo": "T20260912001",
        "summary": "应付款批准,该付增加"
      }
    ],
    "total": 3,
    "page": 1,
    "pageSize": 20
  }
}

8.3 业务失败

8.3.1 账套非 SUPPLIER → 596005:

GET /admin/finance/statements/page?ledgerType=CUSTOMER
{ "code": 596005, "message": "账套非法或本期未开放", "data": null }

8.3.2 入账日期区间倒置 → 596009:

GET /admin/finance/statements/entries/page?ledgerType=SUPPLIER&entryDateStart=2026-09-30&entryDateEnd=2026-09-01
{ "code": 596009, "message": "入账日期区间倒置", "data": null }

8.3.3 ledgerType 缺失 → 400 参数校验:

GET /admin/finance/statements/page
{ "code": 400, "message": "账套不能为空", "data": null }

九、业务边界

适用:

  • 查询供应商维度的净往来余额(我欠他 / 多付他一览)
  • 按供应商 / 方向 / 来源 / 团号 / 入账日期区间逐行溯源流水
  • 多付场景排查(negativeOnly=true 只拉负余额供应商)

不适用:

  • 客户 / 员工等其他账套(本期未开放,传值 → 596005;后续 Epic 逐套开放)
  • 核销、调账流水(未做,writeoffTotal / adjustTotal 恒 0)
  • 流水写入(写入由应付款 / 预付款业务动作联动落,不开放手工录入端点)

特殊边界:

  • 账页是内存聚合现算:期初表 + 流水表全量按 refId 分组后内存过滤分页;业务量日百级流水,性能无虞
  • 期初净额 = 期初应付 − 期初应收(fin_opening_balance 现算),某供应商只有期初没有流水(或反之)也会出现在账页
  • 账页 refName 取流水名优先(供应商改名后取新),无流水才回退期初名;流水行 refName 是写入时快照,不随后续改名变化——两处名字可能不同,属预期
  • 流水行 amount 恒正,正负语义全在 direction;不要对金额自行取负
  • teamNo 可空(预付款无团号),teamNo 筛选是精确匹配,传空 = 不限(查全部,含 teamNo 为 null 的行)

十、修改前后对比

本期为新增接口,无修改前后对比(前端此前无往来账任何页面,按本文一次对接即可)。


十一、影响评估 / 回滚

项 说明
破坏兼容 无——纯新增 2 个 GET 端点,不改任何既有接口
前端同步上线 无强依赖——前端未对接不影响任何既有功能;对接后即可用
回滚方案 后端回滚 = 下线 2 个端点(前端不调用即无感);无 DDL 回滚需求(本批不含表结构变更,建表在 PR-1 #7884 已独立交付)

十二、注意事项

  1. ledgerType 必传且本期仅 SUPPLIER:不传 → 400;传其他账套值(含未来的 CUSTOMER 等)→ 596005。本期直接固定传 SUPPLIER 即可。
  2. direction / sourceType 垃圾值静默空页:不报错、不提示,筛选控件请只用本文 §六 列出的枚举值,避免"查不到数据"的困惑。
  3. 金额恒正 + 方向单列:amount 永远 > 0,不要按借贷习惯对 DECREASE 金额取负;账页净额正负语义 = 正我欠他 / 负多付他。
  4. Long ID 全 String:refId / id / sourceId 均为 String 输出,直接当字符串用,不要 Number() 转换(雪花 ID 超 JS 安全整数)。
  5. 排序固定:账页 refId 升序;流水明细按流水ID降序(最新在前)。两个端点都不支持自定义排序参数。
  6. 日期格式严格 yyyy-MM-dd:entryDateStart / entryDateEnd 已声明 ISO DATE 绑定,传 2026/09/01 或时间戳会 400。
  7. 账页两个占位字段恒 0:writeoffTotal / adjustTotal 本期恒 0(核销 / 调账未做),净额公式暂等价于 openingAmount + increaseTotal − decreaseTotal;请按完整契约字段对接,后续核销 Epic 上线后无需改结构。

十三、关联 / 联系人

项 链接
Epic Issue https://git.1814.love:8443/wx/HL/issues/7883
代码 PR(PR-1 建表 + 流水写入护栏) https://git.1814.love:8443/wx/HL/pulls/7884
文档 PR(SRS / API / DM / 详设同步) https://git.1814.love:8443/wx/HL/pulls/7893
代码基线(dev-v3 HEAD) https://git.1814.love:8443/wx/HL/commit/1d0cd8d965e1
后端负责人 腰苏图(yst)