fujian_water_biz_doc/docs/superpowers/plans/2026-06-14-account-log-baddebt-recovery.md
tangweijie 3eccab2cf9 docs: 文档治理统一 — AGENTS.md 生命周期规则 + 模块归档 + DDL 修正
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
2026-06-16 11:47:16 +08:00

7.2 KiB
Raw Blame History

账务日志功能按钮 + 呆坏账恢复 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: 修复账务日志页功能按钮(撤销/退转款/预转存/呆坏账恢复)根据数据状态正确显示,不再硬编码 false;新增呆坏账恢复入口。

Architecture: 后端 toPageResp() 当前将 canRevoke/canRefund/canPrestore 硬编码为 falsecanRecoverBadDebt 字段不存在。修复后根据 LegacyLogRecordobjectType + resultStatus + approvalStatus 动态判定;前端补 API 调用和按钮。

Tech Stack: Java 17 + Spring Boot (backend), Vue 3 + TypeScript (frontend)


canXxx 判定规则

toPageResp(LegacyLogRecord record) 中按以下规则赋值:

字段 条件 说明
canRevoke approvalStatus == "PENDING_APPROVAL" 待审批状态可撤销
canRefund objectType == "PREPAID_REFUND" && resultStatus == "SUCCESS" 退转款成功后允许二次退款
canPrestore objectType == "PREPAID_REFUND" && resultStatus == "SUCCESS" 退转款成功后允许转预存
canRecoverBadDebt objectType == "BAD_DEBT_RECORD" && resultStatus == "SUCCESS" 坏账已执行可恢复为欠费

Task 1: 后端 VO 加 canRecoverBadDebt

Files:

  • Modify: sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/accountingadjust/accountProcess/vo/AccountingAdjustLogPageRespVO.java

  • Step 1: 在 VO 末尾 canPrestore 后添加字段

    @Schema(description = "是否可恢复呆坏账")
    private Boolean canRecoverBadDebt;

添加位置:紧跟 private Boolean canPrestore; 之后。


Task 2: 后端 Service 修正 canXxx 赋值

Files:

  • Modify: sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImpl.java:520-522

  • Step 1: 替换硬编码 false 为动态判定

toPageResp() 中的三行:

        respVO.setCanRevoke(false);
        respVO.setCanRefund(false);
        respVO.setCanPrestore(false);

替换为:

        // 动态判定功能按钮可见性
        respVO.setCanRevoke("PENDING_APPROVAL".equals(record.approvalStatus));
        boolean refundEnabled = "PREPAID_REFUND".equals(record.objectType) && "SUCCESS".equals(record.resultStatus);
        respVO.setCanRefund(refundEnabled);
        respVO.setCanPrestore(refundEnabled);
        respVO.setCanRecoverBadDebt("BAD_DEBT_RECORD".equals(record.objectType) && "SUCCESS".equals(record.resultStatus));

同时需要更新 AccountingAdjustLogPageReqVOcopyReq 方法: 无需改动canXxx 是响应字段。


Task 3: 前端 API 加 recoverBadDebt

Files:

  • Modify: src/api/accountProcess/accountLog/index.ts

  • Step 1: 添加接口类型和 API 方法

AccountingAdjustPageRespVO 接口中添加 canRecoverBadDebt 字段,并在 AccountLogApi 对象中添加 recoverBadDebt 方法:

// 在 AccountingAdjustPageRespVO 接口中添加
  canRecoverBadDebt?: boolean
// 在 AccountLogApi 对象中添加(放在 revokeAccountLog 之前)
  // 账务日志呆坏账恢复
  recoverBadDebt: async (data: { adjustmentNo: string }) => {
    return await request.post<AccountingAdjustRespVO>({
      url: '/business/accounting-adjust/log-recover-bad-debt',
      data
    })
  },

Task 4: 前端页面加呆坏账恢复按钮

Files:

  • Modify: src/views/accountProcess/accountLog/index.vue

  • Step 1: 在 function 模板中添加按钮

在现有三个按钮之后、</div> 之前添加:

            <el-button
              v-if="scope.row.canRecoverBadDebt"
              link
              type="primary"
              @click="handleRecoverBadDebt(scope.row)"
            >
              <el-tooltip effect="dark" content="恢复呆坏账" placement="top">
                <Icon icon="ep:refresh-left" :size="18" />
              </el-tooltip>
            </el-button>
  • Step 2: 在 script 中添加处理函数

handlePrestore 之后添加:

const handleRecoverBadDebt = async (row: any) => {
  const adjustmentNo = row?.adjustmentNo
  if (!adjustmentNo) {
    message.warning('缺少调整单号,无法恢复')
    return
  }
  try {
    await message.confirm(`确认要将呆坏账调整单「${adjustmentNo}」恢复为欠费状态吗?`)
    await AccountLogApi.recoverBadDebt({ adjustmentNo })
    message.success('呆坏账已恢复为欠费')
    await getList()
  } catch (e: any) {
    if (e !== 'cancel' && e !== 'close') {
      message.error('恢复失败,请稍后重试')
    }
  }
}

Task 5: 编译验证 + 提交

  • Step 1: 后端编译 + 测试
cd /Volumes/Dpan/github/water-workspace/water-backend
mvn test -pl sw-business/sw-business-server -Dtest=AccountingAdjustLogProcessServiceImplTest -DfailIfNoTests=false 2>&1 | grep -E "Tests run|BUILD"

预期Tests run: 4, Failures: 0, BUILD SUCCESS

  • Step 2: 前端 TypeScript 编译
cd /Volumes/Dpan/github/water-workspace/water-frontend
npx vue-tsc --noEmit 2>&1 | grep -i "error\|accountLog" | head -10

预期:无类型错误。

  • Step 3: 提交
# 后端
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/AccountingAdjustLogPageRespVO.java
git add sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/service/accountingadjust/accountProcess/AccountingAdjustLogProcessServiceImpl.java
git commit -m "feat: add canRecoverBadDebt and fix canRevoke/canRefund/canPrestore logic

- Add canRecoverBadDebt field to AccountingAdjustLogPageRespVO
- Replace hardcoded false with dynamic logic in toPageResp():
  canRevoke = approvalStatus is PENDING_APPROVAL
  canRefund/canPrestore = PREPAID_REFUND + SUCCESS
  canRecoverBadDebt = BAD_DEBT_RECORD + SUCCESS"

# 前端
cd /Volumes/Dpan/github/water-workspace/water-frontend
git add src/api/accountProcess/accountLog/index.ts src/views/accountProcess/accountLog/index.vue
git commit -m "feat: add bad debt recovery button and API to account log page

- Add recoverBadDebt API method calling POST log-recover-bad-debt
- Add canRecoverBadDebt field to AccountingAdjustPageRespVO
- Add recovery button with confirm dialog in function column"

Self-Review

1. Spec coverage: 4 个功能按钮全部覆盖canRevoke/canRefund/canPrestore 修正 + canRecoverBadDebt 新增。

2. Placeholder scan: 无占位符,所有步骤含具体代码。

3. Type consistency:

  • record.approvalStatusrecord.resultStatusrecord.objectType 均为 LegacyLogRecord 内部类字段,已存在于 ServiceImpl
  • 前端 canRecoverBadDebt 字段同时加入 AccountingAdjustPageRespVO 接口和 API 调用
  • 后端 recoverBadDebt API 接收 { adjustmentNo: string },与 AdjustExecuteReqDTO 匹配