Files
uniprop-manual/prop-acc/scenarios/meter/init-new-community-batch.md
2026-05-26 00:13:05 +08:00

8.1 KiB
Raw Permalink Blame History

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 导入
批量建表
新社区计量表初始化
init-new-community-batch
场景-新社区批量建表
场景
prop-acc
计量表
表管理
批量导入
业务人员
抄表员
已发布 meter 2026-05-26 2026-05-22

场景:新社区批量建表 + 初始读数 Excel 导入

物业新接管社区(或老社区从 0 接入本系统),需要批量建表 + 录初始读数。通过 MeterInitializationImporter + ImportActionWithExcel 一次性导入。

典型情境

[!example] 真实情境 平台新签了"嘉禾花园"社区,本月底接管。该社区有 300 户业主 + 公共部位 + 商铺,合计约 1,200 张表(每户水电气 3 张 + 公共部位 + 商铺各类)。

物业财务王主管不可能手工建 1,200 张表,走批量导入:

  1. 抄表员李师傅 + 物业前任团队 出 Excel 表(包含每张表的房号、表号、初始读数)
  2. 王主管在系统下载"建表初始化模板"
  3. 把数据填入模板 → 上传 → 系统批量建表

业务人员视角

第 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 → 提交。

系统:

  1. 解析 Excel(走 BaseImporter + ImportActionWithExcel,支持 .xlsx / .xls / .csv)
  2. 每行校验(房号 asset 存在?费用类型存在?表编号是否在该社区重复?)
  3. 批量建 Meter(每行一张 Meter 记录)
  4. 可选:同时建第一条 MeterReading(若模板含"初始读数",建初始 reading 来锁定 previous_reading 起点)
  5. 报告:成功 N 张,失败 M 张 + 每条失败的原因

[!info] BaseImporter + chunk rollback 走 App\Filament\Importers\BaseImporter(host 基类,详见 saas-baseline 规范)+ TransactionalImportCsv job。一批 100 行任意一行失败 → 该批全回滚。

这避免"部分建好部分没建"的脏中间态。失败的批可下载"失败行" Excel,修复后再导入。

第 4 步:核对

导入后:

  • 后台 → 计量表 → 按社区过滤 → 看是否 1,200 张表都在
  • 抽样核对:打开几张表看初始读数对不对

第 5 步:启动月度抄表

接管下一个月 → 抄表员去现场抄读数(走 read-batch-via-excel-importread-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"双义列名"问题。

异常分支

相关文档