fujian_water_biz_doc/docs/evidence/rev004-accounting/late-fee-start-and-daily-recalculation-2026-06-30.md

114 lines
7.4 KiB
Markdown

# Late Fee Start Date and Daily Recalculation Evidence (2026-06-30)
## Scope
- Backend feature: late-fee start-date calculation for four configured modes, billing-time persistence, and daily recalculation for unpaid charges.
- Backend branch: `feat/late-fee-recalc`, merged locally into `develop`
- Backend merge commit: `4f1a99b7e Merge branch 'feat/late-fee-recalc' into develop`
- Docs branch: `feat/rev004-dict-alignment-docs`
## Backend Commits
- `8c2714af2 feat: add late fee begin date calculator`
- `1724f0c3c feat: resolve late fee parameter config`
- `282c327e7 feat: add late fee daily calculator`
- `320e50d73 feat: add late fee recalculation mapper helpers`
- `fd5154f83 feat: save late fee begin date during billing`
- `f7207fe61 feat: add daily late fee recalculation job`
- `af05601f1 fix: harden late fee recalculation batch`
- `3722c54fa fix: paginate late fee recalculation batches`
- `d551dba84 fix: handle late fee reversal and batch transactions`
- `bcc635e81 fix: guard late fee recalculation updates`
## Implemented Files
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeSettingCodes.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeConfig.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeConfigResolver.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeBeginDateCalculator.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeBeginDateApplyService.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeDailyCalculator.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeRecalculationBatchService.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/latefee/LateFeeRecalculationService.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/job/charge/LateFeeRecalculationJob.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/config/ClockConfig.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/mysql/charge/ChargeMapper.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/mysql/paymentrecorddetail/PaymentRecordDetailMapper.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/mysql/latefeereducedetail/LateFeeReduceDetailMapper.java`
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java`
- `script/xxl-job-init.sql`
- `sql/rev004/REV004_late_fee_daily_recalculation_index.sql`
- Unit tests under `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/latefee/`
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeLateFeeBeginDateWiringTest.java`
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackServiceTest.java`
## Review Fixes
- Paid late-fee deduction excludes original `APPLIED` late-fee details that have a `REVERSED` detail referencing them through `relatedDetailId`.
- The daily recalculation batch now selects unpaid charges with non-null `lateFeeBeginDate`, avoiding repeated starvation behind historical rows that cannot be recalculated.
- `script/xxl-job-init.sql` registers handler `lateFeeDailyRecalculation` for business-server with cron `0 30 3 * * ?`.
- `LateFeeRecalculationServiceTest` includes a defensive scenario where a reversed late-fee detail is returned by the mapper and ignored by aggregation.
- The daily recalculation job now uses keyset pagination (`id > lastId`) until no eligible rows remain, so rows after the first page are recalculated in the same run instead of waiting forever behind unchanged earlier rows.
- `LateFeeBeginDateApplyService` centralizes `lateFeeBeginDate` persistence and is reused by normal billing, manual charge creation, counter add-reading formalization, and special billing formalization before `chargeMapper.insert`.
- Focused tests now cover the shared begin-date apply service, keyset pagination across batches, and direct insert path wiring for counter add-reading and special billing.
- Price-diff write-back now applies missing `lateFeeBeginDate` before inserting the replacement unpaid charge.
- Daily recalculation now keeps the outer pagination loop non-transactional and executes each page through `LateFeeRecalculationBatchService.recalculateBatch(...)` with its own transaction boundary.
- Daily recalculation now updates `lateFee` through a conditional mapper update that still requires `payState=UNPAID` and non-null `lateFeeBeginDate`, so a charge paid after selection is not overwritten or counted.
- `LateFeeDailyCalculator` ignores non-positive penalty coefficients defensively.
- `REV004_late_fee_daily_recalculation_index.sql` adds `idx_biz_charge_late_fee_recalc` on `(tenant_id, pay_state, id)` for the tenant-scoped unpaid keyset scan.
## Verification
### Focused Late-Fee Tests
Command:
```bash
mvn -pl sw-business/sw-business-server -am -Dtest=LateFeeBeginDateCalculatorTest,LateFeeBeginDateApplyServiceTest,LateFeeConfigResolverTest,LateFeeDailyCalculatorTest,LateFeeRecalculationServiceTest,ChargeLateFeeBeginDateWiringTest,CounterAddReadingApplicationServiceImplTest,SpecialBillingServiceImplTest,PriceDiffWriteBackServiceTest -Dsurefire.failIfNoSpecifiedTests=false test
```
Result: PASS
- `LateFeeBeginDateApplyServiceTest`: 2 tests, 0 failures, 0 errors, 0 skipped
- `LateFeeRecalculationServiceTest`: 8 tests, 0 failures, 0 errors, 0 skipped
- `LateFeeConfigResolverTest`: 3 tests, 0 failures, 0 errors, 0 skipped
- `LateFeeBeginDateCalculatorTest`: 7 tests, 0 failures, 0 errors, 0 skipped
- `LateFeeDailyCalculatorTest`: 9 tests, 0 failures, 0 errors, 0 skipped
- `ChargeLateFeeBeginDateWiringTest`: 5 tests, 0 failures, 0 errors, 0 skipped
- `PriceDiffWriteBackServiceTest`: 1 test, 0 failures, 0 errors, 0 skipped
- `CounterAddReadingApplicationServiceImplTest`: 24 tests, 0 failures, 0 errors, 0 skipped
- `SpecialBillingServiceImplTest`: 4 tests, 0 failures, 0 errors, 0 skipped
- Total: 63 tests, 0 failures, 0 errors, 0 skipped
### Existing Accounting Regression Tests
Command:
```bash
mvn -pl sw-business/sw-business-server -am -Dtest=LateFeeDateModeCalculatorTest,PaymentRecordServiceImplTest,AccountingAdjustActionServiceImplTest,ChargeServiceBillingValidationTest -Dsurefire.failIfNoSpecifiedTests=false test
```
Result: PASS
- `ChargeServiceBillingValidationTest`: 8 tests, 0 failures, 0 errors, 0 skipped
- `LateFeeDateModeCalculatorTest`: 4 tests, 0 failures, 0 errors, 0 skipped
- `AccountingAdjustActionServiceImplTest`: 19 tests, 0 failures, 0 errors, 0 skipped
- `PaymentRecordServiceImplTest`: 18 tests, 0 failures, 0 errors, 0 skipped
- Total: 49 tests, 0 failures, 0 errors, 0 skipped
### Compile
Command:
```bash
mvn -pl sw-business/sw-business-server -am -DskipTests compile
```
Result: PASS
## Known Warnings
- Maven reports existing effective-model warnings for duplicate or missing plugin declarations in unrelated modules.
- Mockito reports the existing dynamic-agent warning during unit tests.
- These warnings did not fail the executed verification commands.