--- 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 上录入
读数 + 上传照片] 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]]