8.1 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 · 场景 - 新社区批量建表 + 初始读数 Excel 导入 |
|
|
|
已发布 | meter | 2026-05-26 | 2026-05-22 |
场景:新社区批量建表 + 初始读数 Excel 导入
物业新接管社区(或老社区从 0 接入本系统),需要批量建表 + 录初始读数。通过 MeterInitializationImporter + ImportActionWithExcel 一次性导入。
典型情境
[!example] 真实情境 平台新签了"嘉禾花园"社区,本月底接管。该社区有 300 户业主 + 公共部位 + 商铺,合计约 1,200 张表(每户水电气 3 张 + 公共部位 + 商铺各类)。
物业财务王主管不可能手工建 1,200 张表,走批量导入:
- 抄表员李师傅 + 物业前任团队 出 Excel 表(包含每张表的房号、表号、初始读数)
- 王主管在系统下载"建表初始化模板"
- 把数据填入模板 → 上传 → 系统批量建表
业务人员视角
第 1 步:下载初始化模板
后台 → 计量表 → 列表 → 顶部 "下载初始化模板" 按钮(ExportMeterInitializationTemplateAction)。
下载到的 Excel 包含:
| 列 | 说明 | 示例 |
|---|---|---|
| 房号 / 资产编号 | 关联 asset(必填,系统按房号查 asset_id) | 12-3-501 |
| 费用类型 | 水费 / 电费 / 燃气费(必填) | 电费 |
| 表编号 | 物理表牌号(必填) | E-501 |
| 倍率 | multiplier(可选,默认 1) | 1 |
| 初始读数 | initial_reading(必填,首次接管时表上的读数) | 0 / 8523 / etc. |
| 安装日期 | installed_at(可选,默认导入日) | 2026-05-26 |
| 备注 | (可选) | "新装" |
模板列名清晰,业务人员 / 抄表员看得懂。
[!warning] 模板列含义"双义"问题(已知 issue) 当前
MeterInitializationImporter用一个 Importer 处理两种 Excel layout(住宅单元 vs 商铺/公共)。某些列 label 是"双义"形式,导入选项里选错asset_type不报错,只是数据写到错误字段(silent corruption)。issue.md Q5 已记录,待拆成两个独立 Importer。当前预防:务必仔细选 asset_type。
第 2 步:填写数据
物业 / 抄表员把 1,200 张表的信息填入模板。
关键字段对齐:
- 房号:对应系统里 asset 表已存在的编号(若不存在,先到 community 模块建 asset)
- 费用类型:对应系统配置的 FeeType(水/电/燃气,各社区独立配置)
- 表编号:物业自编(常见
<费用类型简写>-<房号>模式) - 初始读数:接管当天的物理表读数(关键!首次接管之前的用量物业不管)
第 3 步:上传 + 导入
后台 → 计量表 → 列表 → 顶部 "导入初始化" 按钮(ImportActionWithExcel + MeterInitializationImporter)→ 选 asset_type(住宅 / 商铺)→ 上传 Excel → 提交。
系统:
- 解析 Excel(走
BaseImporter+ImportActionWithExcel,支持 .xlsx / .xls / .csv) - 每行校验(房号 asset 存在?费用类型存在?表编号是否在该社区重复?)
- 批量建 Meter(每行一张 Meter 记录)
- 可选:同时建第一条 MeterReading(若模板含"初始读数",建初始 reading 来锁定
previous_reading起点) - 报告:成功 N 张,失败 M 张 + 每条失败的原因
[!info] BaseImporter + chunk rollback 走
App\Filament\Importers\BaseImporter(host 基类,详见 saas-baseline 规范)+TransactionalImportCsvjob。一批 100 行任意一行失败 → 该批全回滚。这避免"部分建好部分没建"的脏中间态。失败的批可下载"失败行" Excel,修复后再导入。
第 4 步:核对
导入后:
- 后台 → 计量表 → 按社区过滤 → 看是否 1,200 张表都在
- 抽样核对:打开几张表看初始读数对不对
第 5 步:启动月度抄表
接管下一个月 → 抄表员去现场抄读数(走 read-batch-via-excel-import 或 read-single-meter-manual)→ 系统按 current - initial × multiplier 算用量 → 生成第一份账单(走 bill-generation-pipeline)。
系统流程
sequenceDiagram
participant 王主管
participant Filament
participant ImportActionWithExcel
participant MeterInitializationImporter
participant 数据库
Note over 王主管: 已填好 1200 行 Excel
王主管->>Filament: ListMeters → 导入初始化 → 选 asset_type + 上传
Filament->>ImportActionWithExcel: parse .xlsx
ImportActionWithExcel->>MeterInitializationImporter: 按 chunk 处理(100 行/批)
loop 每批
MeterInitializationImporter->>数据库: 开启事务
loop 每行
MeterInitializationImporter->>数据库: 校验 asset / fee_type / code 唯一
alt 校验通过
MeterInitializationImporter->>数据库: 建 Meter + 可选 initial MeterReading
else 校验失败
MeterInitializationImporter->>MeterInitializationImporter: 收集失败行
end
end
alt 全成功
MeterInitializationImporter->>数据库: 提交
else 任一失败
MeterInitializationImporter->>数据库: 回滚整批
end
end
MeterInitializationImporter-->>Filament: 报告 "成功 1198,失败 2"
Filament-->>王主管: 通知 + 下载失败行 Excel
业户视角
业户不感知这一步。新接管社区会发个公告"本月起本物业系统升级,各位业户的水电气计量将从 X 月 X 日起按本系统记账"。具体业户看到的:
- 接管前最后一份账单(由前任物业 / 自建系统出)
- 接管后第一份账单(由本系统出,用量从接管那天起算)
中间绝不能有"重复账单"或"漏账" —— 接管时的 initial_reading 必须准确反映物理表当时读数。
常见问题
[!question] 为什么需要"初始读数"? 系统计算用量公式是
(current - previous) × multiplier。新表的"上一次读数"在系统里没有,所以接管时存的initial_reading就是"previous_reading的起点"。后续每月抄表 → 当前 - 上次 = 用量。如果不填初始读数 → 第一次抄表算用量会爆炸(
current - 0 = 所有历史用量),业户被收一笔巨账,投诉。
[!question] 导入失败的常见原因?
- 房号(asset)不存在:在 community 模块的 asset 还没建好。先建 asset 再导入表
- 费用类型不存在:RatePlan 没配置。先到 FeeType 配置
- 表编号在该社区重复(社区内 code 应唯一,虽然 issue.md Q5 提到目前是 nullable + 非 unique 的"待治理"状态)
- 倍率格式错(非数字 / 负数)
- 初始读数格式错(非数字 / 负数)
[!question] 失败的行可以单独处理吗? 可以。导入完成后系统提供"下载失败行"Excel(走 host 的
TransactionalImportCsv机制),业务人员修复后单独导入失败行。已成功的不影响。
[!question] 同一社区多次导入会重复建表吗? 视 Importer 实现。若有 unique 校验(asset_id + fee_type_id 不可重复)→ 重复行会失败,需手工合并。若无校验 → 重复建,灾难。
[!question] 老社区已经有一年的抄表历史,接管时怎么办? 简化做法:只导入接管那天的状态(initial_reading = 接管那天的物理读数),历史数据不进系统(在 Excel 备查)。
复杂做法:导入历史 reading 数据,让本系统有完整历史。需要业务方决定(用户对账复杂度 vs 系统数据完整度的权衡)。
[!question] 商铺表 / 公共部位表怎么导入? 同样走
MeterInitializationImporter,但选不同 asset_type(public / shop)。导入时系统按 asset_type 决定列含义。详见 issue.md Q5"双义列名"问题。
异常分支
- 单张新表(后续装机 / 个别加表)→ register-single-meter
- 老表换新表 → replace-broken-meter
- 抄表(初始化后日常)→ read-batch-via-excel-import / read-single-meter-manual