Files
uniprop-manual/prop-acc/concepts/meter/reading-source-and-photo-proof.md

207 lines
6.8 KiB
Markdown
Raw Normal View History

2026-05-25 23:53:01 +08:00
---
title: prop-acc · meter · 抄表来源与拍照存证
aliases:
- 抄表来源
- 抄表拍照存证
- manual vs remote
- MeterReadingSource
tags:
- 概念
- prop-acc
- 计量表
- 数据字典
audience:
- 业务人员
- 抄表员
- 财务
status: 已发布
sub_feature: meter
last_review: 2026-05-25
code_version: 2026-05-22
---
# 抄表来源与拍照存证
每条 `MeterReading`**`source` 字段**标记**抄表数据来源**(`manual` 手抄 vs `remote` 集抄),配合 **`photo_url`** 拍照存证,保证抄表数据**可追溯、可核对、有凭据**。
## `MeterReadingSource` 枚举
```php
enum MeterReadingSource: string
{
case Manual = 'manual'; // 抄表员手动录入
case Remote = 'remote'; // 集抄系统(IoT)自动上报
}
```
只有两种,简洁明了。
## 两种来源对照
| 维度 | `manual`(手抄)| `remote`(集抄 / IoT)|
|---|---|---|
| 触发 | 抄表员到现场读表 + 录入 | 物联网集抄系统定时推送 |
| 数据流 | 抄表员手机 / 抄表机 → App / 后台 | IoT 网关 → 后端 API → 系统 |
| 速度 | 慢(几天到几周完成全社区)| 快(几小时全社区)|
| 准确性 | 中(可能手抖 / 看错)| 高(设备直接传)|
| 拍照存证 | **推荐**(`photo_url` 必填或强烈推荐)| 自动 |
| 操作员(`operated_by`)| 必填(抄表员 ID)| null 或系统账号 |
| 业务上常见 | 中小社区 / 老旧设备 | 新建社区 / 升级改造后 |
| 故障率 | 抄表员漏抄、误抄、不录入 | IoT 设备掉线、数据丢失 |
## 拍照存证(`photo_url`)
### 为什么要拍照
抄表是物业**收业户钱**的依据。万一业户质疑账单金额,物业要拿出证据"5 月 X 日,您家表头读数确实是 280 度,这是抄表当天的照片"。
> [!info] 真实情境
> 张阿姨 5 月电费账单 ¥168(280 度),她声称"我家不可能用这么多",要看证据。
>
> 物业打开后台 → 找 5 月那条 reading → 看 `photo_url` → 给业户看现场拍的表头照片("280" 清晰可见,旁边日期戳)→ **业户无话可说**。
### 实施细节
| 字段 | 实施 |
|---|---|
| `photo_url` | 存储到对象存储(S3 / 阿里云 OSS / 本地)的 URL |
| 上传时机 | 抄表 App 录入读数同时上传(强制)|
| 上传时机(批量导入)| Excel 批量导入时**没有拍照** → 业务上要求抄表员当场拍 + 单独留存,导入时只录数字 |
| 上传时机(remote)| 集抄无拍照(IoT 设备本身就是凭证)|
| 数据保留 | 法律 / 业务规定保留期(通常 3-5 年),与账单同周期 |
### 业务流程上的强制度
| 物业政策 | 实施 |
|---|---|
| **必须拍照**(严)| `MeterReadingsRelationManager` Form 上 `photo` 字段标 `->required()`,无照片不能提交 |
| **建议拍照**(中)| Form 上 `photo` 可空,UI 上有"建议拍照"提示 |
| **不强制**(松)| Form 上 `photo` 可空,无任何提示 |
当前实现**看具体配置**(应该是建议拍照,可空)。生产环境**强烈推荐"必须拍照"**,避免后续举证困难。
## 集抄(remote)的对接
### 数据流
```mermaid
sequenceDiagram
participant Meter[物理表]
participant Gateway[IoT 网关]
participant Backend[第三方集抄平台]
participant API[本系统 API]
participant DB
Note over Meter: 物理表通过 RS485 / NB-IoT 等连网关
loop 定时(每天/每月)
Meter->>Gateway: 读数推送
Gateway->>Backend: 上传(GSM/4G/有线)
Backend->>API: HTTP POST(批量推 reading)
API->>DB: 建 MeterReading(source=remote)
end
```
### 触发账单生成
集抄推数后**通常立即触发账单生成**(详见 [[bill-generation-pipeline]]):
- 集抄 API 接收 → 写 MeterReading → 同事务内或立即触发 `GenerateBillsFromMeterReadingsAction`
- 或者每月固定时间批量(避免账单生成时机不一致)
### 集抄掉线的兜底
| 集抄掉线 | 处置 |
|---|---|
| 个别表掉线(少数)| 抄表员补抄(`source=manual` + 备注"集抄掉线")|
| 大面积掉线(网关故障)| 集抄运维介入 + 物业短期手抄兜底 + 排查恢复 |
| 长期掉线(>2 周)| 重新评估集抄设备的可靠性 |
## 手动抄表的实施
### 工具
- 抄表员手机 App(物业自研 / 第三方)
- 老式:纸质本子 + 后台输入(误差大,逐步淘汰)
### 流程
```mermaid
flowchart TD
A[抄表员到现场] --> B[读表头]
B --> C[拍照]
C --> D[App 上录入<br/>读数 + 上传照片]
D --> E[同步到后台]
E --> F[业务人员审核 / 直接生成账单]
```
### 操作员追踪
每条 `MeterReading``operated_by` 字段(抄表员 ID):
- 业户对账单有疑问 → 后台查 → 看是谁抄的
- 抄表员考核:本月抄了多少表、有无遗漏
- 异常追责:某抄表员的读数频繁错 → 培训 / 换人
## 业务人员视角
后台 `ViewMeter` → 看 Reading 列表(`MeterReadingsRelationManager`),每条 reading 显示:
| 列 | 内容 |
|---|---|
| 抄表日期 | `read_at` |
| 读数 | `current_reading` |
| 用量 | `consumption` |
| 来源 | `manual` / `remote`(图标区分)|
| 抄表员 | `operated_by`(`manual` 时显示)|
| 拍照 | `photo_url`(有图标,点开看照片)|
| 备注 | `memo` |
## 抄表员视角
抄表员李师傅每月 25-30 号集中抄表:
- 拿手机 App 出门
- 按片区(楼栋)走,App 自动按楼层 / 房号给清单
- 每家:开门(若有人)→ 找表 → 读数 → 拍照 → 录入
- 数据**实时上传**(网络可用时)或**离线缓存**(无网时回去再传)
- 当月所有表抄完 → App 显示"完成度 100%" → 提交
每天 KPI:60-100 户(看小区密度)。
## 业户视角
业户**通常感知不到抄表细节**,只看月底账单。对账单有异议时:
- 联系物业询问
- 物业出示 `photo_url` 证据
- 如果证据充分 → 业户认可
- 如果证据不足(无照片 + 抄表员说不清)→ 物业可能减免 / 让业户支付平均月用量
## 系统视角:不可变 + 双锁
详见 [[meter-vs-meter-reading]] "两者的契约" + [[decommission-and-locking]] "已生成 Bill 的 Reading 锁定" 段。
- MeterReading 一经创建**不可改**
- 一旦生成 Bill 后**更不可改**(Policy 双锁)
- 任何错误走"作废 Bill → 改 Reading → 重生成 Bill"的组合流程(详见 [[exception-readings-locked-after-bill]])
## 待补 / 已知问题
| 项 | 状态 |
|---|---|
| 集抄回调签名校验 / 防重放 | 未文档化(可能已实现,看具体集成 |
| 抄表照片的对象存储清理(留存期满)| 未实现,需求看物业法务定 |
| 抄表员位置 / 时间戳防作弊(GPS + 时间)| 未实现,部分物业有此需求 |
| 拍照强制 + AI 识别照片内读数比对录入 | 未实现,高大上但实施成本高 |
## 相关文档
- [[meter-vs-meter-reading]]
- [[bill-generation-pipeline]]
- [[decommission-and-locking]]
- [[read-single-meter-manual]]
- [[read-batch-via-excel-import]]
- [[read-via-iot-remote-source]]
- [[read-with-photo-proof]]