# 機能設計書 26-顧客住所管理

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける顧客の住所情報の管理機能について記載する。

### 本機能の処理概要

本機能は、顧客に紐づく住所（配送先、請求先）の作成・取得・更新・削除を行う機能である。顧客は複数の住所を登録でき、それぞれにデフォルト配送先・デフォルト請求先のフラグを設定できる。登録された住所はカートやチェックアウト時に選択可能となる。

**業務上の目的・背景**：ECサイトにおいて、顧客が複数の配送先や請求先を管理できることは重要である。自宅、勤務先、ギフト送付先など、場面に応じた住所を事前に登録しておくことで、チェックアウト時の利便性が向上する。また、デフォルト住所を設定することで、毎回の入力手間を省くことができる。

**機能の利用シーン**：
- 顧客が新しい住所を登録する時
- 顧客が登録済み住所の一覧を確認する時
- 顧客が住所情報を更新する時
- 顧客が不要な住所を削除する時
- チェックアウト時に登録済み住所から選択する時

**主要な処理内容**：
1. 顧客住所の新規作成
2. 顧客住所の取得（単一/一覧）
3. 顧客住所の更新
4. 顧客住所の削除
5. デフォルト住所（配送/請求）の設定

**関連システム・外部連携**：
- 顧客モジュール: 顧客との関連付け
- カートモジュール: チェックアウト時の住所選択

**権限による制御**：Admin APIでは管理者が任意の顧客の住所を管理可能。Store APIでは認証済み顧客が自身の住所のみを管理可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 管理画面（顧客詳細） | 主画面 | 顧客住所一覧、編集 |
| - | マイページ（住所管理） | 主画面 | 住所一覧、追加、編集、削除 |
| - | チェックアウト画面 | 参照画面 | 登録済み住所の選択 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 住所作成

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| customer_id | string | Yes | 顧客ID | 顧客が存在すること |
| address_name | string | No | 住所名（自宅、勤務先等） | - |
| company | string | No | 会社名 | - |
| first_name | string | No | 名 | - |
| last_name | string | No | 姓 | - |
| address_1 | string | No | 住所1 | - |
| address_2 | string | No | 住所2 | - |
| city | string | No | 市区町村 | - |
| province | string | No | 都道府県 | - |
| postal_code | string | No | 郵便番号 | - |
| country_code | string | No | 国コード | ISO 3166-1 alpha-2 |
| phone | string | No | 電話番号 | - |
| is_default_shipping | boolean | No | デフォルト配送先 | デフォルト: false |
| is_default_billing | boolean | No | デフォルト請求先 | デフォルト: false |
| metadata | object | No | メタデータ | JSON形式 |

### 入力データソース

- Admin API: GET /admin/customers/{id}/addresses（一覧取得）
- Admin API: POST /admin/customers/{id}/addresses（作成）
- Admin API: POST /admin/customers/{id}/addresses/{address_id}（更新）
- Admin API: DELETE /admin/customers/{id}/addresses/{address_id}（削除）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| address | CustomerAddressDTO | 住所情報 |
| address.id | string | 住所ID（cuaddrプレフィックス） |
| address.customer_id | string | 顧客ID |
| address.address_name | string | 住所名 |
| address.is_default_shipping | boolean | デフォルト配送先フラグ |
| address.is_default_billing | boolean | デフォルト請求先フラグ |
| address.first_name | string | 名 |
| address.last_name | string | 姓 |
| address.country_code | string | 国コード |

### 出力先

- APIレスポンス（JSON形式）
- データベース（customer_addressテーブル）

## 処理フロー

### 処理シーケンス（作成）

```
1. リクエスト受信
   └─ customer_idと住所データを取得

2. 顧客の存在確認
   └─ 顧客が存在するか検証

3. デフォルト住所の処理
   ├─ is_default_shipping=trueの場合
   │    └─ 既存のデフォルト配送先をfalseに更新
   └─ is_default_billing=trueの場合
        └─ 既存のデフォルト請求先をfalseに更新

4. 住所作成
   └─ createCustomerAddressesWorkflow実行

5. イベント発行
   └─ address.createdイベント

6. レスポンス返却
   └─ 作成された住所を含む顧客情報を返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[顧客存在確認]
    B --> C{顧客存在?}
    C -->|No| D[エラー返却]
    C -->|Yes| E{デフォルト配送?}
    E -->|Yes| F[既存デフォルト解除]
    E -->|No| G{デフォルト請求?}
    F --> G
    G -->|Yes| H[既存デフォルト解除]
    G -->|No| I[住所作成]
    H --> I
    I --> J[イベント発行]
    J --> K[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | デフォルト配送先一意 | 顧客につきデフォルト配送先は1つのみ | 住所作成・更新時 |
| BR-26-02 | デフォルト請求先一意 | 顧客につきデフォルト請求先は1つのみ | 住所作成・更新時 |
| BR-26-03 | 顧客関連削除 | 顧客削除時に住所もカスケード削除 | 顧客削除時 |
| BR-26-04 | 住所名検索可能 | address_nameは検索対象フィールド | 検索時 |

### 計算ロジック

特になし（データ管理機能のため）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 作成 | customer_address | INSERT | 住所レコード作成 |
| 取得 | customer_address | SELECT | 住所レコード取得 |
| 更新 | customer_address | UPDATE | 住所レコード更新 |
| 削除 | customer_address | UPDATE（論理削除） | deleted_atを設定 |
| デフォルト解除 | customer_address | UPDATE | is_default_shipping/billingをfalseに |

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

#### customer_address

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | id | 自動生成（cuaddrプレフィックス） | 主キー |
| INSERT/UPDATE | customer_id | 顧客ID | 外部キー |
| INSERT/UPDATE | address_name | 住所名 | NULL許可、検索可能 |
| INSERT/UPDATE | is_default_shipping | デフォルト配送先 | boolean |
| INSERT/UPDATE | is_default_billing | デフォルト請求先 | boolean |
| INSERT/UPDATE | company | 会社名 | NULL許可、検索可能 |
| INSERT/UPDATE | first_name | 名 | NULL許可、検索可能 |
| INSERT/UPDATE | last_name | 姓 | NULL許可、検索可能 |
| INSERT/UPDATE | address_1 | 住所1 | NULL許可、検索可能 |
| INSERT/UPDATE | address_2 | 住所2 | NULL許可、検索可能 |
| INSERT/UPDATE | city | 市区町村 | NULL許可、検索可能 |
| INSERT/UPDATE | province | 都道府県 | NULL許可、検索可能 |
| INSERT/UPDATE | postal_code | 郵便番号 | NULL許可、検索可能 |
| INSERT/UPDATE | country_code | 国コード | NULL許可 |
| INSERT/UPDATE | phone | 電話番号 | NULL許可 |
| INSERT/UPDATE | metadata | メタデータ | JSON形式 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | MedusaError | 顧客が存在しない | 有効な顧客IDを指定 |
| NOT_FOUND | MedusaError | 住所が存在しない | 有効な住所IDを指定 |
| INVALID_DATA | MedusaError | country_codeが無効 | 有効なISO国コードを指定 |

### リトライ仕様

データベース接続エラー時は自動リトライが行われる場合がある。

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

- デフォルト住所の解除と新規住所の設定は同一トランザクション内で実行
- エラー発生時はロールバック

## パフォーマンス要件

- 一覧取得: 500ms以内
- 単一操作（作成/更新/削除）: 300ms以内

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

- 住所情報は個人情報として適切に保護
- Admin APIは認証必須
- Store APIでは自身の住所のみアクセス可能

## 備考

- is_default_shipping、is_default_billingにユニークインデックスが設定されている（顧客単位で1つのみtrue）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address.ts | `packages/modules/customer/src/models/address.ts` | 顧客住所モデル定義 |

**主要処理フロー（address.ts）**:
- **4-40行目**: CustomerAddressモデル定義
- **6行目**: IDプレフィックスはcuaddr
- **7-8行目**: address_name, is_default_shipping, is_default_billing
- **21-23行目**: 顧客とのbelongsTo関連
- **25-38行目**: ユニークインデックス（デフォルト配送先、デフォルト請求先）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | route.ts | `packages/medusa/src/api/admin/customers/[id]/addresses/route.ts` | Admin API住所操作 |

**主要処理フロー**:
- **14-38行目**: GET メソッド - 住所一覧取得
- **40-68行目**: POST メソッド - 住所作成（createCustomerAddressesWorkflow使用）

#### Step 3: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | customer-module.ts | `packages/modules/customer/src/services/customer-module.ts` | 住所関連メソッド |

**主要処理フロー**:
- **422-455行目**: createCustomerAddresses - 住所作成
- **457-468行目**: createCustomerAddresses_ - 内部実装
- **470-511行目**: updateCustomerAddresses - 住所更新
- **513-559行目**: updateCustomerAddresses_ - 内部実装

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

```
Admin API /admin/customers/{id}/addresses
    │
    ├─ GET (一覧取得)
    │      └─ remoteQuery → customer_address テーブル
    │
    ├─ POST (作成)
    │      └─ createCustomerAddressesWorkflow
    │             └─ CustomerModuleService.createCustomerAddresses
    │                    └─ customerAddressService_.create
    │
    ├─ POST /{address_id} (更新)
    │      └─ updateCustomerAddressesWorkflow
    │             └─ CustomerModuleService.updateCustomerAddresses
    │                    └─ customerAddressService_.update
    │
    └─ DELETE /{address_id} (削除)
           └─ deleteCustomerAddressesWorkflow
                  └─ CustomerModuleService.deleteCustomerAddresses
```

### データフロー図

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

customer_id      ───┐
住所データ       ───┼──▶ createCustomerAddressesWorkflow ───▶ 作成された住所
                    │         │
                    │         ├─▶ デフォルト住所解除（必要時）
                    │         │
                    │         └─▶ 住所レコード作成 ───▶ customer_address
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| address.ts | `packages/modules/customer/src/models/address.ts` | ソース | 顧客住所モデル定義 |
| route.ts | `packages/medusa/src/api/admin/customers/[id]/addresses/route.ts` | ソース | Admin API（一覧・作成） |
| [address_id]/route.ts | `packages/medusa/src/api/admin/customers/[id]/addresses/[address_id]/route.ts` | ソース | Admin API（更新・削除） |
| customer-module.ts | `packages/modules/customer/src/services/customer-module.ts` | ソース | 顧客モジュールサービス |
