19 KiB
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 已独立交付) |
十二、注意事项
ledgerType必传且本期仅SUPPLIER:不传 → 400;传其他账套值(含未来的 CUSTOMER 等)→ 596005。本期直接固定传SUPPLIER即可。direction/sourceType垃圾值静默空页:不报错、不提示,筛选控件请只用本文 §六 列出的枚举值,避免"查不到数据"的困惑。- 金额恒正 + 方向单列:
amount永远 > 0,不要按借贷习惯对 DECREASE 金额取负;账页净额正负语义 = 正我欠他 / 负多付他。 - Long ID 全 String:
refId/id/sourceId均为 String 输出,直接当字符串用,不要Number()转换(雪花 ID 超 JS 安全整数)。 - 排序固定:账页 refId 升序;流水明细按流水ID降序(最新在前)。两个端点都不支持自定义排序参数。
- 日期格式严格
yyyy-MM-dd:entryDateStart/entryDateEnd已声明 ISO DATE 绑定,传2026/09/01或时间戳会 400。 - 账页两个占位字段恒 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) |