6.8 KiB
6.8 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 · 抄表来源与拍照存证 |
|
|
|
已发布 | meter | 2026-05-25 | 2026-05-22 |
抄表来源与拍照存证
每条 MeterReading 有 source 字段标记抄表数据来源(manual 手抄 vs remote 集抄),配合 photo_url 拍照存证,保证抄表数据可追溯、可核对、有凭据。
MeterReadingSource 枚举
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)的对接
数据流
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(物业自研 / 第三方)
- 老式:纸质本子 + 后台输入(误差大,逐步淘汰)
流程
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 识别照片内读数比对录入 | 未实现,高大上但实施成本高 |