# 画面設計書 33-商品一覧

## 概要

本ドキュメントは、Shopware 6 管理画面（Administration）の商品一覧画面の設計仕様を定義します。この画面は商品管理機能のメイン画面であり、登録されているすべての商品を一覧表示し、検索、フィルタリング、編集、削除などの操作を提供します。

### 本画面の処理概要

**業務上の目的・背景**：商品一覧画面は、ECショップの商品カタログを管理するための中核機能です。管理者は商品在庫の確認、価格設定の確認、商品ステータスの管理、商品の検索・フィルタリングなどを行います。大量の商品を効率的に管理するため、高度な検索・フィルタ機能と、インライン編集機能を提供します。

**画面へのアクセス方法**：左側メインナビゲーションの「カタログ」>「商品」をクリックしてアクセスします。URLパスは `/admin#/sw/product/index` です。権限 `product.viewer` が必要です。

**主要な操作・処理内容**：
1. 商品一覧の表示：ページネーション付きで商品を一覧表示
2. 商品検索：キーワードによる商品検索（バリアント含む）
3. フィルタリング：商品番号、アクティブ状態、在庫、価格、メーカーなどでフィルタ
4. 並び替え：各カラムでのソート（作成日時デフォルト、降順）
5. インライン編集：一覧上で直接商品名、在庫数、アクティブ状態を編集
6. 商品複製：既存商品のクローン作成
7. 一括編集：複数商品の同時編集機能へのアクセス
8. 言語切替：表示言語の変更

**画面遷移**：商品名をクリックすると商品詳細編集画面に遷移します。「新規商品」ボタンで商品作成画面に遷移します。バリアント表示モーダルからバリアント詳細に遷移できます。

**権限による表示制御**：
- `product.viewer`: 商品一覧の閲覧
- `product.editor`: インライン編集、商品複製
- `product.creator`: 新規商品作成ボタンの表示
- `product.deleter`: 削除ボタンの表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | 商品詳細表示 | 主機能 | 商品の一覧表示・検索・フィルタリング |

## 画面種別

一覧

## URL/ルーティング

- **URLパス**: `/admin#/sw/product/index`
- **ルート名**: `sw.product.index`
- **モジュール名**: `sw-product`
- **エンティティ**: `product`

## 入出力項目

### フィルタ入力項目

| 項目名 | 項目ID | 入力形式 | 説明 |
|--------|--------|----------|------|
| 商品番号 | product-number-filter | テキスト | 商品番号での完全一致検索 |
| アクティブ | active-filter | セレクト | 有効/無効の絞り込み |
| 画像なし | product-without-images-filter | セレクト | 画像の有無で絞り込み |
| 発売日 | release-date-filter | 日時範囲 | 発売日の範囲指定 |
| 在庫 | stock-filter | 数値範囲 | 在庫数の範囲指定 |
| 価格 | price-filter | 数値範囲 | 価格の範囲指定 |
| メーカー | manufacturer-filter | エンティティ選択 | メーカーでの絞り込み |
| 販売チャネル | visibilities-filter | エンティティ選択 | 販売チャネルでの絞り込み |
| カテゴリ | categories-filter | エンティティ選択 | カテゴリでの絞り込み |
| 売上数 | sales-filter | 数値範囲 | 売上数の範囲指定 |
| タグ | tags-filter | エンティティ選択 | タグでの絞り込み |
| 商品タイプ | product-type-filter | マルチセレクト | 物理商品/デジタル商品の絞り込み |

### 検索入力項目

| 項目名 | 項目ID | 入力形式 | 説明 |
|--------|--------|----------|------|
| 検索キーワード | term | テキスト | 商品名、商品番号などで検索 |

## 表示項目

### 一覧カラム

| 項目名 | property | 表示形式 | インライン編集 | デフォルト表示 | 説明 |
|--------|----------|----------|---------------|---------------|------|
| 商品名 | name | テキスト+リンク | 可（string） | Yes | 商品詳細へのリンク |
| 商品番号 | productNumber | テキスト | - | Yes | 自然ソート対応 |
| メーカー | manufacturer.name | テキスト | - | Yes | メーカー名 |
| アクティブ | active | チェックボックス | 可（boolean） | Yes | 商品の有効/無効状態 |
| 売上数 | sales | 数値 | - | Yes | 累計売上数 |
| 価格（通貨別） | price-{isoCode} | 通貨 | - | Yes（デフォルト通貨のみ） | 通貨別の価格表示 |
| 在庫 | stock | 数値 | 可（number） | Yes | 現在在庫数 |
| 利用可能在庫 | availableStock | 数値 | - | Yes | 利用可能在庫数 |
| 作成日時 | createdAt | 日時 | - | Yes | 商品作成日時 |
| 更新日時 | updatedAt | 日時 | - | No | 最終更新日時 |

## イベント仕様

### 1-商品一覧取得（getList）

画面表示時および検索・フィルタ・ページング変更時に実行：

1. `productCriteria` に基づいてクエリを構築
2. フィルタ条件を `filterService` でマージ
3. 検索スコアを追加（バリアント検索対応）
4. 親商品のみを取得（`parentId = null`）
5. バリアント検索の場合、親商品IDをクエリに追加
6. 通貨情報を同時に取得
7. 結果を `products` と `currencies` に格納

**主要処理フロー**:
- **315-388行目**: `getList()` メソッドでAPI呼び出し
- **336行目**: 親商品のみをフィルタ（`parentId: null`）
- **357-368行目**: バリアント検索時の親商品ID追加

### 2-インライン編集保存（onInlineEditSave）

一覧上での直接編集保存時の処理：

1. 編集内容の保存を実行
2. 成功時：成功通知を表示
3. 失敗時：一覧を再取得し、エラー通知を表示

### 3-商品複製（onDuplicate）

商品の複製処理：

1. 複製元商品を選択
2. クローンモーダルを表示
3. 複製完了後、新規商品の詳細画面へ遷移

### 4-バリアントモーダル表示（openVariantModal）

バリアント持ち商品のバリアント一覧表示：

1. 商品にバリアントがある場合（`childCount > 0`）
2. バリアント選択モーダルを開く
3. バリアント選択で詳細画面へ遷移

### 5-一括編集（onBulkEditItems）

複数商品の一括編集：

1. 選択された商品を確認
2. デジタル商品の含有をチェック
3. 一括編集画面へ遷移

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | product | SELECT | 商品一覧データの取得 |
| 一覧表示 | currency | SELECT | 通貨情報の取得 |
| インライン編集 | product | UPDATE | 商品情報の更新 |
| 商品削除 | product | DELETE | 商品の削除 |

### テーブル別更新項目詳細

#### product

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | parentId IS NULL、フィルタ条件 | 親商品のみ取得 |
| UPDATE | name, active, stock | インライン編集値 | インライン編集時 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|----------|--------------|
| messageSaveSuccess | 成功 | インライン編集成功 | {name}が保存されました |
| notificationSaveErrorMessageRequiredFieldsInvalid | エラー | バリデーションエラー | 必須フィールドが無効です |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|---------|---------|
| 検索結果なし | 条件に一致する商品なし | 空の状態を表示、フィルタクリアを案内 |
| インライン編集エラー | バリデーション失敗 | エラー通知表示、元の値に戻す |
| 権限エラー | 必要な権限なし | 該当機能を非表示または無効化 |

## 備考

- デフォルトソートは作成日時の降順
- 検索は商品名、商品番号に加えバリアントも対象
- フィルタ状態はユーザー設定として保存される
- 商品タイプフィルタはv6.8.0で`product-states-filter`を置き換え

---

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

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

### 推奨読解順序

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

商品エンティティと関連データの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | product entity | 商品エンティティの定義 | 商品の属性（name, price, stock等）とリレーション |
| 1-2 | default-search-configuration.js | `src/Administration/Resources/app/administration/src/module/sw-product/default-search-configuration.js` | 検索対象フィールドの設定 |

**読解のコツ**: Shopwareの商品は `parentId` で親子関係を持ちます。`parentId = null` が親商品、それ以外がバリアントです。

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

モジュール登録とルーティング設定を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-product/index.js` | モジュール登録、ルート定義、権限設定 |

**主要処理フロー**:
1. **112行目**: `Module.register('sw-product', {...})` でモジュール登録
2. **124-136行目**: `routes.index` で一覧ページのルーティング定義
3. **131-134行目**: `meta.privilege: 'product.viewer'` で閲覧権限を設定
4. **259-277行目**: ナビゲーションメニューの定義

#### Step 3: 一覧コンポーネントを理解する

商品一覧ページのメインロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-list/index.js` | 一覧表示のdata、computed、methodsの実装 |

**主要処理フロー**:
- **31-81行目**: `data()` で状態変数を定義（products, currencies, filterCriteria等）
- **90-92行目**: `productRepository` で商品リポジトリを取得
- **122-136行目**: `productCriteria` でクエリ条件を構築
- **153-260行目**: `listFilterOptions` でフィルタ定義
- **315-388行目**: `getList()` で商品データを取得
- **441-502行目**: `getProductColumns()` で一覧カラムを定義

#### Step 4: 権限設定を理解する

アクセス制御の設定を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-product/acl/index.js` | viewer, editor, creator, deleterの権限定義 |

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

```
sw-product (モジュール)
    |
    +-- sw-product-list (一覧ページコンポーネント)
           |
           +-- createdComponent()
           |      +-- getList() [watch: productCriteria]
           |
           +-- getList()
           |      +-- filterService.mergeWithStoredFilters()
           |      +-- addQueryScores()
           |      +-- productRepository.search(criteria)
           |      +-- currencyRepository.search(currencyCriteria)
           |
           +-- onInlineEditSave()
           |      +-- productRepository.save()
           |      +-- createNotificationSuccess/Error()
           |
           +-- onDuplicate()
           |      +-- sw-product-clone-modal 表示
           |      +-- router.push() → 商品詳細
           |
           +-- openVariantModal()
           |      +-- sw-product-variant-modal 表示
           |
           +-- onBulkEditItems()
                  +-- router.push() → sw.bulk.edit.product
```

### データフロー図

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

検索キーワード  ───▶      sw-product-list            ───▶   商品一覧表示
フィルタ条件              ・productCriteria構築              ページネーション
ページ番号                ・filterService統合               フィルタバッジ
                          ・productRepository.search()

インライン編集  ───▶      onInlineEditSave           ───▶   保存結果通知
                          ・productRepository.save()

商品選択       ───▶       onDuplicate                ───▶   商品詳細画面
                          ・clone処理
                          ・router.push()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-product/index.js` | ソース | モジュール登録・ルーティング定義 |
| index.js | `src/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-list/index.js` | ソース | 一覧ページのメインロジック |
| sw-product-list.html.twig | `src/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-list/sw-product-list.html.twig` | テンプレート | 一覧ページのHTMLテンプレート |
| sw-product-list.scss | `src/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-list/sw-product-list.scss` | スタイル | 一覧ページのスタイル定義 |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-product/acl/index.js` | ソース | 権限マッピング定義 |
| default-search-configuration.js | `src/Administration/Resources/app/administration/src/module/sw-product/default-search-configuration.js` | ソース | 検索設定 |
| sw-product-clone-modal | `src/Administration/Resources/app/administration/src/module/sw-product/component/sw-product-clone-modal/` | ソース | 複製モーダル |
| sw-product-variant-modal | `src/Administration/Resources/app/administration/src/module/sw-product/component/sw-product-variant-modal/` | ソース | バリアント選択モーダル |
