# 画面設計書 168-CRM連絡先一覧

## 概要

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

### 本画面の処理概要

グループに関連付けられた顧客連絡先（CRM Contact）の一覧を表示・管理する画面である。連絡先はイシューに紐付けて顧客対応を追跡するために使用され、組織との関連付けも可能。

**業務上の目的・背景**：ソフトウェア開発プロジェクトにおいて、顧客担当者との連絡履歴や関連イシューを管理する必要がある。本画面により、顧客連絡先を一元管理し、イシューベースの顧客対応を効率化できる。連絡先を組織に関連付けることで、組織全体の連絡先管理も可能。

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

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

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

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

## 関連機能

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

## 画面種別

一覧

## URL/ルーティング

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

## 入出力項目

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

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 名 | customer_relations_contacts.first_name | 連絡先の名 |
| 姓 | customer_relations_contacts.last_name | 連絡先の姓 |
| メールアドレス | customer_relations_contacts.email | メールアドレス |
| 電話番号 | customer_relations_contacts.phone | 電話番号 |
| 説明 | customer_relations_contacts.description | 連絡先の説明 |
| 組織 | customer_relations_organizations.name | 所属組織名 |
| ステータス | customer_relations_contacts.state | Active/Inactive |

## イベント仕様

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

連絡先作成フォームを表示する。

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

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

連絡先編集フォームを表示する。

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

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

連絡先に関連するイシュー一覧を表示。

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

### 4-組織リンククリック

組織一覧画面へ遷移。

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

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

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

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

### 6-ソート変更

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

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

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

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

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

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

#### customer_relations_contacts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全項目 | group_id = グループID | グループのCRM連絡先 |
| INSERT | first_name | ユーザー入力値 | 名（最大255文字） |
| INSERT | last_name | ユーザー入力値 | 姓（最大255文字） |
| INSERT | email | ユーザー入力値 | メール（最大255文字、グループ内unique） |
| INSERT | phone | ユーザー入力値 | 電話番号（最大32文字） |
| INSERT | description | ユーザー入力値 | 説明（最大1024文字） |
| INSERT | organization_id | 選択値 | 所属組織（任意） |
| INSERT | state | 0:inactive / 1:active | ステータス |
| INSERT | group_id | グループID | 所属グループ |
| UPDATE | 上記項目 | ユーザー入力値 | 編集時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG001 | 情報 | No contacts found | 連絡先が見つからない場合 |
| MSG002 | エラー | Something went wrong. Please try again. | API通信エラー発生時 |
| MSG003 | 成功 | Contact was created | 作成成功時 |
| MSG004 | 成功 | Contact was updated | 更新成功時 |
| MSG005 | エラー | Email has already been taken | メール重複時 |

## 例外処理

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

## 備考

- 本画面はVue.jsコンポーネントとVue Routerによるspa構成
- データ取得はGraphQL APIを使用
- CRM機能はルートグループまたはCRMターゲットとして設定されたグループでのみ利用可能
- `validate_crm_group!`でCRMグループの検証を実施
- メールアドレスはグループ内でユニークである必要がある
- 連絡先はイシューに紐付けて顧客対応を追跡可能（`[contact:email]`形式で参照）

---

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

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

### 推奨読解順序

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

CRM連絡先のデータモデルとバリデーションを理解する。

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

**読解のコツ**:
- `enum :state`（行17-20）でステータス定義確認
- `validates :email, uniqueness`（行28）でユニーク制約確認
- `reference_prefix`（行54-56）で参照プレフィックス確認

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

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

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

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

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

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

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

**主要処理フロー**:
- `getGroupContacts`クエリでGraphQL取得
- `getGroupContactsCountByState`でステータスカウント取得
- デフォルトソートは`LAST_NAME_ASC`

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

```
Groups::Crm::ContactsController#index
    │
    ├─ validate_crm_group! (CRMグループ検証)
    │
    ├─ authorize_read_crm_contact! (認可チェック)
    │
    └─ View: index.html.haml
           └─ Vue: ContactsRoot
                  │
                  ├─ GraphQL: getGroupContacts
                  │
                  ├─ GraphQL: getGroupContactsCountByState
                  │
                  └─ Component: PaginatedTableWithSearchAndTabs
```

### データフロー図

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

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

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

### 関連ファイル一覧

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