# 機能設計書 64-GDPRリクエスト作成

## 概要

本ドキュメントは、GDPRリクエスト作成機能の設計仕様を定義する。ユーザーがGDPR（EU一般データ保護規則）に基づくデータリクエスト（削除要求・更新要求）を新規作成する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：GDPRはEU域内のユーザーに対して、自身の個人データに関する権利を保証している。具体的には、データの削除を求める「忘れられる権利」や、データの修正を求める「訂正権」がある。本機能はユーザーがこれらの権利を行使するためのリクエストをショップに送信する手段を提供する。

**機能の利用シーン**：
- ユーザーが自身の個人データの削除をリクエストしたい場合（アカウント削除前など）
- ユーザーが保存されている個人情報の更新・訂正を依頼したい場合
- プライバシー設定画面やGDPRリクエスト一覧画面から「Create Request」ボタンを押した場合

**主要な処理内容**：
1. モーダルダイアログを表示し、リクエストタイプ（DELETE/UPDATE）とメッセージを入力
2. クライアント側でバリデーション（メッセージ必須チェック）
3. GraphQL mutationを呼び出してリクエストを作成
4. 作成成功後、リクエスト一覧を再取得して画面を更新

**関連システム・外部連携**：
- Bagisto GraphQL API（createGdprRequest mutation）

**権限による制御**：ログイン済みユーザーのみ作成可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | GDPRリクエスト画面 | 主画面 | GDPRデータリクエストの新規作成処理 |

## 機能種別

データ作成処理（CREATE操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | Enum (GdprRequestType) | Yes | リクエストタイプ（DELETE/UPDATE） | DELETEまたはUPDATEのいずれか |
| message | String | Yes | リクエストの理由・詳細メッセージ | 空でないこと（trim後） |

### 入力データソース

- CreateRequestModalダイアログのフォーム入力
- DropdownButtonFormFieldからのタイプ選択
- TextFormFieldからのメッセージ入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| status | bool | 作成成功/失敗 |
| message | String | 結果メッセージ |
| gdprRequest | Object | 作成されたリクエストの詳細（id、customerId等） |

### 出力先

- SnackBar表示で成功/失敗を通知
- 成功時はダイアログを閉じ、リクエスト一覧を再取得

## 処理フロー

### 処理シーケンス

```
1. 「Create Request」ボタンタップ
   └─ CreateRequestModalダイアログを表示
2. ユーザーがリクエストタイプを選択
   └─ DropdownButtonFormFieldで選択
3. ユーザーがメッセージを入力
   └─ TextFormFieldで入力
4. 「Save」ボタンタップ
   └─ createGdprRequestメソッド呼び出し
5. クライアント側バリデーション
   └─ FormState.validate()でメッセージ必須チェック
6. バリデーション成功時
   └─ CreateGdprRequestイベントをBlocに発行
7. GdprBlocでイベント処理
   └─ GdprRepositoryのcreateGdprRequestメソッドを呼び出し
8. APIクライアント呼び出し
   └─ GraphQL mutation実行（createGdprRequest）
9. レスポンス処理
   └─ BaseModelにデシリアライズ
10. 状態更新
    └─ CreateGdprRequestState.success発行
11. ダイアログを閉じる
    └─ Navigator.pop(context)
12. 一覧再取得
    └─ FetchGdprRequestsListを再発行
```

### フローチャート

```mermaid
flowchart TD
    A[Create Requestボタンタップ] --> B[CreateRequestModal表示]
    B --> C[タイプ選択 & メッセージ入力]
    C --> D[Saveボタンタップ]
    D --> E{バリデーション成功?}
    E -->|No| F[エラーメッセージ表示]
    E -->|Yes| G[CreateGdprRequest発行]
    G --> H[GdprLoadingState]
    H --> I[GdprBloc処理]
    I --> J[Repository.createGdprRequest]
    J --> K[ApiClient.createGdprRequest]
    K --> L{API成功?}
    L -->|Yes| M[CreateGdprRequestState.success]
    L -->|No| N[CreateGdprRequestState.fail]
    M --> O[ダイアログ閉じる]
    O --> P[一覧再取得]
    N --> Q[エラーSnackBar表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-01 | 認証必須 | ログイン済みユーザーのみ作成可能 | 常時 |
| BR-64-02 | タイプ必須 | DELETE または UPDATE のいずれかを必ず選択 | 常時 |
| BR-64-03 | メッセージ必須 | リクエストの理由・詳細は必須入力 | 常時 |
| BR-64-04 | デフォルトタイプ | タイプのデフォルト値はUPDATE | フォーム初期表示時 |
| BR-64-05 | 成功時一覧更新 | 作成成功後は一覧を自動的に再取得 | API成功時 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

本機能はGraphQL APIを通じてバックエンドにデータを作成する。クライアント側でのデータベース操作は行わない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リクエスト作成 | gdpr_requests（バックエンド） | INSERT | 新規GDPRリクエストを作成 |

### テーブル別操作詳細

#### gdpr_requests（バックエンド）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | customer_id | ログインユーザーID | 自動設定 |
| INSERT | type | DELETE または UPDATE | ユーザー選択値 |
| INSERT | message | ユーザー入力値 | リクエスト詳細 |
| INSERT | status | pending | 初期ステータス（想定） |
| INSERT | created_at | 現在日時 | 自動設定 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | メッセージが未入力 | 「Message is required.」表示 |
| - | API通信エラー | ネットワーク接続失敗 | CreateGdprRequestState.fail発行、SnackBar表示 |
| - | サーバーエラー | バックエンド処理失敗 | エラーメッセージをSnackBar表示 |

### リトライ仕様

自動リトライは実装されていない。ユーザーは再度ダイアログを開いて作成を試みる必要がある。

## トランザクション仕様

バックエンド側で管理。クライアント側ではAPIリクエストを1回発行するのみ。

## パフォーマンス要件

- リクエスト作成: 5秒以内にレスポンス

## セキュリティ考慮事項

- 認証必須（ログインユーザーのみ）
- ユーザーは自身のリクエストのみ作成可能
- GDPRコンプライアンス対応機能

## 備考

- GdprRequestType列挙型はDELETEとUPDATEの2値
- APIにはtypeをstring形式（"DELETE"/"UPDATE"）で送信

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

GDPRリクエスト作成に使用するデータ構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | create_request.dart | `lib/screens/gdpr/view/widget/create_request.dart` | GdprRequestType列挙型の定義 |
| 1-2 | graphql_base_model.dart | `lib/data_model/graphql_base_model.dart` | BaseModelクラスのsuccess、messageフィールド |

**読解のコツ**:
- **create_request.dart 6-9行目**: GdprRequestType列挙型でDELETE、UPDATEを定義
- レスポンスはBaseModelで受け取り、successフラグで成否判定

#### Step 2: エントリーポイントを理解する

処理の起点となるダイアログファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | create_request.dart | `lib/screens/gdpr/view/widget/create_request.dart` | CreateRequestModalウィジェット、フォーム構成 |

**主要処理フロー**:
1. **11-16行目**: CreateRequestModalのコンストラクタでgdprBlocとcustomerEmailを受け取る
2. **20-22行目**: 状態変数（selectedType、message、_formKey）の初期化
3. **25-37行目**: createGdprRequestメソッドでバリデーション後にイベント発行
4. **67-103行目**: DropdownButtonFormFieldでタイプ選択UI
5. **109-141行目**: TextFormFieldでメッセージ入力UI
6. **152-168行目**: Saveボタンでcreateメソッド呼び出し

#### Step 3: イベント・状態管理を理解する

BLoCパターンによる状態管理の仕組みを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | gdpr_event.dart | `lib/screens/gdpr/bloc/gdpr_event.dart` | CreateGdprRequestの定義 |
| 3-2 | gdpr_state.dart | `lib/screens/gdpr/bloc/gdpr_state.dart` | CreateGdprRequestStatusとCreateGdprRequestStateの定義 |
| 3-3 | gdpr_bloc.dart | `lib/screens/gdpr/bloc/gdpr_bloc.dart` | CreateGdprRequestイベントの処理 |

**主要処理フロー**:
- **gdpr_event.dart 12-23行目**: CreateGdprRequestでtype、messageを保持
- **gdpr_state.dart 18行目**: CreateGdprRequestStatusでsuccess/failを定義
- **gdpr_state.dart 51-70行目**: CreateGdprRequestStateでmessage、error、statusを保持
- **gdpr_bloc.dart 38-52行目**: CreateGdprRequestイベントを処理、repositoryのcreateGdprRequestを呼び出し

#### Step 4: リポジトリ層を理解する

API呼び出しの抽象化層を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | gdpr_repository.dart | `lib/screens/gdpr/bloc/gdpr_repository.dart` | createGdprRequestメソッドの定義と実装 |

**主要処理フロー**:
- **9行目**: createGdprRequestメソッド定義（type、message引数）
- **29-39行目**: GdprRequestRepoでApiClient().createGdprRequestを呼び出し

#### Step 5: 親画面との連携を理解する

ダイアログを呼び出す親画面の処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | gdpr_screen.dart | `lib/screens/gdpr/view/gdpr_screen.dart` | ダイアログ呼び出しと成功時の一覧再取得 |

**主要処理フロー**:
- **141-149行目**: Create Requestボタンでダイアログ表示
- **89-101行目**: CreateGdprRequestState成功時にSnackBar表示、一覧再取得

### プログラム呼び出し階層図

```
GdprScreen (gdpr_screen.dart)
    │
    ├─ ElevatedButton("Create Request")
    │      └─ showDialog(CreateRequestModal)
    │
    └─ BlocConsumer listener
           │
           └─ CreateGdprRequestState.success
                  └─ FetchGdprRequestsList再発行

CreateRequestModal (create_request.dart)
    │
    └─ createGdprRequest()
           │
           ├─ FormState.validate()
           └─ GdprBloc.add(CreateGdprRequest)
                  │
                  GdprBloc (gdpr_bloc.dart)
                      │
                      └─ mapEventToState
                             │
                             GdprRepository.createGdprRequest
                                 │
                                 ApiClient.createGdprRequest
                                     │
                                     GraphQL Mutation: createGdprRequest
```

### データフロー図

```
[入力]                        [処理]                              [出力]

タイプ選択 ────────┐
                 │
メッセージ入力 ────┼────▶ FormState.validate() ────▶ CreateGdprRequest
                 │                                        │
                 │                                        ▼
                 │                               GdprBloc
                 │                                        │
                 │                                        ▼
                 │                               GdprRepository.createGdprRequest
                 │                                        │
                 │                                        ▼
                 │                               ApiClient.createGdprRequest
                 │                                        │
                 │                                        ▼
                 │                               GraphQL API
                 │                                        │
                 │                                        ▼
                 │                               BaseModel ───▶ CreateGdprRequestState
                 │                                                     │
                 │                                                     ▼
                 └─────────────────────────────────▶ ダイアログ閉じる & 一覧更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| create_request.dart | `lib/screens/gdpr/view/widget/create_request.dart` | ソース | リクエスト作成ダイアログ |
| gdpr_screen.dart | `lib/screens/gdpr/view/gdpr_screen.dart` | ソース | 親画面（ダイアログ呼び出し元） |
| gdpr_bloc.dart | `lib/screens/gdpr/bloc/gdpr_bloc.dart` | ソース | 状態管理BLoC |
| gdpr_event.dart | `lib/screens/gdpr/bloc/gdpr_event.dart` | ソース | イベント定義 |
| gdpr_state.dart | `lib/screens/gdpr/bloc/gdpr_state.dart` | ソース | 状態定義 |
| gdpr_repository.dart | `lib/screens/gdpr/bloc/gdpr_repository.dart` | ソース | API呼び出しリポジトリ |
| api_client.dart | `lib/services/api_client.dart` | ソース | GraphQL APIクライアント |
| mutation_query.dart | `lib/services/mutation_query.dart` | ソース | GraphQLクエリ定義 |
