# 画面設計書 167-CRM組織一覧

## 概要

本ドキュメントはGitLabのCRM（顧客関係管理）組織一覧画面の設計仕様を記載したものである。

### 本画面の処理概要

グループに関連付けられた顧客組織（CRM Organization）の一覧を表示・管理する画面である。顧客組織は連絡先のグループ化やイシューとの関連付けに使用され、顧客対応の効率化を支援する。

**業務上の目的・背景**：ソフトウェア開発プロジェクトにおいて、顧客やクライアント組織との関係を管理する必要がある。本画面により、顧客組織を一元管理し、関連イシューの追跡、連絡先の管理を効率的に行える。これにより顧客対応品質の向上と情報の一元化を実現する。

**画面へのアクセス方法**：グループメニュー > Customer relations > Organizations からアクセスする。または直接URL `/{group_path}/-/crm/organizations` にアクセスする。

**主要な操作・処理内容**：
1. 組織一覧の表示（名前、説明、デフォルト料金）
2. ステータス（Active/Inactive/All）によるフィルタリング
3. 検索文字列による組織検索
4. ソート（名前、デフォルト料金、説明）
5. 新規組織の作成
6. 既存組織の編集
7. 関連イシューへの遷移

**画面遷移**：
- 遷移元：グループ設定画面、連絡先一覧画面
- 遷移先：組織編集画面、連絡先一覧画面、イシュー一覧画面

**権限による表示制御**：
- `read_crm_organization`権限：組織一覧の閲覧が可能
- `admin_crm_organization`権限：組織の作成・編集が可能
- `read_crm_contact`権限：連絡先リンクが表示される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 134 | 組織管理 | 主機能 | CRM組織の一覧表示 |

## 画面種別

一覧

## URL/ルーティング

- パス: `/{group_path}/-/crm/organizations`
- コントローラー: `Groups::Crm::OrganizationsController#index`
- HTTPメソッド: GET

## 入出力項目

| 項目名 | 項目ID | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|--------|----------|------|------|
| グループパス | group_path | 入力 | String | 必須 | 対象グループのパス |
| 検索クエリ | search | 入力 | String | 任意 | 組織検索文字列 |
| ステータスフィルター | state | 入力 | String | 任意 | active/inactive/all |
| ソート | sort | 入力 | String | 任意 | NAME_ASC/NAME_DESC等 |
| ページカーソル | cursor | 入力 | String | 任意 | ページネーション用 |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 組織名 | customer_relations_organizations.name | 組織名 |
| デフォルト料金 | customer_relations_organizations.default_rate | デフォルト時間単価 |
| 説明 | customer_relations_organizations.description | 組織の説明 |
| ステータス | customer_relations_organizations.state | Active/Inactive |

## イベント仕様

### 1-新規作成ボタン押下

組織作成フォームを表示する。

- トリガー: 「New organization」ボタンクリック
- 処理: Vue Routerで新規作成画面へ遷移
- 条件: `admin_crm_organization`権限を持つ場合のみ表示

### 2-編集ボタン押下

組織編集フォームを表示する。

- トリガー: 行の編集ボタンクリック
- 処理: Vue Routerで編集画面へ遷移
- 遷移先: `/{group_path}/-/crm/organizations/{id}/edit`

### 3-イシュー表示ボタン押下

組織に関連するイシュー一覧を表示。

- トリガー: 行のイシューボタンクリック
- 遷移先: `/{group_path}/-/issues?crm_organization_id={id}`

### 4-連絡先リンククリック

連絡先一覧画面へ遷移。

- トリガー: 「Contacts」リンククリック
- 遷移先: `/{group_path}/-/crm/contacts`
- 条件: `read_crm_contact`権限を持つ場合のみ表示

### 5-ステータスタブ変更

フィルター条件を変更して一覧を再取得。

- トリガー: Active/Inactive/Allタブクリック
- 処理: GraphQL APIでフィルタリングした一覧を取得

### 6-ソート変更

ソート条件を変更して一覧を再取得。

- トリガー: テーブルヘッダークリック
- 処理: GraphQL APIでソートした一覧を取得

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | customer_relations_organizations | SELECT | 組織一覧の取得 |
| 組織作成 | customer_relations_organizations | INSERT | 新規組織作成 |
| 組織編集 | customer_relations_organizations | UPDATE | 組織情報更新 |

### テーブル別更新項目詳細

#### customer_relations_organizations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全項目 | group_id = グループID | グループのCRM組織 |
| INSERT | name | ユーザー入力値 | 組織名（最大255文字） |
| INSERT | description | ユーザー入力値 | 説明（最大1024文字） |
| INSERT | default_rate | ユーザー入力値 | デフォルト料金 |
| INSERT | state | 0:inactive / 1:active | ステータス |
| INSERT | group_id | グループID | 所属グループ |
| UPDATE | name, description, default_rate, state | ユーザー入力値 | 編集時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG001 | 情報 | No organizations found | 組織が見つからない場合 |
| MSG002 | エラー | Something went wrong. Please try again. | API通信エラー発生時 |
| MSG003 | 成功 | Organization was created | 作成成功時 |
| MSG004 | 成功 | Organization was updated | 更新成功時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限不足（read_crm_organization） | 404ページを表示 |
| グループ未存在 | 404ページを表示 |
| 非CRMグループ | 404ページを表示 |
| API通信エラー | エラーメッセージを表示 |

## 備考

- 本画面はVue.jsコンポーネントとVue Routerによるspa構成
- データ取得はGraphQL APIを使用
- CRM機能はルートグループまたはCRMターゲットとして設定されたグループでのみ利用可能
- `validate_crm_group!`でCRMグループの検証を実施
- ステータスカウントは`getGroupOrganizationsCountByStateQuery`で取得

---

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

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

### 推奨読解順序

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

CRM組織のデータモデルとバリデーションを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | organization.rb | `app/models/customer_relations/organization.rb` | モデル定義、バリデーション、スコープ |

**読解のコツ**:
- `enum :state`（行15-18）でステータス定義確認
- `validates :name`（行21-23）でバリデーション確認
- `validate_crm_group`（行74-78）でCRMグループ検証確認

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

HAMLテンプレートとコントローラーの処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html.haml | `app/views/groups/crm/organizations/index.html.haml` | Vueマウントポイント、data属性設定 |
| 2-2 | organizations_controller.rb | `app/controllers/groups/crm/organizations_controller.rb` | コントローラー、権限チェック |

**主要処理フロー**:
1. **行9-17**: `#js-crm-organizations-app`要素にdata属性設定
2. **行7**: `validate_crm_group!`でCRMグループ検証
3. **行8**: `authorize_read_crm_organization!`で権限チェック

#### Step 3: フロントエンド実装を理解する

Vueコンポーネントの実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | organizations_root.vue | `app/assets/javascripts/crm/organizations/components/organizations_root.vue` | メインコンポーネント |

**主要処理フロー**:
- `getGroupOrganizationsQuery`でGraphQL取得
- `getGroupOrganizationsCountByStateQuery`でステータスカウント取得
- `PaginatedTableWithSearchAndTabs`コンポーネントで一覧表示

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

```
Groups::Crm::OrganizationsController#index
    │
    ├─ validate_crm_group! (CRMグループ検証)
    │
    ├─ authorize_read_crm_organization! (認可チェック)
    │
    └─ View: index.html.haml
           └─ Vue: OrganizationsRoot
                  │
                  ├─ GraphQL: getGroupOrganizationsQuery
                  │
                  ├─ GraphQL: getGroupOrganizationsCountByStateQuery
                  │
                  └─ Component: PaginatedTableWithSearchAndTabs
```

### データフロー図

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

URLリクエスト ───▶ OrganizationsController ───▶ HAMLテンプレート
                         │
                         ▼
                  CRMグループ検証
                         │
                         ▼
                  認可チェック
                         │
                         ▼
                  Vue初期化 ───▶ GraphQL API ───▶ 組織一覧表示

フィルター変更 ───▶ GraphQL API ───▶ 一覧更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html.haml | `app/views/groups/crm/organizations/index.html.haml` | テンプレート | Vueマウントポイント定義 |
| organizations_controller.rb | `app/controllers/groups/crm/organizations_controller.rb` | コントローラー | リクエスト処理・認可 |
| organization.rb | `app/models/customer_relations/organization.rb` | モデル | CRM組織データ定義 |
| organizations_root.vue | `app/assets/javascripts/crm/organizations/components/organizations_root.vue` | Vue | メインコンポーネント |
| organization_form_wrapper.vue | `app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue` | Vue | 作成・編集フォーム |
