Files
uniprop-manual/prop-acc/concepts/deposit/red-receipt-design.md
2026-05-25 22:07:35 +08:00

5.4 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 · deposit · 红字凭证设计
红字凭证设计
退款扣罚的金额正负
红字 CollectionOrder
概念
prop-acc
保证金
架构决策
业务人员
架构师
已发布 deposit 2026-05-25 2026-05-22

红字凭证设计

押金的退款和扣罚也走 CollectionOrder + Receipt 链路,通过金额正负表达方向 —— 这就是"红字凭证"。本文说明为什么这么设计,以及它对凭证文案、报表、未来扩展的影响。

核心结论(一句话)

[!tip] 本系统采用「金额正负」而非「新增枚举 case」表达退款/扣罚方向。 缴款 actual_amount = +5000,退款 actual_amount = -3000,扣罚 actual_amount = -2000
Receipt.amount 同样可负。

设计决策表

维度 金额正负(已采用) CollectionType 枚举 case
Schema 改动 零迁移 — actual_amountdecimal 无 CHECK 约束 改 enum + 改 listener match 分支
报表聚合 SUM(actual_amount) 一行算净值(收入 - 退款) GROUP BY type 再相减
中国会计实践 「红字凭证」就是负数,会计师熟悉 不通用,需另解释
未来扩展 同模式可直接复用(账单退款 / 预存款退款) 枚举持续膨胀,每加一个业务加一个 case
类型分类细粒度 DepositTransaction.type 已有 3 档 双重表达,信息冗余

资金流示意

flowchart TD
  subgraph "缴款(蓝字)"
    A1[业户缴 5000] --> A2[DepositTransaction<br/>type=deposit, amount=5000]
    A1 --> A3[CollectionOrder<br/>actual=+5000]
    A3 --> A4[Receipt<br/>amount=+5000<br/>「装修保证金缴纳 ¥5,000」]
  end

  subgraph "退款(红字)"
    B1[业户退 3000] --> B2[DepositTransaction<br/>type=refund, amount=3000]
    B1 --> B3[CollectionOrder<br/>actual=-3000 红字]
    B3 --> B4[Receipt<br/>amount=-3000 红字<br/>「装修保证金退还 ¥-3,000」]
  end

  subgraph "扣罚(红字)"
    C1[物业扣 2000] --> C2[DepositTransaction<br/>type=forfeiture, amount=2000]
    C1 --> C3[CollectionOrder<br/>actual=-2000 红字]
    C3 --> C4[Receipt<br/>amount=-2000 红字<br/>「装修保证金扣罚 ¥-2,000」]
  end

凭证文案如何区分退款/扣罚

Receipt.amount 都是负数,但文案不同,业户一眼能看明白方向。

DepositTransaction.type Receipt 文案 业户感受
refund 装修保证金退还 ¥-3,000 拿回自己的钱
forfeiture 装修保证金扣罚 ¥-2,000 钱被扣了

文案由 Listener generateDepositReceiptItemsDepositTransaction.type 选词,自动注入 Receipt 的 line items。

[!info] 未来增强:PDF 红色字样 Receipt PDF 模板对负数金额当前是普通样式,优先级排期低。可加红字效果(中国习惯)等业务方反馈再上。

CollectionStatus 仍用 Completed 而不是 Disbursed

退款的 CollectionOrder 同样进入 Completed 状态,不新增"Disbursed(已支出)"枚举值。

理由:

  • Completed 语义 = "事务完成",不局限"收到钱"
  • 不加新 case 减少枚举膨胀,符合"最简单实用"
  • 报表里"已完成的 CO" SUM(actual_amount) 就是净值,无需关心方向

refund_status 字段也保持 None,因为退款的 CollectionOrder 是独立的红字单,不是"原单的退款标记"。这与传统电商"在原订单上挂退款"模式不同 —— 那种模式适合一次性商品交易,不适合押金的"账户 + 流水"长期账本。

为什么不在原 CollectionOrder 上挂退款标记?

替代方案:在缴款单上加 refund_amountrefund_status,退款时改这两个字段。

为什么我们没选:

问题 后果
原单状态会被频繁更新 缴款时建立的"已完成快照"被破坏,审计追溯困难
多次部分退款怎么办 原单要记一个数组?变成事实上的子流水,等于在错位置实现
跨期对账 4 月缴的 5000 在 6 月退 3000 → 4 月的报表数据会变,跨期数字不稳定
与新业务复用 账单 / 预存款的退款不能复用此模式,要各自重复实现

红字独立单解决以上全部问题:每张单是不可变快照,跨期数字不变,各业务模块通过相同的"红字 CO + Receipt"模式表达退款。

与一次性收费(adhoc)的对比

维度 adhoc 一次性收费 deposit 保证金
主对象 AdHocEvent DepositAccount
流水/凭证 CollectionOrder + Receipt(单笔) DepositTransaction + 关联 CollectionOrder + Receipt(长期账本)
退款方式 adhoc-void-after-payment 作废 + 退款 红字 CollectionOrder(独立单)
是否进入收入 一次性收入 负债科目(代管款)

详见 deposit-vs-adhoc-vs-prepaid

待补 / 已知限制

状态
Receipt PDF 红色字体样式 待补,优先级低
小程序在线申请退款(走支付网关 webhook) 待补,等业务有需求再加
CollectionOrders/Actions/RecordRefundAction(从原单视角的退款入口) 已知重叠,未来要统一为单一退款流程

相关文档