要件定義・仕様書(概要)
経緯・目的
昨年の学祭にて、滞在時間のほとんどが行列に並んだ無駄な時間、あぁ、芸能人のイベント見たかったなぁ...
ってことで整理券アプリ作れば待ち時間を有効活用できるのでは?
じゃあ頑張って作りますか!
システム概要
大学祭の屋台で「整理券」をデジタル化し、効率的な行列管理を行うための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(主キー) |
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(主キー) |
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アプリ
感想
とりあえず要件定義したけど後々仕様変更するだろうな...トホホ