はじめに
「日次の売上・検査件数・原価・粗利を毎日把握したい」
開業医なら誰もが思うことですが、意外と難しい。電子カルテは患者管理には優れていても、経営分析の視点で数字を出す機能は多くのシステムで貧弱です。
今回紹介するクリニックでも長らくGoogleスプレッドシートで手動管理してきました。毎日CSVをダウンロードし、コピペして、数式を調整して……。これが想像以上に負担で、かつミスも出やすかった。
そこで今年、PHP(Laravel)を使って自前の集計・分析Webアプリを構築しました。この記事では、何が課題でどう解決したか、設計でこだわった点を共有します。
課題:スプレッドシート管理の限界
以下の業務をすべてスプレッドシートで管理していました。
- 日次売上(保険・自由診療の内訳)
- 検査件数(血液・尿・生化学など項目別)
- 検査原価
- 月次予測・年次予測
- 診療カレンダー(休診日の管理)
- 在庫管理(試薬・消耗品の手動記録)
スプレッドシートで運用する問題は大きく4つありました。
コピペ地獄からの解放
CSVをダウンロードして開いて、シートに貼り付けて、集計列を確認して……この繰り返しに毎日時間を奪われていました。
名称ゆれへの対応が辛い
「HbA1c」「HbA1c」「HbA1C」など表記ゆれを手作業で統一するか、複雑なIF式を積み重ねるしかない。
将来の拡張が難しい
「診療カレンダーと月次予測を連動させたい」「在庫管理も一元化したい」となったとき、すぐ限界を迎える。
日々のタスクが散在する
「レセコン締めた?」「売上確認した?」をGoogleのToDoリストで別管理。集計と業務チェックがバラバラで、抜け漏れの温床になっていた。
解決策:Laravel + SQLite の自作Webアプリ
| 要素 | 選定 | 理由 |
|---|---|---|
| フレームワーク | Laravel(PHP) | 習熟しており、Webアプリとして構築しやすい |
| データベース | SQLite | インストール不要、ローカルで完結 |
| フロントエンド | Blade + Vite | SPAにするほど複雑ではないため |
主な機能
-
CSVアップロード・自動取込
電子カルテから出力した「カルテ集計CSV」と「処置行為集計CSV」をWeb画面からアップロードするだけで自動取込されます。
重要なルール:同日データは全削除→再取込。CSVを修正して再アップロードしたとき、古いデータと混在する「重複集計」事故を防ぎます。 -
名称マッピング層
「HbA1c」「HbA1c」などの名称ゆれは、マッピングテーブルで正規名に変換してから処理します。電子カルテのシステムが変わっても、マッピングを更新するだけで対応できます。
-
コストマスタ参照による原価計算
検査1件あたりの原価(試薬費等)はデータベースのコストマスタから取得します。価格のハードコードを禁止しているため、試薬価格が変わったときはマスタを更新するだけで翌日以降の集計に即反映されます。
-
日次集計の自動生成
CSVを取り込むと、保険売上・自由診療売上・検査件数(項目別)・検査原価・粗利概算が日次集計として自動生成されます。毎朝確認するだけで前日の診療実績が把握できます。
-
診療カレンダーと月次・年次予測
診療カレンダーに休診日・祝日を登録しておくと、月の残り診療日数から「今月の着地予測」が自動計算されます。目標に対して現在何%のペースかも一目でわかります。
-
生化学検査の丸め処理・血液検査の分類
生化学検査は点数計算に独特の丸めルールがあります。これをサービスクラスに実装し、手計算によるミスをなくしました。血液検査の詳細分類も対応済みで、検査種別ごとの件数・原価が正確に把握できます。
-
在庫管理の自動取得
試薬や消耗品の在庫をこれまでスプレッドシートに手動で記録していました。CSVデータから在庫数量を自動取得する仕組みに切り替え、手入力によるミスや記録漏れがなくなりました。スナップショット+手動調整の組み合わせで、実態との差異も追跡できます。
-
MoneyForward連携CSV自動出力
日次の会計仕訳データをMoneyForward取り込み形式のCSVとして自動生成します。これまで手入力していた経理連携がワンクリックで完結するようになりました。
-
業務チェックリスト(Google ToDoから卒業)
「レセコン締め」「売上確認」などの日次業務を、以前はGoogleのToDoリストで別管理していました。このシステムにチェックリスト機能を組み込み、集計確認と業務チェックを同じ画面で完結できるようになりました。テンプレートから毎日展開されるため、記入漏れも防げます。
設計でこだわった3つのポイント
データ層を4段階に分ける
CSV原本は必ず保持します。集計ロジックを変えたり、ミスを発見したりしたときに、いつでも再集計できる構造にしておくためです。
ロジックはServiceクラスに集約
コントローラはHTTPリクエストの受け渡しだけ。集計・計算・判定はすべて DailySummaryService、CostCalculationService などのServiceクラスに書きます。これによりテストが書きやすく、業務ロジックが変わったときの修正箇所が明確になります。
未確定ルールは「TODO」で明示し、順次確定させる
開発初期は業務ルールが曖昧なものを仮実装+TODOコメントで残し、「とりあえず動く」状態にしながら確認が必要な箇所をコードベースで追跡しました。生化学丸め・血液検査分類・自由診療判定なども、実運用しながらルールを確定し、TODOを順次解消していきました。
価格はハードコードしない
必ずマスタから取得。試薬価格の変更にも即対応できます。
CSVを破壊しない
原本は常に保持。ロジック変更後に再集計できる設計。
名称ゆれはマッピング層で吸収
CSV文字列でif判定しない。マッピングテーブルで一元管理。
実際に使ってみて――現在は実運用中
現在このシステムはクリニックの日常業務に組み込まれ、毎日稼働しています。導入前と比べて変わったことを挙げると:
毎日のCSV貼り付け作業がゼロになった
生化学丸めを含む検査集計のミスがなくなった
月中に「このペースで大丈夫か」がすぐ判断できるようになった
MoneyForward連携が手入力ゼロになった
開発初期は「まず日次集計だけ動かす」という小さなスタートでした。実運用しながらフィードバックを得て、生化学の丸め処理・血液検査の詳細分類・経理連携といった業務ロジックを順次確定・実装していきました。完璧を目指して開発を止めるより、動くものを早く使い始めることが、結果的に精度の高いシステムへの近道でした。
まとめ
開業医がゼロから自作するのは大変ですが、「スプレッドシートで何を管理しているか」を整理するだけで、自動化できる部分が意外と見えてきます。
今回のツールで使ったのはPHP/Laravelですが、PythonやNode.jsでも同じ考え方で作れます。小さく始めて実運用しながら育てる、というアプローチが医療現場のシステム開発には特に合っていると感じています。
電子カルテのCSVに悩んでいる開業医の方の参考になれば幸いです。
— Clinic Tech Lab 編集部