全国オンライン対応受付 平日 9:00-18:00
お問い合わせ

開発記録 / toi-toi-toi制作記 / Vol.12 toi-toi-toi制作記 Vol.1

記事 03

GASスプレッドシート予約管理——在庫管理と同じ考え方で枠を設計した

予約システムを作ろうとして最初に悩んだのは、「予約枠をスプレッドシートでどう表現するか」だった。

2026-06-07 公開

予約システムを作ろうとして最初に悩んだのは、「予約枠をスプレッドシートでどう表現するか」だった。

これは言い換えると「在庫をどう表現するか」という問いだ。飲食店の席数、ホテルの客室、コンサートのチケット。予約可能な「枠」は全て在庫だ。あればOK、なければNG。二重予約(在庫のマイナス)は絶対に起こしてはいけない。


カレンダー型かリスト型か

スプレッドシートで予約枠を管理するとき、設計は2つに分かれる。

カレンダー型は日付を行に、時刻を列に並べて、セルに「〇」か「×」を入れる。見た目は分かりやすい。しかし、サービスが複数になると途端に複雑になる。「片づけメソッドの片づけレッスン(5時間)」と「暮らしの作戦会議(60分)」が混在するとき、同じカレンダー上に並べるのか、シートを分けるのか。

リスト型は1行が1つの枠を表す。service_id・日付・時刻・予約済みフラグが列に並ぶだけだ。見た目はデータベースのテーブルに近い。GASからの操作がシンプルになる。「このservice_idの空き枠を全件取得する」というクエリがフィルタリングで書ける。

リスト型を選んだ。操作する側(GAS)の都合で設計した。


列の意味を決める

slotsシートの列は以下になった。

slot_id、service_id(1〜6)、日付、時刻、予約済みフラグ(空白=空き / "booked"=予約済み)、予約者名、電話番号、メールアドレス、メモ、予約ID、LINEユーザーID、予約日時。

slot_idが最初にある理由がある。「何行目を予約済みにするか」を判断するとき、行番号を使ってはいけない。行の挿入や削除でズレる。slot_idを持ち歩いて、IDで照合してから書き込む。

予約済みフラグが「true/false」ではなく「空白/"booked"」なのは、スプレッドシートを人間が見たとき、空白の方が「空き」として直感的だからだ。機械より人間の読みやすさを優先した。


空き枠を取得するコード

フロントエンドから「service_idが2の空き枠を教えて」というリクエストが来ると、GASはこれを実行する。

function getSlots(serviceId) {
  const ss = SpreadsheetApp.openById(SHEET_ID);
  const sheet = ss.getSheetByName('slots');
  const rows = sheet.getDataRange().getValues();
  const today = new Date();
  today.setHours(0,0,0,0);
  return rows.slice(1).filter(r =>
    r[1] == serviceId && r[4] === '' && new Date(r[2]) >= today
  ).slice(0,20).map(r => ({
    slot_id: r[0], date: r[2], time: r[3],
    label: r[2] + ' ' + r[3]
  }));
}

全データを取得してフィルタリングする。スプレッドシートをDBとして使う場合の常套手段だ。枠の数が数百件以下なら性能上の問題はない。


ダブルブッキングを防ぐ

空き枠を取得してから予約確定するまでの間に、別の人が同じ枠を選んでいることがある。

「確認したら空き→予約確定を書き込む」の間にロックを入れない設計では、2人が同時に押したとき両方に「予約できました」と返してしまう可能性がある。

GASのLockServiceを使う。

const lock = LockService.getScriptLock();
lock.waitLock(5000);
try {
  const row = findSlotRow(slotId);
  if (row[4] !== '') {
    return { success: false, message: 'すでに予約が入りました' };
  }
  writeBooking(row, bookingData);
  return { success: true };
} finally {
  lock.releaseLock();
}

ロック取得後に枠の状態を再確認する。「ロックを取る前に空きだった」は信頼できない。ロックを取った後で初めて確認する。


管理が「Googleスプレッドシートを開くだけ」で済む理由

オーナーがスマートフォンからスプレッドシートアプリを開いて、新しい行を追加する。service_id・日付・時刻を入力して、フラグの列を空白にしておく。それだけで新しい予約枠として公開される。

管理画面にログインする必要はない。専用ツールを覚える必要もない。スプレッドシートを使えれば、それがシステムの操作方法になる。

「伊藤がいなくても使い続けられるか」を設計の基準にした。答えがYesだと確信できた設計だった。


*次回は「LINE通知設計:予約確認・前日リマインド・キャンセル通知の3本柱」*

*シンプルシステム株式会社 代表 伊藤勝彦*