# 機能設計書 41-注文一覧表示

## 概要

本ドキュメントは、ECモバイルアプリケーションにおける注文一覧表示機能の設計仕様を定義する。ユーザーの過去の注文履歴を一覧形式で表示し、注文状況の確認および詳細画面への遷移を可能にする機能である。

### 本機能の処理概要

この機能は、ログイン済みユーザーが自身の注文履歴を確認し、各注文のステータス・金額・日付などの基本情報を把握できるようにする。

**業務上の目的・背景**：ECサイトにおいて、ユーザーが自身の購買履歴を確認することは顧客体験の重要な要素である。注文状況の透明性を確保することで、配送状況の確認、返品・交換の判断、再購入の意思決定をサポートする。また、カスタマーサポートへの問い合わせを削減する効果も期待できる。

**機能の利用シーン**：ユーザーがダッシュボードまたはナビゲーションメニューから「注文履歴」にアクセスした際に利用される。商品の配送状況を確認したい場合、過去の購入履歴を参照したい場合、再注文を行いたい場合などに頻繁に使用される。

**主要な処理内容**：
1. GraphQL APIを通じて注文一覧データを取得
2. ページネーションによる大量データの段階的読み込み
3. 注文ID・日付・ステータス・金額によるフィルタリング機能
4. 注文ステータスに応じた視覚的な色分け表示
5. 各注文から詳細画面への遷移

**関連システム・外部連携**：バックエンドのBagisto GraphQL APIと連携し、注文データを取得する。認証済みユーザーのセッショントークンを使用してAPIリクエストを行う。

**権限による制御**：ログイン済みユーザーのみがアクセス可能。未ログイン状態でアクセスした場合は、ログイン画面へリダイレクトされる。各ユーザーは自身の注文のみを閲覧できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | 注文履歴一覧画面 | 主画面 | ユーザーの過去注文一覧表示（ステータス、日付、合計金額） |
| 3 | ダッシュボード画面 | 参照画面 | ダッシュボードから最新5件の注文を表示、注文一覧への遷移 |
| 18 | 注文詳細画面 | 遷移先画面 | 注文タップ時に詳細画面へ遷移 |

## 機能種別

データ取得 / 一覧表示 / フィルタリング / ページネーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | String | No | 注文ID（フィルタ用） | 空文字許可 |
| startDate | String | No | 検索開始日（YYYY-MM-DD形式） | 日付形式チェック |
| endDate | String | No | 検索終了日（YYYY-MM-DD形式） | 日付形式チェック |
| status | String | No | 注文ステータス | all/pending/closed/canceled/processing/completed/pending_payment/fraud |
| total | double | No | 合計金額（フィルタ用） | 0以上の数値 |
| page | int | Yes | ページ番号 | 1以上の整数 |
| isFilterApply | bool | No | フィルタ適用フラグ | true/false |

### 入力データソース

- 画面入力：フィルターモーダルからの検索条件入力
- ユーザーセッション：認証トークン（SharedPreferencesから取得）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | int | 注文の内部ID |
| incrementId | String | 注文番号（表示用） |
| status | String | 注文ステータス |
| totalQtyOrdered | int | 注文商品の総数量 |
| createdAt | String | 注文日時 |
| formattedPrice.grandTotal | String | フォーマット済み合計金額 |
| paginatorInfo.currentPage | int | 現在のページ番号 |
| paginatorInfo.lastPage | int | 最終ページ番号 |

### 出力先

- 画面表示：OrdersListTileウィジェットによるカード形式の一覧表示
- ダッシュボード表示：最新5件の注文概要表示

## 処理フロー

### 処理シーケンス

```
1. 画面初期化（initState）
   └─ OrderListBlocを取得し、FetchOrderListEventを発行
2. API呼び出し
   └─ OrderListRepositoryImpがApiClient経由でGraphQL APIを呼び出し
3. レスポンス処理
   └─ OrdersListModelにデシリアライズ
4. 状態更新
   └─ FetchOrderListStateをemitしてUI更新
5. 一覧表示
   └─ OrdersListTileで各注文をカード形式で表示
6. スクロール監視
   └─ maxScrollExtent到達時に次ページを取得（ページネーション）
7. フィルター適用（オプション）
   └─ モーダルから条件入力、再度FetchOrderListEventを発行
```

### フローチャート

```mermaid
flowchart TD
    A[画面表示開始] --> B[OrderListBloc初期化]
    B --> C[FetchOrderListEvent発行]
    C --> D[API呼び出し]
    D --> E{レスポンス成功?}
    E -->|Yes| F[OrdersListModel生成]
    E -->|No| G[エラー表示]
    F --> H{データあり?}
    H -->|Yes| I[注文一覧表示]
    H -->|No| J[空データビュー表示]
    I --> K{スクロール最下部?}
    K -->|Yes| L{次ページあり?}
    K -->|No| M[待機]
    L -->|Yes| N[page++]
    L -->|No| M
    N --> C
    I --> O{フィルターボタン押下?}
    O -->|Yes| P[フィルターモーダル表示]
    O -->|No| M
    P --> Q[条件入力]
    Q --> R[page=1でリセット]
    R --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | 認証必須 | ログイン済みユーザーのみ注文一覧を閲覧可能 | 常時 |
| BR-41-02 | 自己注文のみ | ユーザーは自身の注文のみ閲覧可能 | 常時 |
| BR-41-03 | ダッシュボード制限 | ダッシュボードからの表示は最新5件まで | isFromDashboard=true |
| BR-41-04 | ステータス色分け | 注文ステータスに応じて背景色を変更 | 常時 |
| BR-41-05 | 日付フィルタ形式 | 開始日は00:00:01、終了日は23:59:59を付加 | フィルタ適用時 |

### 計算ロジック

ページネーション判定：
```dart
if (scrollController.offset == scrollController.position.maxScrollExtent &&
    currentPage < lastPage) {
  // 次ページを取得
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 注文一覧取得 | orders | SELECT | ユーザーIDに紐づく注文を取得 |
| 注文一覧取得 | order_items | SELECT | 注文に含まれる商品情報を取得 |

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

#### orders（GraphQL API経由）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, increment_id, status, total_qty_ordered, created_at | customer_id = ログインユーザーID | ページネーション対応 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API通信エラー | ネットワーク接続不可 | エラーメッセージ表示、再試行ボタン |
| - | 認証エラー | セッション切れ | ログイン画面へリダイレクト |
| - | データなし | 注文履歴が空 | EmptyDataView表示 |

### リトライ仕様

- RefreshIndicatorによるプルトゥリフレッシュ機能を提供
- 再読み込み時はpage=1からデータを再取得

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

本機能はデータ取得のみのため、トランザクション管理は不要。

## パフォーマンス要件

- 初回ロード：2秒以内
- ページネーション1ページあたりのデータ数：デフォルト設定（API側で制御）
- スクロール時の追加読み込み：1秒以内

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

- 認証トークンを使用したAPI呼び出し
- ユーザーIDによるデータアクセス制御（サーバーサイド）
- センシティブ情報（決済情報等）は一覧には表示しない

## 備考

- ステータスの色分けはOrderStatusBGColorHelper mixinで管理
- ダッシュボードと注文一覧画面で同じOrdersListウィジェットを共用
- フィルターはローカル状態で管理し、クリアボタンで初期化可能

---

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

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

### 推奨読解順序

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

まず、APIレスポンスのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | orders_list_data_model.dart | `lib/data_model/order_model/orders_list_data_model.dart` | OrdersListModel、Data、PaginatorInfoの構造を理解 |

**読解のコツ**: `@JsonSerializable()`アノテーションはJSON自動変換用。`part`ディレクティブで生成ファイル（.g.dart）を参照。

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

処理の起点となるウィジェットを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | order_list.dart | `lib/screens/orders/screen/order_list.dart` | StatefulWidgetの構造、initStateでのBloc初期化 |

**主要処理フロー**:
1. **36-42行目**: initStateでOrderListBlocを取得し、FetchOrderListEventを発行
2. **40-42行目**: ScrollControllerにリスナーを追加してページネーション監視
3. **43-52行目**: ステータスフィルターの選択肢を初期化
4. **81-88行目**: BlocConsumerでstateの変化を監視しUIを更新
5. **112-126行目**: paginationFunction()でスクロール最下部到達時の処理

#### Step 3: BLoCパターンを理解する

状態管理のBLoCパターンを読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | order_list_event.dart | `lib/screens/orders/bloc/order_list_event.dart` | FetchOrderListEventのパラメータ構造 |
| 3-2 | order_list_state.dart | `lib/screens/orders/bloc/order_list_state.dart` | OrderStatus enum、FetchOrderListStateの成功/失敗パターン |
| 3-3 | order_list_bloc.dart | `lib/screens/orders/bloc/order_list_bloc.dart` | mapEventToStateでイベントを処理しstateをemit |

**主要処理フロー**:
- **order_list_bloc.dart 24-33行目**: FetchOrderListEventを受け取り、repositoryを呼び出してFetchOrderListStateをemit

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

API呼び出しの実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | order_list_repo.dart | `lib/screens/orders/bloc/order_list_repo.dart` | OrderListRepositoryインターフェースと実装 |

**主要処理フロー**:
- **21-33行目**: getOrderListメソッドでApiClientを呼び出し、OrdersListModelを返却

#### Step 5: UI表示を理解する

注文カードの表示ロジックを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | order_list_tile.dart | `lib/screens/orders/widget/order_list_tile.dart` | 注文カードのレイアウト、ステータス色分け、詳細画面遷移 |

**主要処理フロー**:
- **166-176行目**: getOrderBgColor()でステータスに応じた背景色を設定
- **192-199行目**: Navigator.pushNamedで注文詳細画面へ遷移

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

```
OrdersList (Widget)
    │
    ├─ OrderListBloc
    │      │
    │      └─ OrderListRepositoryImp
    │             │
    │             └─ ApiClient.getOrderList()
    │
    ├─ FetchOrderListState
    │      │
    │      └─ OrdersListModel
    │
    └─ OrdersListTile (Widget)
           │
           └─ Navigator.pushNamed → OrderDetailScreen
```

### データフロー図

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

ユーザー操作 ───▶ FetchOrderListEvent ───▶ OrderListBloc
   │                                              │
   │                                              ▼
   │                                    OrderListRepository
   │                                              │
   │                                              ▼
   │                                      ApiClient (GraphQL)
   │                                              │
   │                                              ▼
   │                                      OrdersListModel
   │                                              │
   │                                              ▼
   └─────────────────────────────── FetchOrderListState ───▶ UI更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| order_list.dart | `lib/screens/orders/screen/order_list.dart` | ソース | メイン画面ウィジェット |
| order_list_bloc.dart | `lib/screens/orders/bloc/order_list_bloc.dart` | ソース | 状態管理BLoC |
| order_list_event.dart | `lib/screens/orders/bloc/order_list_event.dart` | ソース | イベント定義 |
| order_list_state.dart | `lib/screens/orders/bloc/order_list_state.dart` | ソース | 状態定義 |
| order_list_repo.dart | `lib/screens/orders/bloc/order_list_repo.dart` | ソース | リポジトリ層 |
| order_list_tile.dart | `lib/screens/orders/widget/order_list_tile.dart` | ソース | 注文カードUI |
| order_loader_view.dart | `lib/screens/orders/widget/order_loader_view.dart` | ソース | ローディング表示 |
| orders_list_data_model.dart | `lib/data_model/order_model/orders_list_data_model.dart` | ソース | データモデル |
| index.dart | `lib/screens/orders/utils/index.dart` | ソース | エクスポート定義 |
