# 帳票設計書 3-Work Items CSV Export

## 概要

本ドキュメントは、GitLabのWork Items一覧をCSV形式でエクスポートする機能の帳票設計書である。

### 本帳票の処理概要

本帳票は、プロジェクトまたはグループ内のWork Items情報を一括でCSVファイルとして出力し、タスク管理の分析、進捗レポート作成、外部ツールとの連携に活用するための機能を提供する。Work Itemsは、Issue、Task、Incident、Requirement等の新しいプランニングシステムを統合したオブジェクトである。

**業務上の目的・背景**：Work Itemsはタスク、エピック、インシデント等を統一的に管理する新しいアーキテクチャである。チームがWork Itemsの進捗状況を外部ツールで分析したい場合や、階層構造を持つタスクの全体像を把握したい場合に、この機能が活用される。また、時間管理（Time Tracking）情報を含めたリソース管理にも使用される。

**帳票の利用シーン**：プロジェクトマネージャーがスプリント計画のためのデータ分析を行う際、チームリーダーが作業配分を確認する際、管理者がリソース利用状況をレポートする際などに利用される。

**主要な出力内容**：
1. Work Item基本情報（ID、IID、Title、Description、Type、URL）
2. 状態情報（State、Confidential、Locked）
3. 分類情報（Milestone、Labels）
4. 担当者情報（Author、Assignee）
5. 日時情報（Created At、Updated At、Closed At、Due Date、Start Date）
6. 階層情報（Parent ID、Parent IID、Parent Title）
7. 時間管理情報（Time Estimate、Time Spent）

**帳票の出力タイミング**：ユーザーがWork Items一覧画面からエクスポート操作を行った際に非同期で処理が開始され、完了後にメールで送信される。

**帳票の利用者**：プロジェクトメンバー、プロジェクトマネージャー、チームリーダー、リソース管理者

## 帳票種別

一覧表（CSVエクスポート）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Project Work Items | `/:namespace/:project/-/work_items` | "Export as CSV"操作 |
| - | Group Work Items | `/:group/-/work_items` | "Export as CSV"操作 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | CSV |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | work_items_export.csv |
| 出力方法 | メール送付 |
| 文字コード | UTF-8 |

### CSV固有設定

| 項目 | 内容 |
|-----|------|
| ヘッダー行 | あり |
| 区切り文字 | カンマ |
| 囲み文字 | ダブルクォート |
| 最大ファイルサイズ | 15MB（Base64エンコード前） |

## 帳票レイアウト

### レイアウト概要

CSVファイルはヘッダー行と明細行で構成される。ウィジェットシステムに基づく動的なカラム構成を持つ。

```
┌─────────────────────────────────────┐
│         ヘッダー行（1行目）           │
├─────────────────────────────────────┤
│         明細行（2行目以降）           │
│       （Work Item毎に1行）           │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ID | Work Item ID | work_items.id | 数値 |
| 2 | IID | Work Item IID | work_items.iid | 数値 |
| 3 | Title | タイトル | work_items.title | 文字列 |
| 4 | Description | 説明 | descriptionウィジェット | 文字列 |
| 5 | Type | Work Item種別 | work_item_types.name | 文字列 |
| 6 | URL | Work ItemのURL | GitlabRoutingHelper | URL文字列 |
| 7 | State | 状態 | work_items.state_id | Open/Closed |
| 8 | Confidential | 機密フラグ | work_items.confidential | Yes/No |
| 9 | Locked | ディスカッションロック | notesウィジェット.discussion_locked | Yes/No |
| 10 | Milestone | マイルストーン名 | milestoneウィジェット.title | 文字列 |
| 11 | Labels | ラベル一覧 | labelsウィジェット | カンマ区切り文字列 |
| 12 | Author | 作成者名 | work_items.author_name | 文字列 |
| 13 | Author Username | 作成者ユーザー名 | users.username | 文字列 |
| 14 | Assignee | 担当者名 | assigneesウィジェット | カンマ区切り文字列 |
| 15 | Assignee Username | 担当者ユーザー名 | assigneesウィジェット | カンマ区切り文字列 |
| 16 | Created At (UTC) | 作成日時 | work_items.created_at | 日時（CSV形式） |
| 17 | Updated At (UTC) | 更新日時 | work_items.updated_at | 日時（CSV形式） |
| 18 | Closed At (UTC) | クローズ日時 | work_items.closed_at | 日時（CSV形式） |
| 19 | Due Date | 期限日 | start_and_due_dateウィジェット.due_date | 日付（CSV形式） |
| 20 | Start Date | 開始日 | start_and_due_dateウィジェット.start_date | 日付（CSV形式） |
| 21 | Parent ID | 親Work Item ID | hierarchyウィジェット.parent.id | 数値 |
| 22 | Parent IID | 親Work Item IID | hierarchyウィジェット.parent.iid | 数値 |
| 23 | Parent Title | 親Work Itemタイトル | hierarchyウィジェット.parent.title | 文字列 |
| 24 | Time Estimate | 見積時間 | time_trackingウィジェット.human_time_estimate | 文字列 |
| 25 | Time Spent | 作業時間 | time_trackingウィジェット.human_total_time_spent | 文字列 |

### 明細部

各Work Itemごとに1行を出力。ウィジェットの有効/無効によりカラムの値が変動する。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| プロジェクト/グループ | 対象スコープ | Yes |
| フィルタ条件 | 一覧画面のフィルタ条件を継承 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | リクエスト時の指定 | 画面のソート順を継承 |

### 改ページ条件

CSVのため改ページなし

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| issues (work_items) | Work Item基本情報 | 主テーブル（Work ItemはIssueを継承） |
| work_item_types | 種別情報 | issues.work_item_type_id = work_item_types.id |
| work_item_widget_definitions | ウィジェット定義 | work_item_types.id = widget_definitions.work_item_type_id |
| users (author) | 作成者情報 | issues.author_id = users.id |
| issue_assignees | 担当者関連 | issues.id = issue_assignees.issue_id |
| milestones | マイルストーン | ウィジェット経由 |
| labels | ラベル | ウィジェット経由 |
| work_item_dates_sources | 日付情報 | ウィジェット経由 |
| timelogs | 時間記録 | ウィジェット経由 |
| work_item_parent_links | 親子関係 | ウィジェット経由 |

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

#### issues (work_items)

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | ID | - | - |
| iid | IID | - | プロジェクト内の連番 |
| title | Title | - | - |
| confidential | Confidential | - | Boolean→Yes/No変換 |
| created_at | Created At (UTC) | - | 日時形式変換 |
| updated_at | Updated At (UTC) | - | 日時形式変換 |
| closed_at | Closed At (UTC) | - | 日時形式変換 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Labels | labels.map(&:title).join(', ') | - | ラベル名のカンマ区切り結合 |
| Assignee | assignees.map(&:name).join(', ') | - | 担当者名のカンマ区切り結合 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Export操作] --> B[エクスポートサービス呼び出し]
    B --> C[WorkItems::ExportCsvService.new]
    C --> D[関連データプリロード]
    D --> E[widget_preloadsで関連データ取得]
    E --> F[csv_builder.render でCSV生成]
    F --> G[各ウィジェットから値取得]
    G --> H{ファイルサイズ確認}
    H -->|15MB以下| I[Notify.export_work_items_csv_email]
    H -->|15MB超過| J[処理中断]
    I --> K[メール送信]
    K --> L[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 機能無効 | Feature Flagが無効 | NotAvailableError | Feature Flagを有効化 |
| データなし | 対象Work Itemsが0件 | - | 空のCSVが送信される |
| ファイルサイズ超過 | 15MB超過 | 処理が途中で打ち切られる | フィルタ条件を絞る |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千件 |
| 目標出力時間 | 非同期処理のため制限なし |
| 同時出力数上限 | Sidekiqワーカーの並列数に依存 |

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

- 認証済みユーザーのみがエクスポート可能
- プロジェクト/グループへの読み取り権限が必要
- 機密Work Items（confidential）も出力対象となるため、アクセス権限のあるユーザーのみに送信
- メールは登録済みメールアドレスにのみ送信

## 備考

- Work Itemsはウィジェットベースのアーキテクチャを採用しており、各項目の取得は`widget_value_for`メソッド経由で行われる
- `prepend_mod`によりEE機能で拡張される可能性がある
- Feature Flagによる機能制御が行われている可能性がある

---

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

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

### 推奨読解順序

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

Work Itemsのウィジェットベースアーキテクチャを理解することが最初のステップ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | header_to_value_hashでCSVカラム定義を確認（24-42行目） |
| 1-2 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | widget_value_forメソッドでウィジェット値取得（91-97行目） |

**読解のコツ**: Work Itemsでは`get_widget`メソッドでウィジェットを取得し、そこから値を取り出す。ウィジェットが存在しない場合はnilが返される。

#### Step 2: ウィジェット定義を理解する

各ウィジェットがどのような値を持つかを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | base_metadata（45-52行目） |
| 2-2 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | dates_data（66-73行目） |
| 2-3 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | parent_item_data（76-81行目） |
| 2-4 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | time_tracking_data（84-88行目） |

**主要処理フロー**:
1. **24-42行目**: `header_to_value_hash`で基本構造を定義
2. **45-88行目**: 各データグループの定義をmergeで結合

#### Step 3: プリロード設定を理解する

パフォーマンスのためのプリロード設定を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | associations_to_preload（16-18行目） |
| 3-2 | export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | widget_preloads（20-22行目） |

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

```
WorkItems::ExportCsvService
    │
    ├─ ExportCsv::BaseService (継承)
    │      │
    │      ├─ csv_builder.render
    │      │      └─ header_to_value_hash経由でデータ取得
    │      │
    │      └─ CsvBuilder
    │
    ├─ widget_value_for
    │      └─ work_item.get_widget(widget_name)
    │             └─ widget.try(field)
    │
    └─ email
           └─ Notify.export_work_items_csv_email
```

### データフロー図

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

Work Items一覧 ───▶ ExportCsvService ───▶ ウィジェット値取得
    │                      │                      │
    │                      ▼                      ▼
    │               widget_value_for ───▶ CsvBuilder.render
    │                      │                      │
    │                      │                      ▼
    └──────────────────────┴─────────────▶ CSV添付メール
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| export_csv_service.rb | `app/services/work_items/export_csv_service.rb` | ソース | Work Items CSV生成サービス |
| base_service.rb | `app/services/export_csv/base_service.rb` | ソース | CSV生成基底クラス |
| work_item.rb | `app/models/work_item.rb` | ソース | Work Itemモデル |
| work_item_type.rb | `app/models/work_items/type.rb` | ソース | Work Item種別モデル |
| widget定義 | `app/models/work_items/widgets/` | ソース | 各ウィジェット実装 |
| notify.rb | `app/mailers/notify.rb` | ソース | メール送信 |
