Flaskアプリ制作演習

2026-03-09

本演習では、社内向けの「備品貸出・在庫管理システム」をFlaskで新規構築いたします。利用者は備品(ノートPC、モニター、ケーブル等)を検索し、貸出申請や返却登録を行うことができます。

管理者は備品マスタ、在庫・状態、貸出ルール、ユーザー権限を管理し、貸出状況の監査が可能です。アプリケーションには、HTML(Jinja2)による管理画面と、外部連携を想定したREST APIを併設いたします。

DBはSQLAlchemyで設計し、Flask-Migrateによってスキーマ変更を管理します。また、画像アップロード(備品写真)とPillowによるサムネイル生成を実装し、静的ファイルはBootstrapで画面品質を担保いたします。

申請承認や期限超過通知はCeleryの非同期タスクで実行し、メール送信を行います。外部API連携として、拠点住所から地図APIで位置情報を取得し、備品の保管場所を地図表示できるようにいたします。

全体を通じて、CSRFやXSS対策、入力バリデーション、エラーハンドリング、ロギング、テスト駆動(単体・統合・カバレッジ)を満たし、キャッシュやクエリ最適化で性能も担保します。

最終的には、要件定義から画面遷移、DB設計、結合テスト、受入テストまで、一通りの実務成果物を作成し、運用を想定した品質で納品可能なレベルを目指してまいります。


要件定義

目的

  • 備品の所在・貸出状況を一元管理し、貸出手続きと監査性を向上する。

対象ユーザー

  • 一般ユーザー:貸出申請、返却登録、自分の履歴閲覧
  • 管理者:備品マスタ管理、申請承認、ユーザー/ロール管理、監査ログ確認

前提/制約

  • 認証必須(ログインなしアクセス不可)
  • 備品写真のアップロードは画像のみ(png/jpg/webp)
  • 期限超過通知は定期タスクで送信
  • 監査ログは改ざん防止のため更新不可(追記のみ)
  • APIはJSON、認証はセッションクッキー(管理画面)+APIトークン(API)

非機能要件

  • セキュリティ:CSRF、XSS、SQLi対策、パスワードハッシュ、権限分離
  • 可用性:想定同時利用 50人、ピーク時も検索が2秒以内
  • 保守性:マイグレーション管理、構造化ログ、テストカバレッジ70%以上
  • 性能:備品一覧はページネーション、検索結果はキャッシュ(短時間)

画面遷移

  • ログイン → ダッシュボード
  • ダッシュボード
    • 備品一覧 → 備品詳細 →(貸出申請)
    • マイページ(自分の貸出履歴)→ 返却登録
    • (管理者のみ)申請一覧 → 申請詳細 → 承認/却下
    • (管理者のみ)備品管理(一覧→新規→編集)
    • (管理者のみ)ユーザー管理(一覧→詳細→ロール変更)
    • (管理者のみ)監査ログ閲覧
  • エラーページ(403/404/500)は共通レイアウトで遷移

機能要件

1. 認証・認可

  • ユーザー登録、ログイン、ログアウト
  • パスワードはハッシュ化して保存
  • ロール(user/admin)によるアクセス制御(デコレータ)

2. 備品管理(管理者)

  • 備品のCRUD
  • 状態(利用可/貸出中/修理中/廃棄)管理
  • 画像アップロード、サムネイル自動生成、表示最適化

3. 貸出フロー(一般+管理者)

  • 一般:貸出申請(開始日・返却予定日・理由)
  • 管理者:承認/却下、却下理由登録
  • 承認後、備品は「貸出中」に遷移
  • 返却登録により「利用可」に戻す(破損時は「修理中」も選択可)

4. 検索・一覧

  • 備品一覧:カテゴリ/状態/キーワードで検索、ページネーション
  • 貸出履歴:ユーザー別、期間フィルタ
  • クエリ最適化(N+1回避)、必要に応じてインデックス

5. 通知(非同期)

  • 承認・却下時メール通知(Celery)
  • 期限超過の定期チェック(1日1回)で督促メール

6. 外部API連携

  • 拠点住所から地図ジオコーディング(requests)
  • 備品保管拠点の地図表示用に緯度経度を保持
  • APIキーは環境変数で管理、ログに出さない

7. REST API

  • GET /api/items(検索+ページネーション)
  • GET /api/items/
  • POST /api/requests(申請)
  • GET /api/requests/mine(自分の申請)
  • 管理者向け:PATCH /api/requests/(承認/却下)
  • エラー時はJSONで統一(コード、メッセージ、詳細)

8. エラーハンドリング/ログ

  • 403/404/500のカスタムページ
  • 例外は適切に握り、監査ログ+アプリログへ記録
  • ログはリクエストIDを付与

9. テスト

  • 単体:モデル、サービス層、バリデーション
  • 統合:主要画面・API・権限
  • カバレッジ計測(閾値設定)

テーブル設計書(案)

users

  • id(PK)
  • email(Unique, NotNull)
  • password_hash(NotNull)
  • name(NotNull)
  • is_active(Bool, default true)
  • created_at, updated_at

roles

  • id(PK)
  • name(Unique) 例: user/admin

user_roles(多対多)

  • user_id(FK users.id, PK)
  • role_id(FK roles.id, PK)

locations(拠点)

  • id(PK)
  • name(NotNull)
  • address(NotNull)
  • latitude, longitude(ジオコーディング結果)
  • created_at, updated_at

items(備品)

  • id(PK)
  • asset_tag(Unique, NotNull) 管理番号
  • name(NotNull)
  • category(NotNull) 例: pc/monitor/other
  • status(NotNull) 例: available/borrowed/repair/disposed
  • location_id(FK locations.id)
  • description(Text)
  • image_path
  • thumb_path
  • created_at, updated_at
  • index: (status), (category), (location_id)

loan_requests(貸出申請)

  • id(PK)
  • user_id(FK users.id, NotNull)
  • item_id(FK items.id, NotNull)
  • start_date(NotNull)
  • due_date(NotNull)
  • reason(Text, NotNull)
  • status(NotNull) 例: pending/approved/rejected/returned
  • decision_by(FK users.id, Null) 承認者
  • decision_note(Text, Null)
  • decided_at(Null)
  • returned_at(Null)
  • created_at, updated_at
  • index: (user_id, status), (item_id, status), (due_date)

audit_logs(監査ログ)

  • id(PK)
  • actor_user_id(FK users.id, Null) 未ログイン操作の可能性考慮
  • action(NotNull) 例: ITEM_CREATE, REQUEST_APPROVE
  • target_type(NotNull) 例: item/request/user
  • target_id(NotNull)
  • detail_json(JSON/Text)
  • ip_address
  • user_agent
  • created_at
  • 更新/削除禁止(アプリ側で制御)

結合テスト(主要観点)

IT-01 認証~一覧表示

  • 前提:一般ユーザーが存在
  • 手順:ログイン→備品一覧表示→検索→ページ遷移
  • 期待:未ログイン時はログインへリダイレクト、検索条件が反映、ページネーション正常

IT-02 申請~承認~状態遷移

  • 前提:備品がavailable、管理者が存在
  • 手順:一般が申請→管理者が承認→備品詳細確認
  • 期待:申請status=approved、備品status=borrowed、承認メールが非同期キューに積まれる

IT-03 却下フロー

  • 手順:申請→却下(理由必須)
  • 期待:status=rejected、備品statusはavailableのまま、却下理由が履歴に残る

IT-04 返却登録

  • 手順:承認済み申請を返却登録(返却時状態選択)
  • 期待:status=returned、returned_at設定、備品statusがavailableまたはrepairへ

IT-05 画像アップロード

  • 手順:備品にjpgをアップロード→詳細表示
  • 期待:拡張子/ContentTypeチェック、サムネ生成、パスがDBに保存、一覧はサムネ表示

IT-06 API認証と権限制御

  • 手順:トークン無しでPOST /api/requests→失敗、一般トークンで管理PATCH→失敗、管理トークンで成功
  • 期待:401/403が正しく返る、エラーJSON形式統一

IT-07 例外とエラーページ

  • 手順:存在しない備品IDアクセス、権限無し画面アクセス
  • 期待:404/403がカスタムページで表示、ログに記録される

IT-08 期限超過通知(疑似)

  • 手順:due_dateが過去のapprovedを作成→定期タスク相当処理を実行
  • 期待:対象抽出が正しい、通知が重複送信されない(送信済みフラグ or auditで制御)

受け入れテスト仕様書(抜粋)

UAT-01 基本業務が完遂できること

  • シナリオ:一般ユーザーが備品を探し、申請し、承認され、返却まで完了
  • 合格条件:各ステップで画面・メール通知・状態遷移が矛盾なく完了

UAT-02 管理者が備品台帳を維持できること

  • シナリオ:備品の新規登録、画像登録、拠点紐付け、廃棄まで実行
  • 合格条件:一覧/検索に反映、監査ログに記録、誤操作時もエラーが分かりやすい

UAT-03 セキュリティ要件を満たすこと

  • シナリオ:CSRFが必要なフォームでトークン無し送信、XSSを含む入力、SQLi風入力
  • 合格条件:送信拒否/無害化、エラーが適切、データ破壊が起きない、機密がログに出ない

UAT-04 性能要件を満たすこと

  • シナリオ:備品1000件、貸出履歴5000件相当データで一覧検索
  • 合格条件:主要検索が2秒以内、ページネーションが破綻しない、N+1が発生しない

UAT-05 運用要件(障害時の追跡)

  • シナリオ:意図的に例外を起こす、404を発生させる
  • 合格条件:ログにリクエストID・ユーザー・エラーが残り、原因追跡が可能