# 機能設計書 1-ダッシュボード表示

## 概要

本ドキュメントは、Fat Free CRMシステムにおけるダッシュボード表示機能の設計を定義する。この機能は、ログイン後のホーム画面として、ユーザーに関連するアクティビティ履歴、タスク、商談、取引先を一覧表示する。

### 本機能の処理概要

ダッシュボード表示機能は、CRMシステムにおける中核的な情報表示機能である。ユーザーがログイン後に最初に目にする画面であり、業務に必要な情報を一元的に把握できるよう設計されている。

**業務上の目的・背景**：営業担当者やマネージャーは、日々の業務において複数のエンティティ（取引先、商談、タスクなど）を管理する必要がある。ダッシュボードは、これらの情報を一画面に集約し、業務効率の向上と重要な情報の見落とし防止を目的としている。特に、期限が迫ったタスクや進行中の商談を即座に確認できることで、適切なアクションを迅速に取ることが可能となる。

**機能の利用シーン**：
- 営業担当者が出社時に当日のタスクと商談状況を確認する場面
- マネージャーがチーム全体のアクティビティを監視する場面
- 顧客対応前に関連する取引先情報を素早く確認する場面

**主要な処理内容**：
1. ユーザー認証の確認とセッション情報の取得
2. ユーザーに紐づくタスク一覧の取得（期限順でソート、最大10件表示）
3. ユーザーに紐づく商談一覧の取得（クローズ日・金額順でソート、最大10件表示）
4. ユーザーに紐づく取引先一覧の取得（名前順でソート、最大10件表示）
5. 最近のアクティビティ履歴の取得（Version履歴から）
6. 各データをビューにレンダリング

**関連システム・外部連携**：本機能は外部システムとの連携はなく、内部データベースからのデータ取得のみで構成される。XLS形式でのエクスポート機能を提供している。

**権限による制御**：ダッシュボードに表示されるデータは、ユーザーのアクセス権限に基づいてフィルタリングされる。各エンティティの`visible_on_dashboard`スコープにより、ユーザーが所有するデータまたは割り当てられたデータのみが表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | ホーム画面（ダッシュボード） | 主画面 | アクティビティ、タスク、商談、取引先の一覧表示 |

## 機能種別

データ表示（READ操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | 本機能は入力パラメータを必要としない | - |

### 入力データソース

- セッション情報（current_user）からユーザー識別情報を取得
- ユーザー設定（Preference）からアクティビティフィルター設定を取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @activities | Array<Version> | 最近のアクティビティ一覧（最大500件） |
| @my_tasks | ActiveRecord::Relation<Task> | ユーザーのタスク一覧 |
| @my_opportunities | ActiveRecord::Relation<Opportunity> | ユーザーの商談一覧 |
| @my_accounts | ActiveRecord::Relation<Account> | ユーザーの取引先一覧 |

### 出力先

- HTML画面表示（デフォルト）
- XLS形式でのエクスポート（リクエストフォーマットによる）

## 処理フロー

### 処理シーケンス

```
1. authenticate_user!によるユーザー認証確認
   └─ 未認証の場合はログイン画面へリダイレクト
2. set_current_tabによるタブ状態の設定
   └─ @current_tab = 'home'
3. get_activitiesメソッドでアクティビティ取得
   └─ ユーザー設定に基づくフィルタリング
   └─ Version.latest()とvisible_to()による取得
4. Task.visible_on_dashboard()でタスク取得
   └─ ユーザー所有または割り当てられたタスク
   └─ 期限順でソート
5. Opportunity.visible_on_dashboard()で商談取得
   └─ ユーザー所有または割り当てられた商談
   └─ クローズ日・金額順でソート
6. Account.visible_on_dashboard()で取引先取得
   └─ ユーザー所有または割り当てられた取引先
   └─ 名前順でソート
7. レスポンスフォーマットに応じた出力
   └─ HTML: index.html.hamlをレンダリング
   └─ XLS: index.xls.builderをレンダリング
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{認証済み?}
    B -->|No| C[ログイン画面へリダイレクト]
    B -->|Yes| D[タブ状態設定]
    D --> E[アクティビティ取得]
    E --> F[タスク取得]
    F --> G[商談取得]
    G --> H[取引先取得]
    H --> I{フォーマット判定}
    I -->|HTML| J[HTML画面レンダリング]
    I -->|XLS| K[XLSエクスポート]
    J --> L[終了]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 表示件数制限 | 各セクション（タスク、商談、取引先）は最大10件まで表示 | 常時 |
| BR-002 | アクティビティ期間 | デフォルトで過去2日間のアクティビティを表示 | ユーザー設定がない場合 |
| BR-003 | アクセス権限フィルタ | ユーザーが所有または割り当てられたデータのみ表示 | 常時 |
| BR-004 | アクティビティ最大件数 | アクティビティは最大500件まで取得 | 常時 |

### 計算ロジック

特に計算ロジックは存在しない。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| タスク取得 | tasks | SELECT | ユーザーに紐づくタスクを取得 |
| 商談取得 | opportunities | SELECT | ユーザーに紐づく商談を取得 |
| 取引先取得 | accounts | SELECT | ユーザーに紐づく取引先を取得 |
| アクティビティ取得 | versions | SELECT | 最近のアクティビティを取得 |

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

#### tasks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = current_user.id OR assigned_to = current_user.id | visible_on_dashboardスコープ |

#### opportunities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | (user_id = :user_id AND assigned_to IS NULL) OR assigned_to = :user_id | visible_on_dashboardスコープ |

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | (user_id = :user_id AND assigned_to IS NULL) OR assigned_to = :user_id | visible_on_dashboardスコープ |

#### versions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | created_at >= Time.zone.now - duration, whodunnit, item_type, event | latestスコープ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | 未ログイン状態でアクセス | ログイン画面へリダイレクト |
| 500 | サーバーエラー | データベース接続エラー | エラーページ表示 |

### リトライ仕様

本機能ではリトライ処理は実装されていない。

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

本機能はSELECT操作のみであり、トランザクション制御は不要。

## パフォーマンス要件

- 画面表示時間: 3秒以内を目標
- アクティビティ取得の最大件数を500件に制限
- 各セクションの表示件数を10件に制限
- includesによるN+1クエリの回避

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

- 認証: Deviseによるユーザー認証が必須
- 認可: アクセス権限に基づくデータフィルタリング
- CSRF: protect_from_forgeryによる対策
- XSS: ERB::Utilによるエスケープ処理

## 備考

- タイムゾーンはセッションに保存されたユーザーのタイムゾーン設定に従う
- ロケールはユーザー設定またはシステム設定に従う

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | version.rb | `app/models/polymorphic/version.rb` | アクティビティデータの構造、スコープ定義 |
| 1-2 | task.rb | `app/models/polymorphic/task.rb` | タスクデータの構造 |
| 1-3 | account.rb | `app/models/entities/account.rb` | 取引先データの構造、visible_on_dashboardスコープ |
| 1-4 | opportunity.rb | `app/models/entities/opportunity.rb` | 商談データの構造 |

**読解のコツ**: Railsのスコープ定義（`scope :name, -> { ... }`）に注目する。`visible_on_dashboard`スコープがダッシュボードでの表示条件を定義している。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.rb | `config/routes.rb` | ルーティング定義（root to: 'home#index'） |
| 2-2 | home_controller.rb | `app/controllers/home_controller.rb` | indexアクションの処理フロー |

**主要処理フロー**:
1. **13-21行目**: indexアクション - データ取得とレスポンス
2. **14行目**: get_activitiesメソッド呼び出し
3. **15行目**: タスク取得（visible_on_dashboard, includes, by_due_at）
4. **16行目**: 商談取得（visible_on_dashboard, includes, by_closes_on, by_amount）
5. **17行目**: 取引先取得（visible_on_dashboard, includes, by_name）

#### Step 3: アクティビティ取得ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | home_controller.rb | `app/controllers/home_controller.rb` | get_activitiesプライベートメソッド |
| 3-2 | version.rb | `app/models/polymorphic/version.rb` | latestスコープ、visible_toメソッド |

**主要処理フロー**:
- **101-109行目**: get_activitiesメソッド - オプション設定とVersion取得
- **46-54行目（version.rb）**: latestクラスメソッド - 条件に基づくVersion取得
- **65-82行目（version.rb）**: visible_toメソッド - アクセス権限フィルタリング

#### Step 4: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.haml | `app/views/home/index.html.haml` | 画面レイアウト構造 |
| 4-2 | _task.html.haml | `app/views/home/_task.html.haml` | タスク表示パーシャル |
| 4-3 | _opportunity.html.haml | `app/views/home/_opportunity.html.haml` | 商談表示パーシャル |
| 4-4 | _account.html.haml | `app/views/home/_account.html.haml` | 取引先表示パーシャル |
| 4-5 | _activity.html.haml | `app/views/home/_activity.html.haml` | アクティビティ表示パーシャル |

**主要処理フロー**:
- **6-11行目**: タスクセクション - 最大10件表示
- **14-20行目**: 商談セクション - 最大10件表示
- **23-29行目**: 取引先セクション - 最大10件表示
- **39-43行目**: アクティビティセクション

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

```
HomeController#index
    │
    ├─ get_activities (private method)
    │      ├─ activity_asset
    │      ├─ activity_event
    │      ├─ activity_user
    │      ├─ activity_duration
    │      └─ Version.latest().visible_to()
    │
    ├─ Task.visible_on_dashboard(current_user)
    │      └─ includes(:user, :asset).by_due_at
    │
    ├─ Opportunity.visible_on_dashboard(current_user)
    │      └─ includes(:account, :user, :tags).by_closes_on.by_amount
    │
    └─ Account.visible_on_dashboard(current_user)
           └─ includes(:user, :tags).by_name
```

### データフロー図

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

セッション情報 ───▶ HomeController#index ───▶ @activities
(current_user)          │                      @my_tasks
                        │                      @my_opportunities
ユーザー設定 ─────▶     │                      @my_accounts
(Preference)            │                          │
                        ▼                          ▼
                    Version.latest()          index.html.haml
                    Task.visible_on_dashboard()    │
                    Opportunity.visible_on_dashboard()
                    Account.visible_on_dashboard() │
                        │                          ▼
                        │                     HTML/XLS出力
                        ▼
                    データベース
                    (versions, tasks,
                     opportunities, accounts)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| home_controller.rb | `app/controllers/home_controller.rb` | ソース | メインコントローラー |
| application_controller.rb | `app/controllers/application_controller.rb` | ソース | 基底コントローラー |
| version.rb | `app/models/polymorphic/version.rb` | ソース | アクティビティモデル |
| task.rb | `app/models/polymorphic/task.rb` | ソース | タスクモデル |
| account.rb | `app/models/entities/account.rb` | ソース | 取引先モデル |
| opportunity.rb | `app/models/entities/opportunity.rb` | ソース | 商談モデル |
| index.html.haml | `app/views/home/index.html.haml` | テンプレート | メイン画面 |
| _task.html.haml | `app/views/home/_task.html.haml` | テンプレート | タスク表示パーシャル |
| _opportunity.html.haml | `app/views/home/_opportunity.html.haml` | テンプレート | 商談表示パーシャル |
| _account.html.haml | `app/views/home/_account.html.haml` | テンプレート | 取引先表示パーシャル |
| _activity.html.haml | `app/views/home/_activity.html.haml` | テンプレート | アクティビティ表示パーシャル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
