From d67494595e089490d82d576216a239afa3d5f812 Mon Sep 17 00:00:00 2001 From: Willie Date: Mon, 25 May 2026 23:48:00 +0800 Subject: [PATCH] vault backup: 2026-05-25 23:48:00 --- .obsidian/workspace.json | 8 +- .../concepts/meter/meter-vs-meter-reading.md | 143 ++++++++++++++++++ 2 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 prop-acc/concepts/meter/meter-vs-meter-reading.md diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 4e612e4..f0993f0 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -195,8 +195,10 @@ "obsidian-git:Open Git source control": false } }, - "active": "b06ed69835363258", + "active": "849c5ff8936a2b67", "lastOpenFiles": [ + "prop-acc/concepts/meter/meter-vs-meter-reading.md", + "prop-acc/concepts/meter", "prop-acc/scenarios/prepaid/audit-low-balance-and-overdue.md", "prop-acc/scenarios/prepaid/exception-refund-on-frozen.md", "prop-acc/scenarios/prepaid/exception-cross-community-consume.md", @@ -223,7 +225,6 @@ "prop-acc/maps/deposit-knowledge-map.md", "prop-acc/concepts/prepaid/consume-via-bill-collection-type.md", "prop-acc/concepts/prepaid/transaction-types.md", - "prop-acc/concepts/prepaid/one-account-per-resident.md", "prop-acc/concepts/prepaid", "prop-acc/scenarios/deposit", "prop-acc/concepts/deposit", @@ -231,7 +232,6 @@ "prop-acc/concepts/adhoc", "resident-portal/scenarios", "resident-portal/reference", - "resident-portal/procedures", - "resident-portal/maps" + "resident-portal/procedures" ] } \ No newline at end of file diff --git a/prop-acc/concepts/meter/meter-vs-meter-reading.md b/prop-acc/concepts/meter/meter-vs-meter-reading.md new file mode 100644 index 0000000..ec5151a --- /dev/null +++ b/prop-acc/concepts/meter/meter-vs-meter-reading.md @@ -0,0 +1,143 @@ +--- +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
bill_id=null] + B -->|GenerateBillsFromMeterReadingsAction| C[Bill 生成
+ MeterReading.bill_id 回写] + C -.业户付账单.-> D[CollectionOrder + Receipt
付款方式可选现金/微信/预存款] +``` + +**关键**: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]](账户+流水模式对比)