# 機能設計書 79-システム設定更新

## 概要

本ドキュメントは、Fat Free CRM の管理者向けシステム設定更新機能の設計を定義する。この機能により、システム管理者はCRM全体の設定を変更することができる。

### 本機能の処理概要

システム設定更新機能は、Fat Free CRM のシステム全体に適用される各種設定を変更する管理者専用機能である。ホスト設定、ロケール設定、アクセス制御設定、メール設定、ステータス・ステージ設定など、多岐にわたる設定を一括で更新できる。フォームから送信された文字列値は、適切な型（ブーリアン、配列、シンボル）に変換されてからデータベースに保存される。

**業務上の目的・背景**：CRM システムの運用においては、業務要件の変更に応じてシステム設定を調整する必要がある。例えば、新しいステータスの追加、アクセス制御の変更、メール設定の更新などが必要になる。この機能により、管理者はシステムの動作を業務要件に合わせて最適化できる。

**機能の利用シーン**：
- 新しいキャンペーンステータスやリードソースを追加する場合
- デフォルトのアクセス権限を変更する場合
- ユーザー登録方式を変更する場合
- メールサーバー設定を更新する場合
- システムのロケール設定を変更する場合

**主要な処理内容**：
1. 設定パラメータの取得（settings_params）
2. 文字列からの型変換（ブーリアン、配列、シンボル）
3. 各設定項目のデータベース保存（Setting[key] = value）
4. キャッシュのクリア
5. 設定画面へのリダイレクト

**関連システム・外部連携**：本機能で更新される設定には、SMTP設定やEmail Dropbox設定など、外部サービスとの連携設定が含まれる。設定変更後は、関連する外部サービスとの通信に影響を与える。

**権限による制御**：この機能は管理者権限を持つユーザーのみが実行可能である。一般ユーザーは管理画面にアクセスできず、システム設定の更新は行えない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 47 | 設定画面 | 主画面 | システム設定の更新 |

## 機能種別

CRUD操作（Update）/ システム設定

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| settings[host] | String | No | アプリケーションのホスト名 | - |
| settings[base_url] | String | No | ベースURL | - |
| settings[locale] | String | No | デフォルトロケール | - |
| settings[per_user_locale] | String | No | ユーザー別ロケール（'1' or '0'） | Boolean変換 |
| settings[default_access] | String | No | デフォルトアクセス権限 | - |
| settings[user_signup] | String | No | ユーザー登録方式 | Symbol変換 |
| settings[compound_address] | String | No | 住所の複合表示（'1' or '0'） | Boolean変換 |
| settings[task_calendar_with_time] | String | No | タスクカレンダー時刻表示（'1' or '0'） | Boolean変換 |
| settings[require_first_names] | String | No | 名の必須化（'1' or '0'） | Boolean変換 |
| settings[require_last_names] | String | No | 姓の必須化（'1' or '0'） | Boolean変換 |
| settings[require_unique_account_names] | String | No | 取引先名一意性（'1' or '0'） | Boolean変換 |
| settings[account_category] | String | No | 取引先カテゴリ（改行区切り） | Array変換 |
| settings[campaign_status] | String | No | キャンペーンステータス（改行区切り） | Array変換 |
| settings[lead_status] | String | No | リードステータス（改行区切り） | Array変換 |
| settings[lead_source] | String | No | リードソース（改行区切り） | Array変換 |
| settings[opportunity_stage] | String | No | 商談ステージ（改行区切り） | Array変換 |
| settings[task_category] | String | No | タスクカテゴリ（改行区切り） | Array変換 |
| settings[task_bucket] | String | No | タスクバケット（改行区切り） | Array変換 |
| settings[smtp] | Hash | No | SMTP設定 | - |
| settings[email_dropbox] | Hash | No | Email Dropbox設定 | - |
| settings[email_comment_replies] | Hash | No | コメント返信メール設定 | - |

### 入力データソース

- 画面入力（設定画面のフォーム）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | - | リダイレクトのみ（フラッシュメッセージあり） |

### 出力先

- リダイレクト（設定画面）
- フラッシュメッセージ（更新完了通知）
- データベース（settingsテーブル）

## 処理フロー

### 処理シーケンス

```
1. updateアクション呼び出し
   └─ 管理者権限チェック（before_action）
2. パラメータ取得
   └─ settings_params でStrong Parameters適用
3. 型変換処理
   └─ ブーリアン変換（'1' → true, '0' → false）
   └─ 配列変換（改行区切り → 配列）
   └─ シンボル変換（user_signup）
   └─ ネストブーリアン変換（ssl設定）
4. 設定保存
   └─ 各設定項目に対して Setting[key] = value
5. リダイレクト
   └─ 設定画面へリダイレクト（成功メッセージ付き）
```

### フローチャート

```mermaid
flowchart TD
    A[設定保存ボタン押下] --> B{管理者権限?}
    B -->|No| C[リダイレクト]
    B -->|Yes| D[updateアクション]
    D --> E[settings_params]
    E --> F[ブーリアン変換]
    F --> G[配列変換]
    G --> H[シンボル変換]
    H --> I[ネストブーリアン変換]
    I --> J[ループ: 各設定項目]
    J --> K[Setting.key = value]
    K --> L{次の設定あり?}
    L -->|Yes| J
    L -->|No| M[リダイレクト + メッセージ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | 管理者権限必須 | システム設定の更新は管理者ユーザーのみ実行可能 | 常時 |
| BR-79-02 | ブーリアン変換 | '1' は true、'0'/'その他' は false に変換 | 指定されたキーの場合 |
| BR-79-03 | 配列変換 | 改行区切りのテキストは配列に変換 | 指定されたキーの場合 |
| BR-79-04 | 即時反映 | 設定変更は即座に反映される | 設定保存時 |

### 計算ロジック

#### ブーリアン変換対象キー
```
per_user_locale, compound_address, task_calendar_with_time,
require_first_names, require_last_names, require_unique_account_names,
comments_visible_on_dashboard, enforce_international_phone_format,
email_dropbox[:ssl], email_comment_replies[:ssl]
```

#### 配列変換対象キー
```
account_category, campaign_status, lead_status, lead_source,
opportunity_stage, task_category, task_bucket, task_completed,
priority_countries
```

#### シンボル変換対象キー
```
user_signup
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | settings | SELECT | 既存設定の確認 |
| 設定保存 | settings | INSERT/UPDATE | 設定値の保存（UPSERT） |

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

#### settings テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | WHERE name = :key | 既存レコード確認 |
| INSERT | name, value | 新規設定の場合 | serialize によりvalue保存 |
| UPDATE | value, updated_at | 既存設定の場合 | serialize によりvalue保存 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 管理者権限がない | ログインページへリダイレクト |
| 500 | InternalServerError | 設定保存失敗 | エラーログ出力、エラーメッセージ表示 |

### リトライ仕様

リトライは不要（ユーザーが再度保存ボタンを押下）

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

各設定項目は個別に保存される（明示的なトランザクション制御なし）。一部の設定保存が失敗しても、既に保存された設定は反映される。

## パフォーマンス要件

- レスポンス時間：3秒以内（全設定項目の保存を含む）
- 設定項目数に応じてSQL発行回数が増加

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

- 管理者認証必須（before_action :require_admin_user）
- Strong Parameters によるマスアサインメント防止
- CSRF トークン検証（Rails標準）
- パスワード等の機密情報は適切に処理（ただし平文保存に注意）

## 備考

- 設定変更はキャッシュにも反映される（Setting[key] = value 内でキャッシュ更新）
- 一部の設定（ロケール等）は次回リクエストから反映される
- メール設定の変更は即座に反映されるが、接続テスト機能は提供されていない

---

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

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

### 推奨読解順序

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

Setting モデルの設定保存メカニズムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | setting.rb | `app/models/setting.rb` | Setting[]=メソッド、save処理、キャッシュ更新 |

**読解のコツ**: `[]=`メソッドが設定保存の中心。既存レコードがあればupdate、なければcreateを行い、同時にキャッシュも更新する。

**主要処理フロー**:
- **setting.rb 70-79行目**: `[]=` メソッド - 設定値の保存
- **setting.rb 75-78行目**: find_or_new + save + キャッシュ更新

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | settings_controller.rb | `app/controllers/admin/settings_controller.rb` | updateアクション、型変換処理、settings_params |

**主要処理フロー**:
- **19-48行目**: `update` アクション - メイン処理
- **20行目**: `settings_params.to_h.with_indifferent_access` - パラメータ取得
- **26-28行目**: ブーリアン変換 - '1' を true に変換
- **31-32行目**: ネストブーリアン変換 - ssl設定の変換
- **35-37行目**: 配列変換 - 改行区切りを配列に変換
- **40行目**: シンボル変換 - user_signupの変換
- **43-45行目**: 設定保存ループ - 各設定をDB保存
- **47行目**: リダイレクト - 成功メッセージ付き
- **52-86行目**: `settings_params` - Strong Parameters定義

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

```
Admin::SettingsController#update
    │
    ├─ Admin::ApplicationController
    │      └─ require_admin_user（管理者権限チェック）
    │
    ├─ settings_params
    │      └─ params.require(:settings).permit(...)
    │
    ├─ 型変換処理
    │      ├─ ブーリアン変換（per_user_locale等）
    │      ├─ ネストブーリアン変換（email_dropbox[:ssl]等）
    │      ├─ 配列変換（account_category等）
    │      └─ シンボル変換（user_signup）
    │
    ├─ 設定保存ループ
    │      └─ Setting[key] = value
    │             ├─ Setting.find_by_name(key)
    │             │      └─ settings テーブル SELECT
    │             │
    │             ├─ setting.value = value
    │             │
    │             ├─ setting.save
    │             │      └─ settings テーブル INSERT/UPDATE
    │             │
    │             └─ cache[key] = value
    │
    └─ redirect_to admin_settings_path, notice: ...
```

### データフロー図

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

settings[*](Form) ──▶ updateアクション ─────────▶ リダイレクト
                              │
                              ▼
                        settings_params
                              │
                              ▼
                        型変換処理
                              │
                              ├─ ブーリアン変換
                              │      └─ '1' → true / '0' → false
                              │
                              ├─ 配列変換
                              │      └─ "line1\nline2" → ["line1", "line2"]
                              │
                              └─ シンボル変換
                                     └─ "allowed" → :allowed
                              │
                              ▼
                        設定保存ループ
                              │
                              ├─ settings テーブル SELECT
                              │
                              ├─ settings テーブル INSERT/UPDATE
                              │
                              └─ キャッシュ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| setting.rb | `app/models/setting.rb` | モデル | Settingモデル、設定値保存 |
| settings_controller.rb | `app/controllers/admin/settings_controller.rb` | コントローラー | 設定更新処理、型変換 |
| application_controller.rb | `app/controllers/admin/application_controller.rb` | コントローラー | 管理者基底コントローラー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（209-213行目） |
