# 通知設計書 2-New Services Installed

## 概要

本ドキュメントは、Shopwareにおいて新しいサービス（プラグイン/アプリ）がインストールされた際に管理者へ送信される「New Services Installed」通知の設計書である。この通知は管理画面のリアルタイム通知として実装されている。

### 本通知の処理概要

New Services Installed通知は、システムに新しいサービスがインストールされた際に、管理者に対して管理画面のリロードを促すためのアプリ内通知である。

**業務上の目的・背景**：ECサイトの拡張性を確保するため、Shopwareではプラグインやアプリを動的にインストールできる。新しいサービスのインストール完了後、管理画面に新機能が追加される可能性があるため、管理者にリロードを促して最新の状態を反映させる必要がある。

**通知の送信タイミング**：NewServicesInstalledEventがディスパッチされた時点。このイベントはサービスのライフサイクル管理においてインストール処理完了後に発火する。

**通知の受信者**：管理者権限（isAdmin）を持つユーザー、またはsystem.plugin_maintain権限を持つユーザー。adminOnlyフラグがtrueに設定されているため、一般ユーザーには表示されない。

**通知内容の概要**：「New services have been installed. Reload your administration to see what's new.」という固定メッセージが表示される。ステータスはpositiveで、成功を示す緑色のトースト通知として表示される。

**期待されるアクション**：管理者は通知を確認後、ブラウザをリロードして新しくインストールされたサービスの機能を管理画面で利用できるようにする。

## 通知種別

アプリ内通知（管理画面リアルタイム通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（イベント駆動 + ポーリング取得） |
| 優先度 | 中 |
| リトライ | なし（データベース永続化） |

### 送信先決定ロジック

1. adminOnly=trueのため、管理者権限を持つユーザーのみ
2. requiredPrivileges=['system.plugin_maintain']のため、プラグイン管理権限を持つユーザーも対象
3. 通知取得時にNotificationServiceでフィルタリング

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示形式 | トースト通知 |
| ステータス | positive（成功/緑色） |

### 本文テンプレート

```
New services have been installed. Reload your administration to see what's new.
```

固定メッセージであり、変数展開なし。

### 添付ファイル

なし（アプリ内通知のため非対応）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定メッセージのため変数なし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システムイベント | NewServicesInstalledEvent | イベント発火時に必ず送信 | サービスインストール完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | イベント発火時は必ず通知を作成 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[サービスインストール完了] --> B[NewServicesInstalledEventディスパッチ]
    B --> C[ServiceLifecycleSubscriber::sendInstalledNotification]
    C --> D[Notification::newServicesInstalled]
    D --> E[NotificationService::createNotification]
    E --> F[notificationテーブルにINSERT]
    F --> G[通知作成完了]

    H[管理者ログイン中] --> I[AdminNotificationWorker]
    I --> J[5秒間隔でポーリング]
    J --> K[GET /api/notification/message]
    K --> L{権限チェック}
    L -->|isAdmin or 権限あり| M[通知取得]
    L -->|権限なし| N[通知スキップ]
    M --> O[トースト通知表示]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| notification | 通知データ取得 | ポーリング時に参照 |

### テーブル別参照項目詳細

#### notification

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | 通知識別子 | - |
| status | ステータス表示 | - |
| message | メッセージ表示 | - |
| admin_only | 管理者限定判定 | WHERE admin_only = true |
| required_privileges | 権限チェック | - |
| created_at | タイムスタンプ比較 | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| notification | INSERT | 通知レコード作成 |

#### notification

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | id | UUID | Uuid::randomHex() |
| INSERT | status | 'positive' | 固定値 |
| INSERT | message | 'New services have been installed...' | 固定値 |
| INSERT | admin_only | true | 固定値 |
| INSERT | required_privileges | ['system.plugin_maintain'] | 固定値 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| DB接続エラー | データベース障害時 | 例外発生、ログ記録 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（イベント駆動のため） |

### 配信時間帯

制限なし（イベント発生時即時）

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

- adminOnly=trueにより一般ユーザーからの参照を防止
- requiredPrivilegesによる追加の権限チェック
- SYSTEM_SCOPEでの通知作成により不正な操作を防止

## 備考

- 本通知はAdmin Notification（No.1）の仕組みを利用した特定用途の通知実装
- メッセージは国際化対応されておらず英語固定（将来的な改善ポイント）
- サービス名などの動的情報は含まれない

---

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

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

### 推奨読解順序

#### Step 1: イベントの発火元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NewServicesInstalledEvent.php | `src/Core/Service/Event/NewServicesInstalledEvent.php` | イベントクラスの構造を確認 |

**読解のコツ**: Shopwareのイベントシステムはsymfony/event-dispatcherを使用。Event継承クラスを確認。

#### Step 2: イベントハンドラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ServiceLifecycleSubscriber.php | `src/Core/Service/Subscriber/ServiceLifecycleSubscriber.php` | イベント購読設定、ハンドラメソッドを確認 |

**主要処理フロー**:
1. **行28-35**: getSubscribedEvents() - イベント購読定義
2. **行42-45**: sendInstalledNotification() - 通知送信処理

#### Step 3: 通知作成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Notification.php | `src/Core/Service/Notification.php` | newServicesInstalled()メソッドの実装 |

**主要処理フロー**:
- **行20-32**: newServicesInstalled() - 固定値での通知作成

#### Step 4: 通知の保存・取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NotificationService.php | `src/Core/Framework/Notification/NotificationService.php` | createNotification/getNotificationsの実装 |

**主要処理フロー**:
- **行33-38**: createNotification() - SYSTEM_SCOPEでの保存
- **行43-91**: getNotifications() - 権限ベースの取得

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

```
NewServicesInstalledEvent [イベントディスパッチ]
    │
    └─ ServiceLifecycleSubscriber::sendInstalledNotification()
           │
           └─ Notification::newServicesInstalled()
                  │
                  └─ NotificationService::createNotification()
                         │
                         ├─ Context::scope(SYSTEM_SCOPE)
                         │
                         └─ EntityRepository::create()
                                │
                                └─ INSERT INTO notification
```

### データフロー図

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

NewServicesInstalledEvent     ServiceLifecycleSubscriber          DB Insert
                              sendInstalledNotification()
                                    │
                                    ▼
                              Notification
                              newServicesInstalled()
                                    │
                                    ▼
                              固定データ作成
                              - id: UUID
                              - status: 'positive'
                              - message: 固定文
                              - adminOnly: true
                              - requiredPrivileges: [...]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ServiceLifecycleSubscriber.php | `src/Core/Service/Subscriber/ServiceLifecycleSubscriber.php` | ソース | イベントサブスクライバー |
| Notification.php | `src/Core/Service/Notification.php` | ソース | 通知作成ヘルパー |
| NewServicesInstalledEvent.php | `src/Core/Service/Event/NewServicesInstalledEvent.php` | ソース | イベントクラス |
| NotificationService.php | `src/Core/Framework/Notification/NotificationService.php` | ソース | 通知サービス |
| NotificationDefinition.php | `src/Core/Framework/Notification/NotificationDefinition.php` | ソース | エンティティ定義 |
| admin-notification-worker.js | `src/Administration/Resources/app/administration/src/core/worker/admin-notification-worker.js` | ソース | フロントエンド表示 |
