Files
uniprop-manual/prop-acc/scenarios/prepaid/deposit-additional-topup.md
2026-05-25 23:22:55 +08:00

164 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: prop-acc · prepaid · 场景 - 已有账户追加充值
aliases:
- 追加充值预存款
- 预存款续充
- deposit-additional-topup
- 场景-预存款追加充值
tags:
- 场景
- prop-acc
- 预存款
- 充值
audience:
- 业户
- 业务人员
status: 已发布
sub_feature: prepaid
last_review: 2026-05-25
code_version: 2026-05-22
---
# 场景:已有账户追加充值
业户**已有 Active 预存款账户**,余额不够 / 想多存,继续充值。比首次开户简单 —— 不建账户,只加流水。
## 典型情境
> [!example] 真实情境
> 张阿姨 3 个月前充了 ¥5,000 预存款,期间扣了 ¥2,400(物业费 800 × 3),余额 ¥2,600。下个月还要扣 ¥800 + ¥600 水电费,觉得余额勉强够,**再充 ¥3,000** 凑个整。
## 业户视角
### 第 1 步:到前台 / 小程序
跟物业管家说"我预存账户加 ¥3,000"。
### 第 2 步:付款
支付方式同首次充值。
### 第 3 步:拿收据
"预付款充值 ¥3,000"。
### 第 4 步:余额查看
后台 / 小程序看到:
- 上次余额 ¥2,600 + 本次 ¥3,000 = **当前余额 ¥5,600**
- 后续账单自动从这扣
## 业务人员视角
> [!info] 与首次充值的差异
> **不开新账户**,在既有账户上 `DepositAction` 加流水。
### 第 1 步:找到既有账户
后台 → 预存款 → 账户列表 → 按业户姓名 / 房号搜索 → 找到 Active 账户。
### 第 2 步:进 `ViewPrepaidAccount`
详情页右上角点 **`DepositAction`**(标签"充值")。
> [!warning] 按钮可见性
> `DepositAction` 守护:`canOperate()`(Active only)+ Policy `->authorize('deposit')`。Frozen / Closed 灰化。
### 第 3 步:Modal 表单
| 字段 | 填什么 |
|---|---|
| **充值金额** | ¥3,000 |
| **支付方式** | 现金 / 微信 / POS / 银行转账 |
| **收款银行账户** | 微信/POS/转账选对应银行 |
| **备注** | 选填 |
### 第 4 步:提交
系统调 `PrepaidAccount::deposit($amount, ...)`,事务内:
1. 模型层校验 `canOperate()`(Active only)
2.`CollectionOrder`(`type=Prepaid`,`actual=+3000`,`Completed`)
3.`PrepaidTransaction`(`type=deposit`,`amount=3000`,`balance_before=2600`,`balance_after=5600`,关联 CO)
4. 更新 `PrepaidAccount.balance=5600`
5. 触发 `CollectionOrderCompleted` → Listener 建 Receipt"预付款充值 ¥3,000"
### 第 5 步:给收据
打印 / 发微信。
## 系统流程
```mermaid
sequenceDiagram
participant 业户
participant 前台
participant Filament
participant PrepaidAccount
participant 数据库
业户->>前台: 给预存账户加 3000
前台->>Filament: ViewPrepaidAccount → DepositAction(modal)
Filament->>PrepaidAccount: deposit(3000, ...)
PrepaidAccount->>PrepaidAccount: canOperate()? Active=true
PrepaidAccount->>数据库: 开启事务
PrepaidAccount->>数据库: 1. 建 CO (Prepaid, +3000, Completed)
PrepaidAccount->>数据库: 2. 建 PrepaidTransaction (deposit, 2600→5600)
PrepaidAccount->>数据库: 3. 更新 balance=5600
PrepaidAccount->>监听器: 触发 CollectionOrderCompleted
监听器->>数据库: 建 Receipt (预付款充值 ¥3,000)
PrepaidAccount->>数据库: 提交
Filament-->>前台: 成功
前台->>业户: 收据
```
## 流水台账(本场景在累计流水中的位置)
| 流水 | 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** | **deposit** | **3000** | **2600** | **5600** | **本次追加** |
## 常见问题
> [!question] Frozen 账户能追加充值吗?
> **不能**。`canOperate()` 只允许 Active。详见 [[exception-refund-on-frozen|三层守护]](deposit / consume / refund 都一样)。
>
> 如果业户硬要充:
> - 系统层无法绕过(模型层兜底)
> - **业务层** 需先 [[unfreeze-after-verification|解冻]] → 再充
> - 不可"暂存钱等解冻后录入" —— 不合规
> [!question] Closed 账户能追加充值吗?
> **不能**(同上)。需要开新账户,但**一户一账约束阻塞**(详见 [[one-account-per-resident]] "已知设计 gap")。
> [!question] 同时多笔追加(一天充两次)可以吗?
> 可以。每次独立 Action,各自一笔 Transaction + CO + Receipt。账户 balance 累加。
> [!question] 充值过多担心退不出来?
> 任何时候可走 [[refund-partial-after-consume]] 或 [[refund-full-resident-moveout]] 退余。预存款不像押金有"装修结束才能退"的业务节点,**随时可退**。
> [!question] 业户问"我能用别人的微信付吗?"
> 系统不限制实际支付来源(微信扫码用谁付都行)。**业务上**:
> - 账面缴款人是业户本人(`PrepaidAccount.community_user_profile_id` 不变)
> - 实际付钱的是谁是业户自己的事
> - 退款时**只退给账面缴款人**(业户本人),不是实际付钱的微信号
## 异常分支
- 业户从未充过 → 走 [[deposit-first-time]] 开户
- 充错金额 → [[refund-partial-after-consume]]
- 账户冻结 → 先 [[unfreeze-after-verification]] 解冻
## 相关文档
- [[deposit-first-time]]
- [[account-state-machine]]
- [[consume-monthly-property-bill]]
- [[refund-partial-after-consume]]
- [[exception-refund-on-frozen]]