# 機能設計書 34-タスク一覧表示

## 概要

本ドキュメントは、Fat Free CRMシステムにおける「タスク一覧表示」機能の設計を定義する。ユーザーのタスクを期限・ステータス別にグループ化して表示するための機能である。

### 本機能の処理概要

タスク一覧表示機能は、営業活動における ToDo 管理を支援するための機能である。

**業務上の目的・背景**：営業担当者は日々多くのタスク（電話、メール、ミーティング、フォローアップ等）を抱えている。タスクを期限別（今日期限、明日期限、今週期限等）や完了状態別にグループ化して表示することで、優先度の高いタスクを把握しやすくし、業務効率を向上させる。また、他のユーザーに割り当てたタスクの進捗も確認可能。

**機能の利用シーン**：毎日の業務開始時にその日のタスク確認、期限切れタスクの確認と対応、週次でのタスク棚卸し、他メンバーに割り当てたタスクの進捗確認、完了タスクの履歴確認。

**主要な処理内容**：
1. ビュー（pending/assigned/completed）に応じたタスク取得
2. 期限別バケット（due_asap、overdue、due_today等）へのグループ化
3. フィルタ条件に応じた表示制御
4. CSV/XLS形式でのエクスポート

**関連システム・外部連携**：タスクは取引先、連絡先、リード、商談、キャンペーンなどのエンティティに紐付け可能。

**権限による制御**：ユーザーが作成したタスク、または自分に割り当てられたタスクのみ表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | タスク一覧画面 | 主画面 | タスクのグループ化表示、CSV/XLSエクスポート |
| 6 | ホーム画面（ダッシュボード） | 参照画面 | ダッシュボードでのタスク表示 |

## 機能種別

CRUD操作（Read） / データ表示・集計

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| view | String | No | 表示ビュー（pending/assigned/completed） | ALLOWED_VIEWSに含まれること |
| format | String | No | 出力形式（html/xls/csv/xml） | Rails標準形式 |

### 入力データソース

- URLパラメータ（view）
- セッション情報（current_user）
- セッション情報（filter_by_task_{view}）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @view | String | 現在の表示ビュー |
| @tasks | Hash | バケット別タスクのハッシュ |
| @task_total | Hash | バケット別タスク件数 |

### 出力先

- 画面表示（HTML）
- ファイル出力（XLS/CSV）
- API応答（XML/JSON）

## 処理フロー

### 処理シーケンス

```
1. indexリクエスト受信
   └─ GET /tasks?view=pending
2. ビューパラメータの検証
   └─ ALLOWED_VIEWSに含まれるか確認
3. タスクのグループ化取得
   └─ Task.find_all_grouped(current_user, @view)
4. サイドバーデータの更新
   └─ update_sidebar
5. 応答フォーマットに応じた出力
   └─ HTML/XLS/CSV/XML
```

### フローチャート

```mermaid
flowchart TD
    A[一覧リクエスト受信] --> B[ビュー検証]
    B --> C{有効なビュー?}
    C -->|No| D[デフォルトビュー適用]
    C -->|Yes| E[タスク取得]
    D --> E
    E --> F[バケット別グループ化]
    F --> G[サイドバー更新]
    G --> H{出力形式}
    H -->|HTML| I[一覧画面表示]
    H -->|XLS| J[Excelファイル出力]
    H -->|CSV| K[CSVファイル出力]
    H -->|XML| L[XML応答]
    I --> M[完了]
    J --> M
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-34-01 | 表示ビュー | pending/assigned/completedの3種類 | 常時 |
| BR-34-02 | myタスク | 自分が作成または自分に割り当てられたタスク | pending/completed表示時 |
| BR-34-03 | assignedタスク | 自分が他者に割り当てたタスク | assigned表示時 |
| BR-34-04 | バケット分類 | 期限に応じてdue_asap/overdue/due_today等に分類 | pending/assigned表示時 |
| BR-34-05 | 完了分類 | 完了日に応じてtoday/yesterday等に分類 | completed表示時 |
| BR-34-06 | フィルタ保持 | フィルタ状態はセッションに保持 | 常時 |

### 計算ロジック

**バケット分類ロジック**:
- due_asap: due_at IS NULL AND bucket = 'due_asap'
- overdue: due_at < 今日0時
- due_today: 今日0時 <= due_at < 明日0時
- due_tomorrow: 明日0時 <= due_at < 明後日0時
- due_this_week: 明後日0時 <= due_at < 今週末
- due_next_week: 今週末 <= due_at < 来週末
- due_later: due_at >= 来週末 OR (due_at IS NULL AND bucket = 'due_later')

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| タスク取得 | tasks | SELECT | ユーザーのタスク取得 |
| ユーザー取得 | users | SELECT | 担当者情報の取得 |

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

#### tasks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = current_user OR assigned_to = current_user | myスコープ |
| SELECT | * | user_id = current_user AND assigned_to IS NOT NULL AND assigned_to != current_user | assigned_byスコープ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無効なビュー | viewパラメータが無効 | デフォルト（pending）を使用 |

### リトライ仕様

特になし。

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

読み取り専用のため、トランザクション制御は不要。

## パフォーマンス要件

- ページ表示: 1秒以内
- includes(:assignee)によるN+1問題の回避
- バケット別のスコープで効率的なクエリ

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

- ユーザーは自分が作成したタスク、または自分に割り当てられたタスクのみ表示可能
- 他ユーザーのタスクは、自分が割り当てた場合のみassignedビューで確認可能
- XSS対策（出力時のエスケープ）

## 備考

- ALLOWED_VIEWS = %w[pending assigned completed]
- バケットのラベルはSetting.unroll(:task_bucket)から取得
- 完了タスクのバケットはSetting.unroll(:task_completed)から取得
- タスク件数のサマリーはサイドバーに表示

---

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

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

### 推奨読解順序

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

タスクモデルのスコープとグループ化ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | task.rb | `app/models/polymorphic/task.rb` | タスクモデルの構造とスコープ |

**読解のコツ**:
- **8-28行目**: スキーマコメントでテーブル構造を把握
- **35行目**: `ALLOWED_VIEWS = %w[pending assigned completed]` - 許可されるビュー
- **46-53行目**: `my` スコープ - 自分のタスク取得条件
- **59-62行目**: `assigned_by` スコープ - 自分が割り当てたタスク
- **66-69行目**: `tracked_by` スコープ - 追跡可能なタスク
- **84-86行目**: `pending`、`assigned`、`completed` スコープ
- **89-95行目**: 期限別スコープ（due_asap、overdue、due_today等）
- **98-103行目**: 完了日別スコープ（completed_today等）
- **177-186行目**: `find_all_grouped` - バケット別グループ化メソッド

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

TasksControllerのindexアクションが処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tasks_controller.rb | `app/controllers/tasks_controller.rb` | indexアクションの実装 |

**主要処理フロー**:
1. **14-23行目**: indexアクション全体
2. **15行目**: `@view = view` - ビューの設定（viewメソッドで検証）
3. **16行目**: `Task.find_all_grouped(current_user, @view)` - グループ化取得
4. **18-22行目**: respond_withによる複数フォーマット対応
5. **222-226行目**: `view` メソッド - ビューパラメータの検証

#### Step 3: サイドバー更新を理解する

フィルタとサイドバーの更新ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tasks_controller.rb | `app/controllers/tasks_controller.rb` | update_sidebarメソッド |

**主要処理フロー**:
- **196-218行目**: `update_sidebar` メソッド
- **198-199行目**: `Task.totals(current_user, @view)` - タスク件数の集計
- **202-210行目**: タスク追加・削除時のフィルタ更新
- **213-217行目**: デフォルトフィルタの作成

#### Step 4: ビューの構造を理解する

一覧表示のビューファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.haml | `app/views/tasks/index.html.haml` | メインビュー |
| 4-2 | _pending.html.haml | `app/views/tasks/_pending.html.haml` | 保留タスクパーシャル |
| 4-3 | _completed.html.haml | `app/views/tasks/_completed.html.haml` | 完了タスクパーシャル |

**主要処理フロー**:
- **3-10行目**: completedビューとその他のビューの分岐
- **12-18行目**: バケット別のループとフィルタ適用
- **20行目**: エクスポートリンク

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

```
TasksController#index
    │
    ├─ view (private method)
    │      └─ ALLOWED_VIEWS.include?(params[:view])
    │
    ├─ Task.find_all_grouped(current_user, @view)
    │      │
    │      ├─ Setting.task_bucket (pending/assigned用)
    │      │      └─ [:due_asap, :overdue, :due_today, ...]
    │      │
    │      ├─ Setting.task_completed (completed用)
    │      │      └─ [:completed_today, :completed_yesterday, ...]
    │      │
    │      └─ 各バケットごとのタスク取得
    │             ├─ my(user).due_asap.pending
    │             ├─ my(user).overdue.pending
    │             └─ ...
    │
    ├─ update_sidebar
    │      ├─ Task.totals(current_user, @view)
    │      └─ session["filter_by_task_#{@view}"] 更新
    │
    └─ respond_with(@tasks)
           ├─ format.html → index.html.haml
           ├─ format.xls → index.xls.builder
           ├─ format.csv → render csv: @tasks
           └─ format.xml → render xml: @tasks
```

### データフロー図

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

GET /tasks?view=pending    TasksController#index
                                   │
                                   ▼
                          ビュー検証 (ALLOWED_VIEWS)
                                   │
                                   ▼
                          Task.find_all_grouped
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
              due_asap        overdue        due_today
              スコープ        スコープ        スコープ
                    │              │              │
                    └──────────────┼──────────────┘
                                   ▼
                          @tasks (Hash)
                          {
                            due_asap: [...],
                            overdue: [...],
                            due_today: [...],
                            ...
                          }
                                   │
                                   ▼
                          update_sidebar
                                   │
                                   ▼
                          @task_total (件数)
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
              HTML表示        XLS出力        CSV出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tasks_controller.rb | `app/controllers/tasks_controller.rb` | コントローラ | タスクCRUD処理 |
| task.rb | `app/models/polymorphic/task.rb` | モデル | タスクのビジネスロジック |
| index.html.haml | `app/views/tasks/index.html.haml` | ビュー | 一覧メインテンプレート |
| _pending.html.haml | `app/views/tasks/_pending.html.haml` | ビュー | 保留タスクパーシャル |
| _assigned.html.haml | `app/views/tasks/_assigned.html.haml` | ビュー | 割当タスクパーシャル |
| _completed.html.haml | `app/views/tasks/_completed.html.haml` | ビュー | 完了タスクパーシャル |
| _sidebar_index.html.haml | `app/views/tasks/_sidebar_index.html.haml` | ビュー | サイドバー |
| index.xls.builder | `app/views/tasks/index.xls.builder` | ビュー | Excelエクスポート |
| tasks_helper.rb | `app/helpers/tasks_helper.rb` | ヘルパー | タスク表示ヘルパー |
| routes.rb | `config/routes.rb` | 設定 | /tasksルーティング（144-153行目） |
