--- schema: "hl-changelog/v2" ticket: "8626" title: "司导往来账账页+明细分页两接口上线:按带团服务人员聚合报账+预支净往来(role 取值含摄影/领队)" consumer: "admin" author: "yst(GIT)" change_type: "新增接口" backend_status: "deployed" gateway_status: "not_required" frontend_status: "implemented" frontend_owner: "hl-admin" frontend_ref: "1a337d86d556062cd78daf7a94ba3a42ac310dce" target_release: "v2.1" verified_at: "2026-09-30" status_note: "财务往来账新增「司导往来账」两个只读查询接口(/admin/finance/statements/guide-ledger/page 账页 + /entries 明细),按带团服务人员(司导)聚合其报账单+预支单现算净往来,纯查询零 DDL、不动 fin_statement_entry、不接上游流水钩子。口径要点:①司导=带团服务人员(导游 GUIDE/司机 DRIVER/摄影 PHOTOGRAPHER/领队 LEADER,均非内部员工),员工借款 fin_staff_loan 不纳入;②净往来只算已生效报账单(排除 PENDING 未批准/RETURNED 已退回),预支算 APPROVED/PAID;③聚合键=报账人/收款人姓名快照(reporterAssignmentId 与 payeeStaffId 分属两套 ID 空间无法 join);④netBalance 正=司导欠公司、负=公司欠司导。两接口入参/出参/枚举/错误码自 2026-09-30 上线起即为本文口径,无历史版本。前端无既有调用,纯新对接。前端已交付:statement.js 加司导段(API 层 page→pageNo,字典四 role/两 bizType/三 direction/PAID 分文案);新建 current-account/guide 页内 v-if 双视图(账页 netBalance 三态+明细三选一标识原样带回);hiddenRoute 先行(后端 sys_menu 未下挂,预期 component=finance/current-account/guide)。" updated_at: "2026-09-30" base: "dev-v3" --- # finance:司导往来账账页 + 明细分页(管理后台) **服务**: hl-order-service-v3(finance 模块,同进程) **PR**: https://git.1814.love/wx/HL/pulls/8574 (账页初版) + https://git.1814.love/wx/HL/pulls/8627 (口径扩摄影/领队) **Issue**: https://git.1814.love/wx/HL/issues/8555 + https://git.1814.love/wx/HL/issues/8626 --- ## 一、接口背景 管理后台「财务 → 往来账」需要一本**司导往来账**:以「带团服务人员(司导)」为单位,把该人的**报账单**(多退少补结算净额)和**预支单**(借款挂账)合并,现算出他当前与公司的净往来余额(谁欠谁、欠多少),并能下钻看每一笔单据。 此前往来账只有供应商一本(`fin_statement_entry`),且只接通应付/预付源;司导/员工的报账、预支走的是另一套表(`fin_reimburse` / `fin_advance`),没有按人聚合的账页。本期新增两个只读接口补齐,**纯查询聚合、零 DDL、不改任何既有账表**。 --- ## 二、变更清单 | 项 | 变更 | |---|---| | `GET /admin/finance/statements/guide-ledger/page` | **新增**:司导往来账账页分页(按人聚合) | | `GET /admin/finance/statements/guide-ledger/entries` | **新增**:司导往来明细分页(报账+预支合并,按日期倒序) | | 出参 `role` 取值集合 | 司导角色快照,取值 ∈ `GUIDE/DRIVER/PHOTOGRAPHER/LEADER`(带团服务人员) | | 数据库表 | 零 DDL | > 这两个接口是**首次上线**,前端无既有调用,按新对接处理即可。 --- ## 三、接口详情 | 端点 | 方法 | 说明 | |---|---|---| | `/admin/finance/statements/guide-ledger/page` | GET | 账页:每个司导一行,聚合其报账净额 + 预支挂账,现算净往来余额 | | `/admin/finance/statements/guide-ledger/entries` | GET | 明细:某个司导名下的报账单+预支单逐笔列出,按单据日期倒序 | --- ## 四、接口入参 ### 4.1 `GET /page`(`GuideLedgerPageReqVO`) | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `pageNo` | int | ✅ | 页码,从 1 开始 | | `pageSize` | int | ✅ | 每页条数 | | `keyword` | string | ❌ | 司导姓名(模糊,匹配报账人/收款人姓名快照);空=不限 | | `onlyOutstanding` | boolean | ❌ | true=只看有往来的司导(净往来≠0 或有未结清单据);默认 false | > 账页**暂无 role 过滤入参**(角色只在出参 `role` 体现);如需按角色过滤,前端可本地过滤或后续提需求加参。 ### 4.2 `GET /entries`(`GuideLedgerEntryReqVO`) | 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | `pageNo` | int | ✅ | 页码 | | `pageSize` | int | ✅ | 每页条数 | | `reporterAssignmentId` | long | 三选一 | 报账人人员分配 ID(账页行 `reporterAssignmentId` 原样带回) | | `payeeStaffId` | long | 三选一 | 收款人员工 ID(账页行 `payeeStaffId` 原样带回) | | `reporterName` | string | 三选一 | 司导姓名(账页行 `staffName` 原样带回,精确匹配) | | `bizType` | string | ❌ | 单据类型过滤:`REIMBURSE` 只看报账 / `ADVANCE` 只看预支;空=两者都要 | > **司导标识三选一必填**(`reporterAssignmentId` / `payeeStaffId` / `reporterName` 至少填一个,全空 → 596010)。由前端从账页行**原样带回**;匹配规则:ID 精确 或 姓名精确,任一命中即归属该司导。 --- ## 五、接口出参 ### 5.1 账页行(`GuideLedgerRowRespVO`,`data.records[]`) | 字段 | 类型 | 说明 | |---|---|---| | `reporterAssignmentId` | long(string) | 报账人人员分配 ID 快照(明细下钻回传用;可空) | | `payeeStaffId` | long(string) | 收款人员工 ID 快照(预支线,明细下钻回传用;可空) | | `staffName` | string | 司导姓名(聚合键) | | `role` | string | 角色快照(`GUIDE` 导游 / `DRIVER` 司机 / `PHOTOGRAPHER` 摄影 / `LEADER` 领队;同一人多角色取任一非空;纯预支无报账可空) | | `reimburseReceivableTotal` | number | 报账应收合计(RECEIVABLE 方向净额合计,司导欠公司) | | `reimbursePayableTotal` | number | 报账应付合计(PAYABLE 方向净额绝对值合计,公司欠司导) | | `advanceTotal` | number | 预支挂账合计(APPROVED/PAID 预支金额合计,多退少补待核单轧差) | | `netBalance` | number | **净往来余额(正=司导欠公司 / 负=公司欠司导 / 0=两清)** | | `outstandingCount` | int | 未结清单据数(报账未两清终态单数 + 预支在途单数) | ### 5.2 明细行(`GuideLedgerEntryRespVO`,`data.records[]`) | 字段 | 类型 | 说明 | |---|---|---| | `id` | long(string) | 单据 ID(REIMBURSE=reimburse_id / ADVANCE=advance_id) | | `bizType` | string | 单据类型:`REIMBURSE` 报账 / `ADVANCE` 预支 | | `bizNo` | string | 单号(报账单号 BZ- / 预支单号 YZ-) | | `orderNo` | string | 团号(订单号快照;可空) | | `amount` | number | 金额(报账=结算金额 \|净额\|,预支=预支金额,恒正) | | `direction` | string | 方向:`PAYABLE` 公司欠司导 / `RECEIVABLE` 司导欠公司 / `BALANCED` 两清(预支恒 RECEIVABLE) | | `status` | string | 单据状态(报账 PENDING/APPROVED/PARTIAL_RECEIVED/PAID/RECEIVED/CLOSED;预支 APPROVED/PAID) | | `bizDate` | datetime | 单据日期(推送生成时间) | > 分页结构:`data.records[]` + `data.total` + `data.page` + `data.pageSize`(PageResult,**注意是 `records` 不是 `list`**)。 > 长整型 ID(`reporterAssignmentId`/`payeeStaffId`/`id`)JSON 序列化为字符串,前端按字符串处理防精度丢失。 --- ## 六、枚举 / 数据字典 ### role 司导角色(快照值,非字典) `GUIDE` 导游 / `DRIVER` 司机 / `PHOTOGRAPHER` 摄影师 / `LEADER` 领队 > 口径:带团服务人员,**均非内部员工**;其余角色(含内部员工)不进司导往来账。员工借款 fin_staff_loan 不纳入。 ### bizType 单据类型 `REIMBURSE` 报账 / `ADVANCE` 预支 ### direction 方向 `PAYABLE` 公司欠司导 / `RECEIVABLE` 司导欠公司 / `BALANCED` 两清 ### status 单据状态(状态机枚举,各源不同) - 报账:`PENDING` 待复核 / `APPROVED` 已批准 / `PARTIAL_RECEIVED` 部分回款 / `PAID` 已付讫 / `RECEIVED` 已回款 / `CLOSED` 已两清(`RETURNED` 已退回不计入往来) - 预支:`APPROVED` 已批准 / `PAID` 已付款 --- ## 七、错误码 | 码 | 含义 | |---|---| | 596010 | 司导标识缺失(entries 三选一全空) | --- ## 八、示例 ### 8.1 账页(典型) ``` GET /admin/finance/statements/guide-ledger/page?pageNo=1&pageSize=10 ``` ```json { "code": 200, "data": { "records": [ { "reporterAssignmentId": null, "payeeStaffId": "2100747615736897537", "staffName": "刘大山", "role": null, "reimburseReceivableTotal": 0, "reimbursePayableTotal": 0, "advanceTotal": 260.00, "netBalance": 260.00, "outstandingCount": 1 } ], "total": 1, "page": 1, "pageSize": 10 } } ``` ### 8.2 明细分页(按收款人 ID 下钻) ``` GET /admin/finance/statements/guide-ledger/entries?pageNo=1&pageSize=10&payeeStaffId=2100747615736897537 ``` ```json { "code": 200, "data": { "records": [ { "id": "2201...", "bizType": "ADVANCE", "bizNo": "YZ-202609290001", "orderNo": null, "amount": 260.0, "direction": "RECEIVABLE", "status": "APPROVED", "bizDate": "2026-09-29T10:00:00" } ], "total": 1, "page": 1, "pageSize": 10 } } ``` ### 8.3 业务失败(entries 三选一全空 → 596010) ``` GET /admin/finance/statements/guide-ledger/entries?pageNo=1&pageSize=10 ``` ```json { "code": 596010, "message": "司导标识缺失" } ``` --- ## 九、业务边界 - **纯查询聚合**:两接口只读,不写任何表、不改 fin_statement_entry、不接上游流水钩子;净往来为现算不落列。 - **只算生效单**:报账单排除 PENDING(未批准不生效)与 RETURNED(已退回,由 version_no+1 新单承接防双算);预支算 APPROVED/PAID。 - **聚合键=姓名快照**:reporterAssignmentId(order 域人员分配 ID)与 payeeStaffId(员工 ID)分属两套 ID 空间无法 join,故按报账人/收款人姓名快照聚合;姓名缺失时退化按 ID 单列。 - **净额方向**:netBalance 正=司导欠公司、负=公司欠司导、0=两清。报账 PAYABLE 方向(公司欠司导)取净额绝对值计入 reimbursePayableTotal。 - **不含员工借款**:司导/摄影/领队均非内部员工,fin_staff_loan 不纳入。 --- ## 十、修改前后对比 新增接口,无修改前版本。 | 维度 | 说明 | |---|---| | 接口 | 首次上线,前端无既有调用 | | role 取值 | 上线即为 4 角色(GUIDE/DRIVER/PHOTOGRAPHER/LEADER),无历史 2 角色版本对外暴露 | --- ## 十一、影响评估 / 回滚 - 后端:新增两个只读端点,零 DDL、零既有逻辑改动;回滚=下线两接口(前端无依赖)。 - 前端:纯新对接,无回归面。 - 数据库:无变更。 --- ## 十二、注意事项 - 分页结构是 `data.records[]`(PageResult),**不是 `list`**,前端取数组时注意。 - 长整型 ID 序列化为字符串,按字符串处理。 - entries 下钻时,账页行的 `reporterAssignmentId`/`payeeStaffId`/`staffName` **原样带回**即可(三选一,无需自己拼)。 - `role` 可能为 null(纯预支无报账的司导),前端渲染时对 null 做兜底(显示「-」或留空),不要假设非空。 --- ## 十三、关联 / 联系人 ### 13.1 链接 - 账页初版 PR:https://git.1814.love/wx/HL/pulls/8574 - 口径扩展 PR:https://git.1814.love/wx/HL/pulls/8627 - Issue:https://git.1814.love/wx/HL/issues/8555 、https://git.1814.love/wx/HL/issues/8626 ### 13.2 联系人 - 后端 / 财务域:yst(腰苏图)