# 帳票設計書 3-Refund（返金伝票）

## 概要

本ドキュメントは、ECモバイルアプリにおける返金伝票（Refund）帳票の設計仕様を定義するものである。注文に対して発行された返金情報を画面上に表示する機能について記述する。

### 本帳票の処理概要

本帳票は、顧客が注文詳細画面から返金情報を確認するための機能を提供する。注文に紐づく返金一覧を取得し、各返金の明細項目、調整額、合計返金額を整形して画面表示する。

**業務上の目的・背景**：ECサイトにおいて、返品・返金処理の透明性を確保することは顧客信頼の維持に重要である。本帳票は、返金ID、返金対象商品の明細、調整返金額（クレジットや補償）、調整手数料（返品手数料や再梱包費用）、最終返金額を提供し、顧客が返金処理の内訳を正確に理解できるようにする。これにより、返金に関する問い合わせ対応の効率化と顧客満足度の向上に寄与する。

**帳票の利用シーン**：顧客が注文履歴から返金処理が行われた注文を選択し、その返金内容を確認する場面で利用される。商品返品後の返金確認、部分返金の内訳確認、返金処理の進捗確認などに使用される。

**主要な出力内容**：
1. 返金ID（Refund ID）
2. 返金明細（SKU、商品名、単価、数量、小計、税額、合計）
3. 価格詳細（小計、配送料、調整返金額、調整手数料、総合計）
4. 配送・支払い情報

**帳票の出力タイミング**：注文詳細画面において、返金情報セクションを選択またはタップした際に、GraphQL APIを通じてデータを取得し画面に表示する。

**帳票の利用者**：返金処理の内容を確認したい一般顧客（エンドユーザー）。

## 帳票種別

返金伝票（Refund / Credit Memo）- 画面表示形式

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 返金詳細画面 | OrderRefundScreen（Flutter Widget） | 注文詳細画面から返金セクションを選択 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | 画面表示（Flutter Widget） |
| 用紙サイズ | N/A（モバイルアプリ画面） |
| 向き | 縦（スクロール可能） |
| ファイル名 | N/A |
| 出力方法 | 画面レンダリング |
| 文字コード | UTF-8 |

### PDF固有設定

N/A（本帳票は画面表示のみ）

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

返金画面は、返金明細部と価格詳細部、配送・支払い情報部で構成される。スクロール可能なシングルカラムレイアウトを採用し、返金が複数存在する場合は縦に並列表示される。

```
┌─────────────────────────────────────┐
│           AppBar（返金）            │
├─────────────────────────────────────┤
│     返金 #ID                        │
│     ─────────────────               │
│     商品明細リスト                   │
│     - SKU / 商品名 / 単価 / 数量等    │
├─────────────────────────────────────┤
│     価格詳細                        │
│     - 小計 / 配送料 / 調整返金額     │
│     - 調整手数料 / 合計             │
├─────────────────────────────────────┤
│     配送・支払い情報                 │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 返金ID | 返金の識別番号 | ViewRefunds.id | "Refunds #" + ID |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | SKU | 商品SKUコード | RefundItems.sku | 文字列 | 自動 |
| 2 | 商品名 | 商品の名称 | RefundItems.name | 文字列 | 自動 |
| 3 | 単価 | 商品1点あたりの返金価格 | RefundItems.formattedPrice.price | 通貨形式 | 自動 |
| 4 | 数量 | 返金数量 | RefundItems.qty | 整数 | 自動 |
| 5 | 小計 | 商品の基本返金額 | RefundItems.formattedPrice.baseTotal | 通貨形式 | 自動 |
| 6 | 税額 | 商品にかかる返金税額 | RefundItems.formattedPrice.taxAmount | 通貨形式 | 自動 |
| 7 | 合計 | 商品の最終返金額 | RefundItems.formattedPrice.total | 通貨形式 | 自動 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 小計 | 全商品の返金小計 | ViewRefunds.formattedPrice.subTotal | 通貨形式 |
| 2 | 配送料 | 返金に含まれる配送料 | ViewRefunds.formattedPrice.shippingAmount | 通貨形式 |
| 3 | 調整返金額 | 追加のクレジットや補償額 | ViewRefunds.formattedPrice.adjustmentRefund | 通貨形式 |
| 4 | 調整手数料 | 返品手数料などの控除額 | ViewRefunds.formattedPrice.adjustmentFee | 通貨形式 |
| 5 | 総合計 | 最終返金金額 | ViewRefunds.formattedPrice.grandTotal | 通貨形式 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 注文ID | 対象注文の識別子 | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 返金ID | APIレスポンス順（デフォルト） |

### 改ページ条件

N/A（画面スクロールにより全件表示）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| refunds | 返金基本情報 | order_id = 指定注文ID |
| refund_items | 返金明細 | refund_id = refunds.id |
| orders | 注文情報 | id = 指定注文ID |

### テーブル別参照項目詳細

#### refunds

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | 返金ID | order_id一致 | - |
| sub_total | 小計 | - | フォーマット済み価格で取得 |
| shipping_amount | 配送料 | - | フォーマット済み価格で取得 |
| adjustment_refund | 調整返金額 | - | フォーマット済み価格で取得 |
| adjustment_fee | 調整手数料 | - | フォーマット済み価格で取得 |
| grand_total | 総合計 | - | フォーマット済み価格で取得 |

#### refund_items

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | 明細ID | refund_id一致 | - |
| sku | SKU | - | - |
| name | 商品名 | - | - |
| qty | 数量 | - | - |
| price | 単価 | - | フォーマット済み |
| base_total | 小計 | - | フォーマット済み |
| tax_amount | 税額 | - | フォーマット済み |
| total | 合計 | - | フォーマット済み |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 商品返金小計 | 単価 × 数量 | サーバー側で計算済み | バックエンドで計算 |
| 税額 | 課税対象額 × 税率 | サーバー側で計算済み | バックエンドで計算 |
| 総返金額 | 小計 + 配送料 + 調整返金額 - 調整手数料 | サーバー側で計算済み | バックエンドで計算 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[注文詳細画面で返金セクションを選択] --> B[OrderRefundScreen初期化]
    B --> C[OrderRefundBloc初期化]
    C --> D[OrderRefundFetchDataEventを発行]
    D --> E[OrderRefundRepositoryでAPI呼び出し]
    E --> F[GraphQL viewRefundsクエリ実行]
    F --> G[OrderRefundModelにパース]
    G --> H{データ取得成功?}
    H -->|Yes| I[OrderRefundListDataState.success発行]
    H -->|No| J[OrderRefundListDataState.fail発行]
    I --> K[refundDetails()で画面レンダリング]
    J --> L[エラー状態表示]
    K --> M[返金明細・価格詳細・配送支払い情報を表示]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | 返金が存在しない | EmptyDataView表示 | 空データビューを表示 |
| 通信エラー | ネットワーク障害 | エラーメッセージ | 再試行またはオフライン対応 |
| APIエラー | サーバー側エラー | エラーメッセージ | エラーログ出力、再試行促進 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1注文あたり0〜数件の返金 |
| 目標出力時間 | 2秒以内 |
| 同時出力数上限 | N/A（ユーザー単位で逐次処理） |

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

- 認証済みユーザーのみがアクセス可能（ログインセッション必須）
- 自身の注文に紐づく返金のみ参照可能（他ユーザーの返金は参照不可）
- GraphQL APIはHTTPS通信で保護
- 返金金額は改ざん防止のためサーバー側で計算・整形済みデータを使用
- 返金情報は財務データとして適切な監査ログの対象とすべき

## 備考

- 本帳票はFlutterアプリ内での画面表示機能であり、PDFや印刷出力には対応していない
- 価格のフォーマット（通貨記号、小数点桁数等）はサーバー側のformattedPriceで処理済み
- ShippingAndPaymentInfoウィジェットで配送・支払い情報を共通表示
- adjustmentRefund（調整返金額）は顧客への追加クレジットを表す
- adjustmentFee（調整手数料）は返品手数料などの控除額を表す

---

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

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

### 推奨読解順序

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

まず、返金データのモデル構造を把握することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | order_refund_model.dart | `lib/data_model/order_model/order_refund_model.dart` | OrderRefundModel、ViewRefunds、RefundItemsの構造を理解。各フィールドがAPIレスポンスのどの部分に対応するか確認 |
| 1-2 | cart_data_model.dart | `lib/screens/cart_screen/cart_model/cart_data_model.dart` | FormattedPriceクラス（157-188行目）を確認。adjustmentRefundとadjustmentFeeが返金固有のフィールド |

**読解のコツ**: `@JsonSerializable()`アノテーションでJSONとの対応付けを確認。adjustmentRefund、adjustmentFeeは返金帳票特有の項目。

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

処理の起点となる画面ウィジェットを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | order_refund_details.dart | `lib/screens/order_refund/order_refund_details.dart` | OrderRefundScreenウィジェットの構造と状態管理を理解 |

**主要処理フロー**:
1. **17-21行目**: initState()でOrderRefundBlocを取得し、OrderRefundFetchDataEventを発行
2. **38-53行目**: BlocConsumerでStateを監視し、成功時にrefundDetails()を呼び出し
3. **56-122行目**: refundDetails()で返金データをUIにレンダリング
4. **140-197行目**: getRefunds()で各返金の明細をListView形式で表示

#### Step 3: BLoCパターンによる状態管理を理解する

Flutterの状態管理としてBLoCパターンを採用している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | order_refund_bloc.dart | `lib/screens/order_refund/bloc/order_refund_bloc.dart` | イベントを受けてリポジトリを呼び出し、結果をStateとして発行する流れ |
| 3-2 | order_refund_state.dart | `lib/screens/order_refund/bloc/order_refund_state.dart` | OrderRefundInitialState、OrderRefundListDataStateの定義 |

**主要処理フロー**:
- **22-35行目（bloc）**: mapEventToStateでOrderRefundFetchDataEventを処理し、成功/失敗に応じてStateを発行

#### Step 4: リポジトリ層とAPI通信を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | order_refund_repository.dart | `lib/screens/order_refund/bloc/order_refund_repository.dart` | ApiClient().getRefundList()の呼び出し |
| 4-2 | api_client.dart | `lib/services/api_client.dart` | 1402-1414行目：getRefundListメソッドでGraphQLクエリを実行 |
| 4-3 | mutation_query.dart | `lib/services/mutation_query.dart` | 1929-1980行目：viewRefundsのGraphQLクエリ定義 |

**主要処理フロー**:
- **1402行目（api_client）**: getRefundList()でmutation.getRefundList()を実行
- **1929行目（mutation_query）**: GraphQLクエリでorderId指定して返金データを取得、adjustmentRefund、adjustmentFeeを含む

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

```
OrderRefundScreen (Widget)
    │
    ├─ initState()
    │      └─ OrderRefundBloc.add(OrderRefundFetchDataEvent)
    │
    ├─ BlocConsumer<OrderRefundBloc, OrderRefundBaseState>
    │      │
    │      └─ OrderRefundBloc.mapEventToState()
    │             └─ OrderRefundRepositoryImp.getRefundList()
    │                    └─ ApiClient.getRefundList()
    │                           └─ mutation.getRefundList() [GraphQL]
    │
    └─ refundDetails()
           ├─ getRefunds() [明細リスト表示]
           ├─ getOrdersRow() [価格行表示]
           │      ├─ 小計
           │      ├─ 配送料
           │      ├─ 調整返金額
           │      ├─ 調整手数料
           │      └─ 総合計
           └─ ShippingAndPaymentInfo [共通ウィジェット]
```

### データフロー図

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

orderId ─────────▶ OrderRefundFetchDataEvent
                          │
                          ▼
                  OrderRefundBloc
                          │
                          ▼
                  OrderRefundRepositoryImp
                          │
                          ▼
                  ApiClient.getRefundList()
                          │
                          ▼
                  GraphQL viewRefunds Query ────▶ Backend Server
                          │
                          ▼
                  OrderRefundModel (JSON Parse)
                          │
                          ▼
                  OrderRefundListDataState.success
                          │
                          ▼
                  OrderRefundScreen.refundDetails() ────▶ UI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| order_refund_details.dart | `lib/screens/order_refund/order_refund_details.dart` | ソース | 返金画面のUI実装 |
| order_refund_bloc.dart | `lib/screens/order_refund/bloc/order_refund_bloc.dart` | ソース | 状態管理BLoC |
| order_refund_state.dart | `lib/screens/order_refund/bloc/order_refund_state.dart` | ソース | 状態定義 |
| order_refund_event.dart | `lib/screens/order_refund/bloc/order_refund_event.dart` | ソース | イベント定義 |
| order_refund_repository.dart | `lib/screens/order_refund/bloc/order_refund_repository.dart` | ソース | リポジトリ層 |
| order_refund_model.dart | `lib/data_model/order_model/order_refund_model.dart` | ソース | データモデル定義 |
| cart_data_model.dart | `lib/screens/cart_screen/cart_model/cart_data_model.dart` | ソース | FormattedPriceモデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント |
| mutation_query.dart | `lib/services/mutation_query.dart` | ソース | GraphQLクエリ定義 |
| index.dart | `lib/screens/order_refund/utils/index.dart` | ソース | エクスポート定義 |
