# 画面設計書 3-サインアップ完了画面

## 概要

本ドキュメントは、Fizzyアプリケーションのサインアップ完了画面（`app/views/signups/completions/new.html.erb`）の設計仕様を記述したものです。

### 本画面の処理概要

サインアップ完了画面は、マジックリンク経由で認証されたユーザーがアカウント作成を完了するための画面です。ユーザーはフルネームを入力することで、新規アカウントとユーザープロファイルが作成され、Fizzyの利用を開始できます。

**業務上の目的・背景**：マジックリンク認証後、ユーザーのIdentityは作成されていますが、まだアカウント（テナント）は存在しない状態です。この画面でフルネームを入力することで、アカウント作成処理が完了し、ユーザーは自分専用のワークスペースを取得できます。シングルテナント環境でも、初回セットアップ時にはこの画面を通じて管理者アカウントが作成されます。

**画面へのアクセス方法**：サインアップ用マジックリンク（メール内のリンク）をクリックして認証が完了した後、自動的にこの画面にリダイレクトされます。また、既に認証済みでアカウントを持っていないユーザーがサインアップ画面にアクセスした場合もこの画面にリダイレクトされます。

**主要な操作・処理内容**：
1. フルネーム（表示名）を入力フィールドに入力する
2. 「Continue」ボタンをクリックしてフォームを送信する
3. バリデーションが実行される（フルネーム必須、最大240文字）
4. アカウント作成処理が実行される（Account、User、初期データのセットアップ）
5. 作成されたアカウントのランディングページにリダイレクトされる
6. または「Or import an exported account」リンクからデータインポート画面に遷移できる

**画面遷移**：
- 遷移元：マジックリンク認証完了後（サインアップ目的の場合）、サインアップ画面（認証済みの場合）
- 遷移先：ランディングページ（作成されたアカウント）、アカウントインポート画面

**権限による表示制御**：
- 認証済みかつアカウントを持たないユーザーのみアクセス可能
- アカウントスコープは無効化されている（`disallow_account_scope`）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | サインアップ | 主機能 | サインアップ完了後の確認表示とアカウント作成 |

## 画面種別

登録（フルネーム入力・アカウント作成）

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| URL | `/signup/completion/new`（表示）、`/signup/completion`（送信先） |
| HTTPメソッド | GET（表示）、POST（送信処理） |
| コントローラー | `Signups::CompletionsController` |
| アクション | `new`（表示）、`create`（送信処理） |
| レイアウト | `public` |

## 入出力項目

### 入力項目

| No | 項目名 | 物理名 | データ型 | 必須 | 最大長 | 入力形式 | バリデーション | 備考 |
|----|--------|--------|---------|------|--------|----------|---------------|------|
| 1 | フルネーム | signup[full_name] | string | 必須 | 240 | text | 空欄不可、240文字以内 | autocomplete="name" |

### 出力項目

| No | 項目名 | データ型 | 説明 |
|----|--------|---------|------|
| 1 | account_id | integer | 作成されたアカウントのID（JSON応答時） |

## 表示項目

| No | 項目名 | 表示条件 | データソース | 備考 |
|----|--------|----------|-------------|------|
| 1 | タイトル「Complete your sign-up」 | 常時 | 固定文言 | - |
| 2 | フルネーム入力フィールド | 常時 | - | placeholder="Enter your full name..." |
| 3 | 案内文 | 常時 | 固定文言 | "You're one step away..." |
| 4 | エラーメッセージ一覧 | @signup.errors.any? == true | @signup.errors | バリデーションエラー時 |
| 5 | 「Continue」ボタン | 常時 | 固定文言 | 矢印アイコン付き |
| 6 | インポートリンク | 常時 | 固定文言 | "Or import an exported account" |
| 7 | フッター | 常時 | _footer部分テンプレート | サポートメール連絡先 |

## イベント仕様

### 1-「Continue」ボタン押下

**トリガー**: フォーム送信（submit）

**処理フロー**:
1. `Signups::CompletionsController#create`が呼び出される
2. `Signup`モデルのインスタンスを作成（full_nameとidentityを設定）
3. `signup.complete`メソッドを実行
4. 成功時：
   - テナント作成（外部アカウント連携がある場合）
   - Account作成（名前は自動生成）
   - User作成（owner権限、verified_at設定）
   - Systemユーザー作成
   - 初期テンプレートのセットアップ（setup_customer_template）
   - `flash[:welcome_letter] = true`を設定
   - 作成されたアカウントのランディングページにリダイレクト
5. 失敗時：
   - バリデーションエラーを@signupに設定
   - new画面を再表示（422ステータス）

**レスポンス**:
- HTML成功時: 作成されたアカウントのランディングページにリダイレクト（`/[account_slug]/landing`）
- HTML失敗時: new画面を再表示（422 Unprocessable Entity）
- JSON成功時: `{ account_id: [id] }`（status: 201）
- JSON失敗時: `{ errors: [...] }`（status: 422）

### 2-インポートリンク押下

**トリガー**: 「Or import an exported account」リンクのクリック

**処理**: アカウントインポート画面（`/account/imports/new`）に遷移

**備考**: `data: { turbo_prefetch: false }`が設定されており、プリフェッチは無効

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| サインアップ完了 | accounts | INSERT | 新規アカウント作成 |
| サインアップ完了 | users | INSERT | Systemユーザー作成 |
| サインアップ完了 | users | INSERT | Ownerユーザー作成 |
| サインアップ完了 | account_join_codes | INSERT | 参加コード作成（after_create） |
| サインアップ完了 | boards | INSERT | 初期ボード作成（テンプレート） |
| サインアップ完了 | columns | INSERT | 初期カラム作成（テンプレート） |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | AccountNameGeneratorで自動生成 | フルネームとメールアドレスから生成 |
| INSERT | external_account_id | ExternalIdSequence.next | 外部ID自動採番 |
| INSERT | created_at | 現在日時 | 自動設定 |
| INSERT | updated_at | 現在日時 | 自動設定 |

#### users（Systemユーザー）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | account_id | 作成されたアカウントのID | 外部キー |
| INSERT | name | "System" | 固定値 |
| INSERT | role | system | enum値 |

#### users（Ownerユーザー）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | account_id | 作成されたアカウントのID | 外部キー |
| INSERT | identity_id | Current.identityのID | 外部キー |
| INSERT | name | 入力されたフルネーム | - |
| INSERT | role | owner | enum値 |
| INSERT | verified_at | 現在日時 | Time.current |

## メッセージ仕様

| No | メッセージ種別 | メッセージ内容 | 表示条件 |
|----|--------------|---------------|---------|
| 1 | エラー | Your changes couldn't be saved: | バリデーションエラー時のヘッダー |
| 2 | エラー | [バリデーションエラーメッセージ] | @signup.errors.full_messagesの各項目 |
| 3 | エラー | Something went wrong, and we couldn't create your account. Please give it another try. | アカウント作成中の例外発生時 |

## 例外処理

| 例外パターン | 対応内容 | 備考 |
|------------|---------|------|
| フルネーム未入力 | new画面を再表示、エラーメッセージ表示 | 422ステータス |
| フルネーム240文字超過 | new画面を再表示、エラーメッセージ表示 | 422ステータス |
| アカウント作成中の例外 | アカウント削除（ロールバック）、エラーログ出力、base errors追加 | destroy_accountで後処理 |
| エラー発生時 | shakeクラスでパネルを振動アニメーション | flash[:alert]がある場合 |

## 備考

- 本画面はマジックリンク認証後にのみ到達可能であり、直接アクセスすると認証が必要
- `disallow_account_scope`が設定されているため、アカウントスコープのURLでアクセスするとルートにリダイレクトされる
- アカウント名は`AccountNameGenerator`により、フルネームとメールアドレスから自動生成される
- `setup_customer_template`により、初期のボード・カラム構成がセットアップされる（skip_account_seedingがfalseの場合）
- フォームにはshakeクラスによるエラー時の振動アニメーションが実装されている
- `data: { controller: "form" }`によりStimulus.jsのformコントローラーが適用される

---

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

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

### 推奨読解順序

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

まず、アカウント作成に関わるデータモデルの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | signup.rb | `app/models/signup.rb` | completeメソッドの処理フロー、バリデーション |
| 1-2 | account.rb | `app/models/account.rb` | create_with_ownerメソッド、関連モデル |
| 1-3 | identity.rb | `app/models/identity.rb` | Identityとアカウントの関係 |

**読解のコツ**: `Signup`モデルの`complete`メソッドが中核処理です。`create_account`プライベートメソッドで`Account.create_with_owner`が呼ばれ、アカウントとユーザーが作成されます。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | completions_controller.rb | `app/controllers/signups/completions_controller.rb` | new/createアクションの処理フロー |

**主要処理フロー**:
1. **6-8行目**: `new`アクション - Current.identityを使ってSignupインスタンス作成
2. **10-18行目**: `create`アクション - completeメソッド実行と結果に応じた分岐
3. **25-34行目**: `welcome_to_account` - 成功時の処理（ランディングページへリダイレクト）
4. **36-41行目**: `invalid_signup` - 失敗時の処理（422で再表示）

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

画面表示のテンプレートを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.erb | `app/views/signups/completions/new.html.erb` | フォーム構造、エラー表示、インポートリンク |

**主要処理フロー**:
- **3行目**: shakeクラスの条件付き付与（flash[:alert]時）
- **7行目**: フルネーム入力フィールド（maxlength: 240）
- **11-20行目**: エラーメッセージ表示ブロック
- **28-32行目**: インポートリンク

#### Step 4: アカウント作成ロジックを理解する

アカウント作成の詳細処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | signup.rb | `app/models/signup.rb` | create_account、generate_account_nameメソッド |
| 4-2 | account.rb | `app/models/account.rb` | create_with_owner、after_createコールバック |
| 4-3 | account_name_generator.rb | `app/models/signup/account_name_generator.rb` | アカウント名自動生成ロジック |

**主要処理フロー**:
- **24-29行目（signup.rb）**: `complete`メソッド - バリデーション後にcreate_tenantとcreate_account
- **56-69行目（signup.rb）**: `create_account`メソッド - Account.create_with_owner呼び出し
- **23-29行目（account.rb）**: `create_with_owner`クラスメソッド - アカウントとユーザー作成

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

```
Signups::CompletionsController#create
    │
    ├─ Signup.new(signup_params)
    │      └─ identity: Current.identity
    │
    └─ @signup.complete
           │
           ├─ valid?(:completion)
           │      └─ [false] return false
           │
           └─ [true]
                  │
                  ├─ create_tenant (nil by default)
                  │
                  └─ create_account
                         │
                         ├─ Account.create_with_owner
                         │      │
                         │      ├─ Account.create!(...)
                         │      │      └─ [after_create] create_join_code
                         │      │
                         │      ├─ users.create!(role: :system)
                         │      │
                         │      └─ users.create!(role: :owner)
                         │
                         └─ account.setup_customer_template
                                └─ [初期データセットアップ]
```

### データフロー図

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

signup[full_name] ───▶ CompletionsController#create
                              │
                              ├──▶ Signup.new
                              │        │
                              │        └─▶ complete
                              │               │
                              │               ├─▶ バリデーション
                              │               │        │
                              │               │        └─[NG]─▶ render :new (422)
                              │               │
                              │               └─[OK]─▶ create_account
                              │                              │
                              │                              ├─▶ Account作成
                              │                              │
                              │                              ├─▶ User(system)作成
                              │                              │
                              │                              ├─▶ User(owner)作成
                              │                              │
                              │                              └─▶ 初期データセットアップ
                              │
                              └──▶ redirect_to landing_url ─▶ /[slug]/landing
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| completions_controller.rb | `app/controllers/signups/completions_controller.rb` | コントローラー | サインアップ完了処理の制御 |
| new.html.erb | `app/views/signups/completions/new.html.erb` | ビュー | サインアップ完了画面テンプレート |
| _footer.html.erb | `app/views/sessions/_footer.html.erb` | パーシャル | フッター表示 |
| signup.rb | `app/models/signup.rb` | モデル | サインアップフォームオブジェクト |
| account.rb | `app/models/account.rb` | モデル | アカウント（テナント）管理 |
| identity.rb | `app/models/identity.rb` | モデル | ユーザー識別情報の管理 |
| account_name_generator.rb | `app/models/signup/account_name_generator.rb` | モデル | アカウント名自動生成 |
| seeder.rb | `app/models/account/seeder.rb` | モデル | 初期データセットアップ |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
