From 07c1f9868accdea6e18590c772a6dda509f38b61 Mon Sep 17 00:00:00 2001 From: tangweijie <877588133@qq.com> Date: Tue, 30 Jun 2026 17:55:09 +0800 Subject: [PATCH] docs: record counter unsettled red flush implementation --- .../02_Detailed_Design/12_REV_Detailed.md | 9 +++- .../03_Technical_Design/01_Database_Design.md | 25 ++++++++++ .../03_Interface_Design.md | 24 +++++++++ .../counter-unsettled-red-flush-2026-06-30.md | 28 +++++++++++ .../2026-06-30-counter-unsettled-red-flush.md | 50 +++++++++++++++++-- 5 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 docs/evidence/bugfix/counter-unsettled-red-flush-2026-06-30.md diff --git a/docs/design/02_Detailed_Design/12_REV_Detailed.md b/docs/design/02_Detailed_Design/12_REV_Detailed.md index 3ca491a..7706aab 100644 --- a/docs/design/02_Detailed_Design/12_REV_Detailed.md +++ b/docs/design/02_Detailed_Design/12_REV_Detailed.md @@ -264,6 +264,10 @@ flowchart TD - 旧系统将“柜台收费”和“柜台结账”拆分为两个菜单,结账阶段包含未结/已结查询、结账红冲、追加抄表和打印动作。 - 当前设计可继续采用统一收费核销模型,但必须补出“收费记录 → 班结结果 → 打印/红冲/查询”的业务闭环,避免柜面日终处理缺口。 - 迁移时需保留结账时间、结账人、网点、收费汇总口径和结账后红冲痕迹,保证财务对账与审计连续。 +- 当前正式实现中,柜台红冲分为已结账红冲与未结账红冲两条路径: + - 已结账红冲以 `biz_settle_record_detail` 为红冲状态源,要求收费记录已结账且结账明细为正常状态,红冲后同步更新结账明细、支付主单和营业账结清状态。 + - 未结账红冲仅允许柜台收费、账单缴费、收款方向、未结账且未绑定结账单的收费记录;执行正式反向支付流水后,将原支付主单标记为 `REVERSED`,将营业账恢复为未收费,并写入未结账红冲投影表用于红冲记录查询。 + - 已结账与未结账收费记录不得混批红冲,前端应在未结账列表提供单笔红冲入口,后端仍以支付主单状态进行最终校验。 #### 账单打印服务 @@ -276,6 +280,7 @@ flowchart TD - 旧系统支持红冲记录查询、导出与明细展开,是收费差错追溯的重要入口。 - 当前设计可将红冲视为收费核销后的修正场景,不强制要求独立实体表,但必须提供历史只读查询口径。 - 红冲迁移最小保留信息应包括原收费记录、红冲时间、红冲金额、原因、经办人、关联账单和后续账务状态。 +- 当前正式实现中,红冲记录查询合并两个来源:已结账红冲来自结账明细状态,未结账红冲来自 `biz_counter_unsettled_red_flush_record` 查询投影;两类记录在查询出口统一按红冲时间排序并支持导出。 ### 接口映射 @@ -285,8 +290,8 @@ flowchart TD ### 落地边界 - **已落地**:营业账主明细、交易流水、回调、异常、托收/代扣主对象。 -- **部分落地**:柜台班结、部分收费汇总类对象可能通过业务流程与报表实现,不一定存在独立表。 -- **文档先行**:部分红冲、实时收费汇总类台账暂不表述为已确认独立实体表。 +- **部分落地**:柜台班结、部分收费汇总类对象可能通过业务流程与报表实现,不一定存在独立表;柜台未结账红冲已落地为正式反向支付流水 + 状态回写 + 查询投影。 +- **文档先行**:实时收费汇总类台账暂不表述为已确认独立实体表。 diff --git a/docs/design/03_Technical_Design/01_Database_Design.md b/docs/design/03_Technical_Design/01_Database_Design.md index 683f4ad..503ea77 100644 --- a/docs/design/03_Technical_Design/01_Database_Design.md +++ b/docs/design/03_Technical_Design/01_Database_Design.md @@ -1172,6 +1172,31 @@ retrieval_priority: P0 > > 边界说明:旧数据字典中的“跨周期水量、特账、红冲、已销调整、呆坏账、实时收费日志”等对象,在当前 backend 范围内未全部识别到独立实体表;数据库专项中统一按“在线骨架承接 / 历史只读保留 / 映射对象追溯”三层口径描述,不误写为已明确落地的真实表。 +### biz_counter_unsettled_red_flush_record (柜台未结账红冲查询投影表) + +| 字段 | 说明 | +| :--- | :--- | +| `id` | 主键,使用 `biz_counter_unsettled_red_flush_record_seq` | +| `payment_record_id`、`payment_no` | 原未结账收费支付主单及单号 | +| `reverse_payment_record_id`、`reverse_payment_no` | 正式反向支付流水及单号 | +| `charge_id` | 关联营业账 | +| `source_cust_id`、`source_cust_code`、`source_cust_name` | 客户快照 | +| `cashier_id` | 原收费员,用于柜台红冲记录查询权限和筛选 | +| `reversed_amount`、`reversed_time`、`reverse_reason` | 红冲金额、时间、原因 | +| `proc_person`、`proc_type` | 经办人与处理类型,未结账红冲固定为 `COUNTER_UNSETTLED_RED_FLUSH` | +| `tenant_id`、`creator`、`create_time`、`updater`、`update_time`、`deleted` | 租户、审计和逻辑删除字段 | + +约束与索引: + +- `uk_counter_unsettled_red_flush_payment(payment_record_id, tenant_id)`:防止同一原收费支付主单重复写入未结账红冲投影。 +- `idx_counter_unsettled_red_flush_cashier_time(cashier_id, reversed_time, tenant_id)`:支撑按收费员和红冲时间查询。 +- `idx_counter_unsettled_red_flush_cust_time(source_cust_code, reversed_time, tenant_id)`:支撑按客户编号和红冲时间查询。 + +设计边界: + +- 该表不是红冲业务主账本,主状态仍以 `biz_payment_record`、`biz_charge` 和正式反向支付流水为准。 +- 该表只承接未结账红冲的查询/导出投影;已结账红冲仍以 `biz_settle_record_detail` 的红冲状态为查询来源。 + ### 旧系统历史台账迁移与只读查询口径 #### 在线主模型承接范围 diff --git a/docs/design/03_Technical_Design/03_Interface_Design.md b/docs/design/03_Technical_Design/03_Interface_Design.md index 9f8eeba..c8c5904 100644 --- a/docs/design/03_Technical_Design/03_Interface_Design.md +++ b/docs/design/03_Technical_Design/03_Interface_Design.md @@ -1777,6 +1777,30 @@ sequenceDiagram | 水表生命周期、检定与库存流转 | `IF-METER-001`、`IF-METER-003` | `biz_meter*` + 历史仓储/检定单据 | 表号、当前状态、单据类型、仓库、检定结论、证书编号、时间 | 支撑表务迁移核查与历史作业追溯 | | 页面参数、业务字段、微信配置 | `IF-REV-012`、`IF-CS-006` | `biz_parameter_settings`、`biz_page_settings*`、`sys_wechat_app_settings` | 参数编码、原值、新值、启用状态、生效时间、适用渠道 | 支撑微网厅后台配置迁移核查 | +### 柜台红冲接口约束补充 + +当前柜台结账红冲统一复用 `POST /business/charge/counter-settle/red-flush`,请求参数为 `paymentRecordIds` 与必填 `reason`。 + +接口按支付主单结账状态分流: + +| 场景 | 请求约束 | 状态变化 | 查询出口 | +| :--- | :--- | :--- | :--- | +| 已结账红冲 | 所有 `paymentRecordIds` 必须存在正常 `biz_settle_record_detail`,支付主单为 `SETTLED` | 写正式反向支付流水;结账明细标记红冲;原支付主单标记 `REVERSED`;营业账清除结账态 | 红冲记录页从结账明细读取 | +| 未结账红冲 | 所有 `paymentRecordIds` 必须为柜台收费、账单缴费、收款方向、`UNSETTLED`、未绑定 `settle_id` | 写正式反向支付流水;原支付主单标记 `REVERSED`;营业账恢复未收费;写入 `biz_counter_unsettled_red_flush_record` | 红冲记录页从未结账红冲投影读取 | + +接口拒绝以下情况: + +- 已结账与未结账支付主单混批提交。 +- 未结账记录不是柜台账单缴费,或缺少可恢复的营业账。 +- 原支付主单已红冲、已结账状态并发变化,或已存在未结账红冲投影。 +- 当前登录收费员尝试红冲其他收费员的收费记录。 + +前端约束: + +- 柜台结账“未结账”列表对单笔可红冲收费记录提供红冲按钮,仅对有 `paymentRecordId`、有 `chargeId` 且业务场景为 `CHARGE_PAYMENT` 的行启用。 +- 柜台结账“已结账”明细继续提供已结账红冲入口。 +- 两类入口都必须采集非空红冲原因后再提交。 + ### 迁移验收对账接口要求 | 验收场景 | 推荐挂靠接口 | 最低查询维度 | 输出要求 | diff --git a/docs/evidence/bugfix/counter-unsettled-red-flush-2026-06-30.md b/docs/evidence/bugfix/counter-unsettled-red-flush-2026-06-30.md new file mode 100644 index 0000000..5e76691 --- /dev/null +++ b/docs/evidence/bugfix/counter-unsettled-red-flush-2026-06-30.md @@ -0,0 +1,28 @@ +# 柜台未结账正式红冲验证记录 + +## 背景 + +柜台结账历史口径要求未结账和已结账记录均可红冲。原实现仅覆盖已结账红冲,本次补齐未结账正式红冲,并在柜台结账未结账列表提供前端入口。 + +## 实现范围 + +- 后端 `POST /business/charge/counter-settle/red-flush` 按支付主单状态分流已结账/未结账红冲。 +- 未结账红冲仅支持柜台收费、账单缴费、收款方向、`UNSETTLED`、`settleId=null` 的支付主单。 +- 未结账红冲生成正式反向支付流水,原支付主单更新为 `REVERSED`,营业账恢复未收费。 +- 新增 `biz_counter_unsettled_red_flush_record` 查询投影,红冲记录查询/导出合并已结账与未结账红冲。 +- 前端柜台结账“未结账”列表新增单笔红冲按钮;已结账明细与未结账入口均要求非空红冲原因。 + +## 验证命令 + +| 范围 | 命令 | 结果 | 说明 | +| :--- | :--- | :--- | :--- | +| 后端单测 | `mvn -pl sw-business/sw-business-server -am -Dtest=CounterSettleApplicationServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test` | 通过 | `CounterSettleApplicationServiceImplTest` 共 31 个用例通过,覆盖未结账红冲成功、混批拒绝、重复/并发拒绝、越权拒绝和红冲记录查询。 | +| 后端最终回归 | `mvn -pl sw-business/sw-business-server -am -Dtest=CounterSettleApplicationServiceImplTest,PaymentRecordServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test` | 通过 | 共 50 个用例通过,其中柜台结账 32 个、支付记录 18 个。 | +| 前端依赖 | `pnpm install` | 通过 | 前端 worktree 初始缺少 `node_modules`,安装依赖后继续验证。 | +| 前端类型检查 | `pnpm ts:check` | 未通过 | 首次执行因 Node 默认 4GB 堆内存 OOM 退出。 | +| 前端类型检查 | `NODE_OPTIONS=--max-old-space-size=8192 pnpm ts:check` | 未通过 | 全仓存在既有 TS 基线错误,主要为自动导入类型未识别和无关业务类型问题。 | +| 前端局部过滤 | `NODE_OPTIONS=--max-old-space-size=8192 pnpm ts:check 2>&1 \| rg "counterCheckout\|counterSettle"` | 通过本次改动检查 | 过滤后仅剩未触碰的 `CheckoutTopSummary.vue`、`CounterSettleConfirmDialog.vue`、`CounterSettledPanel.vue` 自动导入基线错误;本次触碰的 `CounterUnsettledPanel.vue`、`CounterSettledDetailDialog.vue`、`counterCheckout/index.vue`、`counterSettle.ts` 无新增错误。 | + +## 结论 + +柜台未结账正式红冲已完成后端最小闭环验证。红冲后原收费支付主单不再进入待结账候选,营业账恢复未收费,红冲记录查询可追溯未结账红冲投影。前端入口已补齐,但全仓 `vue-tsc` 仍受既有自动导入类型基线影响,需要另行治理。 diff --git a/docs/superpowers/plans/2026-06-30-counter-unsettled-red-flush.md b/docs/superpowers/plans/2026-06-30-counter-unsettled-red-flush.md index b808080..0abed2a 100644 --- a/docs/superpowers/plans/2026-06-30-counter-unsettled-red-flush.md +++ b/docs/superpowers/plans/2026-06-30-counter-unsettled-red-flush.md @@ -4,9 +4,9 @@ **Goal:** Add formal red flush support for unsettled counter charge records without letting flushed records participate in later counter settlement. -**Architecture:** Keep the existing `counter-settle/red-flush` API and split service behavior by payment settlement state. Settled red flush continues through `biz_settle_record_detail`; unsettled red flush writes a new projection table after creating the reverse payment record and marking the original payment record as `REVERSED`. Red flush record query/export merges settled-detail rows and unsettled-projection rows. +**Architecture:** Keep the existing `counter-settle/red-flush` API and split service behavior by payment settlement state. Settled red flush continues through `biz_settle_record_detail`; unsettled red flush writes a new projection table after creating the reverse payment record and marking the original payment record as `REVERSED`. Red flush record query/export merges settled-detail rows and unsettled-projection rows. Frontend reuses the same red flush API from the counter checkout page, adding a single-row action in the unsettled list and keeping the settled-detail action. -**Tech Stack:** Java 17, Spring Boot, MyBatis Plus, Lombok, Kingbase/PostgreSQL SQL migration, JUnit 5, Mockito. +**Tech Stack:** Java 17, Spring Boot, MyBatis Plus, Lombok, Kingbase/PostgreSQL SQL migration, JUnit 5, Mockito, Vue 3, Element Plus, TypeScript. --- @@ -26,6 +26,14 @@ - Add tests for unsettled success, record query, mixed batch rejection, duplicate/concurrent rejection, and access control. - Modify: `sql/rev005/REV005_counter_settle_tables.sql` - Add DDL for `biz_counter_unsettled_red_flush_record`. +- Modify: `water-web/src/views/operatingCharges/counterCheckout/components/CounterUnsettledPanel.vue` + - Add single-row unsettled red flush action with required reason prompt. +- Modify: `water-web/src/views/operatingCharges/counterCheckout/index.vue` + - Add parent API call and refresh chain for unsettled red flush. +- Modify: `water-web/src/views/operatingCharges/counterCheckout/components/CounterSettledDetailDialog.vue` + - Align settled red flush reason with backend required validation. +- Modify: `water-web/src/api/business/charge/counterSettle.ts` + - Mark red flush reason as required and keep response row typing aligned. - Modify: `../water-docs/docs/design/02_Detailed_Design/12_REV_Detailed.md` - Document current formal unsettled red flush behavior. - Modify: `../water-docs/docs/design/03_Technical_Design/01_Database_Design.md` @@ -1141,7 +1149,41 @@ git commit -m "fix(counter-settle): stabilize unsettled red flush verification" If a verification failure required a mapper or DDL fix, add the exact changed mapper or SQL file alongside the service/test paths above before committing. If no code changed, do not create a commit. -## Task 8: Update Formal Docs and Evidence +## Task 8: Add Frontend Unsettled Red Flush Entry + +**Files:** +- Modify: `src/views/operatingCharges/counterCheckout/components/CounterUnsettledPanel.vue` +- Modify: `src/views/operatingCharges/counterCheckout/index.vue` +- Modify: `src/views/operatingCharges/counterCheckout/components/CounterSettledDetailDialog.vue` +- Modify: `src/api/business/charge/counterSettle.ts` + +- [ ] **Step 1: Add operation column in unsettled table** + +Add a fixed right-side `红冲` button for rows that have `paymentRecordId`, `chargeId`, and `bizScene` empty or `CHARGE_PAYMENT`. + +- [ ] **Step 2: Add required reason confirmation** + +Use the existing `useMessage().confirm` and `useMessage().prompt` pattern. Do not submit when the trimmed reason is empty because the backend request VO requires `reason`. + +- [ ] **Step 3: Wire parent API call** + +Call `CounterSettleApi.reverseCounterSettlePayment({ paymentRecordIds: [row.paymentRecordId], reason })`, then refresh unsettled rows, payment summary, and settled list. + +- [ ] **Step 4: Align settled red flush reason typing** + +Make `CounterRedFlushReqVO.reason` required in TypeScript and prevent the settled-detail red flush action from submitting blank reasons. + +- [ ] **Step 5: Frontend verification** + +Run: + +```bash +NODE_OPTIONS=--max-old-space-size=8192 pnpm ts:check +``` + +Expected for the current frontend baseline: full `vue-tsc` may still fail on existing auto-import/global type errors in unrelated files. Filter the output for the touched counter checkout files and ensure there are no new errors in `CounterUnsettledPanel.vue`, `CounterSettledDetailDialog.vue`, `index.vue`, or `counterSettle.ts`. + +## Task 9: Update Formal Docs and Evidence **Files:** - Modify: `../water-docs/docs/design/02_Detailed_Design/12_REV_Detailed.md` @@ -1219,7 +1261,7 @@ git -C ../water-docs add docs/design/02_Detailed_Design/12_REV_Detailed.md \ git -C ../water-docs commit -m "docs: record counter unsettled red flush implementation" ``` -## Task 9: Final Regression and Status Check +## Task 10: Final Regression and Status Check **Files:** - No planned source edits.