Files
uniprop-manual/prop-acc/scenarios/meter/replace-broken-meter.md
2026-05-26 00:13:05 +08:00

8.3 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 · meter · 场景 - 换表:旧表故障/退役,新表带 -R1 后缀
换表
表更换
replace-broken-meter
ReplaceMeterAction
场景-换计量表
场景
prop-acc
计量表
表管理
业务人员
抄表员
已发布 meter 2026-05-26 2026-05-22

场景:换表,旧表故障/退役,新表带 -R1 后缀

物理表老化 / 损坏 / 校验未过,需要换新表。系统通过 ReplaceMeterAction 一步完成:旧表退役 + 新表建立 + replaced_meter_id 关联 + 初始读数继承。新表自动编号 <旧编号>-R1

典型情境

[!example] 真实情境 张阿姨家电表(编号 E-501)用了 8 年,2026 年 5 月例行校验未通过(读数漂移),物业要换新表。

换表当天:

  • 抄表员李师傅现场读旧表:5000 度
  • 卸下旧表 + 装上新表
  • 新表出厂读数:0(物理上)
  • 系统操作:ReplaceMeterAction

系统结果:

  • 旧表 E-501:is_active=false, decommissioned_at=今天, decommission_reason=Replaced, final_reading=5000
  • 新表 E-501-R1:is_active=true, installed_at=今天, replaced_meter_id=旧表 ID, initial_reading=5000(继承), multiplier 继承

抄表员视角(李师傅)

第 1 步:现场操作

到张阿姨家:

  1. 检查旧表状态(确认换表必要性)
  2. 拍照存证旧表当前读数(关键!后续争议时凭证)
  3. 物理换表(断电 → 换表 → 通电)
  4. 拍照新表初始状态(出厂 0)
  5. 把信息回传业务人员(微信 / App / 当面)

[!warning] 拍照不能省 旧表读数没拍照 = 系统里填的"5000" 没物理证据 = 业户事后质疑"我家明明只用了 4500" 时物业百口莫辩。

第 2 步:报回业务

抄表员把信息汇总给王主管(业务人员):

  • 旧表编号:E-501
  • 旧表最后读数:5000
  • 换表日期:2026-05-26
  • 退役原因:校验未过(Replaced)
  • 新表型号:同型号(multiplier=1)

业务人员视角

第 1 步:打开旧表

后台 → 计量表 → 找 E-501 → 进 ViewMeter

第 2 步:点 ReplaceMeterAction

右上角"换表"按钮(标签可能是"更换")。

[!warning] 按钮可见性 守护:is_active=true + Policy ->authorize('replace')。已退役表此按钮灰化。

Modal 表单:

字段 填什么
旧表最后读数(final_reading) 5000(抄表员现场读)
退役原因(decommission_reason) Replaced(其他 4 种见 decommission-and-locking)
退役日期 2026-05-26(默认今天)
新表编号 E-501-R1(系统自动生成,nextReplacementCode(),可改但不推荐)
新表 multiplier 1.0(默认继承旧表)
新表安装日期 2026-05-26(默认今天)
备注 "校验未通过,换新表"

第 3 步:提交

系统在一个事务内:

  1. 校验旧表 is_active=true(否则按钮就不该出现)
  2. 旧表 update:
    • is_active = false
    • decommissioned_at = 2026-05-26
    • decommission_reason = Replaced
    • final_reading = 5000
  3. 建新表:
    • code = E-501-R1(nextReplacementCode($oldCode))
    • is_active = true
    • installed_at = 2026-05-26
    • replaced_meter_id = 旧表 ID
    • initial_reading = 5000(继承自旧表 final_reading)
    • multiplier = 1.0(继承)
    • community_id / asset_id / fee_type_id 继承

第 4 步:验证 + 通知

后台 → 计量表 → 看新旧两张表 → 确认数据正确。

业户可不通知(业户对系统层无感)。

系统流程

sequenceDiagram
    participant 抄表员
    participant 王主管
    participant Filament
    participant ReplaceMeterAction
    participant 数据库

    抄表员->>抄表员: 现场拍照 + 换表(物理)
    抄表员->>王主管: 旧表读数 5000,换表完成

    王主管->>Filament: ViewMeter(旧表) → ReplaceMeterAction
    Filament->>ReplaceMeterAction: handle(oldMeter, finalReading=5000, reason=Replaced)
    ReplaceMeterAction->>数据库: 开启事务
    ReplaceMeterAction->>数据库: 1. 旧表 update:is_active=false, decommissioned_at, decommission_reason=Replaced, final_reading=5000
    ReplaceMeterAction->>数据库: 2. 建新表:code=E-501-R1, is_active=true, replaced_meter_id=旧表id, initial_reading=5000, multiplier=1
    ReplaceMeterAction->>数据库: 提交事务
    Filament-->>王主管: 跳转新表 ViewMeter

旧表 / 新表数据对照

字段 旧表 E-501 新表 E-501-R1
code E-501 E-501-R1
is_active false true
installed_at 2018-XX-XX(原值) 2026-05-26
decommissioned_at 2026-05-26 null
decommission_reason Replaced null
final_reading 5000 null
initial_reading (历史值不动) 5000(继承)
multiplier 1 1(继承)
replaced_meter_id null 旧表 id
community_id, asset_id, fee_type_id 不动 继承

5 月份的抄表 + 账单

换表那个月的账单:

本月用量 = current(新表第一次抄)+ initial(=5000) - previous(=5000)
        = (50 + 5000) - 5000
        = 50 度

新表 5 月底第一次抄读到 50(物理表头),系统存 current_reading = 50 + 5000 = 5050,previous_reading = 5000(继承),consumption = 50。账单按 50 度算,业户感觉不到换表。

[!info] 抄表员录入逻辑 抄表员现场看到新表是 50,系统应自动加上 5000 存为 5050(避免抄表员手动算)。或者抄表员录 50,系统在保存时自动加 5000。具体实现看 MeterReadingsRelationManager 的 form。

业户视角

业户几乎感受不到 —— 只看到下月账单仍是正常用量。

唯一感知:换表当天可能短暂断电断水(物理操作)。物业应提前通知业户。

整链追溯

如果以后这张 E-501-R1 又出问题再换 → 新表 E-501-R2,replaced_meter_id 指 R1。如此累加:

E-501 (原生) → E-501-R1 (第 1 次换) → E-501-R2 (第 2 次换) → E-501-R3 ...

详见 replacement-chain"整条链的追溯"段。

常见问题

[!question] 旧表 final_reading 填错了能改吗? 旧表的 final_reading 严格上属于"已退役表的字段",MeterPolicy::update()is_active=false 时拒绝改(decommission-and-locking 守护)。

改错的话:

  • 通过 tinker 修(运维操作,留备注)
  • 或者把 decommissioned_at = null 让表"复活"(Policy 可能不允许),再走完整换表流程

预防:换表 Modal 提交前与抄表员书面确认 final_reading。

[!question] 新表 multiplier 与旧表不同可以吗? 可以(form 上可改),但强烈不推荐。理由见 replacement-chain"常见问题"段:不同 multiplier 让用量计算公式变,业户对账困难。

[!question] 新表编号 -R1 不喜欢能改成别的吗? Modal 表单允许改 code,但强烈不推荐:

  • -R1 是标准化命名,审计 / 报表 / 后续换表的 -R2 都基于这个 pattern
  • 改成自定义 code(如 "E-501-NEW")会破坏 nextReplacementCode() 算法,下次换表生成 E-501-NEW-R1 看着别扭

[!question] 换表后业户对历史账单有异议怎么办? 历史 reading 都关联到旧表(meter_id=旧表 id),不会因换表丢失。审计可:

  • 后台找旧表 → 看历次 reading(只读)
  • 拿物理表照片(若有)
  • 拿换表前的累计读数(旧表 final_reading)对照

[!question] 业户搬走永久弃用表,这种"换表"怎么处理? 那不是换表,是 decommission-without-replacementdecommission_reason=RemovedExpired,不建新表。

[!question] 旧表是 active 但有未结账 reading,能换表吗? 系统不阻止(Action 不查未结账 reading)。但业务上:

  • 应先生成未结账 reading 的 Bill(走 bill-generation-pipeline)
  • 否则换表后那些 reading 永远不会被处理(它们关联旧表)

推荐流程:换表前先把旧表当月抄表录入 + 生成 Bill → 然后再换表。

异常分支

相关文档