# 画面設計書 18-住所帳ページ

## 概要

本ドキュメントは、Shopware 6のStorefrontにおける「住所帳ページ」の画面設計書です。ログイン済み顧客が登録済みの住所一覧を管理するための画面の仕様を記載しています。

### 本画面の処理概要

住所帳ページは、ログイン済み顧客が自身の住所を管理するための画面です。登録済みの全住所を一覧表示し、デフォルト配送先・請求先の設定、住所の新規作成、編集、削除が可能です。住所マネージャーコンポーネントを使用して、直感的な操作で住所管理を行えます。

**業務上の目的・背景**：顧客が複数の住所を管理できることで、自宅と職場など異なる配送先への発送が容易になります。また、デフォルト住所の設定により、チェックアウト時の入力手間を削減し、購買体験を向上させます。

**画面へのアクセス方法**：
- アカウントホームページからのナビゲーション
- ヘッダーのアカウントメニューから「住所帳」を選択
- 直接URL（/account/address）にアクセス

**主要な操作・処理内容**：
1. 登録済み住所の一覧表示
2. デフォルト配送先住所の設定
3. デフォルト請求先住所の設定
4. 住所の新規作成（別ページへ遷移）
5. 住所の編集（別ページへ遷移）
6. 住所の削除

**画面遷移**：
- 遷移元：アカウントホームページ、アカウントメニュー
- 遷移先：住所作成ページ、住所編集ページ

**権限による表示制御**：ログイン必須（ゲスト顧客は利用不可）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 住所一覧表示 | 主機能 | 住所一覧の表示（AddressController::accountAddressOverview） |
| 12 | デフォルト住所設定 | 補助機能 | デフォルト住所の変更（AddressController::switchDefaultAddress） |
| 14 | 住所削除 | 補助機能 | 住所の削除（AddressController::deleteAddress） |

## 画面種別

一覧表示

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| URL（住所一覧表示） | /account/address |
| ルート名（住所一覧表示） | frontend.account.address.page |
| HTTPメソッド | GET |
| URL（デフォルト住所設定） | /account/address/default-{type}/{addressId} |
| ルート名（デフォルト住所設定） | frontend.account.address.set-default-address |
| HTTPメソッド | POST |
| URL（住所削除） | /account/address/delete/{addressId} |
| ルート名（住所削除） | frontend.account.address.delete |
| HTTPメソッド | POST |

## 入出力項目

### デフォルト住所設定

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| type | string | Yes | 住所タイプ（billing/shipping） |
| addressId | string | Yes | 住所ID（UUIDv4形式） |

### 住所削除

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| addressId | string | Yes | 削除対象の住所ID（UUIDv4形式） |

## 表示項目

| セクション | 表示項目 | データソース |
|------------|----------|--------------|
| タイトル | ページタイトル | 固定テキスト（account.addressModalTitle） |
| 説明文 | 説明テキスト | 固定テキスト（account.addressText） |
| 住所一覧 | デフォルト配送先住所 | context.customer.defaultShippingAddress |
| 住所一覧 | デフォルト請求先住所 | context.customer.defaultBillingAddress |
| 住所マネージャー | 住所カード（各住所） | page.addresses |
| 住所カード | 氏名 | address.firstName/lastName |
| 住所カード | 会社名 | address.company |
| 住所カード | 住所行 | address.street/additionalAddressLine1/2 |
| 住所カード | 郵便番号・市区町村 | address.zipcode/city |
| 住所カード | 国・州 | address.country/countryState |
| 住所カード | デフォルト設定ボタン | 固定 |
| 住所カード | 編集リンク | 固定 |
| 住所カード | 削除ボタン | 固定（デフォルト住所以外） |
| 新規作成 | 住所作成リンク | 固定 |

## イベント仕様

### 1-ページ読み込み時（GET）

1. 顧客のログイン状態を確認（LOGIN_REQUIRED属性）
2. AddressListingPageLoaderでページデータを取得
3. 敬称一覧、国一覧、住所一覧、カート情報を取得
4. AddressListingPageLoadedHookを発火
5. テンプレートをレンダリング

### 2-デフォルト住所設定（POST）

1. addressIdのUUID形式検証
2. typeに応じてaccountServiceのメソッドを呼び出し
3. billing：setDefaultBillingAddress
4. shipping：setDefaultShippingAddress
5. 成功時：成功メッセージを表示して住所帳ページへリダイレクト
6. 住所が見つからない場合：エラーメッセージを表示

### 3-住所削除（POST）

1. addressIdの存在チェック
2. AbstractDeleteAddressRouteで住所を削除
3. 成功時：成功メッセージを表示して住所帳ページへリダイレクト
4. エラー時（デフォルト住所の削除など）：エラーメッセージを表示

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | customer_address | SELECT | 住所一覧の取得 |
| ページ表示 | country | SELECT | 国一覧の取得 |
| ページ表示 | salutation | SELECT | 敬称一覧の取得 |
| デフォルト住所設定 | customer | UPDATE | デフォルト住所IDの更新 |
| 住所削除 | customer_address | DELETE | 住所レコードの削除 |

### テーブル別更新項目詳細

#### customer

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | default_shipping_address_id | addressId | デフォルト配送先設定時 |
| UPDATE | default_billing_address_id | addressId | デフォルト請求先設定時 |

#### customer_address

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | id | addressId | 住所削除時 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|----------|---------------|
| account.addressModalTitle | 情報 | 常時 | ページタイトル |
| account.addressText | 情報 | 常時 | 説明テキスト |
| account.addressDefaultChanged | 成功 | デフォルト住所設定成功時 | デフォルト住所変更完了 |
| account.addressDefaultNotChanged | エラー | デフォルト住所設定失敗時 | デフォルト住所変更失敗 |
| account.addressDeleted | 成功 | 住所削除成功時 | 住所削除完了 |
| account.addressNotDeleted | エラー | 住所削除失敗時 | 住所削除失敗 |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|------|----------|----------|
| CustomerNotLoggedInException | 未ログイン状態でアクセス | ログインページへリダイレクト |
| UuidException | addressIdが不正なUUID形式 | invalidUuidエラー |
| AddressNotFoundException | 指定された住所が見つからない | エラーメッセージを表示 |
| CannotDeleteDefaultAddressException | デフォルト住所を削除しようとした | エラーメッセージを表示 |
| CustomerException | その他の顧客関連エラー | エラーメッセージを表示 |

## 備考

- SEO設定：seo=false（検索エンジンにインデックスさせない）
- キャッシュ：無効化（PlatformRequest::ATTRIBUTE_NO_STORE = true）
- 住所マネージャーコンポーネント（address-manager.html.twig）を使用
- デフォルト住所は削除不可（バリデーションで防止）
- 住所一覧はfirstNameの昇順でソート

---

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

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

### 推奨読解順序

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

住所一覧ページのPageクラスを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AddressListingPage.php | `src/Storefront/Page/Address/Listing/AddressListingPage.php` | addresses/salutations/countries/cart/addressプロパティ |

**読解のコツ**: AddressListingPageは住所一覧、国一覧、敬称一覧、カート情報を保持する複合的なPageクラスです。

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

処理の起点となるコントローラーメソッドを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AddressController.php | `src/Storefront/Controller/AddressController.php` | accountAddressOverview（70-87行目）、switchDefaultAddress（138-169行目）、deleteAddress（263-291行目） |

**主要処理フロー（accountAddressOverviewメソッド）**:
1. **82行目**: AddressListingPageLoaderでページデータ取得
2. **84行目**: AddressListingPageLoadedHookを発火
3. **86行目**: テンプレートをレンダリング

**主要処理フロー（switchDefaultAddressメソッド）**:
1. **150-152行目**: UUIDバリデーション
2. **154-166行目**: typeに応じてAccountServiceでデフォルト住所を設定
3. **168行目**: 住所帳ページへリダイレクト

**主要処理フロー（deleteAddressメソッド）**:
1. **279-281行目**: addressIdの存在チェック
2. **283-285行目**: AbstractDeleteAddressRouteで住所を削除
3. **286-288行目**: 例外処理
4. **290行目**: 住所帳ページへリダイレクト

#### Step 3: PageLoaderを理解する

ページデータの組み立てロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AddressListingPageLoader.php | `src/Storefront/Page/Address/Listing/AddressListingPageLoader.php` | loadメソッドで各種データを取得 |

**主要処理フロー**:
- **50-76行目**: loadメソッド全体
- **52-54行目**: GenericPageLoaderで基本ページ情報を取得
- **57行目**: getSalutationsで敬称一覧を取得
- **59行目**: getCountriesで国一覧を取得
- **61行目**: 住所一覧をCriteriaでfirstName昇順で取得
- **63行目**: AbstractListAddressRouteで住所を取得
- **65行目**: CartServiceでカート情報を取得

#### Step 4: テンプレートを理解する

表示ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.twig | `src/Storefront/Resources/views/storefront/page/account/addressbook/index.html.twig` | メインテンプレート |
| 4-2 | address-manager.html.twig | `src/Storefront/Resources/views/storefront/page/account/addressbook/address-manager.html.twig` | 住所マネージャーコンポーネント |

**主要構造**:
- **4-10行目**: ページヘッダー（タイトル、説明）
- **13-17行目**: 住所マネージャーコンポーネントのインクルード

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

```
AddressController::accountAddressOverview() [GET]
    |
    +-- AddressListingPageLoader::load()
    |       |
    |       +-- GenericPageLoader::load()
    |       |
    |       +-- AbstractSalutationRoute::load()
    |       |
    |       +-- AbstractCountryRoute::load()
    |       |
    |       +-- AbstractListAddressRoute::load()
    |       |
    |       +-- CartService::getCart()
    |
    +-- AddressListingPageLoadedHook
    |
    +-- renderStorefront()

AddressController::switchDefaultAddress() [POST]
    |
    +-- UUID検証
    |
    +-- AccountService::setDefaultShippingAddress/setDefaultBillingAddress()
    |
    +-- redirectToRoute()

AddressController::deleteAddress() [POST]
    |
    +-- AbstractDeleteAddressRoute::delete()
    |
    +-- redirectToRoute()
```

### データフロー図

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

GET Request ─────────> AddressController::accountAddressOverview()
                              |
                              v
                        AddressListingPageLoader
                              |
                        +-----+-----+-----+
                        |     |     |     |
                        v     v     v     v
                   Salutation Country Address Cart
                     Route   Route  Route  Service
                        |     |     |     |
                        +-----+-----+-----+
                              |
                              v
                        AddressListingPage ──────> Twig Template
                        (salutations, countries,       |
                         addresses, cart)              v
                                                  HTML Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AddressController.php | `src/Storefront/Controller/AddressController.php` | コントローラー | ルーティングとリクエスト処理 |
| AddressListingPageLoader.php | `src/Storefront/Page/Address/Listing/AddressListingPageLoader.php` | PageLoader | ページデータの組み立て |
| AddressListingPage.php | `src/Storefront/Page/Address/Listing/AddressListingPage.php` | DTO | ページデータを保持 |
| AddressListingPageLoadedHook.php | `src/Storefront/Page/Address/Listing/AddressListingPageLoadedHook.php` | フック | 拡張ポイント |
| index.html.twig | `src/Storefront/Resources/views/storefront/page/account/addressbook/index.html.twig` | テンプレート | メイン画面 |
| address-manager.html.twig | `src/Storefront/Resources/views/storefront/page/account/addressbook/address-manager.html.twig` | テンプレート | 住所マネージャーコンポーネント |
| AbstractListAddressRoute.php | `src/Core/Checkout/Customer/SalesChannel/AbstractListAddressRoute.php` | Store API | 住所一覧取得API |
| AbstractDeleteAddressRoute.php | `src/Core/Checkout/Customer/SalesChannel/AbstractDeleteAddressRoute.php` | Store API | 住所削除API |
| AccountService.php | `src/Core/Checkout/Customer/SalesChannel/AccountService.php` | サービス | デフォルト住所設定サービス |
