# 機能設計書 29-クイックビュー

## 概要

本ドキュメントは、Shopwareストアフロントにおけるクイックビュー機能の設計を記述したものである。本機能は、商品一覧画面などから商品の詳細情報をモーダルで簡易表示する機能を提供する。

### 本機能の処理概要

クイックビュー機能は、ページ遷移なしに商品の基本情報をモーダルウィンドウで表示し、顧客が素早く商品を確認できるようにする機能を提供する。

**業務上の目的・背景**：ECサイトにおいて、商品一覧を閲覧中に各商品の詳細を確認するために毎回ページ遷移すると、ユーザー体験が損なわれる。クイックビューを提供することで、顧客は現在のページを離れることなく商品の基本情報を確認でき、複数商品の比較検討が容易になる。これにより、商品の閲覧効率が向上し、購買意欲の維持・向上に寄与する。

**機能の利用シーン**：
- 商品一覧ページで商品の詳細を素早く確認したい場合
- 検索結果から商品を比較検討する場合
- カテゴリページで複数の商品を効率的に閲覧する場合
- カートに追加する前に商品情報を確認する場合

**主要な処理内容**：
1. 商品IDによる商品データの取得
2. 関連データ（メーカー、オプション、プロパティ）の読み込み
3. モーダル用のMinimalQuickViewPageを生成
4. モーダルテンプレートのレンダリング

**関連システム・外部連携**：
- AbstractProductDetailRoute: 商品詳細データ取得API
- イベントディスパッチャー: MinimalQuickViewPageCriteriaEvent、MinimalQuickViewPageLoadedEvent

**権限による制御**：
- 公開商品は認証不要でアクセス可能
- XmlHttpRequest（AJAX）として動作

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | 商品クイックビュー | 主画面 | 商品の簡易表示モーダル（ProductController::quickviewMinimal） |

## 機能種別

CRUD操作（Read） / AJAX / モーダル表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| productId | string | Yes | 商品ID（URLパラメータ） | UUID形式 |

### 入力データソース

- URLルートパラメータ（productId）
- SalesChannelContext（販売チャネル情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | MinimalQuickViewPage | クイックビューページオブジェクト |
| page.product | SalesChannelProductEntity | 商品データ |

#### 商品データの詳細項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| product.name | string | 商品名 |
| product.description | string | 商品説明 |
| product.productNumber | string | 商品番号 |
| product.price | PriceCollection | 価格情報 |
| product.manufacturer | ProductManufacturerEntity | メーカー情報 |
| product.cover | ProductMediaEntity | カバー画像 |
| product.options | PropertyGroupOptionCollection | 商品オプション |
| product.properties | PropertyGroupOptionCollection | 商品プロパティ |

### 出力先

- HTMLレスポンス（Twigテンプレート: `@Storefront/storefront/component/product/quickview/minimal.html.twig`）

## 処理フロー

### 処理シーケンス

```
1. quickviewMinimal（GET /quickview/{productId}）
   └─ productIdをURLから取得
   └─ MinimalQuickViewPageLoader.loadを呼び出し
      └─ Criteria構築（Association設定）
      └─ MinimalQuickViewPageCriteriaEventを発火
      └─ AbstractProductDetailRoute.loadで商品取得
      └─ MinimalQuickViewPageを生成
      └─ MinimalQuickViewPageLoadedEventを発火
   └─ ProductQuickViewWidgetLoadedHookを発火
   └─ minimal.html.twigをレンダリング
```

### フローチャート

```mermaid
flowchart TD
    A[クイックビューリクエスト] --> B[productIdをURLから取得]
    B --> C{productId存在?}
    C -->|No| D[MissingRequestParameterException]
    C -->|Yes| E[Criteria構築]
    E --> F[MinimalQuickViewPageCriteriaEvent発火]
    F --> G[AbstractProductDetailRoute.load]
    G --> H{商品存在?}
    H -->|No| I[ProductNotFoundException]
    H -->|Yes| J[MinimalQuickViewPage生成]
    J --> K[MinimalQuickViewPageLoadedEvent発火]
    K --> L[ProductQuickViewWidgetLoadedHook発火]
    L --> M[Twigレンダリング]
    M --> N[HTMLレスポンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | 商品ID必須 | URLにproductIdが含まれていること | 常時 |
| BR-29-02 | 公開状態確認 | 販売チャネルで有効かつ公開状態の商品のみ表示 | 常時 |
| BR-29-03 | 最小データ取得 | 商品詳細ページより少ないAssociationで効率的にデータ取得 | 常時 |
| BR-29-04 | XmlHttpRequest | AJAX呼び出しとして動作 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 商品取得 | product | SELECT | 商品基本情報 |
| メーカー取得 | product_manufacturer | SELECT | メーカー情報 |
| メディア取得 | product_media | SELECT | 商品画像（positionソート） |
| オプション取得 | property_group_option | SELECT | 商品オプション |
| プロパティ取得 | property_group_option | SELECT | 商品プロパティ |
| カテゴリ取得 | category | SELECT | メインカテゴリ |

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

#### Criteria Association設定

以下のAssociationがCriteriaに設定される：
- manufacturer.media
- options.group
- properties.group
- mainCategories.category
- media（position昇順でソート）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MISSING_REQUEST_PARAMETER | パラメータ不足 | productIdが指定されていない | 400エラー |
| PRODUCT_NOT_FOUND | 商品不在 | 指定された商品が存在しないまたは非公開 | エラーレスポンス |

### リトライ仕様

リトライ処理は行わない。商品が存在しない場合はエラーレスポンスを返却。

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

本機能は参照のみのため、トランザクション制御は不要。

## パフォーマンス要件

- レスポンス: 500ms以内
- 商品詳細ページより軽量なAssociationで高速レスポンス
- XmlHttpRequestによるページ全体の再読み込み不要

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

- 公開商品のみ表示（販売チャネルの設定に従う）
- XSS対策（Twigの自動エスケープ）
- AJAX専用エンドポイント

## 備考

- 本機能は商品詳細ページ（No.27）より軽量版として設計されている
- CMSページレイアウトは適用されない（最小限の表示）
- メタ情報（SEO）の設定は行わない
- カートへの商品追加機能と連携して使用される

---

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

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

### 推奨読解順序

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

クイックビュー固有のデータ構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MinimalQuickViewPage.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPage.php` | クイックビューページ構造（productプロパティのみ） |

**読解のコツ**: MinimalQuickViewPageは非常にシンプルで、productプロパティのみを持つ。ProductPageと異なり、configuratorSettingsやcmsPageは含まない。

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

処理の起点となるコントローラーを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ProductController.php | `src/Storefront/Controller/ProductController.php` | quickviewMinimalメソッド |

**主要処理フロー**:
1. **130-143行目**: `quickviewMinimal`メソッド - クイックビュー表示処理
2. **133行目**: XmlHttpRequest属性
3. **138行目**: MinimalQuickViewPageLoader.load呼び出し
4. **140行目**: ProductQuickViewWidgetLoadedHook発火
5. **142行目**: Twigレンダリング

#### Step 3: ページローダーを理解する

クイックビューページの読み込み処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MinimalQuickViewPageLoader.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPageLoader.php` | ページデータの組み立て |

**主要処理フロー**:
- **32-61行目**: `load`メソッド - ページデータの読み込み
- **34-37行目**: productIdの取得と検証
- **39-43行目**: Criteria構築（Association設定）
- **45-47行目**: mediaのソート設定
- **49行目**: MinimalQuickViewPageCriteriaEvent発火
- **51-52行目**: AbstractProductDetailRoute.load
- **54行目**: MinimalQuickViewPage生成
- **56-58行目**: MinimalQuickViewPageLoadedEvent発火

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

```
ProductController
    │
    └─ quickviewMinimal (GET /quickview/{productId})
           │
           ├─ MinimalQuickViewPageLoader.load
           │      ├─ Criteria構築
           │      │      ├─ manufacturer.media Association
           │      │      ├─ options.group Association
           │      │      ├─ properties.group Association
           │      │      └─ mainCategories.category Association
           │      │
           │      ├─ MinimalQuickViewPageCriteriaEvent dispatch
           │      │
           │      ├─ AbstractProductDetailRoute.load
           │      │      └─ 商品データ取得
           │      │
           │      ├─ MinimalQuickViewPage生成
           │      │
           │      └─ MinimalQuickViewPageLoadedEvent dispatch
           │
           ├─ ProductQuickViewWidgetLoadedHook dispatch
           │
           └─ renderStorefront (minimal.html.twig)
```

### データフロー図

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

GET /quickview/{productId} ────┬──────────────────────────────────► モーダルHTML
(XmlHttpRequest)               │
                               ▼
                    ┌─────────────────────┐
                    │ ProductController   │
                    │ ::quickviewMinimal  │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │ MinimalQuickView    │
                    │ PageLoader.load     │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │ ProductDetailRoute  │◄──── product
                    │ .load               │      product_manufacturer
                    └─────────┬───────────┘      product_media
                              │                  property_group_option
                              ▼
                    ┌─────────────────────┐
                    │ MinimalQuickView    │
                    │ Page                │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │ Twig Template       │
                    │ (minimal.html.twig) │─────────────────────────► HTMLレスポンス
                    └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ProductController.php | `src/Storefront/Controller/ProductController.php` | ソース | コントローラー（エントリーポイント） |
| MinimalQuickViewPageLoader.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPageLoader.php` | ソース | ページデータ読み込み |
| MinimalQuickViewPage.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPage.php` | ソース | ページビューモデル |
| AbstractProductDetailRoute.php | `src/Core/Content/Product/SalesChannel/Detail/AbstractProductDetailRoute.php` | ソース | 商品詳細取得API抽象クラス |
| MinimalQuickViewPageCriteriaEvent.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPageCriteriaEvent.php` | ソース | Criteria構築イベント |
| MinimalQuickViewPageLoadedEvent.php | `src/Storefront/Page/Product/QuickView/MinimalQuickViewPageLoadedEvent.php` | ソース | ページ読み込み完了イベント |
| ProductQuickViewWidgetLoadedHook.php | `src/Storefront/Page/Product/QuickView/ProductQuickViewWidgetLoadedHook.php` | ソース | ウィジェット読み込み完了フック |
| minimal.html.twig | `src/Storefront/Resources/views/storefront/component/product/quickview/minimal.html.twig` | テンプレート | クイックビュー表示テンプレート |
