# 機能設計書: プラグイン設定管理

## 1. 機能概要

### 1.1 機能の目的
プラグイン設定管理機能は、InvenTreeシステムにインストールされたプラグインの設定を管理するための機能である。プラグインの有効化/無効化、インストール/アンインストール、各種設定値の管理を行う。

### 1.2 機能の範囲
- プラグイン一覧の表示・フィルタリング
- プラグインの有効化/無効化
- プラグインのインストール/アンインストール
- プラグイン設定の参照・更新
- プラグインユーザー設定の管理
- プラグインレジストリの管理

### 1.3 関連画面
| 画面ID | 画面名 | 関連操作 |
|--------|--------|----------|
| SCR-PLUGIN-LIST | プラグイン一覧 | プラグインの検索・有効化 |
| SCR-PLUGIN-DETAIL | プラグイン詳細 | 設定の編集 |
| SCR-ADMIN | 管理画面 | プラグイン管理 |

## 2. 機能仕様

### 2.1 プラグイン一覧API

#### 2.1.1 エンドポイント
- **URL**: `GET /api/plugins/plugins/`
- **メソッド**: GET
- **シリアライザ**: `PluginConfigSerializer`
- **権限**: 認証済みユーザー（読み取り）

#### 2.1.2 フィルタパラメータ
| パラメータ名 | 型 | 説明 |
|-------------|------|------|
| active | Boolean | 有効/無効 |
| mixin | String | ミックスイン名（カンマ区切り対応） |
| builtin | Boolean | 組み込みプラグインか |
| mandatory | Boolean | 必須プラグインか |
| sample | Boolean | サンプルプラグインか |
| installed | Boolean | インストール済みか |

#### 2.1.3 検索フィールド
- key
- name

#### 2.1.4 ソートフィールド
- key
- name
- active

### 2.2 プラグイン詳細API

#### 2.2.1 エンドポイント
- **URL**: `GET/DELETE /api/plugins/plugins/{key}/`
- **ルックアップフィールド**: key（プラグインキー）
- **シリアライザ**: `PluginConfigSerializer`
- **権限**: スーパーユーザー（削除）、読み取りは認証ユーザー

#### 2.2.2 削除制約
- アクティブなプラグインは削除不可
- 削除前に無効化が必要

### 2.3 プラグインの有効化/無効化

#### 2.3.1 エンドポイント
- **URL**: `PATCH /api/plugins/plugins/{key}/activate/`
- **シリアライザ**: `PluginActivateSerializer`
- **権限**: スーパーユーザー

#### 2.3.2 入力パラメータ
| パラメータ名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| active | Boolean | No | 有効化フラグ（省略時true） |
| pk | Integer | No | プラグインPK（代替指定） |

### 2.4 プラグインのインストール

#### 2.4.1 エンドポイント
- **URL**: `POST /api/plugins/plugins/install/`
- **シリアライザ**: `PluginConfigInstallSerializer`
- **権限**: スーパーユーザー

#### 2.4.2 入力パラメータ
| パラメータ名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| packagename | String | No | PyPIパッケージ名 |
| url | String | No | GitリポジトリURL |
| confirm | Boolean | Yes | インストール確認 |

### 2.5 プラグインのアンインストール

#### 2.5.1 エンドポイント
- **URL**: `PATCH /api/plugins/plugins/{key}/uninstall/`
- **シリアライザ**: `PluginUninstallSerializer`
- **権限**: スーパーユーザー

### 2.6 プラグインの再読み込み

#### 2.6.1 エンドポイント
- **URL**: `POST /api/plugins/plugins/reload/`
- **シリアライザ**: `PluginReloadSerializer`
- **権限**: スーパーユーザー

### 2.7 プラグイン設定管理

#### 2.7.1 設定一覧
- **URL**: `GET /api/plugins/plugins/{key}/settings/`
- **シリアライザ**: `PluginSettingSerializer`
- **権限**: グローバル設定権限

#### 2.7.2 設定詳細
- **URL**: `GET/PATCH /api/plugins/plugins/{key}/settings/{setting_key}/`
- **シリアライザ**: `PluginSettingSerializer`
- **権限**: グローバル設定権限

### 2.8 プラグインユーザー設定

#### 2.8.1 ユーザー設定一覧
- **URL**: `GET /api/plugins/plugins/{key}/user-settings/`
- **シリアライザ**: `PluginUserSettingSerializer`
- **権限**: ユーザー設定権限

#### 2.8.2 ユーザー設定詳細
- **URL**: `GET/PATCH /api/plugins/plugins/{key}/user-settings/{setting_key}/`
- **シリアライザ**: `PluginUserSettingSerializer`
- **権限**: ユーザー設定権限

## 3. データモデル

### 3.1 PluginConfigモデル
```python
class PluginConfig(models.Model):
    key = models.CharField(max_length=255, unique=True)
    name = models.CharField(max_length=255, blank=True)
    active = models.BooleanField(default=False)
    # ... メタデータフィールド
```

### 3.2 PluginSettingモデル
```python
class PluginSetting(InvenTree.models.InvenTreeSettingModel):
    plugin = models.ForeignKey(PluginConfig, ...)
    key = models.CharField(max_length=255)
    value = models.CharField(max_length=2000, blank=True)
```

### 3.3 PluginUserSettingモデル
```python
class PluginUserSetting(InvenTree.models.InvenTreeSettingModel):
    plugin = models.ForeignKey(PluginConfig, ...)
    user = models.ForeignKey(User, ...)
    key = models.CharField(max_length=255)
    value = models.CharField(max_length=2000, blank=True)
```

### 3.4 関連エンティティ
```
PluginConfig
├── key: プラグイン識別子（一意）
├── name: プラグイン名
├── active: 有効フラグ
│
├── PluginSetting (設定: 1:N)
│   ├── key: 設定キー
│   └── value: 設定値
│
└── PluginUserSetting (ユーザー設定: 1:N)
    ├── user: ユーザー
    ├── key: 設定キー
    └── value: 設定値
```

## 4. API仕様

### 4.1 プラグイン一覧取得
```
GET /api/plugins/plugins/
```

### 4.2 有効なプラグインのみ
```
GET /api/plugins/plugins/?active=true
```

### 4.3 ミックスインでフィルタ
```
GET /api/plugins/plugins/?mixin=labels,report
```

### 4.4 プラグインの有効化
```
PATCH /api/plugins/plugins/my-plugin/activate/
Content-Type: application/json

{
  "active": true
}
```

### 4.5 プラグイン設定の更新
```
PATCH /api/plugins/plugins/my-plugin/settings/MY_SETTING/
Content-Type: application/json

{
  "value": "new_value"
}
```

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

### 5.1 推奨読解順序

1. **モデル定義**
   - `src/backend/InvenTree/plugin/models.py`
     - **PluginConfig**: プラグイン設定モデル
     - **PluginSetting**: プラグイン設定モデル
     - **PluginUserSetting**: ユーザー設定モデル

2. **フィルタ定義**
   - `src/backend/InvenTree/plugin/api.py`
     - **41-134行目**: `PluginFilter` - プラグインフィルタ

3. **APIエンドポイント**
   - `src/backend/InvenTree/plugin/api.py`
     - **137-159行目**: `PluginList` - 一覧API
     - **162-193行目**: `PluginDetail` - 詳細API
     - **208-228行目**: `PluginInstall` - インストールAPI
     - **231-242行目**: `PluginUninstall` - アンインストールAPI
     - **245-269行目**: `PluginActivate` - 有効化API
     - **272-281行目**: `PluginReload` - 再読み込みAPI
     - **284-307行目**: `PluginSettingList` - 設定一覧API
     - **389-418行目**: `PluginSettingDetail` - 設定詳細API
     - **421-450行目**: `PluginUserSettingList` - ユーザー設定一覧API
     - **453-477行目**: `PluginUserSettingDetail` - ユーザー設定詳細API

4. **URLルーティング**
   - `src/backend/InvenTree/plugin/api.py`
     - **519-602行目**: `plugin_api_urls` - URLルーティング

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

```
[API Request: GET /api/plugins/plugins/]
    │
    ▼
PluginList.get()
    │
    ├── PluginFilter [41-134行目]
    │   ├── filter_mixin() [57-77行目]
    │   │   └── ミックスインでフィルタ
    │   ├── filter_builtin() [83-91行目]
    │   │   └── 組み込みプラグインでフィルタ
    │   ├── filter_mandatory() [97-106行目]
    │   │   └── 必須プラグインでフィルタ
    │   ├── filter_sample() [112-120行目]
    │   │   └── サンプルプラグインでフィルタ
    │   └── filter_installed() [126-134行目]
    │       └── インストール済みでフィルタ
    │
    └── PluginConfigSerializer.to_representation()
        └── レスポンス生成
```

```
[API Request: PATCH /api/plugins/plugins/{key}/activate/]
    │
    ▼
PluginActivate.patch()
    │
    ├── get_object() [261-265行目]
    │   └── keyまたはpkでプラグイン取得
    │
    ├── PluginActivateSerializer.is_valid()
    │
    └── perform_update() [267-269行目]
        └── serializer.save()
            └── プラグインの有効化/無効化処理
```

### 5.3 データフロー図

```
[プラグイン設定更新]
    │
    ▼
┌─────────────────────────────────────┐
│ PluginSettingDetail.patch()         │
│ ・plugin: プラグインキー           │
│ ・key: 設定キー                    │
│ ・value: 新しい値                  │
└─────────────────────────────────────┘
    │
    ├── check_plugin() [310-358行目]
    │   ├── プラグイン存在確認
    │   ├── プラグイン有効確認
    │   └── プラグインオブジェクト返却
    │
    ▼
┌─────────────────────────────────────┐
│ PluginSettingSerializer             │
│ ・バリデーション                   │
│ ・PluginSetting更新               │
└─────────────────────────────────────┘
```

### 5.4 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `src/backend/InvenTree/plugin/models.py` | Model | PluginConfig, PluginSetting, PluginUserSettingモデル定義 |
| `src/backend/InvenTree/plugin/serializers.py` | Serializer | プラグイン関連シリアライザ定義 |
| `src/backend/InvenTree/plugin/api.py` | API | RESTful APIエンドポイント定義 |
| `src/backend/InvenTree/plugin/registry.py` | Registry | プラグインレジストリ管理 |
| `src/backend/InvenTree/plugin/plugin.py` | Base | InvenTreePluginベースクラス |

## 6. 例外処理

### 6.1 バリデーションエラー
| エラー条件 | エラーメッセージ |
|-----------|-----------------|
| プラグイン未検出 | "Plugin not found" |
| プラグイン非アクティブ | "Plugin '{ref}' is not active" |
| 設定キー未検出 | "Plugin '{slug}' has no setting matching '{key}'" |
| アクティブなプラグインの削除 | "Plugin cannot be deleted as it is currently active" |

### 6.2 権限エラー
| エラー条件 | 必要権限 |
|-----------|---------|
| プラグイン有効化 | スーパーユーザー |
| プラグインインストール | スーパーユーザー |
| プラグインアンインストール | スーパーユーザー |
| グローバル設定変更 | グローバル設定権限 |

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

- プラグインの有効化/インストールはスーパーユーザー権限が必要
- プラグイン設定の変更にはグローバル設定権限が必要
- ユーザー設定は各ユーザーの権限で管理
- プラグインコードはサーバー上で実行されるため、信頼できるソースからのみインストール
