# 画面設計書 37-レビュー管理

## 概要

本ドキュメントは、Shopware 6 管理画面（Administration）のレビュー管理画面の設計仕様を定義します。この画面は顧客が商品に投稿したレビュー（評価）を一覧表示・管理するための機能を提供し、レビューの承認、編集、削除、コメント追加を行います。

### 本画面の処理概要

**業務上の目的・背景**：レビュー管理画面は、顧客からの商品レビューを管理するための機能です。レビューは商品の信頼性向上、購買意思決定の支援、顧客エンゲージメントの向上に貢献します。管理者はレビューのモデレーション（承認/拒否）、不適切なコンテンツの削除、店舗からのコメント追加などを行えます。

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

**主要な操作・処理内容**：
1. レビュー一覧の表示：ページネーション付きでレビューを一覧表示
2. 多彩なフィルタリング：販売チャネル、ステータス、言語、顧客、商品、評価点数でフィルタ
3. 並び替え：ステータス+作成日時でソート（デフォルト）
4. レビュー詳細編集：詳細ページでの編集・コメント追加
5. レビュー削除：不適切なレビューの削除
6. ステータス管理：レビューの承認/非承認状態の管理

**画面遷移**：レビューの商品名をクリックするとレビュー詳細編集画面に遷移します。

**権限による表示制御**：
- `review.viewer`: レビュー一覧の閲覧
- `review.editor`: レビューの編集
- `review.deleter`: 削除ボタンの表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | レビュー管理 | 主機能 | 商品レビューの一覧表示・承認・管理 |

## 画面種別

一覧

## URL/ルーティング

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

### サブルート

| ルート名 | パス | コンポーネント | 説明 |
|---------|------|---------------|------|
| sw.review.detail | `/detail/:id` | sw-review-detail | レビュー詳細編集 |

## 入出力項目

### フィルタ入力項目

| 項目名 | 項目ID | 入力形式 | 説明 |
|--------|--------|----------|------|
| 販売チャネル | sales-channel-filter | エンティティ選択 | 販売チャネルでの絞り込み |
| ステータス | status-filter | ブーリアン | 承認済み/未承認の絞り込み |
| 言語 | language-filter | エンティティ選択 | レビュー言語での絞り込み |
| 顧客 | customer-filter | エンティティ選択 | レビュー投稿者での絞り込み |
| 商品 | product-filter | エンティティ選択 | 対象商品での絞り込み |
| 評価点数 | points-filter | 数値範囲 | 星評価の範囲指定 |

### 検索入力項目

| 項目名 | 項目ID | 入力形式 | 説明 |
|--------|--------|----------|------|
| 検索キーワード | term | テキスト | レビュータイトル、内容で検索 |

## 表示項目

### 一覧カラム

| 項目名 | property | 表示形式 | デフォルト表示 | 説明 |
|--------|----------|----------|---------------|------|
| タイトル | title | テキスト | Yes | レビューのタイトル |
| 評価点数 | points | 数値/星 | Yes | 1-5の評価 |
| 商品 | product.name | テキスト+リンク | Yes（primary） | 対象商品名、詳細へのリンク |
| 投稿者 | customer.lastName, customer.firstName | テキスト | Yes | レビュー投稿者名 |
| 作成日時 | createdAt | 日時 | Yes | レビュー投稿日時 |
| ステータス | status | バッジ | Yes | 承認済み/未承認 |
| コメント | comment | アイコン | Yes | 店舗コメントの有無 |

## イベント仕様

### 1-レビュー一覧取得（getList）

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

1. `criteria` に基づいてクエリを構築
2. `filterService.mergeWithStoredFilters` でフィルタ条件をマージ
3. 関連データ（customer, product, salesChannel, language）をアソシエーション
4. ソート条件を適用（status, createdAt）
5. レビューリポジトリで検索を実行
6. 結果を `items` に格納、`total` を更新

### 2-フィルタ更新（updateCriteria）

フィルタが変更された際の処理：

1. ページを1にリセット
2. クライテリアのフィルタを更新
3. `getList()` を呼び出して一覧を再取得

### 3-レビュー削除（onDelete）

レビューの削除処理：

1. リスティングコンポーネントの削除メソッドを呼び出し
2. リポジトリで検索を再実行
3. 結果を更新

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | product_review | SELECT | レビュー一覧データの取得 |
| 一覧表示 | customer | SELECT | 投稿者情報の取得 |
| 一覧表示 | product | SELECT | 対象商品情報の取得 |
| レビュー削除 | product_review | DELETE | レビューの削除 |

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

#### product_review

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, title, content, points, status, comment, created_at | フィルタ・ソート条件 | 一覧取得 |
| DELETE | id | 指定ID | 削除時 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|----------|--------------|
| deleteSuccess | 成功 | 削除成功 | レビューが削除されました |
| deleteError | エラー | 削除失敗 | 削除中にエラーが発生しました |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|---------|---------|
| 検索結果なし | 条件に一致するレビューなし | 空の状態を表示 |
| 削除エラー | API通信失敗 | エラー通知表示 |
| フィルタエラー | 無効なフィルタ条件 | フィルタをリセット |

## 備考

- デフォルトソートはステータス+作成日時（status, createdAt）
- 継承コンテキストを使用（親商品の情報を含める）
- フィルタ状態は `grid.filter.product_review` キーで保存
- `dateFilter` は v6.8.0 で非推奨

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | product_review entity | レビューエンティティの定義 | title, content, points, status, customer, product等 |

**読解のコツ**: レビューは`product_review`テーブルに保存され、`customer`（投稿者）と`product`（対象商品）への外部キーを持ちます。

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

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

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

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

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

レビュー一覧ページのメインロジックを確認します。

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

**主要処理フロー**:
- **7-14行目**: `DEFAULT_FILTERS` でデフォルトフィルタを定義
- **33-41行目**: `data()` で状態変数を定義
- **51-95行目**: `listFilterOptions` でフィルタ定義（販売チャネル、ステータス、言語、顧客、商品、点数）
- **126-167行目**: `columns()` で一覧カラムを定義
- **174-187行目**: `criteria()` でクエリ条件を構築
- **206-227行目**: `getList()` でレビューデータを取得（継承コンテキスト使用）

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

```
sw-review (モジュール)
    |
    +-- sw-review-list (一覧ページコンポーネント)
           |
           +-- createdComponent()
           |      +-- getList()
           |
           +-- getList()
           |      +-- filterService.mergeWithStoredFilters()
           |      +-- repository.search(criteria, context)
           |
           +-- updateCriteria(criteria)
           |      +-- page = 1
           |      +-- getList()
           |
           +-- onDelete(option)
                  +-- $refs.listing.deleteItem()
                  +-- repository.search()
```

### データフロー図

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

検索キーワード  ───▶      sw-review-list             ───▶   レビュー一覧表示
フィルタ条件              ・criteria構築                    フィルタバッジ
ページ番号                ・filterService統合               activeFilterNumber
                          ・repository.search()

フィルタ変更   ───▶       updateCriteria             ───▶   フィルタ適用
                          ・page リセット                   一覧再取得
                          ・getList()

削除ボタン    ───▶        onDelete                   ───▶   削除結果
                          ・listing.deleteItem()            一覧更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-review/index.js` | ソース | モジュール登録・ルーティング定義 |
| index.js | `src/Administration/Resources/app/administration/src/module/sw-review/page/sw-review-list/index.js` | ソース | 一覧ページのメインロジック |
| sw-review-list.html.twig | `src/Administration/Resources/app/administration/src/module/sw-review/page/sw-review-list/sw-review-list.html.twig` | テンプレート | 一覧ページのHTMLテンプレート |
| sw-review-detail | `src/Administration/Resources/app/administration/src/module/sw-review/page/sw-review-detail/` | ソース | 詳細ページコンポーネント |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-review/acl/index.js` | ソース | 権限マッピング定義 |
