Files
uniprop-manual/prop-acc/concepts/meter/meter-vs-meter-reading.md
2026-05-25 23:48:00 +08:00

144 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: prop-acc · meter · 计量表与抄表流水
aliases:
- 计量表与抄表流水
- Meter 与 MeterReading
- 计量表的双对象模式
tags:
- 概念
- prop-acc
- 计量表
- 核心概念
audience:
- 业务人员
- 抄表员
- 财务
status: 已发布
sub_feature: meter
last_review: 2026-05-25
code_version: 2026-05-22
---
# 计量表与抄表流水
计量表模块底层是**两个对象**配合:**Meter**(物理表的配置)+ **MeterReading**(每次抄表的不可变流水)。模式上与 [[../deposit/deposit-account-vs-transaction|押金账户+流水]]同构,但**对象的物理性**让它有几条独特特征:
- **每张表是真实硬件**(电表 / 水表 / 燃气表),挂在具体房屋(`asset_id`)上
- **不直接产收据** —— 抄表产 `Bill`,后续业户付账单再走 [[../adhoc/collection-order-and-receipt|CollectionOrder + Receipt]]
- **没有"账户余额"概念**(没有 balance 字段),业户余额追踪在 [[../prepaid/prepaid-account-vs-transaction|预存款]]
## 为什么用双对象
> [!info] 类比:实体水表
> - **Meter** = 表面板,上面写编号、安装时间、倍率
> - **MeterReading** = 每次抄表的本子记录:几号几月几日读了多少、谁抄的、有没有拍照
如果只有 Meter 没有 Reading → 不知道每月用了多少,无法算账单。
如果只有 Reading 没有 Meter → 不知道表的物理属性(倍率、装在哪、什么费用),Reading 是孤立数字。
所以两个都要。
## 字段速查
### Meter(计量表)
| 字段 | 含义 |
|---|---|
| `id` | 表 ID |
| `community_id` | 所属物业项目 |
| **`asset_id`** | **绑定的房屋资产**(必填,通过 asset 找业户)|
| **`fee_type_id`** | **费用类型**(水费 / 电费 / 燃气费,决定单价)|
| `replaced_meter_id` | 上一代表(`null` = 原生新表,见 [[replacement-chain]]) |
| `code` | 表编号(物理表牌号,通常物业自编)|
| **`multiplier`** | **倍率**(decimal(10,4),工业表 10/100/1000)|
| `initial_reading` | 初始读数(decimal(12,2)) |
| `is_active` | 是否在役 |
| `installed_at` | 安装日期 |
| `decommissioned_at` | 退役日期(null = 在役)|
| `decommission_reason` | 退役原因(5 种枚举,详见 [[decommission-and-locking]])|
| `final_reading` | 退役时最终读数 |
### MeterReading(抄表流水)
| 字段 | 含义 |
|---|---|
| `id` | 流水 ID |
| `meter_id` | 归属表 |
| `read_at` | 抄表日期 |
| `current_reading` | 本次读数(物理表头数字)|
| `previous_reading` | 上次读数(自动从最近一条 reading 取)|
| **`consumption`** | **用量**(=(current - previous) × multiplier,自动算)|
| `source` | 来源:`manual`(手抄) / `remote`(集抄,详见 [[reading-source-and-photo-proof]])|
| `photo_url` | 拍照存证 URL(可选 / 集抄无)|
| `operated_by` | 抄表员 ID(manual 类型必填) |
| `bill_id` | 关联生成的账单(若已生成 Bill,null = 未生成)|
| `memo` | 备注 |
| 创建后**不可变** | 一旦生成只读;若 `bill_id != null` 更不可改(双锁)|
## 两者的契约
- **每张 Meter 可有多条 MeterReading**(理想情况是每月一条)
- **MeterReading 必属于一张 Meter**(`meter_id` NOT NULL)
- **最新 reading 的 current_reading = 该 meter 的"当前累计读数"**(Meter 自身不存 current,从 reading 推出)
- **consumption = (current - previous) × multiplier**:倍率乘进去就是真实用量(度 / 吨 / 立方米)
## 与"账户+流水"型模块的本质差异
| 维度 | Account + Transaction(deposit / prepaid)| **Meter + MeterReading** |
|---|---|---|
| 主对象表达什么 | 账户余额 | **物理表的配置** |
| 流水表达什么 | 资金变动(deposit / refund / consume) | **抄表读数(用量计算源)** |
| 主对象有 balance 吗 | ✅ 有 | **❌ 无**(余额是用量,在 Reading 里) |
| 流水方向 | + / -(余额加减)| **无方向**(只有"本月读了多少") |
| 自动关账 | 看模块(deposit 自动,prepaid 不) | 走"退役 (decommission)" 不是"关账" |
| 写入操作种类 | 多种(deposit / consume / refund / forfeit) | **单一**(抄表 record_reading)+ 换表 / 退役 |
| 直接产 Receipt | 是 | **否,通过 Bill 中转** |
## 业户视角
业户**通常不直接接触 Meter / MeterReading 概念**。看到的是:
- 月底物业 App 推送账单"5 月电费 ¥168,用电 280 度"
- 收据"水费 ¥54"
- 偶尔小程序"我的计量"页可查看本月用量趋势(若开启)
底下的 Meter 和 MeterReading 是后台运营的事。**唯一**会接触的:**业户对账单金额有异议**时,可申请看历次抄表记录(系统应能展示该业户表的全部 reading 历史)。
## 抄表员视角
李师傅是物业聘的抄表员,每月固定时间挨家挨户(或集中点位)读表头数字:
- 用物业 App / 抄表机 录入 → 系统建 MeterReading(`source=manual`,`operated_by=李师傅`)
- 拍照可选(详见 [[reading-source-and-photo-proof]])
- 如果该社区接入集抄系统(IoT 表),系统自动生成 reading(`source=remote`),李师傅不用跑
## 业务人员视角
物业财务的工作:
-`MeterDashboard`:本月待抄表清单、高用量异常、按费用类型用量走势
- 录入 / 校验 reading(若有异议)
- 触发 `GenerateBillsFromMeterReadingsAction` → 自动生成所有未结账的 reading 对应的 Bill
- 月底对账:每张 reading 是否都有对应 Bill,有 Bill 是否已 Paid
## 系统视角:Bill 生成是单独一步
```mermaid
flowchart LR
A[抄表员录入 MeterReading] -.第一步.-> B[MeterReading<br/>bill_id=null]
B -->|GenerateBillsFromMeterReadingsAction| C[Bill 生成<br/>+ MeterReading.bill_id 回写]
C -.业户付账单.-> D[CollectionOrder + Receipt<br/>付款方式可选现金/微信/预存款]
```
**关键**:MeterReading **不直接**产 CollectionOrder + Receipt。要先经过 **Bill 生成步骤**(可能是月底批量,可能是抄表后立即),然后业户**付账单**才走收款流程。计量表是**计费源**,不是收款源。
## 相关文档
- [[replacement-chain]]
- [[multiplier-and-tiered-pricing]]
- [[bill-generation-pipeline]]
- [[reading-source-and-photo-proof]]
- [[decommission-and-locking]]
- [[../prepaid/consume-via-bill-collection-type]](账单视角的收款,与本模块呼应)
- [[../deposit/deposit-account-vs-transaction]](账户+流水模式对比)