vault backup: 2026-05-25 23:27:56
This commit is contained in:
196
prop-acc/scenarios/prepaid/consume-multiple-bills-priority.md
Normal file
196
prop-acc/scenarios/prepaid/consume-multiple-bills-priority.md
Normal file
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: prop-acc · prepaid · 场景 - 多个未付账单按 due_at 优先级抵扣
|
||||
aliases:
|
||||
- 多账单抵扣优先级
|
||||
- 优先抵最早到期账单
|
||||
- consume-multiple-bills-priority
|
||||
- 场景-多账单优先级抵扣
|
||||
tags:
|
||||
- 场景
|
||||
- prop-acc
|
||||
- 预存款
|
||||
- 消费
|
||||
audience:
|
||||
- 业户
|
||||
- 业务人员
|
||||
status: 已发布
|
||||
sub_feature: prepaid
|
||||
last_review: 2026-05-25
|
||||
code_version: 2026-05-22
|
||||
---
|
||||
|
||||
# 场景:多个未付账单按 due_at 优先级抵扣
|
||||
|
||||
业户某月有**多张未付账单**(物业费、水电费、电梯维护费等),余额需抵多张。**优先抵最早到期的账单**(避免逾期罚款)。本场景描述业务人员的批量抵扣逻辑,也是 [[auto-deduction-design|自动 job]] 的核心算法。
|
||||
|
||||
## 典型情境
|
||||
|
||||
> [!example] 真实情境
|
||||
> 张阿姨家 5 月有 3 张未付账单:
|
||||
>
|
||||
> | 账单 | 金额 | due_at |
|
||||
> |---|---|---|
|
||||
> | 5 月物业费 | ¥800 | 5 月 15 日 |
|
||||
> | 5 月水电费 | ¥1,200 | 5 月 20 日 |
|
||||
> | Q2 电梯维护费 | ¥300 | 5 月 31 日 |
|
||||
>
|
||||
> 合计 ¥2,300,张阿姨账户余额 ¥2,500。**全部能抵**,但顺序很重要:
|
||||
>
|
||||
> 1. 物业费(5 月 15 日)— 最早到期,先抵
|
||||
> 2. 水电费(5 月 20 日)
|
||||
> 3. 电梯维护费(5 月 31 日)
|
||||
>
|
||||
> 抵完余 ¥200。
|
||||
|
||||
## 业户视角
|
||||
|
||||
### 您会感受到什么
|
||||
|
||||
- 5 月底收到 3 张收据(各账单一张),金额对应原账单
|
||||
- 小程序"我的预存款"流水按抵扣时间倒序显示 3 笔 consume
|
||||
- 小程序"我的账单"3 张全部 ✅ Paid
|
||||
- 推送通知"5 月 3 张账单已抵扣,余额 ¥200"
|
||||
|
||||
### 您要做什么
|
||||
|
||||
什么都不用。看明白即可。
|
||||
|
||||
> [!info] 余额够不够全付决定行为
|
||||
> - **够全付**:全部抵,余额剩下的留账户
|
||||
> - **不够全付**:按优先级先抵最早到期的,后面的留 Unpaid 状态 → 推送"余额不足,请充值"
|
||||
|
||||
## 业务人员视角
|
||||
|
||||
### 第 1 步:打开账户
|
||||
|
||||
后台 → 预存款 → 找到张阿姨账户 → 进 `ViewPrepaidAccount`(balance=2500)。
|
||||
|
||||
### 第 2 步:逐张抵扣(手动模式)
|
||||
|
||||
> [!warning] 当前没有"一键全抵"按钮
|
||||
> 业务人员需要**对每张账单各点一次** `ConsumeAction`。这是 [[auto-deduction-design|自动 job]] 要解决的痛点。
|
||||
|
||||
**正确顺序**(按 due_at 升序):
|
||||
|
||||
| 步骤 | 选 Bill | 抵 amount | 之后余额 |
|
||||
|---|---|---|---|
|
||||
| 1 | 5 月物业费(due 5/15) | 800 | 2500 → 1700 |
|
||||
| 2 | 5 月水电费(due 5/20) | 1200 | 1700 → 500 |
|
||||
| 3 | Q2 电梯维护费(due 5/31) | 300 | 500 → 200 |
|
||||
|
||||
每张账单走完整 [[consume-monthly-property-bill]] 流程(Modal → 提交 → 触发监听器 → Receipt)。
|
||||
|
||||
### 第 3 步:核对结果
|
||||
|
||||
- 3 张账单全 ✅ Paid
|
||||
- 账户余额 ¥200
|
||||
- 3 张 Receipt 已生成(分别 ¥800 ¥1,200 ¥300)
|
||||
|
||||
## 优先级排序逻辑(自动 job 用)
|
||||
|
||||
未来自动 job 实现后,**按以下顺序排序未付账单**:
|
||||
|
||||
| 排序键 | 升序/降序 | 业务理由 |
|
||||
|---|---|---|
|
||||
| 1. `due_at` | 升序 | **最早到期的先抵**(避免逾期产生滞纳金 / 影响信用) |
|
||||
| 2. `bill_type` | 自定义("物业费" → "水电费" → "其他") | 物业费是核心服务费,优先 |
|
||||
| 3. `amount` | 升序 | 同优先级下,**小额先抵清**(避免余额不够时多张大账单都半抵)|
|
||||
| 4. `created_at` | 升序 | 兜底:早建的先 |
|
||||
|
||||
伪代码:
|
||||
|
||||
```python
|
||||
unpaid_bills = sorted(
|
||||
bills,
|
||||
key=lambda b: (b.due_at, BILL_TYPE_ORDER[b.bill_type], b.amount, b.created_at)
|
||||
)
|
||||
|
||||
balance = account.balance
|
||||
for bill in unpaid_bills:
|
||||
if balance <= 0:
|
||||
break
|
||||
if balance >= bill.amount:
|
||||
consume(account, bill, bill.amount)
|
||||
balance -= bill.amount
|
||||
else:
|
||||
# 余额不够全付该账单 → 跳过,等业户充值
|
||||
notify(account.resident, "余额不足,无法抵 ¥{bill.amount} 的 {bill.bill_type}")
|
||||
# 或部分抵(看 Bill 是否支持):consume(account, bill, balance); balance = 0; break
|
||||
```
|
||||
|
||||
## 余额不够全付的策略对比
|
||||
|
||||
假设张阿姨账户余额 ¥1,500,3 张账单合计 ¥2,300:
|
||||
|
||||
| 策略 | 行为 | 结果 |
|
||||
|---|---|---|
|
||||
| **全部跳过** | 余额不够任何一笔不动 | 3 张全 Unpaid,余额 ¥1,500 闲置 |
|
||||
| **按优先级抵到不够为止**(推荐) | 物业费 800 → 余 700;水电费 1200 不够跳过;电梯费 300 余 700 ≥ 300 → 抵 → 余 400 | 物业费 + 电梯费 Paid,水电费 Unpaid,余额 ¥400 |
|
||||
| **按优先级抵 + 部分抵末张** | 物业费 800 → 余 700;水电费 1200 > 700 → 抵 700 部分 → 水电费余 500;电梯费 300 余 0 跳过 | 物业费 Paid + 水电费部分付 + 电梯费 Unpaid + 余额 0 |
|
||||
|
||||
**推荐第二种**(按优先级抵到不够为止,不做部分抵)。理由:
|
||||
|
||||
- 简单,Bill 模块不用支持部分付
|
||||
- 业户看到余额还有钱但有账单未付,会主动充值
|
||||
- 避免"抵了一半"的复杂状态
|
||||
|
||||
**第三种**等 Bill 模块支持部分支付后再考虑。
|
||||
|
||||
## 系统流程(手动模式 3 笔操作)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 财务
|
||||
participant Filament
|
||||
participant Account
|
||||
participant 数据库
|
||||
|
||||
Note over 财务: 余额 2500,3 张未付账单
|
||||
|
||||
财务->>Filament: ConsumeAction(物业费 800)
|
||||
Filament->>Account: consume(物业费, 800)
|
||||
Account->>数据库: balance 2500→1700, Bill Paid
|
||||
|
||||
财务->>Filament: ConsumeAction(水电费 1200)
|
||||
Filament->>Account: consume(水电费, 1200)
|
||||
Account->>数据库: balance 1700→500, Bill Paid
|
||||
|
||||
财务->>Filament: ConsumeAction(电梯费 300)
|
||||
Filament->>Account: consume(电梯费, 300)
|
||||
Account->>数据库: balance 500→200, Bill Paid
|
||||
|
||||
Note over 数据库: 3 张账单 Paid + 3 张 Receipt + 余额 200
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
> [!question] 业务人员漏抵某张账单怎么办?
|
||||
> 单纯漏抵 → 后续发现再抵一次。如果业户因此被收滞纳金,物业可走 [[../adhoc/cancel-amount-error-redo]] 之类的补救路径。
|
||||
|
||||
> [!question] 业务人员抵错优先级(先抵晚到期的)?
|
||||
> 不影响资金正确性(账户余额扣对了,账单状态更新对了)。**业务上**可能让早到期的账单进入逾期。**预防** = 培训业务人员看 due_at,**根治** = 上自动 job。
|
||||
|
||||
> [!question] 跨多个业户批量抵扣可以吗?
|
||||
> 当前不行,只能一个账户一个账户操作。**批量是自动 job 的核心需求**。
|
||||
|
||||
> [!question] 业务人员选错账单(选了别人的)?
|
||||
> Modal 的账单下拉**已经过滤同业户 + 同社区**,理论上选不到别人的。除非 UI / 数据有 bug,否则不会发生。
|
||||
|
||||
> [!question] 部分抵扣场景频繁吗?
|
||||
> 业务上罕见 —— 业户通常一次充够覆盖几个月。如果某业户经常余额不够,业务人员应主动提醒"建议充够 3 个月"。
|
||||
|
||||
## 异常分支
|
||||
|
||||
- 单笔抵扣 → [[consume-monthly-property-bill]]
|
||||
- 计量类账单(水电费)→ [[consume-meter-bill]]
|
||||
- 余额不够 → 告知业户充值
|
||||
- 月初批量(未来)→ [[consume-batch-auto-monthly]]
|
||||
- 账户冻结 → [[unfreeze-after-verification]]
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [[consume-monthly-property-bill]]
|
||||
- [[consume-meter-bill]]
|
||||
- [[consume-batch-auto-monthly]]
|
||||
- [[auto-deduction-design]]
|
||||
- [[transaction-types]]
|
||||
Reference in New Issue
Block a user