# 账务日志功能按钮 + 呆坏账恢复 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` 硬编码为 `false`,`canRecoverBadDebt` 字段不存在。修复后根据 `LegacyLogRecord` 的 `objectType` + `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 后添加字段** ```java @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()` 中的三行: ```java respVO.setCanRevoke(false); respVO.setCanRefund(false); respVO.setCanPrestore(false); ``` 替换为: ```java // 动态判定功能按钮可见性 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)); ``` **同时需要更新 `AccountingAdjustLogPageReqVO` 的 `copyReq` 方法:** 无需改动,canXxx 是响应字段。 --- ### Task 3: 前端 API 加 recoverBadDebt **Files:** - Modify: `src/api/accountProcess/accountLog/index.ts` - [ ] **Step 1: 添加接口类型和 API 方法** 在 `AccountingAdjustPageRespVO` 接口中添加 `canRecoverBadDebt` 字段,并在 `AccountLogApi` 对象中添加 `recoverBadDebt` 方法: ```typescript // 在 AccountingAdjustPageRespVO 接口中添加 canRecoverBadDebt?: boolean ``` ```typescript // 在 AccountLogApi 对象中添加(放在 revokeAccountLog 之前) // 账务日志呆坏账恢复 recoverBadDebt: async (data: { adjustmentNo: string }) => { return await request.post({ url: '/business/accounting-adjust/log-recover-bad-debt', data }) }, ``` --- ### Task 4: 前端页面加呆坏账恢复按钮 **Files:** - Modify: `src/views/accountProcess/accountLog/index.vue` - [ ] **Step 1: 在 function 模板中添加按钮** 在现有三个按钮之后、`` 之前添加: ```html ``` - [ ] **Step 2: 在 script 中添加处理函数** 在 `handlePrestore` 之后添加: ```typescript 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: 后端编译 + 测试** ```bash 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 编译** ```bash cd /Volumes/Dpan/github/water-workspace/water-frontend npx vue-tsc --noEmit 2>&1 | grep -i "error\|accountLog" | head -10 ``` 预期:无类型错误。 - [ ] **Step 3: 提交** ```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/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.approvalStatus`、`record.resultStatus`、`record.objectType` 均为 `LegacyLogRecord` 内部类字段,已存在于 ServiceImpl - 前端 `canRecoverBadDebt` 字段同时加入 `AccountingAdjustPageRespVO` 接口和 API 调用 - 后端 `recoverBadDebt` API 接收 `{ adjustmentNo: string }`,与 `AdjustExecuteReqDTO` 匹配