TABLIA / RESERVATION MENU DESIGN

人数分のコースに、
必要な数の追加メニューを。

1つの予約に「メニュー × 数量」の明細を複数持つ設計。
コースの人数分けも、ケーキ1個の追加も、同じ仕組みで扱います。

PR #2541・未マージ 2026年9月8日確認 · 対象コミット 9fdc73018
01 / TWO TYPES

違いは「数量を人数に合わせるか」

メインメニュー

予約人数分を選ぶ

通常は1種類を全員分。店舗が混在を許可すると、種類ごとに人数を分けられます。

5名 → 会席A × 3 + 会席B × 2

Course.isAddOn = false
追加メニュー

人数と独立して選ぶ

複数種類を、それぞれ1〜10点選択。5名の予約にケーキ1個、という指定ができます。

5名 → ケーキ × 1 + 花束 × 2

Course.isAddOn = true

上記は公開予約のルール。追加メニューの0は「未選択」で、明細を作りません。

02 / DATA MODEL

メニューのマスタと、予約の注文明細を分ける

「コース用」「追加メニュー用」のテーブルを分けず、どちらも Course で管理します。ReservationCourse が予約とメニューをつなぎ、数量を保存します。

Reservation
予約本体 / reservations
id 予約ID
storeId 店舗
numAdults 大人人数
numChildren 子ども人数
reservedAt 来店日時

誰が・いつ・何名で来るか
1 → 多
ReservationCourse
予約明細 / reservation_courses
reservationId 予約ID
courseId メニューID
quantity 注文数量

何を・何点選んだか
同じ予約 × メニューは1行
多 ← 1
Course
メニューマスタ / courses
id / storeId ID・店舗
name / price 名称・価格
isAddOn メインか追加か
isPublished 公開状態
提供期間・時間帯・受付締切など

何を提供するか
Store が公開予約の選び方を制御
allowMixedCourses = false が初期値。ONにすると複数種類のメインを選択できます。追加メニューの複数選択は、この設定と独立しています。
DBの制約と、旧データとの互換性
  • 明細の複合主キーは予約IDとメニューID。数量は整数で、DBのCHECK制約により1以上。
  • 予約と明細を同じトランザクションで保存。店舗の一致や選択可否はアプリ側で検証。
  • 通常のメニュー削除はアーカイブのため、過去の明細は残る。物理削除すると対応する明細も削除される。
  • Reservation.courseId も残し、互換用の代表メニューを保存。メインを優先し、同じ種別では数量が多いものを選ぶ。
  • 今回のPRのDB差分は courses.is_add_on の追加。明細テーブルと混在設定は先行実装の土台を利用する。既存メニューはメイン扱い。
03 / TRY THE MODEL

この予約は、どんな明細になる?

例を切り替えると、保存する行と公開予約の判定が変わります。

予約IDメニュー種別quantity

架空のメニューによる説明です。提供日時や公開状態など、ほかの受付条件は満たす前提です。画面は設計の説明用です。

04 / USE CASES

予約時点で、準備する内容をそろえられる

家族・グループ予約

大人コース3名分と子どもコース2名分を1予約にまとめる。

公開予約ではメイン混在をONにする。

記念日・お祝い

コース5名分に、ケーキ1個と花束1束を追加する。

追加の数量は来店人数から切り離す。

料理は当日注文

予約ではお祝いプレートだけを1点指定し、料理は来店後に選ぶ。

追加メニューだけの予約も許可される。

電話予約の例外対応

5名中4名分だけコースを用意するなど、スタッフが数量を調整する。

管理画面は人数不一致を警告しつつ保存できる。

予約確認・通知

選択したメニューと数量を、予約画面やメールの明細で確認する。

「どれが何点か」をメモに埋め込まず扱える。

選択内容に応じた質問

ケーキを選んだ予約だけに、プレートのメッセージを尋ねる。

既存のメニュー別カスタム質問と組み合わせる。
05 / RULES & BOUNDARIES

数量管理の設計。会計や在庫管理は含まない

場面今回の扱い
メインの数量公開予約でメインを選ぶなら、合計は大人+子どもの予約人数に一致させる。
追加の数量公開予約・管理画面の数量入力は各1〜10点。公開予約ではサーバー側でも10点上限を検証する。
メインの選択必須追加メニューだけでも予約可能。追加だけを提供している場合は、何も選ばない予約も可能。
商品ごとの条件公開状態、提供期間、時間帯、入店時刻、受付締切などを確認。最小・最大人数は注文数ではなく予約全体の人数に適用。
飲み放題を全員分人数分の商品としてメインに登録できる。ただし「料理5名分+飲み放題5名分」を別々のメインにすると合計10で人数不一致。料理と飲み放題をまとめたメインにする運用が必要。
注文当時の価格明細に価格のスナップショットは持たず、現在のマスタ価格を参照。注文時点の金額確定や会計台帳には使えない。
個人への割り当て「Aコース3名分」まで。「田中さんがAコース」という個人との対応は保持しない。
在庫・決済・細かい数量条件日別在庫、メニュー別の最小・最大注文数、追加を全員分必須にする設定、コース別の事前決済・キャンセル料計算は対象外。
外部サービス連携複数明細を持てることと、各サービスに全明細を送れることは別。今回のPRだけで外部連携の完全な複数メニュー対応を保証しない。
06 / RELEASE SCOPE

実装済みの内容と、公開状態は別

この資料はPR #2541のコードに基づく説明です。確認時点では未マージ。追加メニューの作成には multiple_reservation_courses の機能フラグが必要で、本番で全店舗に利用可能という意味ではありません。