Files
uniprop-manual/prop-acc/scenarios/meter/generate-bill-min-max-cap.md
2026-05-26 00:28:09 +08:00

8.8 KiB
Raw Blame History

title, aliases, tags, audience, status, sub_feature, last_review, code_version
title aliases tags audience status sub_feature last_review code_version
prop-acc · meter · 场景 - 单笔账单上下限封顶(防异常用量爆账)
min max 封顶
账单封顶
generate-bill-min-max-cap
场景-账单上下限封顶
场景
prop-acc
计量表
账单生成
异常防御
业务人员
财务
业户
已发布 meter 2026-05-26 2026-05-22

场景:单笔账单上下限封顶(防异常用量爆账)

RatePlan 上的 min_amount / max_amount 字段为单笔账单设置上下限:

  • max_amount 防止极端用量(漏水 / 设备故障)导致离谱账单 → 业户友好,但物业承担差额
  • min_amount 防止零用量 / 极低用量逃避基础服务费 → 物业兜底,但业户可能不爽

本场景演示三种触发情境。

典型情境

情境 1:漏水触发 max 封顶

[!example] 真实情境 张阿姨家水管漏水(藏在墙里没发现),5 月用水 800 吨(平时 12 吨)。按阶梯计价:

0-20 吨段:20 × 3.0 = 60
21-30 吨段:10 × 4.5 = 45
31-800 吨段:770 × 6.0 = 4,620
算出金额:4,725 元

RatePlan 配置 max_amount = 1,500,触发封顶:

final_amount = min(4725, 1500) = 1500

账单 ¥1,500,差额 ¥3,225 物业承担(走维修保险 / 业务减免)。

情境 2:零用量触发 min 兜底

[!example] 真实情境 王先生整月出差不在家,水表读数无变化(consumption=0)。按阶梯算 = 0 元。但物业配置 min_amount = 20,兜底:

final_amount = max(0, 20) = 20

账单 ¥20,理由"基础服务费 / 管网维护费"。王先生抱怨"我没用水为什么收钱?",物业解释:小区水管 / 表的维护是公共成本,按户分摊。

情境 3:正常范围,无封顶

[!example] 真实情境 陈先生 5 月用水 35 吨,按阶梯算 135 元。RatePlan 配置 min_amount=20, max_amount=1500:

final_amount = max(20, min(135, 1500)) = 135

账单 ¥135,封顶规则不触发(在合理范围内)。

min / max 算法

if (max_amount !== null && calculated > max_amount) calculated = max_amount;
if (min_amount !== null && calculated < min_amount) calculated = min_amount;
final_amount = calculated;

或等价:final_amount = max(min_amount ?? 0, min(calculated, max_amount ?? INF))

详见 multiplier-and-tiered-pricing"第 3 层 min/max 封顶"段。

系统流程

sequenceDiagram
    participant Calc[MeterBillCalculator]
    participant Service[MeterBillGenerationService]
    participant DB

    Calc->>Calc: 阶梯算法 → calculated_amount
    Note over Calc: 假设漏水算出 4725

    Calc->>Calc: max_amount 检查
    alt calculated > max_amount(4725 > 1500)
        Calc->>Calc: final = max_amount = 1500
    else 在范围内
        Calc->>Calc: 通过
    end

    Calc->>Calc: min_amount 检查
    alt final < min_amount
        Calc->>Calc: final = min_amount
    else 在范围内
        Calc->>Calc: 通过
    end

    Calc-->>Service: 1500
    Service->>DB: 建 Bill(amount=1500, sourceable=reading)
    Note over DB: 业务上是否记录"封顶减免"?目前 Bill 表无此字段,留作业务备注

业户视角

Max 封顶(漏水)

业户收到的账单:

2026 年 5 月水费账单

用水量:800 吨 ⚠️ 用量异常高
按阶梯算应付:¥4,725.00
封顶后实付:¥1,500.00
差额减免:¥3,225.00(由物业 / 维修保险承担)

应付:¥1,500.00

[!info] 账单展示封顶信息 强烈推荐账单展示"按阶梯算 X,封顶 Y,差额 Z 由物业承担"。让业户明白封顶的存在 + 物业的友好。

业户会感激物业封顶,但更会自查漏水 / 设备故障

Min 兜底(零用量)

业户收到的账单:

2026 年 5 月水费账单

用水量:0 吨
按阶梯算应付:¥0.00
基础费(min):¥20.00

应付:¥20.00

业户可能不接受:"我没用水为什么收钱?"。物业要解释:

  • 水管 / 公共部位维护成本
  • 物业服务费的"基础保障"性质(签合同时已告知)
  • 法律 / 政策依据(若有)

业务人员视角

配置 min / max

后台 → 费率管理 → RatePlan → 编辑 → 填字段:

字段 推荐值(参考)
min_amount 10-30 元(看物业 + 费用类型)
max_amount 1000-5000 元(看业户类型,商铺可以更高)

[!warning] 配置要谨慎

max 配低:正常用量也被封顶 → 物业损失收入。例如 max=300,商铺正常月费 ¥500 → 物业每月被减免 ¥200。严重 bug

max 配高(或不配):无封顶 → 极端用量爆账户,业户投诉 + 法律风险。

min 配高:业户不满 + 投诉。

配置后用极端值算例验证(0 度 / 极少 / 正常 / 极高 各算一遍看是否合理)。

触发封顶后的业务流程

触发 业务人员动作
max 触发(异常高用量) 联系业户排查(exception-high-consumption) → 减免数额可能要审批
min 触发(零 / 极低用量) 通常无需介入,业户接受 min 即可
频繁 max 触发 评估是否表 / 设备有问题(漏水 / 故障)

封顶减免的会计处理

封顶差额(max_amount 触发时,实际应付 vs 物业承担)的会计处理:

选项 实现
物业直接承担(本系统当前简化) Bill.amount 直接是封顶后金额。账面收入 ¥1,500(实际应是 ¥4,725)→ 物业少收 ¥3,225
走维修保险(高大上) 物业向保险公司报销 ¥3,225,账面通过应收 / 已收 走完整流程
业户与物业分摊(罕见) 部分协议:超过封顶部分 50% 业户 50% 物业

当前最简单实现:物业直接承担。其他方案需要业务方提需求。

财务视角

月度报表统计封顶情况

-- 本月触发 max 封顶的 reading(假设 Bill 不存"封顶前 amount",我们用 reading 算)
SELECT
    r.id AS reading_id,
    r.consumption,
    -- 重算应付(简化,实际要走 Calculator 逻辑)
    -- calculate(consumption, ratePlan) AS expected_amount
    b.amount AS billed_amount,
    -- (expected - billed) AS reduction
    rp.max_amount
FROM acc_meter_readings r
JOIN acc_meters m ON r.meter_id = m.id
JOIN fee_types ft ON m.fee_type_id = ft.id
JOIN rate_plans rp ON ft.current_rate_plan_id = rp.id
JOIN acc_bills b ON r.bill_id = b.id
WHERE b.amount = rp.max_amount  -- 简化判断:Bill 金额刚好等于封顶值 = 大概率封顶触发了
  AND b.created_at BETWEEN '2026-05-01' AND '2026-05-31';

业务用途:看月度物业因封顶减免多少收入。若太多 → 调整 max 或排查根因(频繁漏水 / 设备故障)。

常见问题

[!question] min_amount 是 0 / null 时不兜底? 是的。若 min_amount=null,系统不兜底,零用量账单 = 0 元(可能不开账单)。物业政策决定是否兜底。

[!question] max 触发后业户反悔说"我自查没漏水,你怎么算出我用 800 吨的?" 业务人员排查:

若所有证据都指向"确实用了 800 吨"(且业户家有漏水迹象)→ 业户认账,封顶后金额是优惠了。

[!question] min 触发后业户拒付怎么办? 物业说服 + 法律协议层面要求(物业合同里通常有"基础服务费"条款)。坚决拒付 → 进入逾期催收。

[!question] 不同业户(住宅 vs 商铺)封顶不同可以吗? 看 RatePlan 设计。当前可能"每个 FeeType 一份 RatePlan",所以同 FeeType 共用 min/max。如果要区分,可:

  • 给商铺单独建 FeeType + RatePlan
  • 或扩展 RatePlan 支持多档 min/max(改 schema)

[!question] 跨月用量(忘了抄一个月,两个月用量算一笔)会触发 max 吗? 可能会(双月用量翻倍)。预防:不要漏抄(走 audit-meters-needing-reading 监控)。漏抄了发现:

  • 把这笔大账单人工拆成两个月(系统不直接支持,业务流程做)
  • 或当作正常账单收 + 与业户沟通

[!question] 封顶后差额怎么入账? 当前最简单实现:Bill.amount 直接是封顶后金额,差额不入账(物业默默承担)。

严格会计:差额应记入"管理费用 / 维修保险报销 / 服务减免"科目。需扩展 schema 才能精确处理。

异常分支

相关文档