# 帳票設計書 1-取引先一覧

## 概要

本ドキュメントは、Fat Free CRMシステムにおける取引先（Accounts）データのエクスポート帳票に関する設計仕様書です。取引先の基本情報、住所情報、カスタムフィールドを含む一覧データをXLS/CSV形式で出力する機能について記述します。

### 本帳票の処理概要

取引先一覧エクスポート機能は、システムに登録された取引先データを一括でダウンロードし、外部ツールでの分析や報告書作成を可能にする帳票出力機能です。

**業務上の目的・背景**：営業活動において、取引先データの一括管理・分析は重要な業務プロセスです。本帳票により、Excelなどの外部ツールでのデータ分析、経営報告書の作成、他システムへのデータ連携、バックアップ目的でのデータ保存など、多様なビジネスニーズに対応します。CRMに蓄積された顧客資産を効果的に活用するための基盤機能として位置づけられます。

**帳票の利用シーン**：月次・四半期の営業報告作成時、取引先情報の外部共有時、データ分析・マーケティング施策立案時、システム移行・バックアップ時に利用されます。

**主要な出力内容**：
1. 取引先基本情報（ID、名前、メール、電話番号、FAX、Webサイト等）
2. 所有者・担当者情報（作成ユーザー、担当者）
3. 分類・評価情報（アクセス権、評価、カテゴリ）
4. 住所情報（請求先住所の各フィールド）
5. タイムスタンプ（作成日、更新日）
6. カスタムフィールド（システム設定による拡張項目）

**帳票の出力タイミング**：取引先一覧画面において、ユーザーがエクスポートボタンをクリックした際にリアルタイムで生成・ダウンロードされます。

**帳票の利用者**：営業担当者、営業マネージャー、マーケティング担当者、システム管理者

## 帳票種別

一覧表（エクスポート帳票）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 取引先一覧画面 | /accounts | XLS/CSVエクスポートリンク |
| - | 取引先一覧画面 | /accounts.xls | XLS形式でダウンロード |
| - | 取引先一覧画面 | /accounts.csv | CSV形式でダウンロード |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | XLS（Excel XML Spreadsheet）/ CSV |
| 用紙サイズ | 該当なし（データエクスポート） |
| 向き | 該当なし |
| ファイル名 | accounts.xls / accounts.csv |
| 出力方法 | ダウンロード |
| 文字コード | UTF-8 |

### Excel固有設定

| 項目 | 内容 |
|-----|------|
| シート名 | Accounts（I18n.t(:tab_accounts)による国際化対応） |
| 保護設定 | 無 |

## 帳票レイアウト

### レイアウト概要

XLS形式のスプレッドシートとして、1行目にヘッダー、2行目以降にデータ行が続く標準的な表形式レイアウトです。

```
┌─────────────────────────────────────┐
│         ヘッダー行（項目名）          │
├─────────────────────────────────────┤
│         データ行1                    │
│         データ行2                    │
│         ...                         │
│         データ行N                    │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ID | 取引先ID | accounts.id | Number |
| 2 | User | 作成ユーザー名 | users.name（via user_id） | String |
| 3 | Assigned To | 担当者名 | users.name（via assigned_to） | String |
| 4 | Name | 取引先名 | accounts.name | String |
| 5 | Email | メールアドレス | accounts.email | String |
| 6 | Phone | 電話番号 | accounts.phone | String |
| 7 | Fax | FAX番号 | accounts.fax | String |
| 8 | Website | Webサイト | accounts.website | String |
| 9 | Background Info | 背景情報 | accounts.background_info | String |
| 10 | Access | アクセス権 | accounts.access | String |
| 11 | Phone Toll Free | フリーダイヤル | accounts.toll_free_phone | String |
| 12 | Rating | 評価 | accounts.rating | Number |
| 13 | Category | カテゴリ | accounts.category | String |
| 14 | Date Created | 作成日 | accounts.created_at | String |
| 15 | Date Updated | 更新日 | accounts.updated_at | String |
| 16 | Street1 | 住所1 | addresses.street1 | String |
| 17 | Street2 | 住所2 | addresses.street2 | String |
| 18 | City | 市区町村 | addresses.city | String |
| 19 | State | 都道府県 | addresses.state | String |
| 20 | Zipcode | 郵便番号 | addresses.zipcode | String |
| 21 | Country | 国 | addresses.country | String |
| 22 | Address | 完全住所 | addresses.full_address | String |
| 23+ | カスタムフィールド | 動的に追加 | fields.name | String/Number |

### 明細部

各取引先レコードについて、ヘッダー部と同じ順序で値を出力します。

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1-22 | （ヘッダー部と同じ） | - | - | - | 自動 |

### フッター部

なし（データ一覧のみ）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ユーザー権限 | 現在のユーザーがアクセス可能な取引先のみ | Yes |
| 検索条件 | 画面で適用されているフィルタ・検索条件を継承 | No |
| ステータスフィルタ | session[:accounts_filter]による状態フィルタ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ユーザー設定 | 設定による |
| 2 | created_at | 降順（デフォルト） |

### 改ページ条件

該当なし（全データを単一シートに出力）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| accounts | 取引先基本情報 | メインテーブル |
| users | ユーザー情報 | accounts.user_id = users.id, accounts.assigned_to = users.id |
| addresses | 住所情報 | addresses.addressable_id = accounts.id AND addresses.addressable_type = 'Account' AND addresses.address_type = 'Billing' |
| fields | カスタムフィールド定義 | fields.klass_name = 'Account' |

### テーブル別参照項目詳細

#### accounts

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | ID | - | 主キー |
| name | Name | - | 必須項目 |
| email | Email | - | - |
| phone | Phone | - | - |
| fax | Fax | - | - |
| website | Website | - | - |
| background_info | Background Info | - | - |
| access | Access | - | Public/Private/Shared |
| toll_free_phone | Phone Toll Free | - | - |
| rating | Rating | - | 0-5の整数 |
| category | Category | - | - |
| created_at | Date Created | - | - |
| updated_at | Date Updated | - | - |

#### addresses（Billing Address）

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| street1 | Street1 | address_type = 'Billing' | - |
| street2 | Street2 | address_type = 'Billing' | - |
| city | City | address_type = 'Billing' | - |
| state | State | address_type = 'Billing' | - |
| zipcode | Zipcode | address_type = 'Billing' | - |
| country | Country | address_type = 'Billing' | - |
| full_address | Address | address_type = 'Billing' | 結合住所 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| データ型判定 | value.respond_to?(:abs) ? 'Number' : 'String' | - | セルのデータ型を動的に判定 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[XLS/CSVエクスポート要求] --> B[AccountsController#index]
    B --> C[EntitiesController#get_list_of_records]
    C --> D[Ransack検索実行]
    D --> E[ページネーション無効化]
    E --> F{出力形式}
    F -->|XLS| G[index.xls.builder実行]
    F -->|CSV| H[FatFreeCRM::ExportCSV.from_array実行]
    G --> I[XMLWorkbook生成]
    H --> J[CSV生成]
    I --> K[ファイルダウンロード]
    J --> K
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | @accounts.empty? | 空のワークシートが出力される | ヘッダー・データ行とも出力されない |
| 認証エラー | 未ログイン | ログイン画面へリダイレクト | ログイン後に再実行 |
| 権限エラー | アクセス権限なし | 権限エラーメッセージ | 管理者に権限付与を依頼 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千件 |
| 目標出力時間 | 5秒以内（1000件程度） |
| 同時出力数上限 | 明示的な制限なし |

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

- ユーザー権限に基づくアクセス制御（uses_user_permissions）により、ユーザーがアクセス権を持つ取引先のみエクスポート可能
- 認証が必要（authenticate_user!）
- Access列の値（Public/Private/Shared）に基づくデータ可視性制御
- パスワード・トークン等の機密情報はCSVエクスポート時に除外される（export_csv.rb:20）

## 備考

- 国際化対応：ヘッダーラベルはI18nを使用して多言語対応
- カスタムフィールド対応：Account.fieldsメソッドにより動的にカスタムフィールドを追加出力
- XLS形式はXML Spreadsheet形式（Office 2003互換）で出力

---

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

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

### 推奨読解順序

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

まず、取引先エンティティの構造とリレーションを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account.rb | `app/models/entities/account.rb` | Accountモデルの定義、関連付け（belongs_to :user, has_one :billing_address）、スコープ定義を確認 |
| 1-2 | address.rb | `app/models/polymorphic/address.rb` | 住所モデルのポリモーフィック関連を理解 |

**読解のコツ**: Railsのhas_one/belongs_to関連、scopeメソッド、acts_as_taggable_onなどのプラグイン記法に注目

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

処理の起点となるコントローラーを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | entities_controller.rb | `app/controllers/entities_controller.rb` | 共通のindexアクション処理、get_list_of_recordsメソッドの動作を理解 |
| 2-2 | application_controller.rb | `app/controllers/application_controller.rb` | respond_to宣言（27行目：xls, csv対応）、認証フィルタを確認 |

**主要処理フロー**:
1. **138-178行目**: get_list_of_recordsでデータ取得、ページネーション制御（XLS/CSV時は無効化:166行目）

#### Step 3: ビューテンプレートを理解する

XLS出力の実際の処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.xls.builder | `app/views/accounts/index.xls.builder` | Builder DSLによるXML生成、ヘッダー定義（8-29行目）、データ出力（45-83行目） |
| 3-2 | header.xls.builder | `app/views/layouts/header.xls.builder` | XMLワークブック構造の定義 |

**主要処理フロー**:
- **7-42行目**: ヘッダー行の生成（I18nによるラベル国際化）
- **32-34行目**: カスタムフィールドラベルの動的追加
- **45-83行目**: データ行の生成
- **72-74行目**: カスタムフィールド値の動的取得

#### Step 4: CSV出力を理解する

CSV形式での出力処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | export_csv.rb | `lib/fat_free_crm/export_csv.rb` | CSV生成ロジック、カラム除外処理（password/token）、タグ対応 |

**主要処理フロー**:
- **15-34行目**: from_arrayメソッドでのCSV生成
- **20行目**: パスワード・トークンカラムの除外

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

```
HTTP Request (GET /accounts.xls)
    │
    ├─ ApplicationController (認証・権限チェック)
    │      └─ authenticate_user!
    │
    ├─ EntitiesController#index (継承元)
    │      └─ get_list_of_records
    │             ├─ ransack_search.result (検索実行)
    │             └─ ページネーション制御
    │
    └─ accounts/index.xls.builder (ビュー)
           ├─ header.xls.builder (レイアウト)
           │      └─ XML Workbook構造
           │
           ├─ @accounts.each (データイテレーション)
           │      ├─ account.user.try(:name)
           │      ├─ account.billing_address.try(:street1)
           │      └─ Account.fields.each (カスタムフィールド)
           │
           └─ XMLセル出力
```

### データフロー図

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

Request             EntitiesController        Response
/accounts.xls  ───▶ #index                ───▶ accounts.xls
                         │
                         ▼
                    get_list_of_records
                         │
                         ▼
                    Ransack検索
                         │
                         ▼
                    @accounts (Collection)
                         │
                         ▼
                    index.xls.builder
                         │
                         ▼
                    XML生成 (Builder)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| account.rb | `app/models/entities/account.rb` | ソース | Accountモデル定義 |
| entities_controller.rb | `app/controllers/entities_controller.rb` | ソース | 共通コントローラー処理 |
| application_controller.rb | `app/controllers/application_controller.rb` | ソース | 基底コントローラー |
| index.xls.builder | `app/views/accounts/index.xls.builder` | テンプレート | XLS出力ビュー |
| header.xls.builder | `app/views/layouts/header.xls.builder` | テンプレート | XLSレイアウト |
| export_csv.rb | `lib/fat_free_crm/export_csv.rb` | ソース | CSV出力ユーティリティ |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（44-62行目） |
