# 機能設計書 22-カートから削除

## 概要

本ドキュメントは、ECモバイルアプリにおけるカート内の個別商品を削除する機能について設計仕様を定義する。

### 本機能の処理概要

本機能は、ショッピングカートに追加された商品を個別に削除し、カート情報を更新する機能である。

**業務上の目的・背景**：ECサイトにおいて、ユーザーが購入予定から外したい商品をカートから簡単に削除できることは、スムーズな購買体験に不可欠である。商品の再検討や予算調整の際に、不要な商品を即座に削除できる機能を提供することで、ユーザーの意思決定を支援する。

**機能の利用シーン**：ユーザーがカート画面を閲覧中に、特定の商品を購入対象から外したい場合に利用される。誤って追加した商品や、他の商品と比較検討した結果不要になった商品を削除する際に活用される。

**主要な処理内容**：
1. カート画面のアイテムリストにて「削除」ボタンを押下
2. 削除確認ダイアログを表示（誤操作防止）
3. ユーザーが「Yes」を選択すると、RemoveCartItemEventを発行
4. GraphQL API経由でサーバーに削除リクエストを送信
5. 成功時はカートからアイテムを削除し、画面を更新
6. 成功メッセージを表示し、カート総数を更新

**関連システム・外部連携**：Bagisto GraphQL APIとの連携により、`removeFromCart` mutationを使用してカートアイテムを削除する。

**権限による制御**：ゲストユーザー・ログインユーザーいずれも本機能を利用可能。自身のカートに属するアイテムのみ削除可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | カート画面 | 主画面 | カート内の個別商品削除処理 |

## 機能種別

CRUD操作（Delete）/ 確認ダイアログ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cartItemId | int | Yes | 削除対象のカートアイテムID | 正の整数であること |

### 入力データソース

画面操作（カートアイテムの「削除」ボタン押下 → 確認ダイアログで「Yes」選択）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | bool | 処理成功可否 |
| message | String | 処理結果メッセージ |
| cart | CartModel | 更新後のカート情報 |
| cart.itemsQty | int | カート内総商品数 |

### 出力先

- 画面表示（カート画面から該当アイテムを削除）
- グローバルカート数表示の更新（GlobalData.cartCountController）
- SharedPreferences（カート数の永続化）

## 処理フロー

### 処理シーケンス

```
1. ユーザーが「削除」ボタンを押下
   └─ CartListItem._onPressRemove呼び出し
2. 削除確認ダイアログを表示
   └─ AlertDialog表示（Yes/No選択肢）
3. ユーザーが「Yes」を選択
   └─ ダイアログを閉じ、RemoveCartItemEventを発行
4. CartScreenBlocがイベントを受信
   └─ repository.removeFromCartを呼び出し
5. CartScreenRepositoryがApiClientを経由でAPI呼び出し
   └─ GraphQL mutation removeFromCartを実行
6. 成功時: RemoveCartItemState.successを発行
   └─ カートデータを再取得し画面更新
7. 成功メッセージを表示、カート総数を更新
```

### フローチャート

```mermaid
flowchart TD
    A[削除ボタン押下] --> B[確認ダイアログ表示]
    B --> C{ユーザー選択}
    C -->|Yes| D[RemoveCartItemEvent発行]
    C -->|No| E[ダイアログを閉じる]
    D --> F[CartScreenBloc処理]
    F --> G[API呼び出し]
    G --> H{成功?}
    H -->|Yes| I[RemoveCartItemState.success]
    I --> J[ローカルリストから削除]
    J --> K[カートデータ再取得]
    K --> L[画面更新]
    L --> M[成功メッセージ表示]
    H -->|No| N[RemoveCartItemState.fail]
    N --> O[エラーメッセージ表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-022-01 | 削除確認 | 削除前に確認ダイアログを表示し、誤操作を防止 | 削除ボタン押下時 |
| BR-022-02 | 即座反映 | 削除成功時は画面から即座にアイテムを削除 | API成功時 |
| BR-022-03 | カート空状態 | 最後の1商品を削除した場合、空カート画面を表示 | アイテム数0時 |

### 計算ロジック

削除後の合計金額 = 残存商品の小計合計 + 配送料 - 割引額 + 税額

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アイテム削除 | cart_items | DELETE | 指定されたカートアイテムを削除 |
| カート合計再計算 | carts | UPDATE | カートの合計金額等を再計算して更新 |

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

#### cart_items

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | cart_item_id = 指定ID | 対象レコードを削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ネットワークエラー | API通信失敗 | エラーメッセージを表示 |
| - | アイテム未存在 | 既に削除済みのアイテムを削除 | カートを再取得 |
| - | セッション切れ | カートセッションが無効 | エラー表示 |

### リトライ仕様

自動リトライは行わない。ユーザーに再操作を促す。

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

サーバー側でトランザクション管理。cart_itemsテーブルの削除とcartsテーブルの再計算は同一トランザクション内で実行される。

## パフォーマンス要件

- API応答時間: 2秒以内を目標
- UI応答: 確認ダイアログは即座に表示

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

- 認証: ゲストユーザーはセッションベース、ログインユーザーはトークン認証
- アクセス権限: 自身のカートアイテムのみ削除可能

## 備考

削除操作は取り消し不可。削除した商品を再度購入するには、商品詳細画面から再追加が必要。

---

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

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

### 推奨読解順序

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

カートアイテムのデータ構造とAPI応答を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cart_data_model.dart | `lib/screens/cart_screen/cart_model/cart_data_model.dart` | Itemsクラスのid, productフィールドに注目 |
| 1-2 | add_to_cart_model.dart | `lib/screens/cart_screen/cart_model/add_to_cart_model.dart` | 削除API応答モデル（CartModelを内包） |

**読解のコツ**: Items.idがcartItemIdとして使用される点に注目。

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

削除ボタン押下から確認ダイアログまでの流れを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cart_item.dart | `lib/screens/cart_screen/widget/cart_item.dart` | _onPressRemoveメソッドと確認ダイアログ実装 |

**主要処理フロー**:
1. **314-318行目**: 削除ボタンのonPressed処理
2. **363-398行目**: _onPressRemoveメソッドで確認ダイアログを表示
3. **386-391行目**: 「Yes」選択時にRemoveCartItemEventを発行

#### Step 3: BLoC層を理解する

状態管理とビジネスロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cart_screen_event.dart | `lib/screens/cart_screen/bloc/cart_screen_event.dart` | RemoveCartItemEventの定義（39-42行目） |
| 3-2 | cart_screen_state.dart | `lib/screens/cart_screen/bloc/cart_screen_state.dart` | RemoveCartItemStateの定義（47-57行目） |
| 3-3 | cart_screen_bloc.dart | `lib/screens/cart_screen/bloc/cart_screen_bloc.dart` | RemoveCartItemEventの処理（38-47行目） |

**主要処理フロー**:
- **38-47行目**: RemoveCartItemEventを受信し、repository経由でAPI呼び出し

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

実際のAPI呼び出し処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cart_screen_repository.dart | `lib/screens/cart_screen/bloc/cart_screen_repository.dart` | removeFromCartメソッド（57-70行目） |
| 4-2 | api_client.dart | `lib/services/api_client.dart` | removeItemFromCartメソッド（514-526行目） |

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

```
CartListItem (cart_item.dart)
    │
    └─ _onPressRemove() - 確認ダイアログ表示
           │
           └─ AlertDialog → 「Yes」押下
                  │
                  └─ RemoveCartItemEvent発行
                         │
                         └─ CartScreenBloc.mapEventToState
                                │
                                └─ CartScreenRepository.removeFromCart
                                       │
                                       └─ ApiClient.removeItemFromCart
```

### データフロー図

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

削除ボタン ───▶ 確認ダイアログ ───▶ RemoveCartItemEvent
   (UI)           (確認UI)            (イベント発行)
                                            │
                      ┌─────────────────────┘
                      ▼
            CartScreenBloc
                      │
                      ▼
            CartScreenRepository
                      │
                      ▼
                ApiClient
                      │
                      ▼
         GraphQL API (removeFromCart)
                      │
                      ▼
            AddToCartModel ───▶ RemoveCartItemState ───▶ UI更新
              (応答データ)         (状態通知)         (アイテム削除)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cart_screen.dart | `lib/screens/cart_screen/cart_screen.dart` | ソース | カート画面メインWidget |
| cart_item.dart | `lib/screens/cart_screen/widget/cart_item.dart` | ソース | カートアイテムリストWidget、削除UI |
| cart_screen_bloc.dart | `lib/screens/cart_screen/bloc/cart_screen_bloc.dart` | ソース | カート画面BLoC |
| cart_screen_event.dart | `lib/screens/cart_screen/bloc/cart_screen_event.dart` | ソース | BLoCイベント定義 |
| cart_screen_state.dart | `lib/screens/cart_screen/bloc/cart_screen_state.dart` | ソース | BLoC状態定義 |
| cart_screen_repository.dart | `lib/screens/cart_screen/bloc/cart_screen_repository.dart` | ソース | カート画面リポジトリ |
| cart_data_model.dart | `lib/screens/cart_screen/cart_model/cart_data_model.dart` | ソース | カートデータモデル |
| add_to_cart_model.dart | `lib/screens/cart_screen/cart_model/add_to_cart_model.dart` | ソース | カート操作応答モデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント |
