From 719f75f8c735c80b67f1393fa742e43e524bbebd Mon Sep 17 00:00:00 2001 From: tangweijie <877588133@qq.com> Date: Fri, 31 Jul 2026 11:12:00 +0800 Subject: [PATCH] docs: record billing water zero fix evidence --- ...-31-meter-entry-check-water-zero-bugfix.md | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/evidence/rev002-billing/2026-07-31-meter-entry-check-water-zero-bugfix.md diff --git a/docs/evidence/rev002-billing/2026-07-31-meter-entry-check-water-zero-bugfix.md b/docs/evidence/rev002-billing/2026-07-31-meter-entry-check-water-zero-bugfix.md new file mode 100644 index 0000000..c317066 --- /dev/null +++ b/docs/evidence/rev002-billing/2026-07-31-meter-entry-check-water-zero-bugfix.md @@ -0,0 +1,104 @@ +# 开账后账单开账水量为零修复验证 + +## 基本信息 + +- 日期: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 -- <本次触及文件> +``` + +结果:无输出。