# 機能設計書 66-GDPRデータダウンロード

## 概要

本ドキュメントは、GDPRデータダウンロード機能の設計仕様を定義する。GDPR（EU一般データ保護規則）に基づくユーザーの「アクセス権」を実現し、ユーザーが自身の個人データをPDF形式またはHTML形式でダウンロード/閲覧できる機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：GDPRはEU域内のユーザーに対して、企業が保有する自身の個人データへのアクセス権を保証している。本機能はユーザーが自身のデータを取得し、どのような情報が保存されているかを確認できるようにする。これにより、ユーザーはプライバシーに関する透明性を確保できる。

**機能の利用シーン**：
- ユーザーが自身のデータがどのように保存されているか確認したい場合
- プライバシー設定の見直しやアカウント削除前のデータバックアップ
- 法的要求やコンプライアンス目的でのデータ確認

**主要な処理内容**：
1. PDFエクスポート: GraphQL APIからBase64エンコードされたPDFデータを取得し、ファイルとして保存
2. HTMLエクスポート: 外部ブラウザでGDPRデータ表示ページを開く

**関連システム・外部連携**：
- Bagisto GraphQL API（downloadGdprData mutation）
- url_launcher（HTMLエクスポート用外部ブラウザ起動）
- DownloadFile（PDFファイル保存）

**権限による制御**：ログイン済みユーザーのみ実行可能。自身のデータのみダウンロード可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | GDPRリクエスト画面 | 主画面 | GDPRに基づくユーザーデータのダウンロード処理 |

## 機能種別

データ取得・エクスポート処理（READ操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| exportType | String | Yes（暗黙） | エクスポート形式（"PDF" または "HTML"） | ボタンにより決定 |

### 入力データソース

- GDPRリクエスト画面のPDF/HTMLエクスポートボタン

## 出力仕様

### 出力データ（PDF形式）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | bool | 取得成功/失敗 |
| string | String | Base64エンコードされたPDFデータ |
| download.fileName | String | ダウンロードファイル名 |
| download.extension | String | ファイル拡張子 |

### 出力データ（HTML形式）

外部ブラウザで `/customer/account/gdpr/html-view` ページを開く

### 出力先

- PDF: デバイスのストレージにファイル保存
- HTML: 外部ブラウザアプリ

## 処理フロー

### 処理シーケンス（PDF）

```
1. PDFボタンタップ
   └─ GdprPdfRequestイベントをBlocに発行
2. GdprBlocでイベント処理
   └─ GdprRepositoryのdownloadGdprDataメソッドを呼び出し
3. APIクライアント呼び出し
   └─ GraphQL mutation実行（downloadGdprData）
4. レスポンス処理
   └─ GdprPdfModelにデシリアライズ
5. 状態更新
   └─ GdprPdfRequestState.success発行
6. ファイル保存
   └─ DownloadFile().saveBase64Stringでデバイスに保存
```

### 処理シーケンス（HTML）

```
1. HTMLボタンタップ
   └─ url_launcherでURLを開く
2. 外部ブラウザ起動
   └─ /customer/account/gdpr/html-view ページを表示
```

### フローチャート

```mermaid
flowchart TD
    A[エクスポートボタンタップ] --> B{PDF or HTML?}
    B -->|PDF| C[GdprPdfRequest発行]
    B -->|HTML| D[launchUrl実行]
    D --> E[外部ブラウザで表示]
    C --> F[GdprLoadingState]
    F --> G[GdprBloc処理]
    G --> H[Repository.downloadGdprData]
    H --> I[ApiClient.downloadGdprData]
    I --> J{API成功?}
    J -->|Yes| K[GdprPdfRequestState.success]
    J -->|No| L[GdprPdfRequestState.fail]
    K --> M[Base64デコード]
    M --> N[DownloadFile.saveBase64String]
    L --> O[エラーSnackBar表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | 認証必須 | ログイン済みユーザーのみ実行可能 | 常時 |
| BR-66-02 | 自己データのみ | ユーザーは自身のデータのみダウンロード可能 | 常時 |
| BR-66-03 | PDF形式 | PDFはBase64エンコードで返却、クライアントでデコード | PDFエクスポート時 |
| BR-66-04 | HTML外部表示 | HTMLは外部ブラウザで表示（LaunchMode.externalApplication） | HTMLエクスポート時 |

### 計算ロジック

該当なし

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

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

本機能はGraphQL APIを通じてバックエンドのデータを読み取るのみで、データベースの更新は行わない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| データ取得 | customers, orders, addresses等（バックエンド） | SELECT | ユーザーに関連する全データを集約して返却 |

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

バックエンドで複数テーブルからユーザーデータを集約してPDF/HTML形式で出力。クライアント側でのDB操作はなし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API通信エラー | ネットワーク接続失敗 | GdprPdfRequestState.fail発行、SnackBar表示 |
| - | ファイル保存エラー | ストレージ権限不足 | エラーメッセージ表示 |
| - | URLオープンエラー | ブラウザ起動失敗 | 例外処理でエラー通知 |

### リトライ仕様

自動リトライは実装されていない。ユーザーは再度ボタンを押して試行する必要がある。

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

読み取り専用のため、トランザクション制御は不要。

## パフォーマンス要件

- PDFデータ取得: ユーザーデータ量に依存、通常5-10秒以内
- HTMLページ表示: 外部ブラウザの起動時間に依存

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

- 認証必須（ログインユーザーのみ）
- 自身のデータのみアクセス可能（バックエンドで検証）
- HTTPSを通じた安全なデータ転送
- GDPRコンプライアンス対応機能

## 備考

- PDFにはユーザーの個人情報、注文履歴、住所等が含まれる
- Base64エンコードによりバイナリデータをJSONで転送

---

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

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

### 推奨読解順序

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

GDPRデータダウンロードのレスポンスモデルを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | gdpr_pdf_model.dart | `lib/data_model/gdpr_models/gdpr_pdf_model.dart` | GdprPdfModel、DownloadPdfクラスの構造 |

**読解のコツ**:
- **6-21行目**: GdprPdfModelでsuccess、string（Base64）、downloadを保持
- **23-37行目**: DownloadPdfでfileName、extensionを保持
- stringフィールドにBase64エンコードされたPDFデータが格納される

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

処理の起点となる画面ファイルのボタン処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | gdpr_screen.dart | `lib/screens/gdpr/view/gdpr_screen.dart` | PDF/HTMLエクスポートボタンと_exportButtonメソッド |

**主要処理フロー**:
1. **139行目**: PDFボタン（`_exportButton('PDF')`）
2. **140行目**: HTMLボタン（`_exportButton('HTML')`）
3. **307-324行目**: `_exportButton`メソッドでボタンUI定義
4. **310-315行目**: PDFの場合は`GdprPdfRequest`発行、HTMLの場合は`launchUrl`実行

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

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

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

**主要処理フロー**:
- **gdpr_event.dart 43-48行目**: GdprPdfRequestイベント（パラメータなし）
- **gdpr_state.dart 112-130行目**: GdprPdfRequestStateでpdfModel、error、statusを保持
- **gdpr_bloc.dart 80-90行目**: GdprPdfRequestイベントを処理、repositoryのdownloadGdprDataを呼び出し

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

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

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

**主要処理フロー**:
- **12行目**: downloadGdprDataメソッド定義
- **65-76行目**: GdprRequestRepoでApiClient().downloadGdprDataを呼び出し

#### Step 5: ファイル保存処理を理解する

PDFファイルの保存処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | file_download.dart | `lib/screens/product_screen/view/file_download.dart` | DownloadFileクラスのsaveBase64Stringメソッド |

**主要処理フロー**:
- BlocConsumer listenerでGdprPdfRequestState.success時にDownloadFile().saveBase64String呼び出し
- E-01の119-121行目参照

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

```
GdprScreen (gdpr_screen.dart)
    │
    ├─ _exportButton('PDF')
    │      └─ GdprBloc.add(GdprPdfRequest)
    │              │
    │              GdprBloc (gdpr_bloc.dart)
    │                  │
    │                  └─ mapEventToState
    │                         │
    │                         GdprRepository.downloadGdprData
    │                             │
    │                             ApiClient.downloadGdprData
    │                                 │
    │                                 GraphQL Mutation: downloadGdprData
    │                                         │
    │                                         ▼
    │                                 GdprPdfModel
    │                                         │
    │                                         ▼
    │                         GdprPdfRequestState.success
    │                                 │
    │                                 ▼
    │                         DownloadFile.saveBase64String
    │
    └─ _exportButton('HTML')
           └─ launchUrl
                  └─ 外部ブラウザ起動
```

### データフロー図

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

PDFボタンタップ ───────▶ GdprPdfRequest発行 ───────▶ GdprBloc
                                                        │
                                                        ▼
                                               GdprRepository.downloadGdprData
                                                        │
                                                        ▼
                                               ApiClient.downloadGdprData
                                                        │
                                                        ▼
                                               GraphQL API
                                                        │
                                                        ▼
                                               GdprPdfModel（Base64 PDF）
                                                        │
                                                        ▼
                                               GdprPdfRequestState.success
                                                        │
                                                        ▼
                                               DownloadFile.saveBase64String
                                                        │
                                                        ▼
                                               デバイスストレージに保存

HTMLボタンタップ ───────▶ launchUrl ───────▶ 外部ブラウザ ───▶ GDPR HTML View表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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呼び出しリポジトリ |
| gdpr_pdf_model.dart | `lib/data_model/gdpr_models/gdpr_pdf_model.dart` | ソース | PDFレスポンスデータモデル |
| file_download.dart | `lib/screens/product_screen/view/file_download.dart` | ソース | ファイル保存ユーティリティ |
| api_client.dart | `lib/services/api_client.dart` | ソース | GraphQL APIクライアント |
| mutation_query.dart | `lib/services/mutation_query.dart` | ソース | GraphQLクエリ定義 |
