# 機能設計書 7-商品タイプ管理

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける商品タイプ（Product Type）管理機能の設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：
商品タイプは、商品の分類・種別を定義するためのマスターデータである。カテゴリとは異なり、階層構造を持たないフラットな分類として機能する。例えば「物理商品」「デジタル商品」「サービス」「サブスクリプション」などの商品種別を管理する。1つの商品は1つのタイプにのみ属する（1対多の関係）。

**機能の利用シーン**：
- 商品種別マスターの登録
- 商品に対するタイプの割り当て
- 商品タイプ別のフィルタリング
- タイプ名の変更
- 不要なタイプの削除

**主要な処理内容**：
1. タイプの新規作成（値の設定）
2. タイプの一覧取得
3. タイプの個別取得
4. タイプの更新
5. タイプの削除

**関連システム・外部連携**：
- 商品モジュール（Product Module）：商品とタイプの1対多関連
- 注文明細：注文時に商品タイプ情報を保持

**権限による制御**：
- Admin API経由のアクセスには認証が必要（AuthenticatedMedusaRequest）
- タイプの作成・更新・削除は管理者権限を持つユーザーのみ実行可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 商品編集画面 | 関連画面 | タイプの選択 |

## 機能種別

CRUD操作（Create / Read / Update / Delete）

## 入力仕様

### 入力パラメータ

#### タイプ作成（POST /admin/product-types）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | string | Yes | タイプ値 | ユニーク（deleted_at IS NULL） |
| metadata | object | No | メタデータ | JSON形式 |

#### タイプ更新（POST /admin/product-types/:id）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | string | No | タイプ値 | ユニーク |
| metadata | object | No | メタデータ | - |

### 入力データソース

- 管理画面（Admin Dashboard）からのフォーム入力
- REST API経由のJSON/リクエストボディ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | タイプID（ptyp_xxx形式） |
| value | string | タイプ値 |
| products | array | 関連商品配列 |
| metadata | object | メタデータ |
| created_at | datetime | 作成日時 |
| updated_at | datetime | 更新日時 |
| deleted_at | datetime | 削除日時 |

### 出力先

- REST APIレスポンス（JSON形式）
- 管理画面への表示

## 処理フロー

### 処理シーケンス

```
1. タイプ作成フロー
   ├─ タイプ作成（createProductTypesStep）
   ├─ フック実行（productTypesCreated）
   └─ イベント発行（ProductTypeWorkflowEvents.CREATED）

2. タイプ取得フロー
   ├─ フィルタ条件の適用
   ├─ remoteQueryによるデータ取得
   └─ レスポンス整形

3. タイプ更新フロー
   ├─ 既存タイプの存在確認
   ├─ タイプ更新（updateProductTypesStep）
   ├─ フック実行（productTypesUpdated）
   └─ イベント発行（ProductTypeWorkflowEvents.UPDATED）

4. タイプ削除フロー
   ├─ タイプ削除（deleteProductTypesStep）
   ├─ リモートリンク削除（removeRemoteLinkStep）
   ├─ フック実行（productTypesDeleted）
   └─ イベント発行（ProductTypeWorkflowEvents.DELETED）
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-PT01 | タイプ値一意性 | valueは削除されていないタイプ間でユニーク | タイプ作成・更新時 |
| BR-PT02 | 商品単一所属 | 1つの商品は1つのタイプにのみ属する | 商品タイプ関連付け時 |
| BR-PT03 | 削除時リンク解除 | タイプ削除時に関連するリモートリンクも削除 | タイプ削除時 |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 作成 | product_type | INSERT | タイプレコードの挿入 |
| 取得 | product_type | SELECT | タイプの取得 |
| 更新 | product_type | UPDATE | タイプの更新 |
| 削除 | product_type | UPDATE | deleted_atの設定（論理削除） |

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

#### product_type

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成（ptyp_xxx形式） | generateEntityId使用 |
| INSERT | value | リクエストの値 | 必須、ユニーク |
| DELETE | deleted_at | 現在日時 | 論理削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | 404 | 指定IDのタイプが存在しない | 正しいIDを指定 |
| INVALID_DATA | 400 | valueが重複 | ユニークな値を指定 |

## 備考

- タイプのIDプレフィックスは「ptyp」
- 商品はproduct.type_idでタイプを参照（belongsTo関係）
- valueフィールドはsearchable/translatable属性を持つ
- 削除時にremoveRemoteLinkStepでリモートリンクも削除される

---

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

### 推奨読解順序

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

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

**主要処理フロー（product-type.ts）**:
- **4-12行目**: ProductTypeモデル定義
- **6行目**: IDプレフィックス「ptyp」
- **7行目**: valueフィールド（searchable, translatable）
- **9-11行目**: 商品との1対多リレーション（hasMany）
- **13-20行目**: ユニークインデックス（value）

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

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

**主要処理フロー（route.ts）**:
- **14-36行目**: GET - remoteQueryでタイプ一覧取得
- **38-58行目**: POST - createProductTypesWorkflowでタイプ作成

**主要処理フロー（[id]/route.ts）**:
- **14-27行目**: GET - 個別タイプ取得
- **29-63行目**: POST - 更新前存在確認、updateProductTypesWorkflow実行
- **65-80行目**: DELETE - deleteProductTypesWorkflow実行

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create-product-types.ts | `packages/core/core-flows/src/product/workflows/create-product-types.ts` | 作成ワークフロー |
| 3-2 | update-product-types.ts | `packages/core/core-flows/src/product/workflows/update-product-types.ts` | 更新ワークフロー |
| 3-3 | delete-product-types.ts | `packages/core/core-flows/src/product/workflows/delete-product-types.ts` | 削除ワークフロー |

**主要処理フロー（create-product-types.ts）**:
- **54-78行目**: createProductTypesWorkflow定義
- **57行目**: createProductTypesStepでタイプ作成
- **58-61行目**: productTypesCreatedフック
- **69-72行目**: ProductTypeWorkflowEvents.CREATEDイベント発行

**主要処理フロー（update-product-types.ts）**:
- **59-90行目**: updateProductTypesWorkflow定義
- **62行目**: updateProductTypesStepで更新
- **63-66行目**: productTypesUpdatedフック
- **81-84行目**: ProductTypeWorkflowEvents.UPDATEDイベント発行

**主要処理フロー（delete-product-types.ts）**:
- **48-76行目**: deleteProductTypesWorkflow定義
- **51行目**: deleteProductTypesStepで削除
- **52-54行目**: productTypesDeletedフック
- **62-70行目**: parallelizeでリモートリンク削除とイベント発行を同時実行

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

```
[Admin Dashboard / REST Client]
    │
    ▼
POST /admin/product-types
    │
    ├──▶ createProductTypesWorkflow
    │       ├── createProductTypesStep
    │       ├── createHook("productTypesCreated")
    │       └── emitEventStep(ProductTypeWorkflowEvents.CREATED)
    │
POST /admin/product-types/:id (更新)
    │
    ├──▶ updateProductTypesWorkflow
    │       ├── updateProductTypesStep
    │       ├── createHook("productTypesUpdated")
    │       └── emitEventStep(ProductTypeWorkflowEvents.UPDATED)
    │
DELETE /admin/product-types/:id
    │
    └──▶ deleteProductTypesWorkflow
            ├── deleteProductTypesStep
            ├── createHook("productTypesDeleted")
            ├── removeRemoteLinkStep (parallelize)
            └── emitEventStep(ProductTypeWorkflowEvents.DELETED)
```

### データフロー図

```
┌─────────────────────────────────────────────────────────┐
│                     Admin API Layer                      │
│  ┌─────────────────────────────────────────────────────┐│
│  │              /admin/product-types/                  ││
│  │  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  ││
│  │  │   GET    │  │   POST   │  │   POST/:id       │  ││
│  │  │(一覧取得)│  │  (作成)  │  │  (更新/削除)     │  ││
│  │  └────┬─────┘  └────┬─────┘  └────┬─────────────┘  ││
│  └───────┼─────────────┼─────────────┼────────────────┘│
└──────────┼─────────────┼─────────────┼─────────────────┘
           │             │             │
           ▼             ▼             ▼
┌─────────────────────────────────────────────────────────┐
│                   Workflow Layer                         │
│  ┌────────────────────┬───────────────┬───────────────┐ │
│  │ createProductTypes │ updateProduct │ deleteProduct │ │
│  │ Workflow           │ TypesWorkflow │ TypesWorkflow │ │
│  └─────────┬──────────┴───────┬───────┴───────┬───────┘ │
│            │                  │               │         │
│            ▼                  ▼               ▼         │
│  ┌────────────────────────────────────────────────────┐ │
│  │           Product Module (Product Type)            │ │
│  │  ┌────────────┬────────────┬────────────────────┐ │ │
│  │  │   create   │   update   │      delete        │ │ │
│  │  └─────┬──────┴─────┬──────┴─────────┬──────────┘ │ │
│  └────────┼────────────┼────────────────┼────────────┘ │
└───────────┼────────────┼────────────────┼──────────────┘
            │            │                │
            ▼            ▼                ▼
┌─────────────────────────────────────────────────────────┐
│                   Database Layer                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │              product_type table                   │  │
│  │  id (ptyp_xxx) | value | metadata | deleted_at   │  │
│  └───────────────────────────────────────────────────┘  │
│                         ▲                               │
│                         │ belongsTo (type_id)           │
│                         │                               │
│  ┌───────────────────────────────────────────────────┐  │
│  │                   product table                   │  │
│  │                    type_id                        │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| product-type.ts | `packages/modules/product/src/models/product-type.ts` | モデル | タイプエンティティ定義 |
| route.ts | `packages/medusa/src/api/admin/product-types/route.ts` | API | 一覧・作成エンドポイント |
| [id]/route.ts | `packages/medusa/src/api/admin/product-types/[id]/route.ts` | API | 詳細・更新・削除 |
| create-product-types.ts | `packages/core/core-flows/src/product/workflows/create-product-types.ts` | ワークフロー | 作成処理 |
| update-product-types.ts | `packages/core/core-flows/src/product/workflows/update-product-types.ts` | ワークフロー | 更新処理 |
| delete-product-types.ts | `packages/core/core-flows/src/product/workflows/delete-product-types.ts` | ワークフロー | 削除処理 |
