# 機能設計書 55-住所削除

## 概要

本ドキュメントは、登録済み住所の削除機能の設計を記述する。

### 本機能の処理概要

本機能は、ログイン済みユーザーが既に登録した配送先・請求先住所を削除する機能を提供する。ユーザーは住所一覧画面から不要な住所を選択し、確認ダイアログを経て住所を削除できる。

**業務上の目的・背景**：ユーザーが不要になった住所（引っ越し後の旧住所、閉鎖した営業所等）を削除できることで、住所一覧の整理が可能となる。不要な住所が残っていると、チェックアウト時に誤って選択するリスクがあるため、削除機能は重要である。

**機能の利用シーン**：住所一覧画面で特定の住所カードの「削除」ボタンをタップした時、不要な住所を整理したい時などにユーザーが利用する。

**主要な処理内容**：
1. 削除確認ダイアログの表示
2. ユーザーの確認（Yes/No）
3. バックエンドAPIへの住所削除リクエスト
4. 削除成功後の一覧画面更新
5. 削除結果の通知表示

**関連システム・外部連携**：GraphQL APIを介してバックエンドサーバーに削除リクエストを送信。

**権限による制御**：ログイン済みユーザーのみがアクセス可能。自身の住所データのみ削除可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | 住所一覧画面 | 主画面 | 登録済み住所の削除処理 |

## 機能種別

データ削除（CRUD - Delete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | String | Yes | 削除対象の住所ID | 存在する住所ID |

### 入力データソース

- 住所一覧画面の住所カード: AddressData.id

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| status | bool | 処理成功/失敗 |
| message | String | 処理結果メッセージ |

### 出力先

- バックエンドデータベース（GraphQL API経由で削除）
- 画面更新（住所一覧から該当住所を除去）
- 通知表示（成功/失敗メッセージ）

## 処理フロー

### 処理シーケンス

```
1. 削除ボタンタップ
   └─ 住所カードの削除ボタンをユーザーがタップ
2. 確認ダイアログ表示
   └─ 「本当に削除しますか？」ダイアログを表示
3. ユーザー選択
   └─ Yes/Noの選択を待機
4. API呼び出し（Yesの場合）
   └─ RemoveAddressEventを発行してAPIを呼び出し
5. レスポンス処理
   └─ 成功時は一覧から削除、失敗時はエラーメッセージを表示
6. 画面更新
   └─ 住所一覧から削除された住所を除去
```

### フローチャート

```mermaid
flowchart TD
    A[削除ボタンタップ] --> B[確認ダイアログ表示]
    B --> C{ユーザー選択}
    C -->|No| D[ダイアログ閉じる]
    D --> E[処理終了]
    C -->|Yes| F[ダイアログ閉じる]
    F --> G[RemoveAddressEvent発行]
    G --> H[API呼び出し]
    H --> I{レスポンス}
    I -->|成功| J[成功通知]
    J --> K[一覧から削除]
    I -->|失敗| L[エラー通知]
    L --> E
    K --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-01 | 削除確認必須 | 削除前に必ず確認ダイアログを表示 | 削除操作時 |
| BR-55-02 | 画面上即時反映 | 削除成功時は一覧から即座に該当住所を除去 | 削除成功時 |
| BR-55-03 | ダイアログ非dismissible | 確認ダイアログは背景タップでは閉じない | ダイアログ表示中 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 住所削除 | customer_addresses | DELETE | 指定IDの住所を削除 |

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

#### customer_addresses

| 操作 | 項目（カラム名） | 削除条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | id = 指定住所ID AND customer_id = ログインユーザーID | 自身の住所のみ削除可能 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API通信エラー | ネットワーク障害 | エラー通知を表示 |
| - | 住所不存在エラー | 指定IDの住所が存在しない | エラー通知を表示 |
| - | 権限エラー | 他ユーザーの住所を削除しようとした | エラー通知を表示 |

### リトライ仕様

エラー発生時はダイアログが閉じられ、ユーザーが再度削除ボタンを押すことで再試行可能。

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

API呼び出しはバックエンド側でトランザクション管理される。クライアント側では単一のAPI呼び出しのため、特別なトランザクション管理は不要。

## パフォーマンス要件

- 削除API呼び出し: 2秒以内
- 一覧更新: 即時（ローカルで削除済みデータを除去）

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

- ログイン済みユーザーのみアクセス可能
- 認証トークン付きでAPIリクエスト送信
- 自身の住所データのみ削除可能（バックエンドで権限チェック）

## 備考

- 削除後の一覧更新はローカルのaddressModelからremoveWhereで即時除去
- 物理削除が実行される（論理削除ではない）

---

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

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

### 推奨読解順序

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

削除処理で使用するイベントとレスポンスを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | RemoveAddressEventの構造 |
| 1-2 | address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | RemoveAddressStateの構造 |

**読解のコツ**: RemoveAddressEventは削除対象のidをString型で保持。RemoveAddressStateはstatusで成功/失敗を判定し、customerDeletedIdで削除されたIDを保持する。

#### Step 2: UIコンポーネントを理解する

削除ボタンと確認ダイアログの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | saved_address_list.dart | `lib/screens/address_list/view/widget/saved_address_list.dart` | 削除ボタンと確認ダイアログの実装 |

**主要処理フロー**:
1. **163-167行目**: 削除ボタンのonPressed処理
2. **196-228行目**: _onPressRemoveメソッドで確認ダイアログを表示
3. **217-221行目**: Yesボタンタップ時にRemoveAddressEventを発行

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

削除処理のロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | RemoveAddressEventの処理 |

**主要処理フロー**:
- **31-39行目**: RemoveAddressEventの処理、callRemoveAddressApiを呼び出し

#### Step 4: Repository層を理解する

API呼び出しのロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | API呼び出し実装 |

**主要処理フロー**:
- **39-49行目**: callRemoveAddressApiメソッドでApiClient().deleteAddress()を呼び出し

#### Step 5: 画面更新を理解する

削除後の一覧更新処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | address_screen.dart | `lib/screens/address_list/view/address_screen.dart` | 削除後の一覧更新 |

**主要処理フロー**:
- **63-69行目**: RemoveAddressStateのリスナーで通知表示
- **107-116行目**: RemoveAddressStateでの一覧更新処理（removeWhere）

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

```
SavedAddressList (saved_address_list.dart)
    │
    └─ _onPressRemove()
           │
           └─ AlertDialog
                  │
                  └─ Yes選択時
                         │
                         └─ AddressBloc.add(RemoveAddressEvent)
                                │
                                └─ AddressRepositoryImp.callRemoveAddressApi()
                                       │
                                       └─ ApiClient.deleteAddress()
                                              │
                                              └─ GraphQL API
                                                     │
                                                     ▼
AddressScreen (address_screen.dart)
    │
    └─ BlocConsumer listener
           │
           └─ RemoveAddressState.success
                  │
                  ├─ ShowMessage.successNotification()
                  └─ _addressModel.removeWhere()
```

### データフロー図

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

削除ボタンタップ ───▶ 確認ダイアログ
                              │
                              ▼
                        Yes選択
                              │
                              ▼
RemoveAddressEvent ───▶ AddressBloc ───▶ RemoveAddressState
(id)                          │
                              ▼
                   AddressRepositoryImp
                              │
                              ▼
                   ApiClient.deleteAddress()
                              │
                              ▼
                       GraphQL API
                              │
                              ▼
                       BaseModel ───▶ 成功/失敗通知
                              │
                              ▼
                   _addressModel.removeWhere() ───▶ 一覧更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| saved_address_list.dart | `lib/screens/address_list/view/widget/saved_address_list.dart` | ソース | 削除ボタンと確認ダイアログ |
| address_screen.dart | `lib/screens/address_list/view/address_screen.dart` | ソース | 削除後の一覧更新 |
| address_bloc.dart | `lib/screens/address_list/bloc/address_bloc.dart` | ソース | 状態管理 |
| address_repository.dart | `lib/screens/address_list/bloc/address_repository.dart` | ソース | API呼び出し |
| address_event.dart | `lib/screens/address_list/bloc/address_event.dart` | ソース | イベント定義 |
| address_state.dart | `lib/screens/address_list/bloc/address_state.dart` | ソース | ステート定義 |
