7.5 KiB
title, aliases, tags, audience, status, sub_feature, last_review, code_version
| title | aliases | tags | audience | status | sub_feature | last_review | code_version | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| prop-acc · prepaid · 场景 - 手动抵扣月度物业费 |
|
|
|
已发布 | prepaid | 2026-05-25 | 2026-05-22 |
场景:手动抵扣月度物业费
预存款最高频操作 —— 月底物业费账单出来后,业务人员后台手动触发 ConsumeAction,从业户的预存款余额扣对应金额、Bill 状态翻 Paid。未来批量自动 job 落地后,这条路径变成"运维个例兜底"(详见 auto-deduction-design)。
典型情境
[!example] 真实情境 张阿姨的 12-3-501 房 5 月物业费账单 ¥800 已出账。张阿姨预存款账户余额 ¥4,200。物业财务王主管月初批量为 100+ 户业户做物业费抵扣,张阿姨是其中一户。
业户视角
您会感受到什么
- 5 月底账单出来后,几天内收到推送:
"您的 5 月物业费 ¥800 已自动从预存款扣减,余额 ¥3,400"
- 收到收据:"物业费 ¥800(5 月)"
- 小程序"我的预存款"显示新流水:
-800.00 抵扣 物业费(5月) - 小程序"我的账单"显示该账单 ✅ 已付
您要做什么
什么都不用做。看看就行 ——
- 如果余额够,账单自动归零,无感
- 如果余额不够,会收到"余额不足"提示,需要您手动充值或现金/微信付
[!info] 与现金付的差异 业户拿到的收据长一样(都是"物业费 ¥800"),只是结算来源不同。详见 consume-via-bill-collection-type。
业务人员视角
第 1 步:确认账单已生成
后台 → 账单(Bill)模块 → 5 月物业费账单批量 → 状态 Unpaid → 列表里有张阿姨的账单。
第 2 步:打开张阿姨的预存款账户
后台 → 预存款 → 账户列表 → 按业户姓名搜 → 找到 Active 账户(balance=4200)→ 进 ViewPrepaidAccount。
第 3 步:点击 ConsumeAction(标签"消费抵扣")
[!warning] 按钮可见性
ConsumeAction守护:canOperate()(Active only)+balance > 0+ Policy->authorize('consume')。Frozen / Closed / 零余额账户灰化。
Modal 表单:
| 字段 | 填什么 |
|---|---|
| 关联账单(Bill) | 选业户的未付账单(下拉显示该业户 community 内 status=unpaid 的账单) |
| 抵扣金额 | 自动带入账单金额(可改,部分抵扣场景) |
| 备注 | 选填,如 "5 月物业费手动抵扣" |
第 4 步:提交
系统调 ConsumeFromPrepaidAccountAction,事务内:
- 校验
canOperate()(Active only) - 校验跨社区(Bill 与 Account 必须同 community)
- 校验余额(≥ 抵扣金额)
- 建
CollectionOrder(type=Bill,actual=+800,meta.fund_source=prepaid,Completed) - 建
CollectionOrderBill关联 CO 与 Bill - 调
PrepaidAccount::consume($bill, $amount):- 加
PrepaidTransaction(type=consume,amount=800,balance_before=4200,balance_after=3400,related_bill_id=...,关联 CO) - 更新
balance=3400
- 加
- 调
Bill::recordPayment($amount):- 更新
Bill.status=Paid
- 更新
- 触发
CollectionOrderCompleted→ Listener 建 Receipt(走 Bill 渠道,文案"物业费 ¥800")
第 5 步:给收据 / 通知
后台找到新建 Receipt → 发业户(微信 / 邮件)。
系统流程
sequenceDiagram
participant 业户
participant 财务
participant Filament
participant ConsumeAction
participant PrepaidAccount
participant Bill
participant 数据库
participant 监听器
Note over 业户,财务: 5 月物业费账单已出,张阿姨 balance=4200
财务->>Filament: ViewPrepaidAccount → ConsumeAction(选 Bill, 800)
Filament->>ConsumeAction: handle(account, bill, 800)
ConsumeAction->>PrepaidAccount: canOperate() ? Active=true
ConsumeAction->>PrepaidAccount: community_id match Bill? yes
ConsumeAction->>PrepaidAccount: balance >= 800? 4200≥800 yes
ConsumeAction->>数据库: 开启事务
ConsumeAction->>数据库: 1. 建 CO(type=Bill, +800, meta.fund_source=prepaid)
ConsumeAction->>数据库: 2. 建 CollectionOrderBill 关联
ConsumeAction->>PrepaidAccount: 3. consume(bill, 800)
PrepaidAccount->>数据库: 建 PrepaidTransaction(consume, 4200→3400, related_bill_id)
PrepaidAccount->>数据库: 更新 balance=3400
ConsumeAction->>Bill: 4. recordPayment(800)
Bill->>数据库: status=Paid
ConsumeAction->>监听器: 5. 触发 CollectionOrderCompleted
监听器->>数据库: 建 Receipt("物业费 ¥800")
ConsumeAction->>数据库: 提交事务
Filament-->>财务: 成功
财务-->>业户: 推送 + 收据
流水台账(本场景在累计流水中)
| 流水 | type | amount | balance_before | balance_after | related_bill_id | 备注 |
|---|---|---|---|---|---|---|
| 1 | deposit | 5000 | 0 | 5000 | — | 首次充值 |
| 2 | consume | 800 | 5000 | 4200 | Bill #5月物业费 | 本场景 |
| (后续 4 月 5 月各 800 ...) |
5 月账单进入 Paid 状态,张阿姨账户余额变 ¥3,400。
部分抵扣的特殊情况
若业户余额不够全付(例如余额 ¥500,账单 ¥800):
| 选项 | 当前实现 |
|---|---|
| 抵扣 ¥500,账单剩 ¥300 待付 | 看 Bill::recordPayment() 是否支持部分支付 |
| 全部跳过(不抵) | 等业户充值或其他方式付 |
当前推荐:跳过,告知业户"余额不足,请充值或选其他方式付"。部分抵扣需 Bill 模块配合。
常见问题
[!question] Modal 表单里"关联账单"下拉如何过滤? 系统只显示:
- 与本账户同社区(community_id 一致)
- 业户本人(resident_id 一致)
- 状态 Unpaid
- 按 due_at 升序(最早到期的先,引导业务人员优先抵)
[!question] 抵扣后业户问"我用预存款付的为啥收据写'物业费'?" 这是有意设计(详见 consume-via-bill-collection-type):业户感知一致,不管怎么付,收据都长一样。如果业户想知道"是用预存款付的",可在小程序"我的账单"看到付款方式 = "预存款抵扣"。
[!question] 抵扣失败如何排查? 看后台 / 日志的错误信息:
- "账户冻结" → 解冻
- "跨社区不允许" → 业务人员选错账单 / 账户
- "余额不足" → 业户先充值
- "账单已 Paid" → 不要重复抵扣
[!question] 月底 100+ 户挨个 Modal 抵扣太慢了吧? 是的,这就是月初批量自动抵扣 job 的存在意义(详见 auto-deduction-design)。job 实现前业务人员必须挨个手动。
[!question] 已抵扣的账单想撤回怎么办? 不可变流水设计。如果抵错(例如抵了别人的账单):
- 走退款 refund-partial-after-consume —— 但这退的是预存款余额,不是"撤销抵扣"
- 撤销账单需 Bill 模块支持 reverse,不在本场景
- 实际:预防胜于补救,Modal 表单提交前再三确认 Bill ID
异常分支
- 余额不够 → 业户先充 deposit-additional-topup 再来抵
- 账户 Frozen → 先 unfreeze-after-verification
- 多张账单一起抵 → consume-multiple-bills-priority
- 计量类账单 → consume-meter-bill
- 月初批量(未来)→ consume-batch-auto-monthly