# 機能設計書 68-ストアCRUD

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおけるストア情報の管理機能の設計を記述する。ストアの作成、取得、更新、削除を提供する。

### 本機能の処理概要

**業務上の目的・背景**：ECサイトの基本情報（ストア名、デフォルト設定等）を管理するためにストアCRUD機能が必要である。ストアは通常1つのMedusaインスタンスに1つ存在し、サイト全体の設定の基盤となる。サポートする通貨やロケール、デフォルトの販売チャネル・地域・ロケーションなどの設定を管理する。

**機能の利用シーン**：
- ストア名の変更
- サポート通貨の追加・削除
- サポートロケールの設定
- デフォルト販売チャネル・地域・ロケーションの設定
- ストアメタデータの管理

**主要な処理内容**：
1. ストア一覧取得（通常は1件のみ）
2. ストア詳細取得
3. ストア作成（初期セットアップ時）
4. ストア更新（設定変更）
5. サポート通貨・ロケールの管理

**関連システム・外部連携**：
- 通貨モジュールとの連携（サポート通貨設定）
- 販売チャネルモジュールとの連携（デフォルト販売チャネル）
- 地域モジュールとの連携（デフォルト地域）
- ロケーションモジュールとの連携（デフォルトロケーション）
- 価格設定モジュールとの連携（通貨別税込設定）

**権限による制御**：ストアの作成・更新・削除は認証済み管理者のみ可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 108 | ストア詳細画面 | 主画面 | ストア情報の表示 |
| 109 | ストア編集画面 | 主画面 | ストア情報の編集 |
| 112 | ストアメタデータ編集画面 | 主画面 | ストアメタデータの編集 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### ストア作成

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | No | ストア名 | デフォルト「Medusa Store」、トリミング処理 |
| default_sales_channel_id | string | No | デフォルト販売チャネルID | 有効なID |
| default_region_id | string | No | デフォルト地域ID | 有効なID |
| default_location_id | string | No | デフォルトロケーションID | 有効なID |
| supported_currencies | StoreCurrencyInput[] | No | サポート通貨リスト | 重複なし、1つのデフォルト必須 |
| supported_locales | StoreLocaleInput[] | No | サポートロケールリスト | 重複なし |
| metadata | object | No | メタデータ | - |

#### StoreCurrencyInput

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| currency_code | string | Yes | 通貨コード | 小文字に正規化 |
| is_default | boolean | No | デフォルト通貨フラグ | 1つのみtrue |
| is_tax_inclusive | boolean | No | 税込価格フラグ | - |

#### StoreLocaleInput

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| locale_code | string | Yes | ロケールコード（BCP 47形式） | 重複なし |

### 入力データソース

- Admin API HTTPリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | ストアID（store_プレフィックス） |
| name | string | ストア名 |
| default_sales_channel_id | string | null | デフォルト販売チャネルID |
| default_region_id | string | null | デフォルト地域ID |
| default_location_id | string | null | デフォルトロケーションID |
| supported_currencies | StoreCurrencyDTO[] | サポート通貨リスト |
| supported_locales | StoreLocaleDTO[] | サポートロケールリスト |
| metadata | object | null | メタデータ |
| created_at | Date | 作成日時 |
| updated_at | Date | 更新日時 |

### 出力先

- Admin API HTTPレスポンス

## 処理フロー

### 処理シーケンス

```
1. ストア一覧取得
   └─ remoteQueryでstoreテーブル検索

2. ストア詳細取得
   ├─ remoteQueryでID指定検索
   └─ サポート通貨・ロケールをリレーションで取得

3. ストア作成
   ├─ 入力正規化（name trim、currency_code小文字化）
   ├─ バリデーション（通貨重複、デフォルト通貨、ロケール重複）
   └─ upsertWithReplaceでストア・通貨・ロケール作成

4. ストア更新
   ├─ 存在確認
   ├─ 入力正規化
   ├─ バリデーション
   ├─ updateStoresWorkflow実行
   └─ 価格優先設定更新（税込設定がある場合）
```

### フローチャート

```mermaid
flowchart TD
    A[API リクエスト] --> B{操作種別}
    B -->|GET /stores| C[ストア一覧取得]
    B -->|GET /stores/:id| D[ストア詳細取得]
    B -->|POST /stores/:id| E[ストア更新]

    C --> F[remoteQuery実行]
    D --> F
    F --> G[結果返却]

    E --> H[存在確認]
    H --> I{存在する?}
    I -->|No| J[NOT_FOUNDエラー]
    I -->|Yes| K[入力正規化]
    K --> L[バリデーション]
    L --> M{バリデーションOK?}
    M -->|No| N[INVALID_DATAエラー]
    M -->|Yes| O[updateStoresWorkflow]
    O --> P{税込設定あり?}
    P -->|Yes| Q[価格優先設定更新]
    P -->|No| R[refetchStore]
    Q --> R
    R --> S[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | ストア名デフォルト | nameのデフォルト値は「Medusa Store」 | 作成時 |
| BR-68-02 | 通貨コード正規化 | currency_codeは小文字に正規化 | 作成・更新時 |
| BR-68-03 | 通貨重複禁止 | 同一ストアに同じ通貨コードは登録不可 | 作成・更新時 |
| BR-68-04 | デフォルト通貨必須 | supported_currenciesを指定する場合、1つのis_default=trueが必須 | 作成・更新時 |
| BR-68-05 | 複数デフォルト禁止 | is_default=trueは1つの通貨のみ | 作成・更新時 |
| BR-68-06 | ロケール重複禁止 | 同一ストアに同じロケールコードは登録不可 | 作成・更新時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | store | SELECT | フィルタ・ページネーション付き |
| 詳細取得 | store | SELECT | ID指定、リレーション含む |
| 作成 | store | INSERT | 新規ストアレコード |
| 作成 | store_currency | INSERT | サポート通貨レコード |
| 作成 | store_locale | INSERT | サポートロケールレコード |
| 更新 | store | UPDATE | ストア情報更新 |
| 更新 | store_currency | UPSERT | サポート通貨の追加・更新・削除 |
| 更新 | store_locale | UPSERT | サポートロケールの追加・更新・削除 |

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

#### store

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成（store_プレフィックス） | - |
| INSERT | name | 入力値またはデフォルト | searchable |
| INSERT | default_sales_channel_id | 入力値 | nullable |
| INSERT | default_region_id | 入力値 | nullable |
| INSERT | default_location_id | 入力値 | nullable |

#### store_currency

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成（stocur_プレフィックス） | - |
| INSERT | currency_code | 入力値（小文字化） | searchable |
| INSERT | is_default | 入力値 | デフォルトfalse |
| INSERT | store_id | ストアID | 外部キー |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | MedusaError | 指定IDのストアが存在しない | 404レスポンス |
| INVALID_DATA | MedusaError | 通貨コード重複 | 400レスポンス |
| INVALID_DATA | MedusaError | デフォルト通貨が複数 | 400レスポンス |
| INVALID_DATA | MedusaError | デフォルト通貨が0個 | 400レスポンス |
| INVALID_DATA | MedusaError | ロケールコード重複 | 400レスポンス |

### リトライ仕様

データベース操作失敗時のリトライはワークフローエンジンで管理。

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

- ストア作成・更新はワークフロー内でトランザクション管理
- @InjectTransactionManagerデコレータで内部トランザクションを制御
- upsertWithReplaceでストア・通貨・ロケールを一括更新

## パフォーマンス要件

- nameカラムはsearchableで全文検索対応
- ストアIDに主キーインデックス
- currency_codeカラムにインデックス

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

- 認証必須エンドポイント
- RBACによる権限制御可能

## 備考

- ストアIDはstore_プレフィックス付きで自動生成
- 通貨IDはstocur_プレフィックス付きで自動生成
- ロケールIDはstloc_プレフィックス付きで自動生成
- supported_localesはバージョン2.12.3で追加

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | store.ts | `packages/modules/store/src/models/store.ts` | Storeモデルの構造（id, name, default設定、supported_currencies, supported_locales） |
| 1-2 | currency.ts | `packages/modules/store/src/models/currency.ts` | StoreCurrencyモデルの構造（id, currency_code, is_default, store） |
| 1-3 | locale.ts | `packages/modules/store/src/models/locale.ts` | StoreLocaleモデルの構造（id, locale_code, store） |

**読解のコツ**: Storeはsupported_currenciesとsupported_localesを持つ。cascades.deleteで関連レコードも削除される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | route.ts | `packages/medusa/src/api/admin/stores/route.ts` | GET - ストア一覧取得 |
| 2-2 | [id]/route.ts | `packages/medusa/src/api/admin/stores/[id]/route.ts` | GET, POST - ストア詳細・更新 |

**主要処理フロー**:
1. **route.ts 11-33行目**: 一覧取得、remoteQuery使用
2. **[id]/route.ts 15-30行目**: 詳細取得
3. **[id]/route.ts 32-61行目**: 更新処理、updateStoresWorkflow使用

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | store-module-service.ts | `packages/modules/store/src/services/store-module-service.ts` | StoreModuleServiceの実装 |

**主要処理フロー**:
- **68-79行目**: createStores - ストア作成
- **81-96行目**: create_ - 正規化、バリデーション、upsertWithReplace
- **193-208行目**: update_ - 更新処理
- **210-223行目**: normalizeInput - currency_code小文字化、name trim
- **225-263行目**: validateCreateRequest - 通貨・ロケールバリデーション

#### Step 4: ワークフローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | update-stores.ts | `packages/core/core-flows/src/store/workflows/update-stores.ts` | 更新ワークフロー |

**主要処理フロー**:
- **42-88行目**: 入力正規化、updateStoresStep、価格優先設定更新

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

```
Admin API Route
    │
    ├─ GET /stores
    │      └─ remoteQuery (store エントリーポイント)
    │
    ├─ GET /stores/:id
    │      └─ remoteQuery (store エントリーポイント)
    │
    └─ POST /stores/:id
           └─ updateStoresWorkflow
                  ├─ normalizeInput
                  ├─ updateStoresStep
                  │      └─ storeService_.upsertWithReplace
                  │             └─ supported_currencies, supported_locales
                  │
                  └─ updatePricePreferencesAsArrayStep (税込設定時)
```

### データフロー図

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

ストア更新
  name ─────────────▶ normalizeInput ───────────▶ Store record
  supported_currencies    │
  supported_locales       ▼
                   validateCreateRequest
                          │
                  ┌───────┴───────┬──────────────┐
                  ▼               ▼              ▼
            通貨重複チェック  デフォルトチェック  ロケール重複チェック
                  │               │              │
                  ▼               ▼              ▼
              OK / Error      OK / Error     OK / Error
                  │               │              │
                  └───────┬───────┴──────────────┘
                          │
                          ▼
                   upsertWithReplace
                          │
                   ┌──────┴──────┐
                   ▼             ▼
               store        store_currency
                                 │
                                 ▼
                           store_locale
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| store.ts | `packages/modules/store/src/models/store.ts` | ソース | Storeモデル定義 |
| currency.ts | `packages/modules/store/src/models/currency.ts` | ソース | StoreCurrencyモデル定義 |
| locale.ts | `packages/modules/store/src/models/locale.ts` | ソース | StoreLocaleモデル定義 |
| store-module-service.ts | `packages/modules/store/src/services/store-module-service.ts` | ソース | StoreModuleService |
| route.ts | `packages/medusa/src/api/admin/stores/route.ts` | ソース | ストア一覧API |
| [id]/route.ts | `packages/medusa/src/api/admin/stores/[id]/route.ts` | ソース | ストア詳細・更新API |
| update-stores.ts | `packages/core/core-flows/src/store/workflows/update-stores.ts` | ソース | 更新ワークフロー |
