# 機能設計書 37-イシュー編集

## 概要

本ドキュメントは、GitLabのイシュー編集機能の設計仕様を記載する。本機能は既存イシューのタイトル、説明、ラベル、担当者などの編集を提供する。

### 本機能の処理概要

イシュー編集機能は、既存のイシューの属性を更新する機能である。タイトル、説明の変更から、担当者、ラベル、マイルストーンの変更、期限の設定など、イシューのあらゆる属性を更新できる。

**業務上の目的・背景**：プロジェクトの進行に伴いイシューの内容や優先度、担当者が変わることがある。柔軟にイシューを編集できることで、常に最新の状態を反映したプロジェクト管理が可能となる。

**機能の利用シーン**：要件の追加・変更に伴う説明の更新、担当者の変更、優先度変更に伴うラベルの付け替え、スプリント変更に伴うマイルストーン変更など。

**主要な処理内容**：
1. タイトル・説明の編集
2. 担当者の変更
3. ラベルの追加・削除
4. マイルストーンの変更
5. 期限日の設定
6. イシュータイプの変更
7. 別プロジェクトへの移動

**関連システム・外部連携**：NotificationServiceを通じた変更通知、Webhookによる外部システム連携、GraphQL APIによるリアルタイム更新

**権限による制御**：update_issue権限を持つユーザーがイシューを編集可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 49 | 課題詳細 | 主画面 | 課題の詳細表示・編集 |
| 47 | 課題一覧 | 参照画面 | 編集後の一覧表示更新 |

## 機能種別

データ更新（CRUD - Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | イシューID（iid） | 存在チェック |
| title | String | No | タイトル | 空文字不可（更新時） |
| description | String | No | 説明 | - |
| assignee_ids | Array[Integer] | No | 担当者ID配列 | 有効なユーザー |
| milestone_id | Integer | No | マイルストーンID | 有効なマイルストーン |
| label_ids | Array[Integer] | No | ラベルID配列 | 有効なラベル |
| due_date | Date | No | 期限日 | 日付形式 |
| confidential | Boolean | No | 機密フラグ | - |
| state_event | String | No | 状態変更イベント | 'close', 'reopen' |

### 入力データソース

- 画面入力（インライン編集、サイドバー編集）
- API呼び出し
- クイックアクション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| issue | Issue | 更新されたイシュー |

### 出力先

- 画面表示（更新内容の反映）
- データベース（issuesテーブル等の更新）
- 通知（メール、Webhook）

## 処理フロー

### 処理シーケンス

```
1. 入力検証
   └─ パラメータのバリデーション
2. 更新前処理
   └─ スパムチェック、タイプ変更処理
3. イシュー更新
   └─ UpdateServiceでDB更新
4. 変更処理
   └─ 担当者変更通知、ラベル変更通知等
5. 後処理
   └─ Todo更新、Webhook実行
```

### フローチャート

```mermaid
flowchart TD
    A[編集操作] --> B[入力検証]
    B --> C{スパムチェック}
    C -->|スパム疑い| D[CAPTCHA表示]
    C -->|OK| E[更新処理]
    D -->|認証成功| E
    E --> F{担当者変更?}
    F -->|Yes| G[担当者変更通知]
    F -->|No| H{ラベル変更?}
    G --> H
    H -->|Yes| I[ラベル変更通知]
    H -->|No| J[保存完了]
    I --> J
    J --> K[Todo更新]
    K --> L[Webhook実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | タイトル必須 | タイトルを空にすることは不可 | 更新時 |
| BR-37-02 | 機密変更制限 | 機密フラグ変更は特定の権限が必要 | 機密変更時 |
| BR-37-03 | 移動制限 | 別プロジェクトへの移動は権限チェック | 移動時 |
| BR-37-04 | 楽観的ロック | lock_versionによる同時更新制御 | 更新時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 基本情報更新 | issues | UPDATE | title, description等 |
| 担当者変更 | issue_assignees | INSERT/DELETE | 担当者関連付け変更 |
| ラベル変更 | label_links | INSERT/DELETE | ラベル関連付け変更 |
| イベント記録 | events | INSERT | 更新イベント記録 |
| リソースイベント | resource_*_events | INSERT | 各種変更イベント |

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

#### issues

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | title | 新しいタイトル | |
| UPDATE | description | 新しい説明 | |
| UPDATE | updated_by_id | 更新者ID | |
| UPDATE | updated_at | 現在時刻 | |
| UPDATE | lock_version | インクリメント | 楽観的ロック |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | update_issue権限なし | エラーメッセージ表示 |
| 409 | Conflict | lock_version不一致 | 再読み込みを促す |
| 422 | Unprocessable | バリデーションエラー | エラーメッセージ表示 |

### リトライ仕様

特になし。コンフリクト時はユーザーに再操作を促す。

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

イシュー更新と関連レコードの更新は同一トランザクション内で実行。

## パフォーマンス要件

- urgency :low指定（低優先度）

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

- update_issue権限チェック
- スパムチェック（perform_spam_check）
- 機密イシューのアクセス制御

## 備考

- WorkItem Descriptionへの同期が行われる
- GraphqlTriggers.work_item_updatedでリアルタイム更新

---

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

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

### 推奨読解順序

#### Step 1: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | update_service.rb | `app/services/issues/update_service.rb` | イシュー更新ロジック |

**主要処理フロー**:
- **17-21行目**: executeメソッド
- **30-36行目**: before_update（スパムチェック、タイプ変更）
- **48-73行目**: handle_changes（各種変更処理）
- **75-86行目**: handle_assignee_changes（担当者変更）

#### Step 2: 変更処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | update_service.rb | `app/services/issues/update_service.rb` | 各変更ハンドラー |
| 2-2 | base_service.rb | `app/services/issuable_base_service.rb` | 共通更新処理 |

**主要処理フロー**:
- handle_confidential_change - 機密変更処理
- handle_added_labels - ラベル追加通知
- handle_severity_change - 重要度変更

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

```
IssuesController#update
    │
    └─ Issues::UpdateService#execute
           │
           ├─ handle_move_between_ids
           ├─ change_issue_duplicate
           ├─ move_issue_to_new_container (optional)
           │
           └─ update (IssuableBaseService)
                  │
                  ├─ before_update (spam check)
                  ├─ issue.update
                  ├─ handle_changes
                  │      ├─ handle_assignee_changes
                  │      ├─ handle_confidential_change
                  │      ├─ handle_added_labels
                  │      └─ ...
                  └─ after_update
                         └─ GraphqlTriggers.work_item_updated
```

### データフロー図

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

編集データ ───▶ IssuesController#update
                       │
                       ▼
                 UpdateService
                       │
                       ▼
                 before_update ───▶ スパムチェック
                       │
                       ▼
                 issue.update ───▶ issuesテーブル
                       │
                       ▼
                 handle_changes
                       │
                       ├─▶ NotificationService (担当者変更等)
                       └─▶ EventStore (変更イベント)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| issues_controller.rb | `app/controllers/projects/issues_controller.rb` | コントローラー | イシュー操作 |
| update_service.rb | `app/services/issues/update_service.rb` | サービス | イシュー更新 |
| base_service.rb | `app/services/issues/base_service.rb` | サービス | 基底クラス |
| issuable_base_service.rb | `app/services/issuable_base_service.rb` | サービス | Issuable共通 |
| issue.rb | `app/models/issue.rb` | モデル | イシューモデル |
