diff --git a/changelogs-v2/2026-09/30_8507_财务初始化三tab对齐原型-修改接口-管理后台.md b/changelogs-v2/2026-09/30_8507_财务初始化三tab对齐原型-修改接口-管理后台.md new file mode 100644 index 00000000..32018883 --- /dev/null +++ b/changelogs-v2/2026-09/30_8507_财务初始化三tab对齐原型-修改接口-管理后台.md @@ -0,0 +1,303 @@ +--- +schema: "hl-changelog/v2" +ticket: "8507" +title: "财务初始化页面 tab 结构纠偏:应为 3 tab(应收初始化/应付初始化/现金银行初始化),删「员工往来」tab,应收初始化内按往来对象选 CUSTOMER/SUPPLIER_RECV(#8507 #8511)" +consumer: "admin" +author: "yst(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "not_required" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-30" +status_note: "财务初始化(菜单:参数设置/财务初始化)前端页面 tab 结构与原型不符的纠偏单。原型只有 3 个 tab(应收初始化/应付初始化/现金银行初始化),按「初始化场景」划分,初始化里**没有「员工往来」期初**(员工借款/备用金属付款管理业务流程,不在初始化)。当前前端做成了 4 个 tab(客户应收/供应商应付/供应商应收/员工往来),按「往来对象类型」划分,需重构。后端接口零改动、已全部部署测试服并验证通过:应收/应付走 /admin/finance/opening-balances(按 ledgerType 区分 CUSTOMER/SUPPLIER_RECV/SUPPLIER),现金银行走 /admin/finance/fund-accounts(账户期初结存),两套接口互相独立。本文自包含全部入参/出参/枚举/错误码/示例。" +updated_at: "2026-09-30" +base: "dev-v3" +--- + +# finance:财务初始化三 tab 对齐原型(管理后台) + +> **性质**:前端实现纠偏。后端接口无新增/无变更,已在测试服就绪。本文告诉前端「正确的 tab 结构 + 每个 tab 怎么调既有接口」。 + +## 1. 接口背景 + +财务初始化是账套启用前录入期初数据的入口(菜单:**参数设置 / 财务初始化**)。 + +原型 `finance-prototype.html`(页面 id `cfg-fininit`)规定财务初始化**只有 3 个 tab**,按「初始化场景」划分: + +``` +财务初始化 +├─ 应收初始化 启用前欠我们的款(客户欠款 + 供应商杂项应收) +├─ 应付初始化 启用前我们欠供应商的款 +└─ 现金银行初始化 各资金账户启用前已有结存 +``` + +**当前前端实现错误**:做成了 4 个 tab(客户应收 / 供应商应付 / 供应商应收 / 员工往来),按「往来对象类型」划分。两处偏差: +1. tab 划分维度错了——应按「初始化场景」(应收/应付/现金银行),不是按「往来对象类型」(客户/供应商/员工)。 +2. 多出了「员工往来」tab——原型财务初始化**没有员工往来期初**。员工借款/备用金是「付款管理 / 员工借款」的业务单据流(页面 `loan-stf` / `payex-stfloan`),不属于财务初始化。 + +**「供应商应收」不是独立 tab**:它是「应收初始化」tab 内部、往来对象选「供应商」时的一种(供应商欠我们的杂项应收:押金退还/赔偿款/口车费/其他应收)。 + +## 2. 变更清单(前端 tab 结构改动) + +| # | 改动 | 说明 | +|---|------|------| +| 1 | 删除「员工往来」tab | 初始化无此场景 | +| 2 | tab 改 3 个并改名 | `应收初始化` / `应付初始化` / `现金银行初始化` | +| 3 | 「客户应收」+「供应商应收」合并进「应收初始化」一个 tab | tab 内用「往来对象」下拉(客户/供应商)切换 ledgerType | +| 4 | 「供应商应付」改名「应付初始化」 | 固定 ledgerType=SUPPLIER,去掉对象细分字段 | +| 5 | 新增「现金银行初始化」tab | 接 `/admin/finance/fund-accounts` 系列接口(账户期初结存) | + +## 3. tab ↔ 接口 / 账套映射(核心) + +| 前端 tab | tab 内「往来对象」 | 调接口 | 传 `ledgerType` | +|---|---|---|---| +| 应收初始化 | 客户 | `POST /admin/finance/opening-balances` 等 | `CUSTOMER` | +| 应收初始化 | 供应商 | 同上 | `SUPPLIER_RECV` | +| 应付初始化 | (固定供应商,无此下拉) | 同上 | `SUPPLIER` | +| 现金银行初始化 | — | `/admin/finance/fund-accounts` 系列 | —(无 ledgerType 概念) | + +> 应收初始化一个 tab 对应两个 ledgerType,按用户选的「往来对象」决定传哪个;金额字段填 `openingReceivable`。应付初始化固定 `SUPPLIER`,金额填 `openingPayable`。 + +--- + +## 4. 应收初始化 tab(ledgerType = CUSTOMER / SUPPLIER_RECV) + +### 4.1 列表(分页) + +`GET /admin/finance/opening-balances/page` + +**入参(query)**: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---|---| +| pageNo | int | 是 | 页码 | +| pageSize | int | 是 | 每页 | +| ledgerType | string | 是 | `CUSTOMER` 或 `SUPPLIER_RECV` | +| kind | string | 否 | `INIT` 初始 / `ADJUST` 期初调整;空=全部 | +| refName | string | 否 | 往来对象名模糊搜索 | + +> 应收初始化 tab 顶部建议加「往来对象」筛选(全部/客户/供应商):客户→`CUSTOMER`、供应商→`SUPPLIER_RECV`、全部→两个 ledgerType 各查一次合并。 + +**出参(`data.records[]`)**: + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | string | 期初行 ID | +| ledgerType | string | 账套回显 | +| refId | string | 往来对象 ID | +| refName | string | 往来对象名称 | +| customerCategory | string | 对象细分编码(CUSTOMER=客户分类 / SUPPLIER_RECV=应收性质;SUPPLIER 为 null) | +| customerCategoryName | string | **对象细分中文名**(列表直接显示这个;字典不可用为 null) | +| companyId | string | 所属公司主体 ID | +| companyName | string | 所属公司主体名 | +| openingDate | string | 期初基准日(=当前未封账账期起始日),只读 | +| kind | string | `INIT` / `ADJUST` | +| openingPayable | number | 期初应付(应收 tab 恒 null,忽略) | +| openingReceivable | number | **期初应收(本 tab 显示这个金额)** | +| evidenceUrl | string | 佐证材料影像 URL(可空) | +| recordedByName | string | 录入人姓名 | +| createTime | string | 创建时间 | + +### 4.2 新建期初 + +`POST /admin/finance/opening-balances` + +**表单(按原型应收表单三段递进)**: + +1. **往来对象**(下拉必填):`客户` / `供应商` +2. **对象细分**(下拉必填,标签随往来对象变): + - 客户 → 标签「客户分类」,选项 = 字典 `fin_customer_category` + - 供应商 → 标签「应收性质」,选项 = 字典 `fin_recv_nature` +3. **往来对象名称**(下拉必填): + - 供应商 → `GET /admin/supplier/items/list?status=ACTIVE`(取 `supplierId` + `shortName`/`fullName`) + - 客户 → 客户列表(按所选客户分类过滤) +4. **应收欠款**(数字必填,>0) +5. **所属公司**(下拉单选必填):`GET /v3/admin/travel-agency/enabled`(取 `agencyId`+`agencyName`) +6. **记账日期**(只读):前端不传,后端落 `openingDate`=当前账期起始日 +7. **备注**(文本域选填,≤200 字) + +**请求体**: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---|---| +| ledgerType | string | 是 | `CUSTOMER`(选了客户)/ `SUPPLIER_RECV`(选了供应商) | +| refId | Long | 是 | 往来对象 ID | +| refName | string | 是 | 往来对象名称(≤128) | +| customerCategory | string | 条件必填 | 对象细分编码:CUSTOMER→fin_customer_category 编码;SUPPLIER_RECV→fin_recv_nature 编码。**两账套均必填** | +| companyId | Long | 是 | 所属公司主体 ID | +| openingReceivable | number | 是 | 期初应收金额,>0 | +| openingPayable | — | 否 | 应收 tab 不传(传了后端也忽略不落库) | +| evidenceUrl | string | 否 | 佐证材料影像 URL | +| remark | string | 否 | 备注(≤200) | + +**响应**:`data.id` = 新建期初行 ID。 + +**请求示例(供应商应收)**: +```json +{ + "ledgerType": "SUPPLIER_RECV", + "refId": 2104918057506041857, + "refName": "柴河星悦酒店", + "customerCategory": "DEPOSIT_REFUND", + "companyId": 2051922156798779394, + "openingReceivable": 1.01, + "remark": "押金退还期初" +} +``` + +**响应示例**: +```json +{ "code": 200, "message": "成功", "data": { "id": "2105077077235662849" }, "success": true } +``` + +### 4.3 期初调整 + +`POST /admin/finance/opening-balances/adjust` + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---|---| +| ledgerType | string | 是 | 同新建 | +| refId | Long | 是 | 往来对象 ID(须已有 INIT 行,否则 598404) | +| openingReceivable | number | 条件 | **调整后期初应收(全量值非差额)**;CUSTOMER/SUPPLIER_RECV 落库 | +| openingPayable | number | 条件 | 调整后期初应付;仅 SUPPLIER 落库 | +| evidenceUrl | string | 否 | 佐证影像 | +| reason | string | **是** | 调整原因(≤200) | + +> 分类/性质/公司沿用 INIT 行快照,调整单不开放改。 + +--- + +## 5. 应付初始化 tab(ledgerType = SUPPLIER) + +接口同应收(`/admin/finance/opening-balances` 一套),差异: + +| 项 | 应付初始化 | +|---|---| +| ledgerType | 固定 `SUPPLIER` | +| 往来对象 | 固定「供应商」,无客户/供应商下拉;直接供应商列表 `GET /admin/supplier/items/list?status=ACTIVE` | +| customerCategory | **不传**(SUPPLIER 忽略,供应商类别随供应商档案带出不手选) | +| 金额字段 | 传 `openingPayable`(期初应付,>0),**不传** `openingReceivable` | + +列表看 `openingPayable`(`openingReceivable` 恒 null)。 + +--- + +## 6. 现金银行初始化 tab(走资金账户接口,独立) + +此 tab 是**资金账户的期初结存**,与应收/应付的 opening-balances **完全独立**,接 `/admin/finance/fund-accounts`: + +| 操作 | 接口 | 说明 | +|---|---|---| +| 列表 | `GET /admin/finance/fund-accounts/page` | 本 tab 列表(列:账户名称/类型/期初结存/操作) | +| 新建账户(录期初结存) | `POST /admin/finance/fund-accounts` | 建户时录账户信息+期初结存 | +| 期初调整 | `POST /admin/finance/fund-accounts/{id}/opening-adjust` | 唯一改期初途径,落 OPENING 留痕流水 | +| 建户表单三组下拉 | `GET /admin/finance/fund-accounts/options` | accountType/nature/channel(字典 fin_fund_account_*) | + +> ⚠️ `opening-adjust` 差额为 0 时返 `595105`(不落流水),**非 200 幂等**——前端需区分「200 调整成功」vs「595105 无需调整」,不要把 595105 当失败弹错。 + +--- + +## 7. 枚举 / 数据字典 + +### 7.1 ledgerType(账套,OpeningLedgerTypeEnum) + +**所属字段**:`ledgerType` | **类型**:`String` | **必填**:✅ + +| 值 | 中文 | 金额字段 | 用于 tab | +|----|------|------|------| +| `SUPPLIER` | 供应商应付(我欠他) | openingPayable | 应付初始化 | +| `CUSTOMER` | 客户应收(他欠我们) | openingReceivable | 应收初始化(往来对象=客户) | +| `SUPPLIER_RECV` | 供应商应收(他欠我们:押金退还/赔偿款/口车费/其他应收) | openingReceivable | 应收初始化(往来对象=供应商) | + +### 7.2 kind(类别) + +**所属字段**:`kind` | **类型**:`String` | **必填**:❌(查询过滤用) + +| 值 | 中文 | 说明 | +|----|------|------| +| `INIT` | 初始 | 首次录入(同对象仅一次) | +| `ADJUST` | 期初调整 | 对已有 INIT 的调整留痕 | + +### 7.3 应收性质(字典 fin_recv_nature,SUPPLIER_RECV 的 customerCategory) + +| 值 | 中文 | +|----|------| +| `DEPOSIT_REFUND` | 押金退还 | +| `COMPENSATION` | 赔偿款 | +| `CAR_FEE` | 口车费 | +| `OTHER` | 其他应收 | + +### 7.4 客户分类(字典 fin_customer_category,CUSTOMER 的 customerCategory) + +经 `GET /admin/dict/all` 或字典接口取 `fin_customer_category` 当前生效值。 + +--- + +## 8. 下拉数据源汇总 + +| 下拉 | 接口 / 字典 | +|---|---| +| 供应商列表 | `GET /admin/supplier/items/list?status=ACTIVE` | +| 公司主体 | `GET /v3/admin/travel-agency/enabled` | +| 客户分类(应收-客户) | 字典 `fin_customer_category` | +| 应收性质(应收-供应商) | 字典 `fin_recv_nature`(押金退还/赔偿款/口车费/其他应收) | +| 资金账户类型/性质/渠道 | `GET /admin/finance/fund-accounts/options` | + +--- + +## 9. 错误码 + +| code | 含义 | 触发场景 | +|------|------|----------| +| 598401 | 同往来对象 INIT 已录过 | 重复新建初始期初 | +| 598403 | 账期已封账 | 封账后新建/调整 | +| 598404 | 须先录初始期初 | 调整时无 INIT 行 | +| 598405 | 期初金额须大于0 | 金额 ≤0 | +| 598407 | 公司主体非法 | companyId 无效 | +| 598408 | 客户分类必填 | CUSTOMER 缺 customerCategory | +| 598409 | 供应商应收性质必填 | SUPPLIER_RECV 缺 customerCategory | +| 598410 | 对象细分取值非法 | customerCategory 不在字典内 | +| 595105 | 期初调整差额为 0 | 现金银行 opening-adjust 无需调整(非错误) | + +--- + +## 10. 修改前后对比 + +| 项 | 改前(当前前端错误) | 改后(对齐原型) | +|---|---|---| +| tab 数 | 4 个 | **3 个** | +| tab 名 | 客户应收/供应商应付/供应商应收/员工往来 | **应收初始化/应付初始化/现金银行初始化** | +| 划分维度 | 往来对象类型 | **初始化场景** | +| 员工往来 tab | 有(多出) | **删除** | +| 供应商应收 | 独立 tab | **并入应收初始化**(往来对象=供应商,ledgerType=SUPPLIER_RECV) | +| 现金银行初始化 | 缺 | **新增**(接 fund-accounts 期初) | + +--- + +## 11. 影响评估 / 回滚 + +- **后端接口变更**:无(零改动,已 deployed) +- **是否破坏向后兼容**:前端页面重构,接口契约不变 +- **前端是否必须同步上线**:是(当前 4 tab 结构与后端账套语义不符,「员工往来」tab 调任何接口都会失败——后端无员工往来账套) + +## 12. 注意事项 + +- 金额字段二选一:应收 tab 填 `openingReceivable`、应付 tab 填 `openingPayable`,**不要同传两个**(后端按 ledgerType 只落对应方向,另一方向忽略)。 +- 记账日期只读、前端不传,后端落当前账期起始日。 +- 同一往来对象 INIT 仅可录一次;要改走「期初调整」。 +- 「现金银行初始化」与「应收/应付初始化」是两套独立接口(fund-accounts vs opening-balances),不要混用。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#8507](https://git.1814.love/wx/HL/issues/8507) / [#8511](https://git.1814.love/wx/HL/issues/8511) +- **PR**: [#8509](https://git.1814.love/wx/HL/pulls/8509) / [#8513](https://git.1814.love/wx/HL/pulls/8513) + +### 13.2 联系人 + +- **后端负责人**: @yst +- **前端对接(管理后台)**: 待认领