1045 lines
41 KiB
Markdown
1045 lines
41 KiB
Markdown
# REV-004 Unsold Preview Options Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** Make unsold-adjust preview checkbox options flow into formal submission, audit records, and final write-back calculation consistently.
|
||
|
||
**Architecture:** Keep the existing REV-004 unsold-adjust endpoints and services. Extend the current VO/DTO/formalization/write-back chain so preview options are explicit formal adjustment parameters instead of transient preview-only flags.
|
||
|
||
**Tech Stack:** Java 17, Spring Boot, MyBatis Plus, JUnit 5, Mockito, Maven, Markdown evidence in `../water-docs`.
|
||
|
||
---
|
||
|
||
## File Structure
|
||
|
||
Backend files:
|
||
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustUnsoldAdjustSubmitReqVO.java`
|
||
- Add formal water-adjust options `updateAccumulated` and `updateBaseCode`.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustSubmitReqVO.java`
|
||
- Carry water-adjust options through accountProcess services.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/AccountingAdjustActionController.java`
|
||
- Map water and price-diff option fields from endpoint-specific VO to unified submit VO.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/charge/vo/AccountingAdjustReqVO.java`
|
||
- Carry water-adjust options into `ChargeServiceImpl`.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImpl.java`
|
||
- Pass water-adjust options into legacy/core adjustment request.
|
||
- Pass price-diff options into formal create DTO.
|
||
- `sw-business/sw-business-api/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/dto/PriceDiffAdjustCreateReqDTO.java`
|
||
- Add `calculateGarbageFee` and `updateAccumulatedVolume`.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/PriceDiffAdjustInternalApiImpl.java`
|
||
- Move price-diff options from API DTO to formalization VO.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/dataobject/pricediffadjustdetail/PriceDiffAdjustDetailDO.java`
|
||
- Add `calculateGarbageFee` and `updateAccumulatedVolume`.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationService.java`
|
||
- Persist all price-diff option values in formal detail rows.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/AccountingAdjustActionServiceImpl.java`
|
||
- Read price-diff options from formal/log detail and send them into write-back.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackService.java`
|
||
- Align default option semantics with preview and apply `updateAccumulatedVolume`.
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java`
|
||
- Apply formal water-adjust options and record option values in operation log details.
|
||
|
||
Backend test files:
|
||
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/AccountingAdjustActionControllerTest.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImplTest.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationServiceTest.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackServiceTest.java`
|
||
|
||
Docs files:
|
||
|
||
- `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md`
|
||
|
||
## Task 0: Preserve Current Usage-Adjustment Fix
|
||
|
||
**Files:**
|
||
- Modify: `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-usage-adjust-zero-and-recovery-2026-06-19.md`
|
||
- Existing backend changes:
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImpl.java`
|
||
- `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImplTest.java`
|
||
- `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java`
|
||
|
||
- [ ] **Step 1: Confirm the current backend diff only contains the prior usage-adjustment fix**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git status --short
|
||
git diff -- sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImpl.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImplTest.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java
|
||
```
|
||
|
||
Expected:
|
||
|
||
- `UnsoldTrialPreviewServiceImpl` accepts zero target water and rejects negative target water.
|
||
- `ChargeServiceImpl` allows target water above read/check water only for supplementary/recovery reasons.
|
||
- Tests cover zero-water preview and supplementary reading recovery.
|
||
|
||
- [ ] **Step 2: Re-run the already-passing validation**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=UnsoldTrialPreviewServiceImplTest,ChargeServiceAccountingAdjustTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
Tests run: 36, Failures: 0, Errors: 0, Skipped: 0
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 3: Add evidence for the prior usage-adjustment fix**
|
||
|
||
Create `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-usage-adjust-zero-and-recovery-2026-06-19.md`:
|
||
|
||
```markdown
|
||
# REV-004 未销水量调整零水量与补抄追收验证记录
|
||
|
||
## 变更范围
|
||
|
||
- 按水量调整预算允许 `targetBillWater=0`,仍拒绝负数水量。
|
||
- 正式水量调整默认保留“调整后水量不能超过抄见水量”限制。
|
||
- 当原因编码或原因说明属于补抄、追收、漏抄、少抄、估抄偏低、补征等场景时,允许目标水量超过原抄见水量。
|
||
|
||
## 验证命令
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=UnsoldTrialPreviewServiceImplTest,ChargeServiceAccountingAdjustTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
## 验证结果
|
||
|
||
- `UnsoldTrialPreviewServiceImplTest`: 12 tests, 0 failures, 0 errors.
|
||
- `ChargeServiceAccountingAdjustTest`: 24 tests, 0 failures, 0 errors.
|
||
- Maven reactor: `BUILD SUCCESS`.
|
||
|
||
## 风险说明
|
||
|
||
- 本次未放开已收费、已开票、已结账、缺少抄表依据、缺少附件等既有校验。
|
||
- 补抄追收白名单为后端兼容策略,后续可在正式原因字典稳定后收敛为字典值校验。
|
||
```
|
||
|
||
- [ ] **Step 4: Commit the prior usage-adjustment fix**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImpl.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/trial/UnsoldTrialPreviewServiceImplTest.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java
|
||
git commit -m "fix(accounting): relax unsold usage adjust water validation"
|
||
```
|
||
|
||
Then in docs repo:
|
||
|
||
```bash
|
||
git -C ../water-docs add docs/evidence/rev004-accounting/rev004-unsold-usage-adjust-zero-and-recovery-2026-06-19.md
|
||
git -C ../water-docs commit -m "docs(accounting): record unsold usage adjust validation evidence"
|
||
```
|
||
|
||
Expected:
|
||
|
||
- Backend and docs commits are separate.
|
||
- `git status --short` in backend is clean before Task 1 starts.
|
||
|
||
## Task 1: Add Water-Adjust Option Fields to Request Chain
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustUnsoldAdjustSubmitReqVO.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustSubmitReqVO.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/charge/vo/AccountingAdjustReqVO.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/AccountingAdjustActionController.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImpl.java`
|
||
- Test: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImplTest.java`
|
||
|
||
- [ ] **Step 1: Write failing service mapping test**
|
||
|
||
Add this test to `AccountingAdjustProcessServiceImplTest` near the existing `createUnsoldAdjust_shouldDelegateUsageAdjustToUnifiedChargeService` test:
|
||
|
||
```java
|
||
@Test
|
||
void createUnsoldAdjust_shouldPassWaterOptionFlagsToUnifiedChargeService() {
|
||
AccountingAdjustSubmitReqVO reqVO = new AccountingAdjustSubmitReqVO();
|
||
reqVO.setChargeId(15801L);
|
||
reqVO.setTargetBillWater(new BigDecimal("0.000"));
|
||
reqVO.setReasonCode("REV004_USAGE_FIX");
|
||
reqVO.setReason("零水量更正");
|
||
reqVO.setAttachmentRefs(List.of("proof-001"));
|
||
reqVO.setUpdateAccumulated(true);
|
||
reqVO.setUpdateBaseCode(true);
|
||
reqVO.setCurrentReading(new BigDecimal("1234.000"));
|
||
|
||
AccountingAdjustRespVO expected = AccountingAdjustRespVO.of(
|
||
"REV004-15801-20260619110000",
|
||
null,
|
||
"SUCCESS",
|
||
false,
|
||
"NOT_REQUIRED",
|
||
"UPDATED",
|
||
"REV004-15801-20260619110000",
|
||
"水量调整成功"
|
||
);
|
||
when(chargeService.adjustAccounting(any(AccountingAdjustReqVO.class))).thenReturn(expected);
|
||
|
||
AccountingAdjustRespVO actual = service.createUnsoldAdjust(reqVO);
|
||
|
||
assertEquals("SUCCESS", actual.getResultStatus());
|
||
ArgumentCaptor<AccountingAdjustReqVO> captor = ArgumentCaptor.forClass(AccountingAdjustReqVO.class);
|
||
verify(chargeService).adjustAccounting(captor.capture());
|
||
AccountingAdjustReqVO coreReq = captor.getValue();
|
||
assertEquals(new BigDecimal("0.000"), coreReq.getTargetBillWater());
|
||
assertEquals(Boolean.TRUE, coreReq.getUpdateAccumulated());
|
||
assertEquals(Boolean.TRUE, coreReq.getUpdateBaseCode());
|
||
assertEquals(new BigDecimal("1234.000"), coreReq.getCurrentReading());
|
||
}
|
||
```
|
||
|
||
Ensure imports exist:
|
||
|
||
```java
|
||
import org.mockito.ArgumentCaptor;
|
||
```
|
||
|
||
- [ ] **Step 2: Run test to verify it fails**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=AccountingAdjustProcessServiceImplTest#createUnsoldAdjust_shouldPassWaterOptionFlagsToUnifiedChargeService \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected: compile failure or assertion failure because `getUpdateAccumulated` and `getUpdateBaseCode` are not present or not mapped.
|
||
|
||
- [ ] **Step 3: Add fields to request VOs**
|
||
|
||
In `AccountingAdjustUnsoldAdjustSubmitReqVO`, add after `currentReading`:
|
||
|
||
```java
|
||
@Schema(description = "是否更新累计量;未传默认false", example = "true")
|
||
private Boolean updateAccumulated;
|
||
|
||
@Schema(description = "是否更新底码;未传默认false", example = "true")
|
||
private Boolean updateBaseCode;
|
||
```
|
||
|
||
In `AccountingAdjustSubmitReqVO`, add near `currentReading`:
|
||
|
||
```java
|
||
private Boolean updateAccumulated;
|
||
|
||
private Boolean updateBaseCode;
|
||
```
|
||
|
||
In `AccountingAdjustReqVO`, add after `currentReading`:
|
||
|
||
```java
|
||
@Schema(description = "是否更新累计量,仅 legacy-only 水量调整使用;未传默认 false", example = "true")
|
||
private Boolean updateAccumulated;
|
||
|
||
@Schema(description = "是否更新底码,仅 legacy-only 水量调整使用;未传默认 false", example = "true")
|
||
private Boolean updateBaseCode;
|
||
```
|
||
|
||
- [ ] **Step 4: Map fields through Controller and process service**
|
||
|
||
In `AccountingAdjustActionController.toUnsoldSubmitReq(AccountingAdjustUnsoldAdjustSubmitReqVO reqVO)`, add:
|
||
|
||
```java
|
||
target.setUpdateAccumulated(reqVO.getUpdateAccumulated());
|
||
target.setUpdateBaseCode(reqVO.getUpdateBaseCode());
|
||
```
|
||
|
||
In `AccountingAdjustProcessServiceImpl.buildLegacyAdjustReq(...)`, add:
|
||
|
||
```java
|
||
coreReq.setUpdateAccumulated(reqVO.getUpdateAccumulated());
|
||
coreReq.setUpdateBaseCode(reqVO.getUpdateBaseCode());
|
||
```
|
||
|
||
- [ ] **Step 5: Run test to verify it passes**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=AccountingAdjustProcessServiceImplTest#createUnsoldAdjust_shouldPassWaterOptionFlagsToUnifiedChargeService \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 6: Commit Task 1**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustUnsoldAdjustSubmitReqVO.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustSubmitReqVO.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/charge/vo/AccountingAdjustReqVO.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/AccountingAdjustActionController.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImpl.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImplTest.java
|
||
git commit -m "feat(accounting): carry water preview options into unsold submit"
|
||
```
|
||
|
||
## Task 2: Apply Water-Adjust Options in ChargeService
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java`
|
||
- Test: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java`
|
||
|
||
- [ ] **Step 1: Write failing test for updateBaseCode requiring currentReading**
|
||
|
||
Add to `ChargeServiceAccountingAdjustTest`:
|
||
|
||
```java
|
||
@Test
|
||
void testAdjustAccounting_usageUpdateBaseCodeRequiresCurrentReading() {
|
||
ChargeDO charge = buildCharge(123L, PayStateEnum.UNPAID.getValue(), new BigDecimal("18.50"));
|
||
charge.setRecordId(923L);
|
||
charge.setReadWater(new BigDecimal("30.000"));
|
||
when(chargeMapper.selectById(123L)).thenReturn(charge);
|
||
|
||
ReadingDataDO readingData = new ReadingDataDO();
|
||
readingData.setId(923L);
|
||
readingData.setReadWater(new BigDecimal("30.000"));
|
||
readingData.setCheckWater(new BigDecimal("30.000"));
|
||
when(readingDataService.getReadingDataByIds(Collections.singletonList(923L)))
|
||
.thenReturn(Collections.singletonList(readingData));
|
||
when(chargeDetailService.getChargeDetailsByFeeIds(Collections.singletonList(123L)))
|
||
.thenReturn(Collections.emptyList());
|
||
|
||
AccountingAdjustReqVO reqVO = new AccountingAdjustReqVO();
|
||
reqVO.setChargeId(123L);
|
||
reqVO.setAdjustType("USAGE");
|
||
reqVO.setTargetBillWater(new BigDecimal("20.000"));
|
||
reqVO.setReasonCode("REV004_USAGE_FIX");
|
||
reqVO.setReason("底码更正");
|
||
reqVO.setAttachmentRefs(List.of("proof-001"));
|
||
reqVO.setUpdateBaseCode(true);
|
||
|
||
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
|
||
() -> chargeService.adjustAccounting(reqVO));
|
||
|
||
assertEquals("更新底码必须传入本次抄码", ex.getMessage());
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Write failing test for updateBaseCode and updateAccumulated effects**
|
||
|
||
Add to `ChargeServiceAccountingAdjustTest`:
|
||
|
||
```java
|
||
@Test
|
||
void testAdjustAccounting_usageOptionsUpdateReadingAndAccumulatedWater() {
|
||
ChargeDO charge = buildCharge(124L, PayStateEnum.UNPAID.getValue(), new BigDecimal("18.50"));
|
||
charge.setRecordId(924L);
|
||
charge.setReadWater(new BigDecimal("30.000"));
|
||
charge.setReading(new BigDecimal("1000.000"));
|
||
charge.setTotalWater(new BigDecimal("500.000"));
|
||
when(chargeMapper.selectById(124L)).thenReturn(charge);
|
||
|
||
ReadingDataDO readingData = new ReadingDataDO();
|
||
readingData.setId(924L);
|
||
readingData.setReadWater(new BigDecimal("30.000"));
|
||
readingData.setCheckWater(new BigDecimal("30.000"));
|
||
when(readingDataService.getReadingDataByIds(Collections.singletonList(924L)))
|
||
.thenReturn(Collections.singletonList(readingData));
|
||
when(chargeDetailService.getChargeDetailsByFeeIds(Collections.singletonList(124L)))
|
||
.thenReturn(Collections.emptyList());
|
||
|
||
CustDO cust = new CustDO();
|
||
cust.setId(1L);
|
||
cust.setPriceTemplateCode("PRICE-001");
|
||
when(custService.getCust(1L)).thenReturn(cust);
|
||
when(custWaterUseSchemeService.getCustWaterUseSchemeByCustId(1L)).thenReturn(null);
|
||
|
||
PriceTemplateDO priceTemplate = new PriceTemplateDO();
|
||
priceTemplate.setId(11L);
|
||
priceTemplate.setCode("PRICE-001");
|
||
priceTemplate.setAdjustmentSnapCode("SNAP-001");
|
||
when(priceTemplateService.getPriceTemplatesByCodes(Collections.singletonList("PRICE-001")))
|
||
.thenReturn(Collections.singletonList(priceTemplate));
|
||
|
||
PriceCostAdjustmentDO costAdjustment = new PriceCostAdjustmentDO();
|
||
costAdjustment.setId(21L);
|
||
costAdjustment.setCostComponentCode(ChargeCalculateHelper.COST_CODE_WATER);
|
||
when(priceCostAdjustmentService.getPriceCostAdjustmentsByTemplateIds(Collections.singletonList(11L)))
|
||
.thenReturn(Collections.singletonList(costAdjustment));
|
||
|
||
PriceTierAdjustmentDO tierAdjustment = new PriceTierAdjustmentDO();
|
||
tierAdjustment.setId(31L);
|
||
tierAdjustment.setCostAdjustmentId(21L);
|
||
tierAdjustment.setTierLevel(1);
|
||
tierAdjustment.setStartVolume(BigDecimal.ZERO);
|
||
tierAdjustment.setEndVolume(new BigDecimal("999999"));
|
||
tierAdjustment.setPrice(new BigDecimal("1.0000"));
|
||
when(priceTierAdjustmentService.getPriceTierAdjustmentsByCostAdjustmentIds(Collections.singletonList(21L)))
|
||
.thenReturn(Collections.singletonList(tierAdjustment));
|
||
|
||
AccountingAdjustReqVO reqVO = new AccountingAdjustReqVO();
|
||
reqVO.setChargeId(124L);
|
||
reqVO.setAdjustType("USAGE");
|
||
reqVO.setTargetBillWater(new BigDecimal("20.000"));
|
||
reqVO.setReasonCode("REV004_USAGE_FIX");
|
||
reqVO.setReason("同步累计量和底码");
|
||
reqVO.setAttachmentRefs(List.of("proof-001"));
|
||
reqVO.setUpdateBaseCode(true);
|
||
reqVO.setUpdateAccumulated(true);
|
||
reqVO.setCurrentReading(new BigDecimal("1010.000"));
|
||
|
||
AccountingAdjustRespVO respVO = chargeService.adjustAccounting(reqVO);
|
||
|
||
assertEquals("SUCCESS", respVO.getResultStatus());
|
||
assertEquals(new BigDecimal("1010.000"), charge.getReading());
|
||
assertEquals(new BigDecimal("510.000"), charge.getTotalWater());
|
||
verify(chargeMapper).updateById(charge);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Run tests to verify they fail**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=ChargeServiceAccountingAdjustTest#testAdjustAccounting_usageUpdateBaseCodeRequiresCurrentReading+testAdjustAccounting_usageOptionsUpdateReadingAndAccumulatedWater \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected: at least one failure because `updateBaseCode` and `updateAccumulated` are not implemented.
|
||
|
||
- [ ] **Step 4: Implement validation and write-back**
|
||
|
||
In `ChargeServiceImpl.validateUsageAdjust(...)`, after reason/attachment checks are available and before recalculation, add:
|
||
|
||
```java
|
||
if (Boolean.TRUE.equals(reqVO.getUpdateBaseCode()) && reqVO.getCurrentReading() == null) {
|
||
throw new IllegalArgumentException("更新底码必须传入本次抄码");
|
||
}
|
||
```
|
||
|
||
In `ChargeServiceImpl.handleUsageAdjust(...)`, preserve original water before recalculation:
|
||
|
||
```java
|
||
BigDecimal beforeBillWater = state.getChargeDO().getBillWater();
|
||
```
|
||
|
||
After `copyRecalculatedFees(recalculated, state.getChargeDO());`, add:
|
||
|
||
```java
|
||
applyUsageAdjustOptions(state.getChargeDO(), state.getReqVO(), beforeBillWater);
|
||
```
|
||
|
||
Add helper method near `copyRecalculatedFees`:
|
||
|
||
```java
|
||
private void applyUsageAdjustOptions(ChargeDO chargeDO, AccountingAdjustReqVO reqVO, BigDecimal beforeBillWater) {
|
||
if (Boolean.TRUE.equals(reqVO.getUpdateBaseCode())) {
|
||
chargeDO.setReading(reqVO.getCurrentReading());
|
||
}
|
||
if (Boolean.TRUE.equals(reqVO.getUpdateAccumulated())) {
|
||
BigDecimal beforeTotalWater = chargeDO.getTotalWater();
|
||
if (beforeTotalWater != null) {
|
||
BigDecimal oldWater = beforeBillWater == null ? BigDecimal.ZERO : beforeBillWater;
|
||
BigDecimal newWater = reqVO.getTargetBillWater() == null ? BigDecimal.ZERO : reqVO.getTargetBillWater();
|
||
chargeDO.setTotalWater(beforeTotalWater.add(newWater.subtract(oldWater)));
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 5: Include option values in operation log details**
|
||
|
||
In the operation-log detail builder for accounting adjustments in `ChargeServiceImpl`, add details for:
|
||
|
||
```java
|
||
addOperatLogDetail(dto, "updateAccumulated", "是否更新累计量", null, reqVO.getUpdateAccumulated(), EnumColumnType.NORMAL_TYPE);
|
||
addOperatLogDetail(dto, "updateBaseCode", "是否更新底码", null, reqVO.getUpdateBaseCode(), EnumColumnType.NORMAL_TYPE);
|
||
```
|
||
|
||
- [ ] **Step 6: Run Task 2 tests**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=ChargeServiceAccountingAdjustTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 7: Commit Task 2**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceAccountingAdjustTest.java
|
||
git commit -m "feat(accounting): apply water adjust preview options"
|
||
```
|
||
|
||
## Task 3: Add Price-Diff Options to Formal Object Chain
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-api/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/dto/PriceDiffAdjustCreateReqDTO.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/PriceDiffAdjustInternalApiImpl.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImpl.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/dataobject/pricediffadjustdetail/PriceDiffAdjustDetailDO.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationService.java`
|
||
- Test: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationServiceTest.java`
|
||
|
||
- [ ] **Step 1: Write failing formalization test**
|
||
|
||
In `PriceDiffFormalizationServiceTest`, add:
|
||
|
||
```java
|
||
@Test
|
||
void ensurePendingRecord_shouldPersistPriceDiffOptionFlags() {
|
||
ChargeDO sourceCharge = new ChargeDO();
|
||
sourceCharge.setId(15801L);
|
||
sourceCharge.setCustCode("C001");
|
||
sourceCharge.setBillMonth(202606);
|
||
sourceCharge.setBillAmount(new BigDecimal("100.00"));
|
||
sourceCharge.setExtendedAmount(new BigDecimal("100.00"));
|
||
sourceCharge.setPriceTemplateCode("OLD");
|
||
sourceCharge.setAdjustmentSnapCode("OLD-SNAP");
|
||
sourceCharge.setPayState(PayStateEnum.UNPAID.getValue());
|
||
|
||
AccountingAdjustSubmitReqVO reqVO = new AccountingAdjustSubmitReqVO();
|
||
reqVO.setChargeId(15801L);
|
||
reqVO.setPriceDiffAmount(new BigDecimal("15.50"));
|
||
reqVO.setReasonCode("REV004_PRICE_DIFF");
|
||
reqVO.setReason("价差调整");
|
||
reqVO.setNewPriceTemplateCode("NEW");
|
||
reqVO.setAdjustmentSnapCode("NEW-SNAP");
|
||
reqVO.setIsLadder(false);
|
||
reqVO.setCalculateGarbageFee(false);
|
||
reqVO.setUpdateAccumulatedVolume(false);
|
||
|
||
service.ensurePendingRecord("REV004-PD-C001-15801-20260619110000", sourceCharge, reqVO);
|
||
|
||
ArgumentCaptor<PriceDiffAdjustDetailDO> detailCaptor = ArgumentCaptor.forClass(PriceDiffAdjustDetailDO.class);
|
||
verify(priceDiffAdjustDetailMapper).insert(detailCaptor.capture());
|
||
PriceDiffAdjustDetailDO detail = detailCaptor.getValue();
|
||
assertEquals(Short.valueOf((short) 0), detail.getIsLadder());
|
||
assertEquals(Short.valueOf((short) 0), detail.getCalculateGarbageFee());
|
||
assertEquals(Short.valueOf((short) 0), detail.getUpdateAccumulatedVolume());
|
||
}
|
||
```
|
||
|
||
Ensure imports exist:
|
||
|
||
```java
|
||
import org.mockito.ArgumentCaptor;
|
||
```
|
||
|
||
- [ ] **Step 2: Run test to verify it fails**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=PriceDiffFormalizationServiceTest#ensurePendingRecord_shouldPersistPriceDiffOptionFlags \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected: compile failure because `getCalculateGarbageFee` and `getUpdateAccumulatedVolume` are not defined on `PriceDiffAdjustDetailDO`.
|
||
|
||
- [ ] **Step 3: Extend DTO and DO**
|
||
|
||
In `PriceDiffAdjustCreateReqDTO`, add:
|
||
|
||
```java
|
||
private Boolean calculateGarbageFee;
|
||
private Boolean updateAccumulatedVolume;
|
||
```
|
||
|
||
In `PriceDiffAdjustDetailDO`, add:
|
||
|
||
```java
|
||
private Short calculateGarbageFee;
|
||
private Short updateAccumulatedVolume;
|
||
```
|
||
|
||
- [ ] **Step 4: Pass options into formalization VO**
|
||
|
||
In `AccountingAdjustProcessServiceImpl.createUnsoldPriceDiff(...)`, after `dto.setIsLadder(reqVO.getIsLadder());`, add:
|
||
|
||
```java
|
||
dto.setCalculateGarbageFee(reqVO.getCalculateGarbageFee());
|
||
dto.setUpdateAccumulatedVolume(reqVO.getUpdateAccumulatedVolume());
|
||
```
|
||
|
||
In `PriceDiffAdjustInternalApiImpl.create(...)`, after `vo.setIsLadder(reqDTO.getIsLadder());`, add:
|
||
|
||
```java
|
||
vo.setCalculateGarbageFee(reqDTO.getCalculateGarbageFee());
|
||
vo.setUpdateAccumulatedVolume(reqDTO.getUpdateAccumulatedVolume());
|
||
```
|
||
|
||
- [ ] **Step 5: Persist options in formal detail**
|
||
|
||
In `PriceDiffFormalizationService.ensurePendingRecord(...)`, set the new fields in `PriceDiffAdjustDetailDO.builder()`:
|
||
|
||
```java
|
||
.isLadder(toShortDefaultTrue(reqVO.getIsLadder()))
|
||
.calculateGarbageFee(toShortDefaultTrue(reqVO.getCalculateGarbageFee()))
|
||
.updateAccumulatedVolume(toShortDefaultTrue(reqVO.getUpdateAccumulatedVolume()))
|
||
```
|
||
|
||
Add helper method:
|
||
|
||
```java
|
||
private Short toShortDefaultTrue(Boolean value) {
|
||
return Boolean.FALSE.equals(value) ? (short) 0 : (short) 1;
|
||
}
|
||
```
|
||
|
||
Use this helper for `isLadder` as well, replacing the current `Boolean.TRUE.equals(...) ? 1 : 0` default so missing values default to true.
|
||
|
||
- [ ] **Step 6: Run formalization test**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=PriceDiffFormalizationServiceTest#ensurePendingRecord_shouldPersistPriceDiffOptionFlags \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 7: Commit Task 3**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sw-business/sw-business-api/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/dto/PriceDiffAdjustCreateReqDTO.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/api/accountingadjust/PriceDiffAdjustInternalApiImpl.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustProcessServiceImpl.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/dataobject/pricediffadjustdetail/PriceDiffAdjustDetailDO.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationService.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffFormalizationServiceTest.java
|
||
git commit -m "feat(accounting): persist price diff preview options"
|
||
```
|
||
|
||
## Task 4: Apply Price-Diff Options During Write-Back
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/AccountingAdjustActionServiceImpl.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackService.java`
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java`
|
||
- Test: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackServiceTest.java`
|
||
|
||
- [ ] **Step 1: Write failing test for calculateGarbageFee default true**
|
||
|
||
In `PriceDiffWriteBackServiceTest`, add or adapt a test:
|
||
|
||
```java
|
||
@Test
|
||
void cancelAndCreate_shouldDefaultCalculateGarbageFeeToTrueWhenOptionMissing() {
|
||
ChargeDO original = new ChargeDO();
|
||
original.setId(15801L);
|
||
original.setPayState(PayStateEnum.UNPAID.getValue());
|
||
original.setBillWater(new BigDecimal("10.000"));
|
||
original.setTotalWater(new BigDecimal("100.000"));
|
||
when(chargeMapper.selectById(15801L)).thenReturn(original);
|
||
|
||
PriceTemplateDO template = new PriceTemplateDO();
|
||
template.setCode("NEW");
|
||
template.setAdjustmentSnapCode("SNAP-NEW");
|
||
when(priceTemplateService.getPriceTemplateByCode("NEW")).thenReturn(template);
|
||
|
||
when(priceDiffPreviewService.recalculate(eq(original), eq(template), eq(true), eq(true)))
|
||
.thenReturn(Map.of(
|
||
"101", new BigDecimal("20.00"),
|
||
"103", new BigDecimal("3.00")
|
||
));
|
||
|
||
Long newChargeId = service.cancelAndCreate(15801L, "NEW", "SNAP-NEW", null, null, null, "价差调整");
|
||
|
||
assertNull(newChargeId);
|
||
ArgumentCaptor<ChargeDO> insertCaptor = ArgumentCaptor.forClass(ChargeDO.class);
|
||
verify(chargeMapper).insert(insertCaptor.capture());
|
||
assertEquals(new BigDecimal("3.00"), insertCaptor.getValue().getGarbageFee());
|
||
verify(priceDiffPreviewService).recalculate(original, template, true, true);
|
||
}
|
||
```
|
||
|
||
The unit test mock does not assign an ID during `chargeMapper.insert(newCharge)`, so `newChargeId` remains `null` in this test.
|
||
|
||
- [ ] **Step 2: Write failing test for calculateGarbageFee false**
|
||
|
||
Add:
|
||
|
||
```java
|
||
@Test
|
||
void cancelAndCreate_shouldExcludeGarbageFeeWhenOptionFalse() {
|
||
ChargeDO original = new ChargeDO();
|
||
original.setId(15802L);
|
||
original.setPayState(PayStateEnum.UNPAID.getValue());
|
||
original.setBillWater(new BigDecimal("10.000"));
|
||
when(chargeMapper.selectById(15802L)).thenReturn(original);
|
||
|
||
PriceTemplateDO template = new PriceTemplateDO();
|
||
template.setCode("NEW");
|
||
template.setAdjustmentSnapCode("SNAP-NEW");
|
||
when(priceTemplateService.getPriceTemplateByCode("NEW")).thenReturn(template);
|
||
|
||
when(priceDiffPreviewService.recalculate(eq(original), eq(template), eq(false), eq(false)))
|
||
.thenReturn(Map.of("101", new BigDecimal("20.00")));
|
||
|
||
service.cancelAndCreate(15802L, "NEW", "SNAP-NEW", false, false, false, "价差调整");
|
||
|
||
ArgumentCaptor<ChargeDO> insertCaptor = ArgumentCaptor.forClass(ChargeDO.class);
|
||
verify(chargeMapper).insert(insertCaptor.capture());
|
||
assertEquals(BigDecimal.ZERO, insertCaptor.getValue().getGarbageFee());
|
||
verify(priceDiffPreviewService).recalculate(original, template, false, false);
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Run tests to verify failure**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=PriceDiffWriteBackServiceTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected: failure because `calculateGarbageFee` currently defaults to false in write-back when null.
|
||
|
||
- [ ] **Step 4: Fix write-back default semantics**
|
||
|
||
In `PriceDiffWriteBackService.cancelAndCreate(...)`, replace:
|
||
|
||
```java
|
||
Map<String, BigDecimal> newFeeMap = priceDiffPreviewService.recalculate(original, newTemplate, isLadder, calculateGarbageFee != null && calculateGarbageFee);
|
||
```
|
||
|
||
with:
|
||
|
||
```java
|
||
Boolean effectiveIsLadder = Boolean.FALSE.equals(isLadder) ? false : true;
|
||
Boolean effectiveCalculateGarbageFee = Boolean.FALSE.equals(calculateGarbageFee) ? false : true;
|
||
Map<String, BigDecimal> newFeeMap = priceDiffPreviewService.recalculate(
|
||
original, newTemplate, effectiveIsLadder, effectiveCalculateGarbageFee);
|
||
```
|
||
|
||
- [ ] **Step 5: Apply updateAccumulatedVolume behavior**
|
||
|
||
In `PriceDiffWriteBackService.cancelAndCreate(...)`, after `newCharge.setTotalWater(source.getTotalWater())` is copied by `cloneChargeMetadata`, set:
|
||
|
||
```java
|
||
if (Boolean.FALSE.equals(updateAccumulatedVolume)) {
|
||
newCharge.setTotalWater(original.getTotalWater());
|
||
}
|
||
```
|
||
|
||
Do not alter customer-level accumulated volume in this task because this service currently only clones and inserts `ChargeDO`.
|
||
|
||
- [ ] **Step 6: Write price-diff option values to operation log details**
|
||
|
||
In `ChargeServiceImpl.recordAccountingAdjustLog(...)`, add these log details near `priceDiffAmount`:
|
||
|
||
```java
|
||
addOperatLogDetail(dto, "newPriceTemplateCode", "新水价模板代码", null, reqVO.getNewPriceTemplateCode(), EnumColumnType.NORMAL_TYPE);
|
||
addOperatLogDetail(dto, "adjustmentSnapCode", "调价号", null, reqVO.getAdjustmentSnapCode(), EnumColumnType.NORMAL_TYPE);
|
||
addOperatLogDetail(dto, "isLadder", "是否阶梯计费", null, reqVO.getIsLadder(), EnumColumnType.NORMAL_TYPE);
|
||
addOperatLogDetail(dto, "calculateGarbageFee", "是否计算垃圾费", null, reqVO.getCalculateGarbageFee(), EnumColumnType.NORMAL_TYPE);
|
||
addOperatLogDetail(dto, "updateAccumulatedVolume", "是否更新累计量", null, reqVO.getUpdateAccumulatedVolume(), EnumColumnType.NORMAL_TYPE);
|
||
```
|
||
|
||
`AccountingAdjustActionServiceImpl.applyPriceDiffWriteBack(...)` already reads these exact column names:
|
||
|
||
```java
|
||
Boolean isLadder = parseBoolean(detailColumnValue(detail, "isLadder"));
|
||
Boolean calculateGarbageFee = parseBoolean(detailColumnValue(detail, "calculateGarbageFee"));
|
||
Boolean updateAccumulatedVolume = parseBoolean(detailColumnValue(detail, "updateAccumulatedVolume"));
|
||
```
|
||
|
||
- [ ] **Step 7: Run write-back tests**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=PriceDiffWriteBackServiceTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 8: Commit Task 4**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/AccountingAdjustActionServiceImpl.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackService.java \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/charge/ChargeServiceImpl.java \
|
||
sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/pricediff/PriceDiffWriteBackServiceTest.java
|
||
git commit -m "fix(accounting): align price diff option writeback"
|
||
```
|
||
|
||
## Task 5: Add Database Migration for Price-Diff Detail Options
|
||
|
||
**Files:**
|
||
- Create: `sql/rev004/REV004_price_diff_option_fields_deploy.sql`
|
||
- Modify: `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md`
|
||
|
||
- [ ] **Step 1: Add deploy SQL**
|
||
|
||
Create `sql/rev004/REV004_price_diff_option_fields_deploy.sql`:
|
||
|
||
```sql
|
||
ALTER TABLE biz_price_diff_adjust_detail
|
||
ADD calculate_garbage_fee SMALLINT DEFAULT 1 NULL;
|
||
|
||
COMMENT ON COLUMN biz_price_diff_adjust_detail.calculate_garbage_fee IS '是否计算垃圾费:0-否,1-是';
|
||
|
||
ALTER TABLE biz_price_diff_adjust_detail
|
||
ADD update_accumulated_volume SMALLINT DEFAULT 1 NULL;
|
||
|
||
COMMENT ON COLUMN biz_price_diff_adjust_detail.update_accumulated_volume IS '是否更新累计量:0-否,1-是';
|
||
```
|
||
|
||
- [ ] **Step 2: Run compile to validate entity changes**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am -DskipTests compile
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 3: Commit Task 5**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git add \
|
||
sql/rev004/REV004_price_diff_option_fields_deploy.sql \
|
||
sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/dal/dataobject/pricediffadjustdetail/PriceDiffAdjustDetailDO.java
|
||
git commit -m "chore(accounting): add price diff option fields ddl"
|
||
```
|
||
|
||
## Task 6: End-to-End Regression and Evidence
|
||
|
||
**Files:**
|
||
- Modify: `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md`
|
||
|
||
- [ ] **Step 1: Run focused unit tests**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=AccountingAdjustProcessServiceImplTest,ChargeServiceAccountingAdjustTest,PriceDiffFormalizationServiceTest,PriceDiffWriteBackServiceTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 2: Run existing trial preview tests**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=UnsoldTrialPreviewServiceImplTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
Expected:
|
||
|
||
```text
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
- [ ] **Step 3: Add evidence document**
|
||
|
||
Create or update `../water-docs/docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md`:
|
||
|
||
```markdown
|
||
# REV-004 未销调整预算参数正式化验证记录
|
||
|
||
## 变更范围
|
||
|
||
- 水量调整正式提交承接 `updateAccumulated`、`updateBaseCode`。
|
||
- 价差调整正式对象承接 `isLadder`、`calculateGarbageFee`、`updateAccumulatedVolume`。
|
||
- 价差正式回写与预算使用一致默认值:未传 `isLadder` 和 `calculateGarbageFee` 时按 `true` 处理。
|
||
|
||
## 验证命令
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=AccountingAdjustProcessServiceImplTest,ChargeServiceAccountingAdjustTest,PriceDiffFormalizationServiceTest,PriceDiffWriteBackServiceTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
```bash
|
||
mvn -pl sw-business/sw-business-server -am \
|
||
-Dtest=UnsoldTrialPreviewServiceImplTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false test
|
||
```
|
||
|
||
## 验证结果
|
||
|
||
- 聚焦账务调整测试:通过。
|
||
- 未销试算测试:通过。
|
||
|
||
## 数据库变更
|
||
|
||
- 新增 `sql/rev004/REV004_price_diff_option_fields_deploy.sql`。
|
||
- `biz_price_diff_adjust_detail` 新增 `calculate_garbage_fee` 与 `update_accumulated_volume`。
|
||
|
||
## 风险说明
|
||
|
||
- 水量调整仍使用 legacy-only 即时回写,checkbox 审计通过操作日志明细承接。
|
||
- 价差正式对象已承接 checkbox;部署前需在目标库执行新增字段 SQL。
|
||
```
|
||
|
||
- [ ] **Step 4: Validate evidence document**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
make validate-file FILE=docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md
|
||
```
|
||
|
||
from `../water-docs`.
|
||
|
||
Expected:
|
||
|
||
```text
|
||
文档验证通过
|
||
```
|
||
|
||
- [ ] **Step 5: Commit evidence**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git -C ../water-docs add docs/evidence/rev004-accounting/rev004-unsold-preview-options-formalization-2026-06-19.md
|
||
git -C ../water-docs commit -m "docs(accounting): record unsold preview option evidence"
|
||
```
|
||
|
||
## Task 7: Final Status Check
|
||
|
||
**Files:**
|
||
- No file edits.
|
||
|
||
- [ ] **Step 1: Check backend status**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git status --short
|
||
git log --oneline -5
|
||
```
|
||
|
||
Expected:
|
||
|
||
- No unstaged backend files.
|
||
- Recent commits include usage validation, water option chain, price-diff option persistence, price-diff write-back, and DDL.
|
||
|
||
- [ ] **Step 2: Check docs status**
|
||
|
||
Run:
|
||
|
||
```bash
|
||
git -C ../water-docs status --short
|
||
git -C ../water-docs log --oneline -5
|
||
```
|
||
|
||
Expected:
|
||
|
||
- No unstaged docs files.
|
||
- Recent commits include design, plan, and evidence.
|
||
|
||
- [ ] **Step 3: Summarize implementation**
|
||
|
||
Report:
|
||
|
||
```text
|
||
Implemented REV-004 unsold preview option formalization.
|
||
|
||
Backend commits:
|
||
- Include the short SHA and subject for each backend commit from `git log --oneline -6`.
|
||
|
||
Docs commits:
|
||
- Include the short SHA and subject for each docs commit from `git -C ../water-docs log --oneline -3`.
|
||
|
||
Validation:
|
||
- Focused Maven command: BUILD SUCCESS
|
||
- Preview Maven command: BUILD SUCCESS
|
||
```
|
||
|
||
## Self-Review
|
||
|
||
Spec coverage:
|
||
|
||
- Water preview options entering formal submit: covered by Tasks 1 and 2.
|
||
- Price-diff preview options entering formal object and write-back: covered by Tasks 3 and 4.
|
||
- Data persistence for price-diff formal detail: covered by Task 5.
|
||
- Evidence under `docs/evidence/rev004-accounting/`: covered by Tasks 0 and 6.
|
||
- Validation and final status: covered by Tasks 6 and 7.
|
||
|
||
Plan specificity scan:
|
||
|
||
- The plan contains concrete file paths, commands, expected outputs, and code snippets for each implementation task.
|
||
- No implementation step depends on unnamed additional work.
|
||
|
||
Type consistency:
|
||
|
||
- Water option field names are `updateAccumulated` and `updateBaseCode` across endpoint VO, unified submit VO, core charge VO, and service logic.
|
||
- Price-diff option field names are `isLadder`, `calculateGarbageFee`, and `updateAccumulatedVolume` across submit VO, DTO, formal detail, and write-back.
|