# 機能設計書：46-ワークアイテム管理

## 1. 機能概要

### 1.1 機能の目的
ワークアイテム管理機能は、GitLabにおけるIssueの進化形として、さまざまな種類の作業項目（Issue、Incident、Task、Epic等）を統一的なフレームワークで管理する機能である。ウィジェットベースの拡張可能なアーキテクチャにより、ワークアイテムタイプごとに異なる機能セットを提供し、階層構造による親子関係の管理を可能にする。

### 1.2 関連画面
| 画面ID | 画面名 | パス |
|--------|--------|------|
| SCR-WORK-ITEMS | ワークアイテム一覧 | `/:namespace/:project/-/work_items` |
| SCR-WORK-ITEM | ワークアイテム詳細 | `/:namespace/:project/-/work_items/:iid` |

### 1.3 関連API
| APIエンドポイント | メソッド | 概要 |
|-------------------|----------|------|
| `/projects/:id/work_items` | GET | ワークアイテム一覧取得 |
| `/projects/:id/work_items/:iid` | GET | ワークアイテム詳細取得 |
| GraphQL `workItem` | Query | ワークアイテム詳細取得 |
| GraphQL `workItemCreate` | Mutation | ワークアイテム作成 |
| GraphQL `workItemUpdate` | Mutation | ワークアイテム更新 |
| GraphQL `workItemDelete` | Mutation | ワークアイテム削除 |

## 2. データモデル

### 2.1 主要エンティティ

#### WorkItem
```
issues テーブル（Issueと同一テーブルを使用）
├── id: bigint (PK)
├── title: varchar(512)
├── description: text
├── project_id: bigint (FK)
├── namespace_id: bigint (FK)
├── author_id: bigint (FK)
├── work_item_type_id: bigint (FK)
├── state_id: smallint
├── confidential: boolean
├── iid: integer
├── created_at: timestamp
├── updated_at: timestamp
└── closed_at: timestamp
```

#### WorkItems::Type（ワークアイテムタイプ）
```
work_item_types テーブル
├── id: bigint (PK)
├── name: varchar(255)
├── icon_name: varchar(255)
├── base_type: smallint
├── created_at: timestamp
└── updated_at: timestamp

base_type enum:
- 0: issue（Issue）
- 1: incident（Incident）
- 2: test_case（Test Case）※EE
- 3: requirement（Requirement）※EE
- 4: task（Task）
- 5: objective（Objective）※EE
- 6: key_result（Key Result）※EE
- 7: epic（Epic）※EE
- 8: ticket（Ticket）
```

#### WorkItems::ParentLink（親子関係）
```
work_item_parent_links テーブル
├── id: bigint (PK)
├── work_item_id: bigint (FK, UNIQUE)
├── work_item_parent_id: bigint (FK)
├── relative_position: integer
├── created_at: timestamp
└── updated_at: timestamp

制約:
- MAX_CHILDREN = 5000（親あたりの最大子数）
- 循環参照禁止
- 機密性の整合性チェック
- 階層制限の検証
```

#### WorkItems::WidgetDefinition（ウィジェット定義）
```
work_item_widget_definitions テーブル
├── id: bigint (PK)
├── work_item_type_id: bigint (FK)
├── widget_type: smallint
├── name: varchar(255)
├── disabled: boolean
├── widget_options: jsonb
├── created_at: timestamp
└── updated_at: timestamp

widget_type enum:
- 0: assignees（担当者）
- 1: description（説明）
- 2: hierarchy（階層）
- 3: labels（ラベル）
- 4: milestone（マイルストーン）
- 5: notes（ノート/コメント）
- 6: start_and_due_date（開始日・期日）
- 7: health_status（健康状態）※EE
- 8: weight（重み）※EE
- 9: iteration（イテレーション）※EE
- 14: notifications（通知）
- 15: current_user_todos（ToDo）
- 16: award_emoji（絵文字）
- 17: linked_items（関連アイテム）
- 20: participants（参加者）
- 21: time_tracking（時間追跡）
- 22: designs（デザイン）
- 23: development（開発）
- 24: crm_contacts（CRM連絡先）
- 25: email_participants（メール参加者）
- 27: linked_resources（関連リソース）
- 29: error_tracking（エラートラッキング）
```

### 2.2 ER図
```
┌─────────────────────┐      ┌──────────────────────┐
│     WorkItem        │      │   WorkItems::Type    │
│     (issues)        │      │(work_item_types)     │
├─────────────────────┤      ├──────────────────────┤
│ id                  │──────│ id                   │
│ title               │      │ name                 │
│ description         │      │ icon_name            │
│ work_item_type_id   │◄─────│ base_type            │
│ namespace_id        │      └──────────────────────┘
│ project_id          │               │
│ state_id            │               │1
│ confidential        │               │
└─────────────────────┘               │
         │                            ▼ *
         │               ┌──────────────────────────┐
         │               │ WorkItems::WidgetDefinition│
         │               ├──────────────────────────┤
         │               │ id                       │
         │               │ work_item_type_id        │
         │               │ widget_type              │
         │               │ name                     │
         │               │ disabled                 │
         │               └──────────────────────────┘
         │
         │1
         ▼ *
┌─────────────────────────┐
│ WorkItems::ParentLink   │
├─────────────────────────┤
│ id                      │
│ work_item_id (UNIQUE)   │
│ work_item_parent_id     │
│ relative_position       │
└─────────────────────────┘
```

## 3. 処理フロー

### 3.1 ワークアイテム作成フロー
```
[クライアント]
     │
     │ GraphQL workItemCreate / REST API
     ▼
[WorkItems::CreateService]
     │
     ├── 1. 権限チェック (create_work_item)
     │
     ├── 2. BuildServiceで初期化
     │   └── WorkItems::BuildService
     │
     ├── 3. Issues::CreateService継承
     │   ├── パラメータ検証
     │   ├── スパムチェック (perform_spam_check)
     │   └── ワークアイテム保存
     │
     ├── 4. ウィジェット処理
     │   └── WidgetableService
     │       ├── widget_paramsの処理
     │       └── 各ウィジェットのコールバック実行
     │
     ├── 5. トラッキング
     │   └── Gitlab::WorkItems::Instrumentation::TrackingService
     │
     └── 6. 結果返却
         └── ServiceResponse (success/error)
```

### 3.2 ワークアイテム更新フロー
```
[クライアント]
     │
     │ GraphQL workItemUpdate
     ▼
[WorkItems::UpdateService]
     │
     ├── 1. Issues::UpdateService継承
     │   ├── 権限チェック
     │   ├── パラメータ検証
     │   └── ワークアイテム更新
     │
     ├── 2. ウィジェット処理
     │   └── WidgetableService
     │
     ├── 3. 日付変更処理
     │   └── handle_date_changes
     │       └── GraphqlTriggers.issuable_dates_updated
     │
     ├── 4. ラベル変更トラッキング
     │   └── WorkItemActivityUniqueCounter.track_work_item_labels_changed_action
     │
     └── 5. 結果返却
```

### 3.3 親子関係設定フロー
```
[クライアント]
     │
     │ GraphQL workItemAddLinkedItems / set_parent
     ▼
[WorkItems::ParentLinks::CreateService]
     │
     ├── 1. 権限チェック
     │
     ├── 2. ParentLink作成
     │   ├── 階層制限の検証
     │   │   └── HierarchyRestriction参照
     │   ├── 循環参照チェック
     │   │   └── ancestors確認
     │   ├── 最大子数チェック (MAX_CHILDREN = 5000)
     │   └── 機密性整合性チェック
     │
     ├── 3. 相対位置設定
     │   └── move_to_start
     │
     ├── 4. ノート作成
     │   └── SystemNoteService
     │
     ├── 5. ResourceLinkEvent作成
     │
     └── 6. GraphQL通知
         └── GraphqlTriggers.work_item_updated
```

## 4. ウィジェットシステム

### 4.1 ウィジェットアーキテクチャ
```
[WorkItem]
     │
     │ widgets(except_types:, only_types:)
     ▼
[widget_definitions]
     │
     │ WidgetDefinition.build_widget(work_item)
     ▼
[WorkItems::Widgets::*]
     │
     ├── Assignees     - 担当者管理
     ├── Description   - 説明
     ├── Hierarchy     - 階層構造
     ├── Labels        - ラベル
     ├── Milestone     - マイルストーン
     ├── Notes         - コメント/ノート
     ├── StartAndDueDate - 開始日・期日
     ├── Notifications - 通知設定
     ├── CurrentUserTodos - ToDo
     ├── AwardEmoji    - 絵文字リアクション
     ├── LinkedItems   - 関連アイテム
     ├── Participants  - 参加者
     ├── TimeTracking  - 時間追跡
     ├── Designs       - デザイン
     ├── Development   - 開発（ブランチ、MR）
     ├── CrmContacts   - CRM連絡先
     ├── EmailParticipants - メール参加者
     ├── LinkedResources - 関連リソース
     └── ErrorTracking - エラートラッキング
```

### 4.2 Hierarchyウィジェット
```ruby
# 親子関係の管理
class WorkItems::Widgets::Hierarchy < Base
  def parent          # 親ワークアイテム取得
  def children        # 子ワークアイテム取得（state: opened/closed）
  def ancestors       # 祖先一覧取得
  def has_parent?     # 親の存在チェック
  def rolled_up_counts_by_type  # タイプ別集計
  def depth_limit_reached_by_type  # 深度制限チェック
end

# Quick Actions
:set_parent      # 親設定
:add_child       # 子追加
:remove_parent   # 親解除
:remove_child    # 子解除
```

## 5. ビジネスルール

### 5.1 ワークアイテムタイプの制約
| ルールID | ルール | 実装箇所 |
|----------|--------|----------|
| WI-R01 | ワークアイテムはIssueを継承 | WorkItem < Issue |
| WI-R02 | 同一テーブル（issues）を使用 | self.table_name = 'issues' |
| WI-R03 | タイプ変更可能: issue, incident, test_case | CHANGEABLE_BASE_TYPES |
| WI-R04 | タイプごとに有効なウィジェットが異なる | WidgetDefinition.enabled |

### 5.2 階層構造の制約
| ルールID | ルール | 実装箇所 |
|----------|--------|----------|
| WI-R05 | 親は1つのみ（work_item_id UNIQUE） | ParentLink validates uniqueness |
| WI-R06 | 最大子数: 5000 | MAX_CHILDREN = 5000 |
| WI-R07 | 循環参照禁止 | validate_cyclic_reference |
| WI-R08 | 許可された親子タイプのみ | HierarchyRestriction |
| WI-R09 | 深度制限あり（タイプ別） | maximum_depth |
| WI-R10 | 関連リンクと親子リンクの重複禁止 | check_existing_related_link |

### 5.3 機密性の制約
| ルールID | ルール | 実装箇所 |
|----------|--------|----------|
| WI-R11 | 機密親の子は機密必須 | validate_confidentiality |
| WI-R12 | 非機密親の子は非機密可能 | parent_link_confidentiality |
| WI-R13 | 機密化時は全子が機密必須 | work_item.rb:438-440 |

### 5.4 クイックアクション
```
/type <type_name>        - タイプ変更
/promote_to <type_name>  - タイプ昇格
/set_parent <reference>  - 親設定
/add_child <reference>   - 子追加
/remove_parent           - 親解除
/remove_child <reference> - 子解除
```

## 6. セキュリティ・権限

### 6.1 必要な権限
| 操作 | 必要な権限 | 説明 |
|------|------------|------|
| 一覧表示 | `read_work_item` | プロジェクト/グループメンバー |
| 詳細表示 | `read_work_item` | プロジェクト/グループメンバー |
| 作成 | `create_work_item` | Reporter以上 |
| 更新 | `update_work_item` | 担当者または Reporter以上 |
| 削除 | `delete_work_item` | Author または Admin |
| インポート | `import_work_items` | Maintainer以上 |

### 6.2 クロスプロジェクト参照
```ruby
# 異なるプロジェクトのワークアイテム参照時
linked_items = Ability.work_items_readable_by_user(
  linked_items,
  current_user,
  filters: { read_cross_project: cross_project_filter }
)
```

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

### 7.1 読み解く順序
1. **モデル層**: WorkItem、WorkItems::Type、WorkItems::ParentLink
2. **ウィジェット層**: WorkItems::Widgets::Base、各ウィジェット
3. **サービス層**: CreateService、UpdateService、DeleteService
4. **Finder**: WorkItemsFinder

### 7.2 プログラム呼び出し階層図
```
WorkItems::CreateService
├── Issues::CreateService (継承)
│   ├── IssuableBaseService
│   │   └── BaseContainerService
│   └── WorkItems::BuildService
├── WidgetableService (include)
│   └── 各ウィジェットのコールバック
└── Gitlab::WorkItems::Instrumentation::TrackingService

WorkItems::ParentLinks::CreateService
├── WorkItems::ParentLinks::BaseService
│   └── IssuableLinks::CreateService
├── WorkItems::ParentLink
│   ├── validate_hierarchy_restrictions
│   ├── validate_cyclic_reference
│   ├── validate_max_children
│   └── validate_confidentiality
└── ResourceLinkEvent
```

### 7.3 データフロー図
```
[GraphQL Mutation]
       │
       ▼
[Resolver] ──────────────────────────────────────┐
       │                                          │
       ▼                                          │
[WorkItems::CreateService]                        │
       │                                          │
       ├── params                                 │
       │   ├── title, description                 │
       │   └── work_item_type_id                  │
       │                                          │
       ├── widget_params                          │
       │   ├── assignees_widget                   │
       │   ├── labels_widget                      │
       │   ├── hierarchy_widget                   │
       │   └── ...                                │
       │                                          │
       ▼                                          │
[WorkItem] ◄─────────────────────────────────────┘
       │
       ├── widgets
       │   └── WidgetDefinition.build_widget
       │
       └── parent_link
           └── WorkItems::ParentLink
```

### 7.4 関連ファイル一覧
| ファイルパス | 責務 |
|--------------|------|
| `app/models/work_item.rb` | ワークアイテムモデル |
| `app/models/work_items/type.rb` | ワークアイテムタイプ |
| `app/models/work_items/parent_link.rb` | 親子関係モデル |
| `app/models/work_items/widget_definition.rb` | ウィジェット定義 |
| `app/models/work_items/widgets/*.rb` | 各ウィジェット実装 |
| `app/controllers/projects/work_items_controller.rb` | コントローラー |
| `app/services/work_items/create_service.rb` | 作成サービス |
| `app/services/work_items/update_service.rb` | 更新サービス |
| `app/services/work_items/delete_service.rb` | 削除サービス |
| `app/services/work_items/parent_links/create_service.rb` | 親子関係作成 |
| `app/finders/work_items/work_items_finder.rb` | 検索Finder |
| `lib/gitlab/work_items/work_item_hierarchy.rb` | 階層構造ユーティリティ |

## 8. 拡張ポイント

### 8.1 EE拡張
- **追加タイプ**: Epic、Objective、Key Result、Requirement、Test Case
- **追加ウィジェット**: Health Status、Weight、Iteration、Progress、Status、Color、Custom Fields、Vulnerabilities
- **グループレベルワークアイテム**: グループ直下のワークアイテム

### 8.2 カスタムウィジェット追加手順
1. `WorkItems::WidgetDefinition` にウィジェットタイプ追加
2. `WorkItems::Widgets::*` にウィジェットクラス実装
3. DBシーダーでワークアイテムタイプに関連付け

### 8.3 新規ワークアイテムタイプ追加手順
1. `WorkItems::Type::BASE_TYPES` に定義追加
2. `WorkItems::Type::TYPE_NAMES` に名前追加
3. DBマイグレーションでシード
4. `HierarchyRestriction` で階層制限設定
