Files
uniprop-manual/prop-acc/scenarios/prepaid/refund-partial-after-consume.md
2026-05-25 23:32:57 +08:00

5.8 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 · 场景 - 部分消费后退余(不自动关账)
部分退预存款
退一部分留账户
refund-partial-after-consume
场景-预存款部分退余
场景
prop-acc
预存款
退款
业户
业务人员
已发布 prepaid 2026-05-25 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 可继续抵账单"。

系统流程

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 月费)。

异常分支

相关文档