# 帳票設計書 6-タスク一覧

## 概要

本ドキュメントは、Fat Free CRMシステムにおけるタスク（Tasks）データのエクスポート帳票に関する設計仕様書です。タスクの基本情報、期限、完了状態、担当者情報を含む一覧データをXLS/CSV形式で出力する機能について記述します。

### 本帳票の処理概要

タスク一覧エクスポート機能は、システムに登録されたタスクデータを一括でダウンロードし、業務進捗の管理や担当者別の作業量分析を可能にする帳票出力機能です。

**業務上の目的・背景**：タスク管理は営業・マーケティング活動の実行を支える重要な業務プロセスです。本帳票により、担当者別のタスク負荷分析、期限別のタスク一覧確認、完了済みタスクの実績集計、チーム全体の作業進捗レビュー、外部プロジェクト管理ツールへのデータ連携など、多様な業務管理ニーズに対応します。タスクは取引先・連絡先・商談などの各エンティティに紐付けられるため、顧客対応履歴としても活用できます。

**帳票の利用シーン**：週次の業務進捗レビュー時、担当者間のタスク再配分検討時、プロジェクト管理ツールへのデータ移行時、チームパフォーマンス分析時に利用されます。

**主要な出力内容**：
1. タスク基本情報（ID、名前、期限、カテゴリ）
2. 状態情報（作成日、更新日、完了日）
3. 担当者情報（作成ユーザー、担当者）
4. 背景情報

**帳票の出力タイミング**：タスク一覧画面において、ユーザーがエクスポートボタンをクリックした際にリアルタイムで生成・ダウンロードされます。

**帳票の利用者**：営業担当者、マーケティング担当者、チームリーダー、マネージャー

## 帳票種別

一覧表（エクスポート帳票）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | タスク一覧画面 | /tasks | XLS/CSVエクスポートリンク |
| - | タスク一覧画面 | /tasks.xls | XLS形式でダウンロード |
| - | タスク一覧画面 | /tasks.csv | CSV形式でダウンロード |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | XLS（Excel XML Spreadsheet）/ CSV |
| 用紙サイズ | 該当なし（データエクスポート） |
| 向き | 該当なし |
| ファイル名 | tasks.xls / tasks.csv |
| 出力方法 | ダウンロード |
| 文字コード | UTF-8 |

### Excel固有設定

| 項目 | 内容 |
|-----|------|
| シート名 | Tasks（I18n.t(:tab_tasks)による国際化対応） |
| 保護設定 | 無 |

## 帳票レイアウト

### レイアウト概要

XLS形式のスプレッドシートとして、1行目にヘッダー、2行目以降にデータ行が続く標準的な表形式レイアウトです。

```
┌─────────────────────────────────────┐
│         ヘッダー行（項目名）          │
├─────────────────────────────────────┤
│         データ行1                    │
│         データ行2                    │
│         ...                         │
│         データ行N                    │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ID | タスクID | tasks.id | Number |
| 2 | Name | タスク名 | tasks.name | String |
| 3 | Due | 期限 | task.computed_bucket（translated） | String |
| 4 | Date Created | 作成日 | tasks.created_at | String |
| 5 | Date Updated | 更新日 | tasks.updated_at | String |
| 6 | Completed | 完了日 | tasks.completed_at | String |
| 7 | User | 作成ユーザー名 | users.name（via user_id） | String |
| 8 | Assigned To | 担当者名 | users.name（via assigned_to） | String |
| 9 | Category | カテゴリ | tasks.category | String |
| 10 | Background Info | 背景情報 | tasks.background_info | String |

### 明細部

各タスクレコードについて、ヘッダー部と同じ順序で値を出力します。

### フッター部

なし（データ一覧のみ）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ユーザー権限 | 現在のユーザーが作成または担当するタスク | Yes |
| ビュー | pending/assigned/completedの3種類 | Yes |
| バケットフィルタ | due_today/due_tomorrow等の期限フィルタ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | バケット（期限グループ） | 設定順 |
| 2 | タスクID | 降順 |

### 改ページ条件

該当なし（全データを単一シートに出力）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| tasks | タスク基本情報 | メインテーブル |
| users | ユーザー情報 | tasks.user_id = users.id, tasks.assigned_to = users.id |

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

#### tasks

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | ID | - | 主キー |
| name | Name | - | タスク名、必須、最大255文字 |
| due_at | Due | - | 期限日時、computed_bucketで表示 |
| created_at | Date Created | - | - |
| updated_at | Date Updated | - | - |
| completed_at | Completed | - | 完了日時 |
| category | Category | - | カテゴリ、最大32文字 |
| background_info | Background Info | - | 背景情報、最大255文字 |
| bucket | （内部） | - | 期限バケット |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Due（表示） | I18n.t(task.computed_bucket) | - | バケット名を国際化して表示 |
| computed_bucket | due_atに基づいてoverdue/due_today/due_tomorrow等を算出 | - | Taskモデルのメソッド |
| データ型判定 | value.respond_to?(:abs) ? 'Number' : 'String' | - | セルのデータ型を動的に判定 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[XLS/CSVエクスポート要求] --> B[TasksController#index]
    B --> C[Task.find_all_grouped]
    C --> D[ビュー別タスク取得]
    D --> E[バケット別グループ化]
    E --> F{出力形式}
    F -->|XLS| G[index.xls.builder実行]
    F -->|CSV| H[FatFreeCRM::ExportCSV.from_array実行]
    G --> I[XMLWorkbook生成]
    H --> J[CSV生成]
    I --> K[ファイルダウンロード]
    J --> K
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | @tasks.empty? | 空のワークシートが出力される | ヘッダー・データ行とも出力されない |
| 認証エラー | 未ログイン | ログイン画面へリダイレクト | ログイン後に再実行 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数十〜数百件 |
| 目標出力時間 | 2秒以内（100件程度） |
| 同時出力数上限 | 明示的な制限なし |

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

- タスクはアクセス制御（access列）を持たないが、my/assigned_byスコープにより自分が関連するタスクのみ参照可能
- 認証が必要（authenticate_user!）
- パスワード・トークン等の機密情報はCSVエクスポート時に除外

## 備考

- 国際化対応：ヘッダーラベルおよびバケット名はI18nを使用して多言語対応
- タスクはカスタムフィールドに対応していない（他エンティティとは異なる）
- タスクはポリモーフィック関連（asset）により、取引先・連絡先・商談・リード・キャンペーンに紐付け可能
- ビューは3種類：pending（自分の未完了）、assigned（他者に割り当て済み）、completed（完了済み）
- computed_bucketメソッドにより、due_atをoverdue/due_today/due_tomorrow/due_this_week/due_next_week/due_laterに分類

---

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

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

### 推奨読解順序

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

まず、タスクエンティティの構造とリレーションを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | task.rb | `app/models/polymorphic/task.rb` | Taskモデルの定義、belongs_to :asset（ポリモーフィック）、バケットスコープ、computed_bucketメソッドを確認 |

**読解のコツ**: ALLOWED_VIEWS定数、各バケットスコープ（due_asap/overdue/due_today等）、find_all_groupedクラスメソッドに注目

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

処理の起点となるコントローラーを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tasks_controller.rb | `app/controllers/tasks_controller.rb` | indexアクション（14-23行目）、Task.find_all_grouped呼び出し |
| 2-2 | application_controller.rb | `app/controllers/application_controller.rb` | respond_to宣言、認証フィルタを確認 |

**主要処理フロー**:
1. **14-23行目**: indexアクションでTask.find_all_grouped実行
2. **19行目**: XLS出力時はheaderレイアウトを使用
3. **20行目**: CSV出力時は@tasks.map(&:second).flattenでフラット化

#### Step 3: ビューテンプレートを理解する

XLS出力の実際の処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.xls.builder | `app/views/tasks/index.xls.builder` | ヘッダー定義（8-17行目）、@tasks.map(&:second).flattenでデータフラット化（28行目） |
| 3-2 | header.xls.builder | `app/views/layouts/header.xls.builder` | XMLワークブック構造の定義 |

**主要処理フロー**:
- **7-25行目**: ヘッダー行の生成
- **28行目**: @tasks.map(&:second).flattenでグループ化されたタスクをフラット化
- **32行目**: I18n.t(task.computed_bucket)で期限バケットを国際化表示

#### Step 4: グループ化ロジックを理解する

タスクのグループ化処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | task.rb | `app/models/polymorphic/task.rb` | find_all_groupedメソッド（177-186行目）、バケット別のタスク取得ロジック |

**主要処理フロー**:
- **177-186行目**: ビュー（pending/assigned/completed）に応じてバケット設定を取得し、各バケットのタスクをグループ化

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

```
HTTP Request (GET /tasks.xls)
    │
    ├─ ApplicationController (認証チェック)
    │      └─ authenticate_user!
    │
    ├─ TasksController#index
    │      └─ Task.find_all_grouped(current_user, @view)
    │             │
    │             ├─ Setting.task_bucket (バケット設定取得)
    │             │
    │             └─ バケット毎のスコープ実行
    │                    ├─ due_asap
    │                    ├─ overdue
    │                    ├─ due_today
    │                    ├─ due_tomorrow
    │                    ├─ due_this_week
    │                    ├─ due_next_week
    │                    └─ due_later
    │
    └─ tasks/index.xls.builder (ビュー)
           ├─ header.xls.builder (レイアウト)
           │
           ├─ @tasks.map(&:second).flatten (フラット化)
           │      ├─ task.name
           │      ├─ I18n.t(task.computed_bucket) (期限)
           │      ├─ task.user.try(:name)
           │      └─ task.assignee.try(:name)
           │
           └─ XMLセル出力
```

### データフロー図

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

Request             TasksController           Response
/tasks.xls     ───▶ #index                ───▶ tasks.xls
                         │
                         ▼
                    Task.find_all_grouped
                         │
                         ├─ my(user) または assigned_by(user)
                         │
                         ▼
                    @tasks (Hash: bucket => tasks)
                         │
                         ├─ { due_today: [...], due_tomorrow: [...], ... }
                         │
                         ▼
                    @tasks.map(&:second).flatten
                         │
                         ▼
                    index.xls.builder
                         │
                         ▼
                    XML生成 (Builder)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| task.rb | `app/models/polymorphic/task.rb` | ソース | Taskモデル定義 |
| tasks_controller.rb | `app/controllers/tasks_controller.rb` | ソース | タスクコントローラー |
| application_controller.rb | `app/controllers/application_controller.rb` | ソース | 基底コントローラー |
| index.xls.builder | `app/views/tasks/index.xls.builder` | テンプレート | XLS出力ビュー |
| header.xls.builder | `app/views/layouts/header.xls.builder` | テンプレート | XLSレイアウト |
| export_csv.rb | `lib/fat_free_crm/export_csv.rb` | ソース | CSV出力ユーティリティ |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（144-153行目） |
