コンテンツにスキップ

予約カレンダー表示

Document ID: SRS-RES-001 Parent: SRS-ROOT-001 v0.5 Version: 0.2 Status: Draft Last Updated: 2026-05-05 Depends on: SRS-MST-001 v0.6, SRS-MST-005 v0.2, SRS-CUS-004 v0.1, SRS-RES-002 v0.5, SRS-RES-004 v0.3, SRS-RES-005 v0.4 依存される: SRS-RES-002, SRS-RES-003

本書は SRS-ROOT-001 v0.5 に従う。


管理画面で 1 日単位の予約カレンダーを表示する。Phase 1 は日次のみ、縦軸 staff × 横軸 time、未指名列は左端固定。リアルタイム同期は SSE ではなく 30 秒 polling(親 §8 で SSE は Phase 2 採用)。


  • As a 受付, I want to 1 日の予約を staff 別に一覧したい, so that 受付の全体把握ができる
  • As a 店長, I want to 未指名予約を左端で見たい, so that 当日割当を漏らさない
  • As a スタッフ, I want to 予約詳細へすぐ飛びたい, so that 当日運用が速い
  • As a スタッフ, I want to オプションで「自分担当のみ」フィルタを使いたい, so that 朝確認が速い

  1. TanStack Routersearch.date=YYYY-MM-DD で画面を開く
  2. GET /api/admin/staff で active staff 一覧を取得
  3. GET /api/admin/reservations?date=YYYY-MM-DD で当日予約 snapshot を取得
  4. クライアントが先頭に「未指名」列を合成
  5. 30 秒ごとに since=<last_server_time> 付きで再取得
  6. 変更がなければ 304、変更ありなら当日 snapshot を再描画
  • AF-1 印刷: @media print で簡易印刷レイアウト
  • AF-2 詳細表示: 予約クリックで detail panel へ遷移
  • AF-3 staff 0 名: 未指名列だけ表示
  • AF-4 「自分担当のみ」フィルタ: operator_staff_link の active link が存在する operator のみ UI 上にフィルタを表示。サーバ側でも staff_id 自動絞り込み(Phase 1 はクライアント側絞り込みでも可)
  • EF-1 date 不正: 400 RESERVATION.CALENDAR_DATE_INVALID
  • EF-2 権限不足: 403
  • EF-3 304: body なし、既存 snapshot を維持
  • EF-4 日付跨ぎ予約: starts_at の営業日で所属日を決める

  • 日付ナビゲーション
  • staff columns(staff.display_order ASC
  • 未指名固定列(左端)
  • 時間グリッド(store_settings.reservation_slot_minutes 単位)
  • 予約ブロック
  • detail side panel
  • print button
  • 「自分担当のみ」トグル(operator_staff_link あり時のみ表示)
  • search.dateYYYY-MM-DD
  • 未来・過去とも表示可
  • Phase 1 で週表示 / 月表示は出さない

MethodPath用途permission
GET/api/admin/reservations?date=&since=&staff_id=日次カレンダー snapshotadmin:reservation:read
GET/api/admin/reservations/{id}detail paneladmin:reservation:read

query:

  • date: YYYY-MM-DD required
  • since?: ISO8601
  • staff_id?: uuid(self-scope filter)

200 response:

  • data.date
  • data.timezone = 'Asia/Tokyo'
  • data.server_time
  • data.reservations[].id
  • data.reservations[].code(RES-002 v0.5 で追加された人間可読コード)
  • data.reservations[].staff_id
  • data.reservations[].status
  • data.reservations[].starts_at, ends_at
  • data.reservations[].customer_name
  • data.reservations[].menu_summary(最初の menu の name_snapshot
  • data.reservations[].version

304 response: body なし

  • RESERVATION.CALENDAR_DATE_INVALID
  • RESERVATION.FORBIDDEN

  • スキーマ変更なし(既存 reservations aggregate を流用)
  • 一覧 query は from/to/cursor 中心から date/since 中心へ拡張
  • 0019_reservation_phase1_finalize.sql で必要なら index 調整(既存 reservation_store_starts_idx でカバー)

  • 未指名staff.display_order ASC
  • staff_id IS NULL は未指名列
  • 30 秒固定
  • since は delta ではなく “conditional full snapshot” 用
  • 変更ありなら full snapshot 返却、なければ 304
  • reservations の updated_at のみ
  • staff layout 変更は別 API で管理
  • expired は既定非表示
  • その他 status は表示対象(paid / cancelled 系も含めて当日表示)
  • staff_id query パラメータでフィルタリング可能
  • operator_staff_link がある operator は UI で “自分のみ” トグルを表示
  • サーバ側強制(self-scope の権限境界)は Phase 2 OQ
  • read 系のため通常監査対象外

  • 初期表示 1 秒以下(親 §6.1)
  • 100 reservations/day を SLA
  • 1000/day の virtualization は Phase 2

  • admin:reservation:read(全 role)
  • detail も同じ permission
  • staff_id filter による情報絞りはアプリ層判定

10. 受け入れ基準(Given-When-Then)

Section titled “10. 受け入れ基準(Given-When-Then)”
  • GWT-1: date=2026-05-05 / 画面表示 / 当日予約が staff 別に表示される
  • GWT-2: staff_id=NULL の予約 / 表示 / 未指名列の左端に出る
  • GWT-3: since 以降変更なし / polling / 304
  • GWT-4: since 以降変更あり / polling / full snapshot
  • GWT-5: operator が staff A に linked / “自分のみ” toggle ON / staff_id=A でフィルタされた予約が返る
  • GWT-6: expired 予約 / 既定表示 / 含まれない

  • Integration: date query, 304/200 切替, self-scope filter
  • E2E (Phase 2): polling, detail panel

  • なし

#内容扱い
OQ-RES-001-01cancelled 系の表示色ルールUI レイヤ
OQ-RES-001-02深夜営業日跨ぎの “営業日” 定義Phase 1 は starts_at 基準
OQ-RES-001-03self-scope のサーバ強制Phase 2
OQ-RES-001-04SSE への移行タイミングPhase 2

VersionDateAuthorChange
0.12026-05-05Codex / yudai初版
0.22026-05-05yudai (with Codex co-design)Round 2 反映: polling 30s 確定、SSE は Phase 2、reservation.code 表示、operator_staff_link 連動の self-scope filter(Phase 1 は UI option のみ)