169 lines
5.8 KiB
Markdown
169 lines
5.8 KiB
Markdown
|
|
---
|
||
|
|
title: prop-acc · prepaid · 场景 - 部分消费后退余(不自动关账)
|
||
|
|
aliases:
|
||
|
|
- 部分退预存款
|
||
|
|
- 退一部分留账户
|
||
|
|
- refund-partial-after-consume
|
||
|
|
- 场景-预存款部分退余
|
||
|
|
tags:
|
||
|
|
- 场景
|
||
|
|
- prop-acc
|
||
|
|
- 预存款
|
||
|
|
- 退款
|
||
|
|
audience:
|
||
|
|
- 业户
|
||
|
|
- 业务人员
|
||
|
|
status: 已发布
|
||
|
|
sub_feature: prepaid
|
||
|
|
last_review: 2026-05-25
|
||
|
|
code_version: 2026-05-22
|
||
|
|
---
|
||
|
|
|
||
|
|
# 场景:部分消费后退余(不自动关账)
|
||
|
|
|
||
|
|
业户**部分使用**预存款后,想**退余下一部分**(不全退,继续保留账户)。退完仍 Active,业户可后续继续充值复用。本场景突出 prepaid 与 deposit 的**关键差异**:零余额不自动关账,部分余额更不会。
|
||
|
|
|
||
|
|
## 典型情境
|
||
|
|
|
||
|
|
> [!example] 真实情境
|
||
|
|
> 陈先生 3 个月前充了 ¥5,000 预存款,期间扣了 ¥2,400(3 个月物业费),余额 ¥2,600。他最近现金流紧张,想**先退 ¥1,500 应急**,留 ¥1,100 在账户继续扣物业费。
|
||
|
|
|
||
|
|
## 业户视角
|
||
|
|
|
||
|
|
### 第 1 步:跟物业说要退一部分
|
||
|
|
|
||
|
|
- "我想从预存款退 ¥1,500,留点继续用"
|
||
|
|
- 提供退款渠道
|
||
|
|
|
||
|
|
### 第 2 步:等退款
|
||
|
|
|
||
|
|
- 业务人员核实余额、操作
|
||
|
|
|
||
|
|
### 第 3 步:收到红字收据 + 退款
|
||
|
|
|
||
|
|
- 红字收据"预付款退款 ¥-1,500"
|
||
|
|
- 银行 / 微信收到 ¥1,500
|
||
|
|
|
||
|
|
### 第 4 步:账户保持 Active
|
||
|
|
|
||
|
|
- 小程序"我的预存款"显示余额 ¥1,100
|
||
|
|
- 仍可继续抵账单
|
||
|
|
- 后续可继续充值
|
||
|
|
|
||
|
|
> [!info] 与 deposit 的核心差异
|
||
|
|
> deposit 退完余额到 0 会自动 Closed。prepaid **退完无论余额多少都不自动关**,业户随时可继续用。
|
||
|
|
|
||
|
|
## 业务人员视角
|
||
|
|
|
||
|
|
### 第 1 步:打开账户
|
||
|
|
|
||
|
|
后台 → 预存款 → 陈先生账户(Active,balance=2600)→ 进 `ViewPrepaidAccount`。
|
||
|
|
|
||
|
|
### 第 2 步:`RefundAction` Modal
|
||
|
|
|
||
|
|
| 字段 | 填什么 |
|
||
|
|
|---|---|
|
||
|
|
| **退款金额** | **¥1,500**(不是全额,**手动改**)|
|
||
|
|
| 退款渠道 | 微信 / 银行 |
|
||
|
|
| 备注 | 选填,如 "业户申请部分退款" |
|
||
|
|
|
||
|
|
> [!warning] 易错点
|
||
|
|
> Modal 默认带入**当前余额全额**(¥2,600)。**必须手动改为 ¥1,500**,否则就成了全退。
|
||
|
|
|
||
|
|
### 第 3 步:提交
|
||
|
|
|
||
|
|
系统调 `RefundFromPrepaidAccountAction`,事务内:
|
||
|
|
|
||
|
|
1. 校验 `canOperate()`
|
||
|
|
2. 校验金额 ≤ 余额(1500 ≤ 2600 ✓)
|
||
|
|
3. 建 `CollectionOrder`(`type=Prepaid`,`actual=-1500` 红字,`Completed`)
|
||
|
|
4. 调 `account.refund(1500)`:
|
||
|
|
- 加 `PrepaidTransaction`(type=refund, 2600→1100,关联 CO)
|
||
|
|
- 更新 balance=1100
|
||
|
|
5. **不关账**(余额非 0)
|
||
|
|
6. 触发监听器 → Receipt"预付款退款 ¥-1,500"
|
||
|
|
|
||
|
|
### 第 4 步:走线下退款 + 给收据
|
||
|
|
|
||
|
|
银行 / 微信退 ¥1,500;红字收据交业户。**账户保持 Active,余额 ¥1,100**。
|
||
|
|
|
||
|
|
### 第 5 步:告知业户
|
||
|
|
|
||
|
|
"已退 ¥1,500,账户还有 ¥1,100 可继续抵账单"。
|
||
|
|
|
||
|
|
## 系统流程
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant 业户
|
||
|
|
participant 财务
|
||
|
|
participant Filament
|
||
|
|
participant 数据库
|
||
|
|
|
||
|
|
Note over 业户: 余额 2600,要退 1500
|
||
|
|
|
||
|
|
业户->>财务: 退 1500
|
||
|
|
财务->>Filament: ViewPrepaidAccount → RefundAction(modal, **改成 1500**)
|
||
|
|
Filament->>数据库: RefundFromPrepaidAccountAction
|
||
|
|
数据库->>数据库: 建 CO(-1500 红字) + PrepaidTransaction(refund, 2600→1100)
|
||
|
|
数据库->>数据库: balance=1100(**不关账**)
|
||
|
|
数据库->>监听器: 触发监听器 → Receipt("预付款退款 ¥-1,500")
|
||
|
|
财务-->>业户: 微信退 1500 + 红字收据 + 告知余额 1100
|
||
|
|
```
|
||
|
|
|
||
|
|
## 流水台账(累计)
|
||
|
|
|
||
|
|
| 流水 | type | amount | balance_before | balance_after | 备注 |
|
||
|
|
|---|---|---|---|---|---|
|
||
|
|
| 1 | deposit | 5000 | 0 | 5000 | 3 个月前首次充值 |
|
||
|
|
| 2 | consume | 800 | 5000 | 4200 | 第 1 月物业费 |
|
||
|
|
| 3 | consume | 800 | 4200 | 3400 | 第 2 月物业费 |
|
||
|
|
| 4 | consume | 800 | 3400 | 2600 | 第 3 月物业费 |
|
||
|
|
| **5** | **refund** | **1500** | **2600** | **1100** | **本场景** |
|
||
|
|
|
||
|
|
账户余额 ¥1,100,**仍 Active**,后续可继续抵账单或充值。
|
||
|
|
|
||
|
|
## 与 deposit 退款的差异
|
||
|
|
|
||
|
|
| 维度 | deposit 部分退款(refund-partial-after-forfeit) | prepaid 部分退款(本场景) |
|
||
|
|
|---|---|---|
|
||
|
|
| 退款产生的 CO 类型 | type=Deposit, -N 红字 | type=Prepaid, -N 红字 |
|
||
|
|
| 退完余额 0 | **自动 Closed** | **仍 Active** |
|
||
|
|
| 退完余额非 0 | 仍 Active(deposit 也允许部分退后继续动)| 仍 Active |
|
||
|
|
| 业务背景 | 押金扣罚 + 退余 | 业户应急需现金,部分提取 |
|
||
|
|
|
||
|
|
## 常见问题
|
||
|
|
|
||
|
|
> [!question] 退完余额变 0,会自动关账吗?
|
||
|
|
> **不会**。即使全退到 0,prepaid 仍保持 Active。详见 [[account-state-machine]]"零余额不自动关账"段 + [[close-with-zero-balance-decision]]。
|
||
|
|
|
||
|
|
> [!question] 业务人员退多了(改余额时手抖)?
|
||
|
|
> 系统会校验 `amount ≤ balance` 守护拦截。例如余额 2600,改成 3000 提交 → 抛错 "amount exceeds balance"。**预防**:Modal 提交前再三确认数字。
|
||
|
|
|
||
|
|
> [!question] 业户想退完了又改主意,要充回去?
|
||
|
|
> 当然可以。直接走 [[deposit-additional-topup|追加充值]] 把钱充回账户即可。账户一直 Active 没动过。
|
||
|
|
|
||
|
|
> [!question] 业户拿到红字收据后困惑"我没买东西啊为什么收据是负数"?
|
||
|
|
> 解释:
|
||
|
|
> - 红字 = 钱从物业流出 / 回到您手里
|
||
|
|
> - 这不是消费收据,是退款收据
|
||
|
|
> - 详见 [[../deposit/red-receipt-design]](deposit 模块的概念,prepaid 复用相同设计)
|
||
|
|
|
||
|
|
> [!question] 业户问"我现在余额 1100,还能扣账单吗?"
|
||
|
|
> 当然能。账户 Active,余额 > 0,正常用。物业费下月扣完后余额会变 ¥300(假设 ¥800 月费)。
|
||
|
|
|
||
|
|
## 异常分支
|
||
|
|
|
||
|
|
- 全额退 → [[refund-full-resident-moveout]]
|
||
|
|
- Frozen 状态退 → 先 [[unfreeze-after-verification]] 再退
|
||
|
|
- 退完想关账 → 走 [[close-with-zero-balance-decision]]
|
||
|
|
- 业户搬走全退 + 关账 → [[refund-full-resident-moveout]] + [[close-resident-moveout]]
|
||
|
|
|
||
|
|
## 相关文档
|
||
|
|
|
||
|
|
- [[refund-full-resident-moveout]]
|
||
|
|
- [[account-state-machine]]
|
||
|
|
- [[close-with-zero-balance-decision]]
|
||
|
|
- [[transaction-types]]
|
||
|
|
- [[../deposit/red-receipt-design]]
|