1. AGENTS.md 更新 - water-docs: 新增 specs/ 与 docs/design/ 生命周期规则章节 - water-backend: 更新协作引用(建设期/建成后、evidence 模块化) 2. specs/ 重复合并 - 006-reminder-event-design 合并入 003-rev006-reminder-event-design - 001-rev004-accounting 删除冗余 data-model.md + contracts/ - 002-rev005-invoice-flow 删除冗余 data-model.md + contracts/ 3. evidence 按模块归档 - 35 个 REV-004 文件归入 evidence/rev004-accounting/ - 7 个通用 bugfix 文件归入 evidence/bugfix/ 和 bugfix/frontend/ - 新建 rev005-invoice/、rev006-reminder/、rev007-statistics/ 目录 4. guides/ 清理 - 14 个 REV004_*.md 移入 evidence/rev004-accounting/ 5. 遗留文件处理 - docs/research/ 归档到 Archive/06_Migration_Plans/ - backend-check detached worktrees 清理 6. 交叉引用修复 - 006-reminder-event-design → 003-rev006-reminder-event-design - docs/guides/REV004_ → docs/evidence/rev004-accounting/REV004_ 7. DB 设计文档修正(01_Database_Design.md) - biz_invoice 明确为开票配置表,非发票记录表 - 新增 biz_invoice_record 为发票申请/结果主表 - 新增 biz_charge_invoice_rel 账单-发票关联说明 - REV-005 承接口径表名全部修正 8. 发票审计证据 - 新增 evidence/rev005-invoice/2026-06-16-invoice-document-audit.md
256 lines
11 KiB
Markdown
256 lines
11 KiB
Markdown
# 账务日志统计字段对齐 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:** 修复 `getLogStat` 返回字段与前端 `AccountingAdjustStatRespVO` 不匹配的问题,使账务日志统计面板正确显示金额汇总、各状态笔数。
|
||
|
||
**Architecture:** 后端已有 `AccountingAdjustLogController`(含 `log-page`/`log-stat`/`log-detail`)和 `AccountingAdjustActionController`(含 `log-refund`/`log-prestorage`/`log-revoke`/`log-process`/`log-attachments`/`log-export`),6 个操作端点均已存在。唯一缺口是 `log-stat` 返回的 `AccountingAdjustLogStatRespVO` 使用 `totalAmount`/`completedCount` 等旧字段名,而前端期望 `totalActionAmount`/`successCount`/`failCount` 等 8 个新字段。
|
||
|
||
**Tech Stack:** Java 17, Spring Boot, MyBatis-Plus, JUnit 5 + Mockito, Lombok
|
||
|
||
---
|
||
|
||
## 前置说明:端点已存在
|
||
|
||
前端调用的 6 个操作端点均已在 `AccountingAdjustActionController` 中实现,路径对比如下:
|
||
|
||
| 前端 API | 后端 Controller | 状态 |
|
||
|---|---|---|
|
||
| `GET log-export` | `ActionController.exportLog()` | ✅ |
|
||
| `GET log-process` | `ActionController.getLogProcess()` | ✅ |
|
||
| `GET log-attachments` | `ActionController.getLogAttachments()` | ✅ |
|
||
| `POST log-refund` | `ActionController.createLogRefund()` | ✅ |
|
||
| `POST log-prestorage` | `ActionController.createLogPrestorage()` | ✅ |
|
||
| `POST log-revoke` | `ActionController.revokeLog()` | ✅ |
|
||
|
||
本次只修 **统计字段对齐** 一个问题。
|
||
|
||
---
|
||
|
||
### Task 1: 扩展 StatRespVO 字段
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustLogStatRespVO.java`
|
||
- Reference: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImpl.java:95-107` (current `getLogStat`)
|
||
|
||
**当前字段(6个,与前端不匹配):**
|
||
|
||
```java
|
||
private Long totalCount; // 总条数 → 保留
|
||
private BigDecimal totalAmount; // 调整金额 → 改为 totalActionAmount
|
||
private BigDecimal totalWaterVolume; // 调整水量 → 保留兼容
|
||
private Long completedCount; // 已完成数量 → 替换
|
||
private Long pendingCount; // 未完成数量 → 替换
|
||
private Long cancelledCount; // 已撤销数量 → 替换
|
||
```
|
||
|
||
**前端期望字段(需新增):**
|
||
|
||
```java
|
||
private BigDecimal totalActionAmount; // 金额汇总
|
||
private Long totalCount; // 总笔数 (已有)
|
||
private Long successCount; // 成功笔数
|
||
private Long failCount; // 失败笔数
|
||
private Long pendingApprovalCount; // 待审批笔数
|
||
private Long approvalRequiredCount; // 需要审批笔数
|
||
private Long approvedCount; // 审批通过笔数
|
||
private Long rejectedCount; // 审批驳回笔数
|
||
```
|
||
|
||
- [ ] **Step 1: 修改 VO 字段**
|
||
|
||
用以下完整内容替换 `AccountingAdjustLogStatRespVO.java`:
|
||
|
||
```java
|
||
package cn.com.emsoft.sw.business.controller.admin.accountingadjust.accountProcess.vo;
|
||
|
||
import io.swagger.v3.oas.annotations.media.Schema;
|
||
import lombok.Data;
|
||
|
||
import java.math.BigDecimal;
|
||
|
||
@Schema(description = "管理后台 - 账务日志兼容统计 Response VO")
|
||
@Data
|
||
public class AccountingAdjustLogStatRespVO {
|
||
|
||
@Schema(description = "金额汇总(所有记录 actionAmount 求和)")
|
||
private BigDecimal totalActionAmount;
|
||
|
||
@Schema(description = "总笔数")
|
||
private Long totalCount;
|
||
|
||
@Schema(description = "成功笔数 (resultStatus == SUCCESS)")
|
||
private Long successCount;
|
||
|
||
@Schema(description = "失败笔数 (resultStatus == FAIL)")
|
||
private Long failCount;
|
||
|
||
@Schema(description = "待审批笔数 (approvalStatus == PENDING_APPROVAL)")
|
||
private Long pendingApprovalCount;
|
||
|
||
@Schema(description = "需要审批笔数 (approvalRequired == true)")
|
||
private Long approvalRequiredCount;
|
||
|
||
@Schema(description = "审批通过笔数 (approvalStatus == APPROVED)")
|
||
private Long approvedCount;
|
||
|
||
@Schema(description = "审批驳回笔数 (approvalStatus == REJECTED)")
|
||
private Long rejectedCount;
|
||
|
||
// 保留旧字段兼容已有调用方(如单元测试中的 getTotalAmount())
|
||
@Schema(description = "调整金额(兼容别名,等同于 totalActionAmount)")
|
||
private BigDecimal totalAmount;
|
||
|
||
@Schema(description = "调整水量")
|
||
private BigDecimal totalWaterVolume;
|
||
|
||
@Schema(description = "已完成数量(兼容别名,等同于 successCount)")
|
||
private Long completedCount;
|
||
|
||
@Schema(description = "未完成数量(兼容别名,等同于 pendingApprovalCount)")
|
||
private Long pendingCount;
|
||
|
||
@Schema(description = "已撤销数量(兼容别名,等同于 failCount + rejectedCount)")
|
||
private Long cancelledCount;
|
||
}
|
||
```
|
||
|
||
**设计要点:保留旧字段 `totalAmount`/`completedCount`/`pendingCount`/`cancelledCount` 作为兼容别名,Service 中同时设置新旧两套字段,避免破坏已有单元测试。**
|
||
|
||
---
|
||
|
||
### Task 2: 更新 getLogStat 实现
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImpl.java:95-107`
|
||
- Test: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImplTest.java`
|
||
|
||
- [ ] **Step 1: 替换 getLogStat 方法体**
|
||
|
||
将 `AccountingAdjustLogProcessServiceImpl.java` 中 `getLogStat` 方法(当前约 12 行)替换为:
|
||
|
||
```java
|
||
@Override
|
||
public AccountingAdjustLogStatRespVO getLogStat(AccountingAdjustLogPageReqVO reqVO) {
|
||
List<LegacyLogRecord> records = loadRecords(reqVO);
|
||
AccountingAdjustLogStatRespVO respVO = new AccountingAdjustLogStatRespVO();
|
||
|
||
// 新字段:前端直接使用
|
||
respVO.setTotalActionAmount(records.stream()
|
||
.map(record -> nvl(record.actionAmount))
|
||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||
respVO.setTotalCount((long) records.size());
|
||
respVO.setSuccessCount(records.stream()
|
||
.filter(record -> "SUCCESS".equals(record.resultStatus)).count());
|
||
respVO.setFailCount(records.stream()
|
||
.filter(record -> "FAIL".equals(record.resultStatus)).count());
|
||
respVO.setPendingApprovalCount(records.stream()
|
||
.filter(record -> "PENDING_APPROVAL".equals(record.approvalStatus)).count());
|
||
respVO.setApprovalRequiredCount(records.stream()
|
||
.filter(record -> Boolean.TRUE.equals(record.approvalRequired)).count());
|
||
respVO.setApprovedCount(records.stream()
|
||
.filter(record -> "APPROVED".equals(record.approvalStatus)).count());
|
||
respVO.setRejectedCount(records.stream()
|
||
.filter(record -> "REJECTED".equals(record.approvalStatus)).count());
|
||
|
||
// 旧字段兼容(供已有单元测试和未迁移调用方使用)
|
||
respVO.setTotalAmount(respVO.getTotalActionAmount());
|
||
respVO.setTotalWaterVolume(records.stream()
|
||
.map(record -> nvl(record.waterVolumeChange))
|
||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||
respVO.setCompletedCount(respVO.getSuccessCount());
|
||
respVO.setPendingCount(respVO.getPendingApprovalCount());
|
||
respVO.setCancelledCount(respVO.getFailCount() + respVO.getRejectedCount());
|
||
|
||
return respVO;
|
||
}
|
||
```
|
||
|
||
**注意:`LegacyLogRecord` 中 `actionAmount`、`resultStatus`、`approvalStatus`、`approvalRequired`、`waterVolumeChange` 字段已在 Service 内部类中定义,无需额外 import。**
|
||
|
||
- [ ] **Step 2: 编译验证**
|
||
|
||
```bash
|
||
cd /Volumes/Dpan/github/water-workspace/water-backend
|
||
mvn compile -pl sw-business/sw-business-server -am -q 2>&1 | tail -10
|
||
```
|
||
|
||
预期:`BUILD SUCCESS`
|
||
|
||
---
|
||
|
||
### Task 3: 更新单元测试
|
||
|
||
**Files:**
|
||
- Modify: `sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImplTest.java`
|
||
|
||
- [ ] **Step 1: 在已有测试中添加新字段断言**
|
||
|
||
在 `getLogDetailAndStat_shouldReturnMergedDetailsAndCounts` 测试方法末尾(`assertEquals(new BigDecimal("5.00"), stat.getTotalAmount());` 之后),追加新字段断言:
|
||
|
||
```java
|
||
// 新统计字段断言
|
||
assertEquals(new BigDecimal("5.00"), stat.getTotalActionAmount());
|
||
assertEquals(1L, stat.getSuccessCount());
|
||
assertEquals(0L, stat.getFailCount());
|
||
assertEquals(1L, stat.getPendingApprovalCount());
|
||
assertEquals(1L, stat.getApprovalRequiredCount());
|
||
assertEquals(0L, stat.getApprovedCount());
|
||
assertEquals(0L, stat.getRejectedCount());
|
||
// 保持旧字段兼容断言
|
||
assertEquals(new BigDecimal("5.00"), stat.getTotalAmount());
|
||
assertEquals(1L, stat.getCompletedCount());
|
||
assertEquals(1L, stat.getPendingCount());
|
||
assertEquals(0L, stat.getCancelledCount());
|
||
```
|
||
|
||
- [ ] **Step 2: 运行测试验证**
|
||
|
||
```bash
|
||
cd /Volumes/Dpan/github/water-workspace/water-backend
|
||
mvn test -pl sw-business/sw-business-server -Dtest=AccountingAdjustLogProcessServiceImplTest -q 2>&1 | tail -15
|
||
```
|
||
|
||
预期所有测试通过(4 个 test case,含新增断言)。
|
||
|
||
---
|
||
|
||
### Task 4: 全量编译 + 提交
|
||
|
||
- [ ] **Step 1: 全量编译**
|
||
|
||
```bash
|
||
cd /Volumes/Dpan/github/water-workspace/water-backend
|
||
mvn compile -pl sw-business/sw-business-server -am -q 2>&1 | tail -10
|
||
```
|
||
|
||
- [ ] **Step 2: 提交**
|
||
|
||
```bash
|
||
cd /Volumes/Dpan/github/water-workspace/water-backend
|
||
git add sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustLogStatRespVO.java
|
||
git add sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImpl.java
|
||
git add sw-business/sw-business-server/src/test/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImplTest.java
|
||
git commit -m "fix: align log-stat response fields with frontend AccountingAdjustStatRespVO
|
||
|
||
- Add totalActionAmount, successCount, failCount, pendingApprovalCount,
|
||
approvalRequiredCount, approvedCount, rejectedCount to StatRespVO
|
||
- Update getLogStat() to compute new fields from loaded records
|
||
- Keep legacy fields (totalAmount, completedCount, pendingCount,
|
||
cancelledCount) as compatibility aliases
|
||
- Update unit test with new field assertions"
|
||
```
|
||
|
||
---
|
||
|
||
## Self-Review
|
||
|
||
**1. Spec coverage:** 统计字段对齐是唯一的后端缺口,Task 1-3 完整覆盖。
|
||
|
||
**2. Placeholder scan:** 无 TBD/TODO/占位符,所有步骤都有具体代码和命令。
|
||
|
||
**3. Type consistency:**
|
||
- `LegacyLogRecord` 内部类字段 `actionAmount`(BigDecimal)、`resultStatus`(String)、`approvalStatus`(String)、`approvalRequired`(Boolean)、`waterVolumeChange`(BigDecimal)均在 ServiceImpl 中定义,与 `getLogStat` 新实现一致。
|
||
- `AccountingAdjustLogStatRespVO` 新旧字段并存,旧测试 `getTotalAmount()` 等调用不受影响。
|
||
- 前端 `AccountingAdjustStatRespVO` 的 8 个字段名与新增 VO 字段名完全一致(驼峰命名)。
|