# 機能設計書 6-取引先作成

## 概要

本ドキュメントは、Fat Free CRMシステムにおける取引先作成機能の設計を定義する。この機能は、新規取引先を作成し、同時にコメントを追加することを可能にする。

### 本機能の処理概要

取引先作成機能は、CRMシステムに新しい取引先（顧客企業）を登録するための機能である。基本情報の登録に加え、住所情報やカスタムフィールドの設定、アクセス権限の設定が可能である。

**業務上の目的・背景**：営業活動において、新規顧客を獲得した際に、その企業情報をシステムに登録する必要がある。本機能により、取引先の基本情報を効率的に登録し、以降の営業活動の基盤を構築できる。また、作成時にコメントを追加できることで、初回コンタクトの経緯などを記録できる。

**機能の利用シーン**：
- 営業担当者が新規顧客を獲得した際に企業情報を登録する場面
- 展示会やセミナーで名刺交換した企業を一括登録する場面
- 既存顧客から紹介された企業を登録する場面

**主要な処理内容**：
1. 新規取引先フォームの表示（newアクション）
2. デフォルト値の設定（所有者、アクセス権限）
3. 入力データのバリデーション
4. 取引先レコードの作成
5. コメントの追加（オプション）
6. サイドバーデータの更新

**関連システム・外部連携**：本機能は外部システムとの連携はなく、内部データベースへの登録のみで構成される。

**権限による制御**：認証済みユーザーは取引先を作成可能。作成された取引先の所有者は作成者となり、アクセス権限設定により他ユーザーとの共有が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | 取引先新規作成フォーム | 主画面 | 新規取引先情報入力、コメント追加、作成実行 |

## 機能種別

データ作成（CREATE操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| account[name] | String | Yes | 取引先名 | 必須、64文字以内、一意性チェック（設定による） |
| account[category] | String | No | カテゴリ | 設定で定義されたカテゴリ値 |
| account[access] | String | No | アクセス権限 | Public/Private/Shared |
| account[user_ids] | Array | No | 共有ユーザーID | access=Sharedの場合は必須 |
| account[assigned_to] | Integer | No | 担当者ID | 存在するユーザーID |
| account[website] | String | No | Webサイト | 64文字以内 |
| account[email] | String | No | メールアドレス | 64文字以内 |
| account[phone] | String | No | 電話番号 | 32文字以内 |
| account[toll_free_phone] | String | No | フリーダイヤル | 32文字以内 |
| account[fax] | String | No | FAX番号 | 32文字以内 |
| account[rating] | Integer | No | レーティング | 0-5の範囲 |
| account[background_info] | String | No | 背景情報 | 255文字以内 |
| account[billing_address_attributes] | Hash | No | 請求先住所 | ネスト属性 |
| account[shipping_address_attributes] | Hash | No | 配送先住所 | ネスト属性 |
| comment_body | String | No | コメント | - |

### 入力データソース

- フォーム入力
- セッション情報（current_user）
- システム設定（default_access）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @account | Account | 作成された取引先（成功時）/エラー情報付き取引先（失敗時） |
| @accounts | ActiveRecord::Relation<Account> | 取引先一覧（成功時、一覧画面更新用） |
| @account_category_total | HashWithIndifferentAccess | カテゴリ別件数（成功時） |

### 出力先

- AJAX応答（create.js.haml）
- データベース（accounts, comments, versions）

## 処理フロー

### 処理シーケンス

```
【newアクション】
1. load_and_authorize_resourceによる新規オブジェクト作成
2. デフォルト属性の設定
   ├─ user: current_user
   ├─ access: Setting.default_access
   └─ assigned_to: nil
3. relatedパラメータがある場合は関連エンティティ設定
4. respond_with(@account)

【createアクション】
1. load_and_authorize_resourceによるオブジェクト作成
2. @comment_body = params[:comment_body]
3. @account.save実行
4. 成功時:
   ├─ add_comment_by_userでコメント追加
   ├─ get_accountsで一覧取得
   └─ get_data_for_sidebarでサイドバー更新
5. respond_with(@account)
```

### フローチャート

```mermaid
flowchart TD
    A[フォーム送信] --> B[パラメータ取得]
    B --> C[バリデーション]
    C --> D{有効?}
    D -->|No| E[エラー表示]
    D -->|Yes| F[取引先保存]
    F --> G{成功?}
    G -->|No| E
    G -->|Yes| H{コメントあり?}
    H -->|Yes| I[コメント追加]
    H -->|No| J[一覧取得]
    I --> J
    J --> K[サイドバー更新]
    K --> L[AJAX応答]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 名前必須 | 取引先名は必須入力 | 常時 |
| BR-002 | 名前一意性 | 取引先名は一意（設定による） | require_unique_account_names=true |
| BR-003 | 共有ユーザー必須 | access=Sharedの場合、1名以上のユーザー指定必須 | access=Shared |
| BR-004 | デフォルト所有者 | 所有者は作成者 | 常時 |
| BR-005 | デフォルトアクセス | アクセス権限はシステム設定値 | access未指定時 |

### 計算ロジック

特に計算ロジックは存在しない。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 取引先作成 | accounts | INSERT | 新規取引先レコード作成 |
| 住所作成 | addresses | INSERT | 請求先/配送先住所（ある場合） |
| コメント作成 | comments | INSERT | 初期コメント（ある場合） |
| 履歴作成 | versions | INSERT | 作成履歴（PaperTrail） |
| 権限作成 | permissions | INSERT | 共有権限（access=Sharedの場合） |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name, category, access, user_id, assigned_to, website, email, phone, etc. | フォーム入力値 | バリデーション後 |

#### comments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | comment, user_id, commentable_type, commentable_id | comment_body, current_user.id, 'Account', @account.id | add_comment_by_user |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | 未ログイン状態でアクセス | ログイン画面へリダイレクト |
| 422 | バリデーションエラー | 必須項目未入力、一意性違反等 | エラーメッセージ表示 |

### リトライ仕様

本機能ではリトライ処理は実装されていない。バリデーションエラー時はフォームを再表示。

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

取引先、住所、コメント、権限の作成はActiveRecordのトランザクション内で実行される。いずれかが失敗した場合はロールバック。

## パフォーマンス要件

- 作成処理時間: 2秒以内を目標
- 一意性チェックはデータベースインデックスを使用

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

- 認証: Deviseによるユーザー認証が必須
- CSRF: protect_from_forgeryによる対策
- Strong Parameters: params.permit!による許可（注意が必要）

## 備考

- 作成は取引先一覧画面からのみ実行可能（コメントによる制約）
- 住所はネスト属性として一括保存

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account.rb | `app/models/entities/account.rb` | バリデーション、accepts_nested_attributes_for |
| 1-2 | address.rb | `app/models/polymorphic/address.rb` | 住所モデル |
| 1-3 | comment.rb | `app/models/polymorphic/comment.rb` | コメントモデル |

**読解のコツ**:
- validates_presence_of :name（76行目）で名前必須を確認
- validates_uniqueness_of :name（77行目）で一意性チェック条件を確認
- accepts_nested_attributes_for（46-47行目）で住所のネスト保存を確認

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.rb | `config/routes.rb` | POST /accounts ルート |
| 2-2 | accounts_controller.rb | `app/controllers/entities/accounts_controller.rb` | new, createアクション |

**主要処理フロー**:
1. **34-43行目**: newアクション - デフォルト値設定
2. **55-66行目**: createアクション - 保存処理
3. **56行目**: @comment_body = params[:comment_body]
4. **58-64行目**: 保存成功時の処理

#### Step 3: コメント追加ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | comment_extensions.rb | `lib/fat_free_crm/comment_extensions.rb` | add_comment_by_userメソッド |

**主要処理フロー**:
- add_comment_by_userはコメント本文が存在する場合のみコメントを作成

#### Step 4: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | new.js.haml | `app/views/accounts/new.js.haml` | フォーム表示JS |
| 4-2 | _new.html.haml | `app/views/accounts/_new.html.haml` | 作成フォーム |
| 4-3 | create.js.haml | `app/views/accounts/create.js.haml` | 作成結果JS |

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

```
AccountsController#new
    │
    ├─ load_and_authorize_resource (Account.new)
    └─ @account.attributes = {...}
           ├─ user: current_user
           ├─ access: Setting.default_access
           └─ assigned_to: nil

AccountsController#create
    │
    ├─ load_and_authorize_resource (Account.new with params)
    ├─ @comment_body = params[:comment_body]
    │
    └─ @account.save
           │
           ├─ 【成功時】
           │   ├─ add_comment_by_user(@comment_body, current_user)
           │   │      └─ Comment.create (if comment_body.present?)
           │   ├─ get_accounts
           │   └─ get_data_for_sidebar
           │
           └─ 【失敗時】
               └─ エラー情報付き@account返却
```

### データフロー図

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

フォーム入力 ───▶ AccountsController#create ───▶ @account (成功/失敗)
(account params,      │                          @accounts (成功時)
 comment_body)        │                          @account_category_total
                      │
                      ├─ バリデーション
                      ├─ Account.save
                      ├─ Comment.create
                      │
                      ▼
               データベース
               (accounts,
                addresses,
                comments,
                permissions,
                versions)
                      │
                      ▼
               create.js.haml
                      │
                      ▼
               AJAX画面更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| accounts_controller.rb | `app/controllers/entities/accounts_controller.rb` | ソース | メインコントローラー |
| account.rb | `app/models/entities/account.rb` | ソース | 取引先モデル |
| address.rb | `app/models/polymorphic/address.rb` | ソース | 住所モデル |
| comment.rb | `app/models/polymorphic/comment.rb` | ソース | コメントモデル |
| comment_extensions.rb | `lib/fat_free_crm/comment_extensions.rb` | ソース | コメント拡張 |
| new.js.haml | `app/views/accounts/new.js.haml` | テンプレート | フォーム表示JS |
| _new.html.haml | `app/views/accounts/_new.html.haml` | テンプレート | 作成フォーム |
| create.js.haml | `app/views/accounts/create.js.haml` | テンプレート | 作成結果JS |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
