# 开账后账单开账水量为零修复验证 ## 基本信息 - 日期:2026-07-31 - 范围:REV-002 抄表开账 / 抄表录入 - 前端基线:`7e0f9b49` - 后端基线:`5d856e4e8` - 变更仓库:`water-frontend`、`water-backend` ## 根因 账单开账水量来自后端 `ReadingDataDO.checkWater`,普通开账时直接写入 `biz_charge.bill_water`。 抄表录入页面保存单条手工抄表时,提交参数使用 `checkWater: row.checkWater || 0`。录入页在保存前只更新 `readWater`,未同步维护 `row.checkWater`,导致普通正水量记录会把空开账水量转换成 `0` 提交到后端。 后端复核逻辑只在 `checkWater == null` 时回退到 `readWater`;当请求已显式传入 `0` 时,会把 `0` 当作有效开账水量保留,最终普通开账将该值写入 `biz_charge.bill_water`。 历史提交定位: - 前端污染源:`0101ef433a2c4a2fcaeaa790ad143de25bc94c48`,作者/提交者 `Linxx`,`2026-06-09 16:20:04 +0800`,`checkWater: row.checkWater || 0`。 - 后端复核保留逻辑:`7fed0d25b812a20cc3179b4eaabe03498f21bf35`,作者/提交者 `tangweijie`,`2026-07-28 17:22:55 +0800`,非空 `checkWater` 原样保留。 - 账单赋值旧逻辑:`076c1759462c05a7624fbf7e7e1d60d152fbf2ed`,作者/提交者 `Shaco-C`,`2025-10-18 23:38:12 +0800`,`charge.setBillWater(readingData.getCheckWater())`。 ## 修复 - `src/views/meterRead/meterEnter/index.vue` - 新增 `calcManualCheckWater(row)`,按 `readWater + replaceWater + refundWater` 计算提交用开账水量。 - `buildManualMeterReadingInfo` 改为提交 `checkWater: calcManualCheckWater(row)`,不再把空值直接置为 `0`。 - `tests/meterRead/meterEnterOverCircleRule.test.mjs` - 增加契约测试,禁止回退到 `checkWater: row.checkWater || 0`。 - `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/readingdata/impl/ReadingDataServiceImpl.java` - 保存手工抄表记录时不再信任请求中的 `checkWater`,统一按 `readWater + replaceWater + refundWater` 写入。 - 复核时如果 `checkWater == 0` 但 `readWater + replaceWater + refundWater` 为正数,则修正为计算后的水量。 - 保留真实零水量场景,例如 `readWater + replaceWater + refundWater == 0`。 - `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/readingdata/ReadingCheckWaterHelper.java` - 集中封装开账水量计算与“污染 0 修复”规则,避免保存、复核、开账各写一套公式。 - `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java` - 开账生成账单前增加兜底修正:同样只修复“计算水量为正但 `checkWater` 为 0”的异常记录。 - 修正后同步 `ReadingDataDO.checkWater`,再继续生成 `ChargeDO.billWater`。 - 通用新建/修改营业账入口增加保护:`readWater + replaceWater` 为正但 `billWater` 为空或 0 时拒绝写入。 - `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/counteraddreading/CounterAddReadingApplicationServiceImpl.java` - 柜台加抄持久化前增加保护:计算水量为正但 `checkWater` 为空、负数或 0 时拒绝写入。 - 后端新增回归用例: - `ReadingDataServiceImplManualReadingTest.processSingleReadingData_shouldCalculateCheckWaterInsteadOfTrustingSubmittedZero` - `ChargeServiceBillingValidationTest.generateChargeBatch_shouldRepairZeroCheckWaterBeforeCreatingChargeWhenReadWaterIsPositive` - `ReadingDataServiceImplCheckValidationTest.batchReCheckReadingData_shouldRepairZeroCheckWaterWhenReadWaterIsPositive` - `ChargeLateFeeBeginDateWiringTest.createCharge_shouldRejectZeroBillWaterWhenReadWaterIsPositive` - `CounterAddReadingApplicationServiceImplTest.validateCounterAddReadingCheckWater_shouldRejectZeroCheckWaterWhenReadWaterIsPositive` ## 验证 前端: ```bash node --test tests/meterRead/meterEnterOverCircleRule.test.mjs src/views/meterRead/meterCheck/zero-water-validation.contract.test.mjs ``` 结果:11 个测试全部通过,0 失败。 补充执行: ```bash node --test tests/meterRead/*.test.mjs src/views/meterRead/meterCheck/zero-water-validation.contract.test.mjs ``` 结果:18 个测试通过,1 个既有失败。失败用例为 `tests/meterRead/bookAdjustBehavior.test.mjs` 的册本调整取消用户过滤契约,与本次开账水量提交链路无关。 后端: ```bash mvn -pl sw-business/sw-business-server -Dtest=ChargeServiceBillingValidationTest#generateChargeBatch_shouldRepairZeroCheckWaterBeforeCreatingChargeWhenReadWaterIsPositive test ``` 结果:未进入目标测试,模块编译被既有错误阻塞: - `CustApiImpl.java:[348,30] cannot find symbol getWorkerOrderId()` - `OpenApiConfiguration.java:[24,53] cannot find symbol OPEN_API_AUTHENTICATION_FILTER` ```bash mvn -pl sw-business/sw-business-server -Dtest=ReadingDataServiceImplCheckValidationTest#batchReCheckReadingData_shouldRepairZeroCheckWaterWhenReadWaterIsPositive test ``` 结果:同样被上述模块编译错误阻塞。 ```bash mvn -pl sw-business/sw-business-server -Dtest=ReadingDataServiceImplManualReadingTest#processSingleReadingData_shouldCalculateCheckWaterInsteadOfTrustingSubmittedZero test ``` 结果:同样被上述模块编译错误阻塞。 ```bash mvn -pl sw-business/sw-business-server -Dtest=ReadingDataServiceImplManualReadingTest#processSingleReadingData_shouldCalculateCheckWaterInsteadOfTrustingSubmittedZero,ReadingDataServiceImplCheckValidationTest#batchReCheckReadingData_shouldRepairZeroCheckWaterWhenReadWaterIsPositive,ChargeServiceBillingValidationTest#generateChargeBatch_shouldRepairZeroCheckWaterBeforeCreatingChargeWhenReadWaterIsPositive,ChargeLateFeeBeginDateWiringTest#createCharge_shouldRejectZeroBillWaterWhenReadWaterIsPositive,CounterAddReadingApplicationServiceImplTest#validateCounterAddReadingCheckWater_shouldRejectZeroCheckWaterWhenReadWaterIsPositive test ``` 结果:同样未进入目标测试,模块编译仍被上述 2 个既有错误阻塞;未出现本次新增 helper 或校验相关的新编译错误。 空白检查: ```bash git diff --check -- <本次触及文件> ``` 结果:无输出。