# 機能設計書 25-顧客CRUD

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける顧客情報の作成・取得・更新・削除（CRUD）機能について記載する。

### 本機能の処理概要

本機能は、ECサイトの顧客（Customer）データを管理するための基本的なCRUD操作を提供する。顧客情報には氏名、メールアドレス、電話番号、会社名などの基本情報が含まれ、顧客グループや住所との関連も管理される。管理者が顧客データを一元管理し、顧客セグメンテーションやマーケティング施策に活用できる基盤を提供する。

**業務上の目的・背景**：ECサイトにおいて顧客データの管理は事業運営の根幹である。顧客情報を適切に管理することで、パーソナライズされたマーケティング、顧客サポートの効率化、購買履歴に基づく商品レコメンドなどが可能となる。また、has_accountフラグにより、ゲスト購入者と会員登録済み顧客を区別して管理できる。

**機能の利用シーン**：
- 管理者が新規顧客を手動で登録する時
- 顧客一覧を検索・フィルタリングして閲覧する時
- 顧客情報を更新する時（氏名変更、連絡先変更等）
- 顧客データを削除（論理削除）する時
- 顧客がストア側で会員登録する時

**主要な処理内容**：
1. 顧客の新規作成（Create）
2. 顧客の取得（Read）- 単一/一覧
3. 顧客の更新（Update）
4. 顧客の削除（Delete）- 論理削除
5. 顧客検索（フィルタリング、ページネーション）

**関連システム・外部連携**：
- 認証モジュール（Auth Module）: has_accountフラグと連動した認証管理
- 注文モジュール（Order Module）: 顧客の注文履歴との関連
- カートモジュール（Cart Module）: カートと顧客の紐付け

**権限による制御**：Admin APIは認証された管理者のみアクセス可能。Store APIでは認証済み顧客が自身の情報を参照・更新可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 管理画面（顧客一覧） | 主画面 | 顧客一覧表示、検索 |
| - | 管理画面（顧客詳細） | 主画面 | 顧客情報表示、編集 |
| - | ストア（会員登録） | 参照画面 | 顧客作成 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 顧客作成

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| email | string | No | メールアドレス | 有効なメール形式 |
| first_name | string | No | 名 | - |
| last_name | string | No | 姓 | - |
| company_name | string | No | 会社名 | - |
| phone | string | No | 電話番号 | - |
| has_account | boolean | No | アカウント有無 | デフォルト: false |
| metadata | object | No | メタデータ | JSON形式 |
| addresses | AddressDTO[] | No | 住所配列 | - |

#### 顧客更新

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string | Yes | 顧客ID | 顧客が存在すること |
| email | string | No | メールアドレス | 有効なメール形式 |
| first_name | string | No | 名 | - |
| last_name | string | No | 姓 | - |
| company_name | string | No | 会社名 | - |
| phone | string | No | 電話番号 | - |
| metadata | object | No | メタデータ | JSON形式 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| customer | CustomerDTO | 顧客情報 |
| customer.id | string | 顧客ID（cusプレフィックス） |
| customer.email | string | メールアドレス |
| customer.first_name | string | 名 |
| customer.last_name | string | 姓 |
| customer.company_name | string | 会社名 |
| customer.phone | string | 電話番号 |
| customer.has_account | boolean | アカウント有無 |
| customer.groups | CustomerGroupDTO[] | 所属グループ |
| customer.addresses | CustomerAddressDTO[] | 住所一覧 |
| customer.created_by | string | 作成者ID |
| customer.created_at | DateTime | 作成日時 |
| customer.updated_at | DateTime | 更新日時 |

### 出力先

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

## 処理フロー

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

```
1. リクエスト受信
   └─ 顧客データを取得

2. バリデーション
   └─ メールアドレス形式、一意性検証

3. 顧客作成ワークフロー実行
   └─ createCustomersWorkflow
      ├─ 顧客レコード作成
      └─ 住所がある場合は住所も作成

4. イベント発行
   └─ customer.createdイベント

5. レスポンス返却
   └─ 作成された顧客情報を返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{操作種別}
    B -->|Create| C[バリデーション]
    B -->|Read| D[顧客取得]
    B -->|Update| E[顧客更新]
    B -->|Delete| F[顧客削除]

    C --> G{メール重複?}
    G -->|Yes| H[エラー返却]
    G -->|No| I[顧客作成]
    I --> J[住所作成]
    J --> K[イベント発行]
    K --> L[レスポンス返却]

    D --> L

    E --> M{顧客存在?}
    M -->|No| H
    M -->|Yes| N[顧客更新実行]
    N --> K

    F --> O{顧客存在?}
    O -->|No| H
    O -->|Yes| P[論理削除]
    P --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | メール一意性 | email + has_accountの組み合わせが一意 | 顧客作成・更新時 |
| BR-25-02 | 論理削除 | 顧客削除は物理削除ではなく論理削除（deleted_at設定） | 削除時 |
| BR-25-03 | カスケード削除 | 顧客削除時に住所も連動して削除 | 削除時 |
| BR-25-04 | グループ関連 | 顧客削除時にグループ関連はdetach（削除されない） | 削除時 |
| BR-25-05 | 作成者記録 | 管理者が作成した場合、created_byに管理者IDを記録 | 管理画面からの作成時 |

### 計算ロジック

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

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 作成 | customer | INSERT | 顧客レコード作成 |
| 取得 | customer | SELECT | 顧客レコード取得（関連含む） |
| 更新 | customer | UPDATE | 顧客レコード更新 |
| 削除 | customer | UPDATE（論理削除） | deleted_atを設定 |
| 住所作成 | customer_address | INSERT | 顧客住所作成（作成時） |
| 住所削除 | customer_address | UPDATE（論理削除） | 顧客削除時にカスケード |

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

#### customer

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | id | 自動生成（cusプレフィックス） | 主キー |
| INSERT/UPDATE | email | メールアドレス | NULL許可、検索可能 |
| INSERT/UPDATE | first_name | 名 | NULL許可、検索可能 |
| INSERT/UPDATE | last_name | 姓 | NULL許可、検索可能 |
| INSERT/UPDATE | company_name | 会社名 | NULL許可、検索可能 |
| INSERT/UPDATE | phone | 電話番号 | NULL許可、検索可能 |
| INSERT/UPDATE | has_account | アカウント有無 | デフォルト: false |
| INSERT/UPDATE | metadata | メタデータ | JSON形式 |
| INSERT/UPDATE | created_by | 作成者ID | NULL許可 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | MedusaError | 顧客が存在しない | 有効な顧客IDを指定 |
| INVALID_DATA | MedusaError | メールアドレスが無効な形式 | 有効なメール形式を指定 |
| DUPLICATE_ERROR | MedusaError | メール+has_accountの組み合わせが重複 | 別のメールアドレスを使用 |

### リトライ仕様

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

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

- 顧客作成と住所作成は同一トランザクション内で実行
- 顧客削除と関連住所の削除は同一トランザクション内で実行
- エラー発生時はロールバック

## パフォーマンス要件

- 一覧取得: ページネーション対応、1000件以下のレスポンスは1秒以内
- 単一取得: 200ms以内
- 作成・更新・削除: 500ms以内

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

- Admin APIは認証必須
- 顧客のメールアドレスは個人情報として適切に保護
- パスワードは顧客モジュールでは管理しない（Auth Moduleで管理）

## 備考

- email + has_accountの組み合わせでユニークインデックスが設定されている
- フィールドにはsearchableフラグが設定されており、全文検索が可能

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: MedusaのモデルはDomain定義形式。searchable()で全文検索対応、cascades設定でリレーション削除挙動を定義。

**主要処理フロー（customer.ts）**:
- **6-37行目**: Customerモデル定義
- **8行目**: IDプレフィックスはcus
- **9-15行目**: 各フィールド（searchable設定あり）
- **17-20行目**: グループとのmanyToMany関連
- **21-23行目**: 住所とのhasMany関連
- **25-28行目**: cascades - 削除時の住所削除、グループdetach
- **29-35行目**: email + has_accountのユニークインデックス

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | route.ts | `packages/medusa/src/api/admin/customers/route.ts` | Admin API顧客一覧・作成 |
| 2-2 | [id]/route.ts | `packages/medusa/src/api/admin/customers/[id]/route.ts` | Admin API顧客詳細・更新・削除 |

**主要処理フロー（route.ts）**:
- **15-38行目**: GET メソッド - 顧客一覧取得（remoteQueryでフィルタリング・ページネーション）
- **40-68行目**: POST メソッド - 顧客作成（createCustomersWorkflow使用）
- **54-55行目**: created_byに認証済み管理者IDを設定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | customer-module.ts | `packages/modules/customer/src/services/customer-module.ts` | 顧客モジュールサービス |

**主要処理フロー**:
- **93-120行目**: createCustomers - 顧客作成（住所作成を含む）
- **122-158行目**: createCustomers_ - 内部実装、customerService_.createを呼び出し
- **160-196行目**: updateCustomers - 顧客更新
- **198-237行目**: updateCustomers_ - 内部実装

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

```
Admin API /admin/customers
    │
    ├─ GET (一覧取得)
    │      └─ remoteQuery → customer テーブル
    │
    ├─ POST (作成)
    │      └─ createCustomersWorkflow
    │             └─ CustomerModuleService.createCustomers
    │                    ├─ customerService_.create
    │                    └─ createCustomerAddresses (住所あれば)
    │
    ├─ POST /{id} (更新)
    │      └─ updateCustomersWorkflow
    │             └─ CustomerModuleService.updateCustomers
    │                    └─ customerService_.update
    │
    └─ DELETE /{id} (削除)
           └─ deleteCustomersWorkflow
                  └─ CustomerModuleService.softDeleteCustomers
                         └─ customerService_.softDelete
```

### データフロー図

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

顧客データ ─────────▶ createCustomersWorkflow ───▶ 作成された顧客
(email, name等)               │
                              ├─▶ 顧客レコード作成 ───▶ customer
                              │
                              └─▶ 住所作成 ───▶ customer_address

顧客ID ─────────────▶ deleteCustomersWorkflow ───▶ 削除確認
                              │
                              ├─▶ 顧客論理削除 ───▶ customer.deleted_at
                              │
                              └─▶ 住所カスケード削除 ───▶ customer_address.deleted_at
```

### 関連ファイル一覧

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