導入(問題提起)

予約が重なる、確認漏れが出る、当日キャンセルが多い。運用で“頑張る”のにも限界があります。本質的な対策は、そもそも「起きにくい設計」にすること。Excelや無料フォームでは実現しにくい同時編集制御・通知・変更導線・リソース束縛を、Webシステム開発で“小さく”実装していくのが現実解です。本記事では、Pythonを活用しながら予約カレンダーを設計・実装するポイントを、具体例と技術解説付きで整理します。キーワードは「Webシステム開発」「業務システム」「Python」「Excel Web化」です。

課題の詳細説明

予約運用で典型的に起きる失敗パターン:

  • 二重予約:同時刻に複数の予約が通ってしまう(拠点/スタッフ/部屋の制約を越える)。
  • 連絡漏れ:SMS/メールが届かず来店率が低下。送信履歴やエラーが追跡できない。
  • 受付条件の曖昧さ:前日/当日受付の線引きが不明、結果として現場判断がバラバラ。
  • 変更/キャンセル導線不足:ユーザが自助解決できず、電話が集中し人的コストが増大。
  • 外部カレンダーとの不整合:Google/Outlookと二重管理で抜け漏れが発生。
  • 決済未整備:悪質キャンセルの抑止が難しく、売上機会損失が発生。

解決方法

以下の6原則で“小さく強い”予約システムを作ります。

  1. リソース設計:staff / room / equipment を明示し、1枠の収容上限を定義(例:1スタッフ×1部屋×1機材)。
  2. アトミック予約:DBトランザクションで1枠1予約を保証。楽観/悲観制御のどちらを採るかを明記。
  3. ポリシー整備:受付締切、キャンセル締切、ペナルティのルールを画面上に明示(同意チェック)。
  4. 通知自動化:直後・前日・当日朝の多段リマインド(メール/LINE/SMS)。配信結果と開封を記録。
  5. 変更導線:確認ページからワンクリック変更/キャンセル。本人確認トークンを採用。
  6. 外部同期:Google/Outlookのブロックと相互連携。二重管理を防ぐ片方向/双方向の方針を決定。

具体例

使いやすさと運用を両立するUI/機能の例:

  • 枠の自動生成:営業日・営業時間・休憩・メニュー所要時間から自動作成。
  • 料金と処理時間:メニューごとに価格と所要時間を設定、複数メニュー合算も可能。
  • 事前決済/デポジット:当日ドタキャン率を低減。ルールはメニュー単位で切替。
  • リマインド:予約直後/前日/当日朝の自動送信。未達時は別チャネルで補完。
  • スタッフアサイン:スキルタグで担当候補を絞り、手動/自動で最適配置。

技術的な解説(Python × 予約アーキテクチャ)

最小構成は「Python + FastAPI(またはBottle) + SQLite」。将来はPostgreSQL+外部カレンダーAPIに拡張。

  • データモデル(例:SQLite)

CREATE TABLE resources(
  id INTEGER PRIMARY KEY,
  type TEXT CHECK(type IN ('STAFF','ROOM','EQUIP')),
  name TEXT NOT NULL
);
CREATE TABLE slots(
  id INTEGER PRIMARY KEY,
  start DATETIME NOT NULL,
  end   DATETIME NOT NULL,
  capacity INTEGER NOT NULL DEFAULT 1
);
CREATE TABLE slot_resources(
  slot_id INTEGER REFERENCES slots(id),
  resource_id INTEGER REFERENCES resources(id),
  PRIMARY KEY(slot_id, resource_id)
);
CREATE TABLE reservations(
  id INTEGER PRIMARY KEY,
  slot_id INTEGER NOT NULL REFERENCES slots(id),
  customer_name TEXT,
  customer_email TEXT,
  status TEXT CHECK(status IN ('PENDING','CONFIRMED','CANCELLED')),
  token TEXT UNIQUE
);
CREATE UNIQUE INDEX uniq_slot_confirmed ON reservations(slot_id) WHERE status='CONFIRMED';
  • ルーティング(FastAPI例)

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
import sqlite3, secrets

app = FastAPI()

def db():
    return sqlite3.connect('reserve.db')

class ReserveReq(BaseModel):
    slot_id: int
    name: str
    email: EmailStr

@app.post('/reserve')
def reserve(req: ReserveReq):
    token = secrets.token_urlsafe(24)
    with db() as con:
        try:
            con.execute('INSERT INTO reservations(slot_id,customer_name,customer_email,status,token) VALUES(?,?,?,?,?)',
                        (req.slot_id, req.name, req.email, 'CONFIRMED', token))
        except sqlite3.IntegrityError:
            raise HTTPException(409, 'double booking')
    return {'ok': True, 'token': token}
  • 二重予約防止:UNIQUE INDEX とトランザクションで保証。APIは409 Conflictを返す。
  • 通知:送信キュー(DBテーブル)に積み、ワーカーが順次配信。未達はリトライ。
  • 変更/キャンセル:トークンURLで本人認証し、枠の再開放までを一括処理。
  • カレンダー同期:Google Calendar APIで“ブロック”イベントを作成し、双方向で更新検知。

導入の流れ

  1. 現状棚卸:メニュー、所要時間、リソース制約、受付/キャンセルポリシーを定義。
  2. PoC:単一メニュー・単一拠点・単一スタッフで試行。Excel Web化の延長として最小構成を稼働。
  3. 通知導入:メール/LINEの二系統に。未達時のフォールバックを検証。
  4. 変更導線の整備:確認ページとワンクリックキャンセルを提供。電話問合せを段階的に減らす。
  5. 同期:Google/Outlookのどちらを主とするか方針を決め、片方向→双方向に拡張。
  6. 事前決済:ドタキャン率に応じてメニュー単位で適用。返金ポリシーを明文化。

まとめ

予約は「設計8割・運用2割」。枠の定義と二重予約防止、通知、変更導線を最小構成で押さえれば、小規模でも十分に安定運用が可能です。Pythonによる業務システムとしてWeb化することで、担当者依存から脱却し、成長に合わせて機能拡張できます。

「Webシステム開発のご相談は monou まで」