整理券アプリを作る（要件定義編）

## 要件定義・仕様書(概要)
### 経緯・目的
昨年の学祭にて、滞在時間のほとんどが行列に並んだ無駄な時間、あぁ、芸能人のイベント見たかったなぁ...
ってことで整理券アプリ作れば待ち時間を有効活用できるのでは？
じゃあ頑張って作りますか！

### システム概要
大学祭の屋台で「整理券」をデジタル化し、効率的な行列管理を行うためのWebアプリケーションを構築する。ユーザー（客）はメール認証によるアカウント登録後、希望する店舗の整理券をオンラインで取得することが可能。また、店舗側は管理用アカウントでログインし、現在の待ち状況や整理券情報の閲覧、呼び出し（商品引き渡し）の通知送信が可能。

## システム構成（あまり分かっていない）
　・フロントエンド（React,TypeScript）
　・バックエンド（何にしよう）
　・データベース（多分MySQL）
  
## 利用者一覧
1.客
　・整理券の取得、待ち状況の確認、呼び出し通知の受信
　・プロフィール管理(氏名、ふりがな、ニックネーム、年齢、誕生日、性別、メールアドレス、電話番号など)
2.店舗
　・自店舗の整理券発行状況、待ち行列管理、呼び出し通知の送信
　・プロフィール管理　（店舗名、責任者名、メールアドレス、電話番号など）

 ## 機能要件
 1.ユーザー登録・認証
 　・メールアドレスとパスワードを用いたアカウント登録フォーム
 　・メールアドレスの有効性確認（メールに送信されるURLクリックによる認証）
 　・ログイン・ログアウト機能
 　・パスワードリセット機能（メール経由）、機能自体はできたらやる
 　・店側、客側でアカウント種別が異なるため、「種別選択」で選択可能

2.整理券管理(客側)
　・店舗一覧表示（取得可能な整理券の数、待ち時間予測）
　・整理券発行（特定の店舗を選択して「整理券を取得」）
　・現在の自分の順番や待ち人数の確認

3.整理券管理(店側)
　・発行済みの整理券一覧の表示
　・呼び出し機能：順番が来た整理券に紐づくユーザーに通知送信
　・整理券ステータス変更（「待ち中」→「呼び出し中」→「商品引渡し完了(クローズ)」）

 4.通知機能
　・呼び出し時にメール通知、もしくはプッシュ通知（Web Pushなど）を行う
　・店側が「呼び出し」を行った際、客側はリアルタイムで更新（WebSocket等を利用）または一定間隔ポーリングで通知を受け取る

 5.UI要件
  ・Reactを用いてSPA的なUI
  ・レスポンシブデザイン（スマホ/PC対応）
  ・ナビゲーションバーから自分のプロフィール、取得した整理券状況、ログアウトへのアクセスが可能

6.セキュリティ要件
 ・パスワードはハッシュ化(サーバー側処理)
 ・SQLインジェクション対策(Prepared Statements)
 ・XSS/CSRF対策 (CSRFトークン、Reactでの適切なエスケープ処理)
 ・HTTPS通信

7.拡張性
 ・将来的な機能拡張を考慮し、API設計はRESTful
 ・将来的に多店舗対応や分析機能追加を想定

 ## データベース設計
 ### userテーブル（客）
 カラム名|型|Not Null|説明
--- | --- | --- | ---
id|INT PK AUTO_INC|YES|ユーザーID(主キー)
email|VARCHAR(255)|YES|メールアドレス(ユニーク)
password_hash|VARCHAR(255)|YES|パスワードハッシュ
last_name|VARCHAR(50)|YES|姓
first_name|VARCHAR(50)|YES|名
last_name_kana|VARCHAR(50)|YES|姓(カナ)
first_name_kana|VARCHAR(50)|YES|名(カナ)
nickname|VARCHAR(50)|YES|ニックネーム
gender|VARCHAR(10)|YES|性別(男性, 女性)
birthdate|DATE|YES|生年月日
age|INT|YES|年齢
phone_number|VARCHAR(20)|YES|電話番号
email_verified|BOOLEAN|YES|メール認証完了フラグ
created_at|DATETIME|YES|登録日時
updated_at|DATETIME|YES|更新日時

### storeテーブル（店舗）
カラム名|型|Not Null|説明
--- | --- | --- | ---
id|INT PK AUTO_INC|YES|店舗ID(主キー)
email|VARCHAR(255)|YES|メールアドレス(ユニーク)
password_hash|VARCHAR(255)|YES|パスワードハッシュ
store_name|VARCHAR(100)|YES|店舗名
manager_name|VARCHAR(100)|YES|責任者名
phone_number|VARCHAR(20)|YES|電話番号
email_verified|BOOLEAN|YES|メール認証完了フラグ
created_at|DATETIME|YES|登録日時
updated_at|DATETIME|YES|更新日時

### ticketテーブル（整理券情報）
カラム名|型|Not Null|説明
--- | --- | --- | ---
id|INT PK AUTO_INC|YES|整理券ID(主キー)
store_id|INT|YES|発行元店舗ID(fk: stores.id)
user_id|INT|YES|整理券取得ユーザーID(fk: users.id)
status|VARCHAR(20)|YES|状態("waiting", "calling", "completed")
issued_at|DATETIME|YES|発行日時
called_at|DATETIME|NO|呼び出し日時(null可)
completed_at|DATETIME|NO|完了日時(null可)

## APIエンドポイント（例）
### 客認証系
・`POST /api/auth/user/register` : 客ユーザー登録(メール送信)
・`POST /api/auth/user/verify` : 客ユーザー認証完了処理
・`POST /api/auth/user/login` : ログイン
・`POST /api/auth/user/logout` : ログアウト
・`POST /api/auth/user/forgot_password` : パスワードリセット要求
・`POST /api/auth/user/reset_password` : パスワードリセット実行
### 店舗認証系
・`POST /api/auth/store/register`
・`POST /api/auth/store/verify`
・`POST /api/auth/store/login`
・...（上記と同様）
### 整理券系
・`GET /api/stores` : 店舗一覧取得
・`POST /api/tickets` : 整理券発行（パラメータ: store_id, user_id）
・`GET /api/tickets/user` : ログイン中の客の整理券一覧取得
・`GET /api/tickets/store` : ログイン中の店の整理券一覧取得
・`PATCH /api/tickets/:id/call` : 店側が整理券を呼び出しステータスへ変更、通知処理
・PATCH /api/tickets/:id/complete : 整理券完了処理

## 通知手順
・呼び出し時、サーバーサイドでメールまたはWeb Pushを送信
・React側はWebSocketやSSEなどでリアルタイム更新、または一定間隔でステータスチェック
`WebSocket`:リアルタイム通信の仕組み。サーバーとクライアント間で常時接続を維持し、双方向にデータを送受信できるプロトコル。
`SSE`:サーバーからクライアントへの一方向のリアルタイム通信を実現する技術
## インストール・デプロイ
・Webで完結させるため、バックエンドはクラウド上のサーバー(APIサーバー)、フロントエンドはホスティングサービス（Firebase HostingやVercel等）で提供
・React側はSPAとしてビルド後にデプロイ
・DBはクラウドDB（RDS等）を想定
`ホスティングサービス`:WebアプリやAPIをインターネット上に公開するサービス。
`SPA(Single Page Application)`:1枚のHTMLで構成されるWebアプリ

## 感想
とりあえず要件定義したけど後々仕様変更するだろうな...ﾄﾎﾎ