業務をつなげる
授業、講師、シフト、給与を独立したデータとして管理するのではなく、一連の業務として連動させる。
Classroom Operations Platform
授業からシフト、給与、LINE通知まで。
教室運営を一つにつなぐ業務管理システム。
アルバイト先の教室で、Excelを中心に行われていた授業・生徒・講師・シフト・給与・振替などの業務を一元化するために開発しているWebアプリケーションです。
アルバイト先では、授業予定や講師シフト、給与など多くの業務をExcelを中心に管理していました。
以前、Excelのシフト表を取り込み、講師へLINEで勤務前通知を送る「シフト通知システム」を開発し、現在も実際の教室で運用しています。
その運用をきっかけに、毎月の授業予定をExcelで作成する負担など、他の業務についてもシステム化の相談を受けました。
そこで現在は、授業・生徒・講師・教室・シフト・給与・振替を一つにつなげて管理する教室管理システムへと発展させています。
授業、講師、シフト、給与を独立したデータとして管理するのではなく、一連の業務として連動させる。
定期授業から月間授業や講師シフトを自動生成し、毎月の作業を削減する。
すべてを自動化するのではなく、自動生成後に管理者が行った手動調整を保持できるようにする。
Excelで分かれていた情報を、授業を起点に連動させて管理します。
授業 → シフト → 給与 → LINE通知と、機能同士がつながっていることがこのシステムの特徴です。
Serverless Architecture on Cloudflare
実際の教室で長期的に利用することを想定し、現時点ではランニングコストをかけずに運用できることを一つの設計上の制約としました。
そのため常時稼働するサーバーを持たず、Cloudflare Workersを中心にD1、R2、Queues、Cron Triggers、Workflowsを組み合わせたサーバーレス構成を採用しています。
生徒・講師の情報を扱うため、入口からデータまで複数レイヤーで守ります。
生徒・講師の情報を扱う業務システムであるため、アプリケーション内の認証だけに依存せず、複数レイヤーでアクセスを制御しています。
本番の管理画面ではCloudflare AccessとMFAを前段に配置し、その内側でアプリケーション独自の認証・認可を行います。
短命Access TokenとHttpOnly Refresh Cookieを利用し、認証情報をlocalStorageへ保存しない設計。
管理者・講師のRoleを分離し、講師は許可された自身のデータのみ操作可能。
R2は非公開とし、個人情報やTokenをログへ出力しない。LINE User IDなど必要な機密データは暗号化。
Cloudflare AccessとMFAで本番の管理画面・APIへの入口を制限し、アプリケーション側でも入力値検証、Rate Limit、CORS制限、Security Headers、Prepared Statementなどを実施。
従来は、管理者が作成した月間シフト画像をLINEグループへ手動で送信していました。これをLINE Messaging APIで自動化し、講師へ確実に届ける方法を検討しました。
LINE Messaging APIのリクエストはJSON形式です。画像メッセージでは、元画像とプレビュー画像の2つのURLを指定します。
{
"type": "image",
"originalContentUrl": "https://example.com/original.png",
"previewImageUrl": "https://example.com/preview.png"
} LINE側がこのURLから画像を取得するため、非公開R2のオブジェクトをそのまま指定することはできません。画像を公開すれば送信できますが、シフト情報を外部公開することになります。
そこで、画像をLINEのImage Messageとして直接配信するのではなく、LINEを認証済みの閲覧画面への入口として使う方法を採用しました。LINEにはLIFFへの導線だけを渡し、画像は本人確認・講師アカウントとの紐付け・管理者承認の後にWorker API経由で取得します。
シフト表には講師の勤務情報が含まれるため、R2を直接公開していません。本人確認・アカウント紐付け・管理者承認を終えたユーザーだけが、Worker API経由で非公開R2の画像を閲覧できます。
講師が新しいアプリや別のログイン画面へ移動せず、普段使っているLINEからシフト表を確認できるようにするため、LIFFを採用しました。LINE内のWebViewで画面を開き、LIFFから取得したLINE ID Tokenを使って本人確認・講師アカウントとの紐付けへつなげます。
LINEから非公開R2までの認証・取得フロー
現場で継続して使われることを前提にした、3つの設計判断。
定期授業から月間授業と講師の仮シフトを自動生成します。一方で、管理者が手動で変更した授業やシフトには編集状態を保持し、同じ月を再生成しても上書きしません。
「すべて自動化する」のではなく、自動化と現場での手動調整を共存させることを重視しました。
LINE通知をHTTPリクエスト内で直接送信するのではなく、D1にOutboxを保存してCloudflare Queuesへ処理を渡します。
Queueへの投入やLINE APIへの送信が一時的に失敗した場合もCronから回収・再送でき、Retry Keyによって重複通知も抑制します。
公開処理では、対象月の授業・シフトをD1から取得し、画像生成の前に公開前バリデータを実行します。
シフトのstatusや担当講師の関連を確認し、仮シフトや未設定を検出します。講師の出勤不可日は勤務日と突合し、時間重複は講師ごとに開始時刻で並べた勤務区間を比較して検出します。
検証結果はエラー一覧として返し、1件でも問題が残っている場合は画像生成とLINE配信へ進みません。
statusが仮シフトのまま残っていないか先行して開発したシフト通知システムは、現在も実際の教室で継続運用されています。
その運用をきっかけに他の教室業務についても改善を依頼され、本システムの開発へと発展しました。
現在は授業自動生成、シフト・給与・振替管理、LINE連携など主要機能の実装を終え、実際の教室への導入を進めています。
実際のユーザーがいる環境で、課題の発見から要件整理、設計、実装、セキュリティ、運用まで一貫して取り組んでいるプロジェクトです。