fujian_water_biz_doc/docs/superpowers/specs/2026-06-08-revenue-bugfix-clear-scope-design.md

169 lines
7.7 KiB
Markdown
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.

# 营收明确缺陷第一批修复设计
日期2026-06-08
## 背景
本设计用于收敛当前营收缺陷中代码证据最明确、可闭环验收的一批问题。前期排查表明,部分缺陷并非单纯后端写库失败,而是前后端接口契约、页面状态文案、查询语义和锁恢复流程不一致导致用户认为“成功但未生效”或“查不到记录”。
本轮不改变账务调整审批规则,不把待审批动作改成即时落账;目标是让系统行为与用户提示一致,并补齐明确漏查和重试闭环。
## 修复范围
本轮纳入以下缺陷:
- `#78` 水价调整:执行报错后,用户不应只能关闭菜单从头开始。
- `#39` 柜台结账:柜台预存缴费记录应能进入待结清并完成结账。
- `#50` 柜台结账:收费员筛选不应被后端无条件覆盖为当前登录用户。
- `#53` 柜台收费:预存抵扣金额需要前后端契约保护和回归验证。
- `#58/#59` 红冲记录:柜台红冲后应能在红冲记录页按红冲时间查到。
- `#69/#76` 未销分账、呆坏账:前端应准确表达“申请已提交,待审批/待回写”,不得提示为已生效。
以下缺陷不进入本轮实现,仅保留后续复现或产品确认:
- `#70` 未销调整提示成功但账单未变:现有后端金额/水量调整路径会写回,需要先抓请求体确认字段和值。
- `#9` 抄表状态修改无影响:需要产品确认状态配置影响已生成任务还是仅影响后续任务。
## 设计原则
1. 保持最小闭环,不重构完整账务调整体系。
2. 保留现有审批流语义,修正文案和状态展示,不把待审批改为立即落账。
3. 查询接口按业务语义返回数据,页面筛选字段与后端字段一致。
4. 后端对关键金额和状态做兜底校验,前端负责交互提示和用户确认。
5. 所有修改需要有最小单测、前端合约测试或页面 smoke 覆盖。
## 后端设计
### 水价调整锁恢复
`PriceTemplateServiceImpl.updatePriceTemplate()` 继续保持执行完成后释放调价锁的总体策略,但失败路径需要让前端能够明确恢复:
- 后端异常响应保持业务错误信息可读。
- 前端失败后重新进入 `startAdjustment()` 流程获取新锁。
- `PriceTemplateAdjustmentLockRedisDAO.refreshLock()` 不再采用 `forceUnlock()` 后重新 `tryLock()` 的刷新模式,改为安全续期,避免刷新瞬间锁被其他用户抢占。
### 柜台预存缴费进入结账
`PaymentRecordMapper.selectCounterUnsettledRecords()` 从仅查询 `CHARGE_PAYMENT` 扩展为同时包含 `DEPOSIT_TOPUP`
- `CHARGE_PAYMENT` 表示账单收费记录。
- `DEPOSIT_TOPUP` 表示柜台预存充值记录。
`CounterSettleApplicationServiceImpl.confirm()` 需要支持预存充值记录无营业账 ID
- 结账总金额仍以 `PaymentRecord.paymentAmount` 汇总。
- 写入结账明细时,`chargeId``billMonth` 可为空。
- `chargeMapper.markCounterSettled()` 只处理真实账单收费记录对应的 `chargeIds`
### 收费员筛选
柜台结账查询的收费员解析规则改为:
- 请求 `cashierId` 为空时,默认使用当前登录用户。
- 请求 `cashierId` 非空时,使用请求值查询。
- 如后续接入完整数据权限,可在此基础上限制普通用户只能查自己、管理员可查指定收费员。本轮先不让后端无条件覆盖前端筛选值。
### 预存抵扣校验
柜台收费继续由前端传入 `prepayDeductAmount`
- 后端校验抵扣金额不得小于 0。
- 抵扣金额不得超过账单应收金额。
- 抵扣金额不得超过账户预存余额。
- 抵扣金额大于 0 时扣减账户余额,并在支付记录 `extJson` 中保留 `prepayDeductAmount`
本轮不启用后端自动计算抵扣金额,避免改变用户输入语义。
### 柜台红冲记录查询
红冲记录页应基于柜台结账红冲链路展示,而不是复用账务调整日志:
- 查询来源为 `settle_record``settle_record_detail``payment_record` 的柜台红冲结果。
- 默认包含部分红冲和全部红冲状态。
- 日期筛选使用红冲时间 `reversedTime`,而不是账务日志的创建时间或处理时间。
- 返回字段至少包含结账单号、收费员、客户、红冲金额、红冲时间、红冲原因。
## 前端设计
### 水价调整失败恢复
水价调整提交失败后,前端不再只把页面退出调整态。推荐交互:
1. 显示调价失败原因。
2. 自动调用 `startAdjustment()` 尝试重新获取锁。
3. 重新获取成功时保留当前页面数据,提示用户可继续修正后提交。
4. 重新获取失败时提示锁被占用或已过期,并引导用户重新开始调价。
### 待审批动作状态文案
未销分账、呆坏账、价差调整、违约金减免等提交后,根据响应状态显示文案:
- `approvalRequired=true``resultStatus=PENDING_APPROVAL`:显示“申请已提交,待审批”。
- `writeBackStatus=PENDING`:显示“待回写”或“待执行”,不刷新为已生效。
- `resultStatus=SUCCESS``writeBackStatus=UPDATED`:显示“处理完成”。
页面不得仅用“提交成功”表达所有结果。
### 柜台结账页面
未结账列表需要正常展示预存充值记录:
-`chargeId``billMonth` 时显示 `--`
- 客户、收费员、金额、缴费时间正常展示。
- 结账确认汇总包含预存充值金额。
收费员筛选继续保留,前端传入的 `cashierId` 应与后端查询语义一致。
### 红冲记录页面
红冲记录页面改为柜台红冲记录视图:
- 查询接口改为柜台红冲记录接口。
- 日期筛选标签改为“红冲时间”。
- 参数使用 `beginReversedTime``endReversedTime`
- 列表展示柜台红冲相关字段,不再按账务调整日志字段组织。
### 预存抵扣交互
柜台收费页面保留当前按选中账单分摊 `prepayDeductAmount` 的逻辑,并补充交互保护:
- 抵扣金额不得超过预存余额。
- 抵扣金额不得超过选中账单应收合计。
- 用户开启预存抵扣但计算抵扣为 0 时,提交前给出明确提示或确认。
## 测试设计
### 后端测试
- 水价调整:覆盖失败后前端可重新开始调价;覆盖刷新锁不释放抢占。
- 柜台结账:覆盖 `CHARGE_PAYMENT``DEPOSIT_TOPUP` 都进入未结账;覆盖预存记录结账时不要求 `chargeId`
- 收费员筛选:覆盖请求 `cashierId` 非空时后端按请求值查询。
- 预存抵扣:覆盖正常抵扣、余额不足、非法金额。
- 红冲记录:覆盖红冲状态默认可查,按 `reversedTime` 范围筛选。
### 前端测试
- 水价调整提交失败后重新获取锁或展示重获锁失败提示。
- 分账和呆坏账返回待审批时提示“申请已提交,待审批”。
- 柜台结账未结账列表能展示预存充值记录。
- 红冲记录页调用柜台红冲记录接口,并按红冲时间传参。
- 预存抵扣开启但抵扣金额为 0 时出现确认或提示。
## 验收标准
1. 用户在水价调整报错后无需关闭菜单即可继续修正并重新提交。
2. 柜台预存缴费能在柜台结账待结清列表中查询并完成结账。
3. 柜台结账收费员筛选不再无条件固定为当前登录用户。
4. 柜台红冲成功后,红冲记录页可按红冲时间查询到记录。
5. 分账、呆坏账等待审批动作不再被前端表达为已生效。
6. 预存抵扣金额写入支付记录并扣减账户余额,非法金额有明确错误。
## 实施边界
本设计不包含以下内容:
- 不重构完整 REV004 账务调整状态机。
- 不新增完整 BPM 审批能力。
- 不修改呆坏账、分账从待审批到已执行的业务规则。
- 不处理未复现的 `#70` 和产品规则未确认的 `#9`