# 通知設計書 10-面接官アサインメール

## 概要

本ドキュメントは、AureusERPシステムにおける面接官アサインメール（InterviewerAssignedMail）通知機能の設計仕様を定義するものである。

### 本通知の処理概要

本通知は、応募者の面接官として社内ユーザーがアサインされた際に、アサインされた面接官に対して送信される通知メールである。

**業務上の目的・背景**：採用活動において、面接官のスケジュール調整と応募者情報の共有は重要である。本通知により、面接官に面接の担当が割り当てられたことを即座に知らせ、応募者情報へのアクセスを促すことで、採用プロセスの効率化を図る。

**通知の送信タイミング**：応募者レコードの編集時に、面接官リスト（interviewer）に新しいユーザーが追加された場合に送信される。ただし、自分自身を面接官として追加した場合は通知されない。

**通知の受信者**：新たにアサインされた面接官（User）のメールアドレス。

**通知内容の概要**：面接官としてアサインされたことの通知、応募者名、応募者レコードへのリンク、および内部コミュニケーション用の注意書きが含まれる。

**期待されるアクション**：面接官はメール内のリンクをクリックして応募者情報を確認し、面接の準備を行うことが期待される。

## 通知種別

メール通知（HTML形式、Laravel Mailableコンポーネント使用）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（Queueable trait使用） |
| 優先度 | 中 |
| リトライ | Laravelキューのデフォルト設定に依存 |

### 送信先決定ロジック

1. 応募者レコード保存時に面接官リストの変更を検出
2. 新たに追加された面接官（以前のリストに存在しないユーザー）を抽出
3. 自分自身（現在のログインユーザー）を除外
4. 残った面接官に対して個別にメール送信

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | payload['from']['address']（送信者設定） |
| 送信元名称 | payload['from']['name']（送信者名） |
| 件名 | "Interview Assignment: {applicant_name}" |
| 形式 | HTML（Bladeビュー） |

### 本文テンプレート

```html
<div class="breadcrumb">
    Interview for: {応募者名}
</div>

<div class="notification">
    <p>Hello {面接官名},</p>
    <p>You have been assigned as an interviewer for <strong>{応募者名}</strong>.</p>
    <hr class="separator">
    <p class="internal-note">
        <strong>Internal Communication:</strong> This is an internal notification.
    </p>
    <div class="view-button-container">
        <a href="{応募者レコードURL}" class="view-button">
            View Applicant
        </a>
    </div>
</div>

<div class="company-info">
    <div class="company-name">{会社名}</div>
    <p class="company-details">
        {電話番号} | {メールアドレス} | {ウェブサイト}
    </p>
</div>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | 通常は添付なし | 添付機能は実装されているが通常使用しない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| payload.record_name | 応募者名 | $record->candidate->name | Yes |
| payload.record_url | 応募者レコードへのURL | $this->getRedirectUrl() | Yes |
| payload.subject | メール件名 | 翻訳キーで生成 | Yes |
| payload.to.address | 送信先メールアドレス | $interviewer->email | Yes |
| payload.to.name | 送信先名 | $interviewer->name | Yes |
| payload.from.company | 送信元会社情報 | Auth::user()->defaultCompany | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 応募者レコード編集・保存 | 面接官リストに新しいユーザーが追加された場合 | 面接官アサイン通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 追加された面接官が自分自身 | Auth::id()と一致する面接官には送信されない |
| 面接官リストに変更なし | 新規追加がない場合は送信されない |
| 追加された面接官のリストが空 | 全員が除外された場合は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[担当者が応募者レコードを編集・保存] --> B[mutateFormDataBeforeSaveで面接官変更検出]
    B --> C{面接官リストに変更あり?}
    C -->|No| D[通知なしで終了]
    C -->|Yes| E[afterSaveフック実行]
    E --> F[interviewer関連を同期]
    F --> G[sendInterviewerAssignmentNotificationメソッド呼び出し]
    G --> H[新規追加面接官を抽出]
    H --> I[自分自身を除外]
    I --> J{追加面接官リストが空でない?}
    J -->|No| K[終了]
    J -->|Yes| L[面接官ごとにループ]
    L --> M[prepareInterviewerNotificationPayloadでペイロード作成]
    M --> N[InterviewerAssignedMail送信]
    N --> O[次の面接官へ]
    O --> P{全面接官処理完了?}
    P -->|No| L
    P -->|Yes| K
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| recruitments_applicants | 応募者情報取得 | $record |
| recruitments_candidates | 候補者情報取得 | $record->candidate |
| recruitments_applicant_interviewers | 面接官関連取得 | $record->interviewer |
| users | 面接官ユーザー情報取得 | User::find() |

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

#### recruitments_applicants

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| candidate_id | 候補者関連取得 | 対象レコード |

#### recruitments_applicant_interviewers

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| user_id | 面接官ユーザーID | 対象レコードの関連 |

#### users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ユーザーID | 面接官ID |
| name | 面接官名 | 送信先名 |
| email | 面接官メールアドレス | 送信先 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| recruitments_applicant_interviewers | SYNC | 面接官関連の同期 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー等 | Laravelキューの標準リトライ機構に依存 |
| ユーザー取得失敗 | User::findで見つからない | スキップ（if ($interviewer)チェック） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Laravelキュー設定に依存 |
| リトライ間隔 | Laravelキュー設定に依存 |
| リトライ対象エラー | キュー処理時の一時的なエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（システム設定に依存） |
| 1日あたり上限 | 制限なし（システム設定に依存） |

### 配信時間帯

特に制限なし。レコード保存に応じて即時送信される。

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

- 応募者レコードへの直接URLが含まれるため、受信者は適切なアクセス権を持っている必要がある
- 内部ユーザーのみが受信対象のため、外部への情報漏洩リスクは低い
- 送信元アドレスと名称はEmailServiceの設定に基づく
- 「内部コミュニケーション」であることがメール本文に明記される

## 備考

- 本機能はWebkul Recruitmentsプラグインの一部として実装されている
- EditApplicantページクラスのafterSaveフックで処理される
- EmailServiceを通じてメール送信が行われる
- ビューテンプレートはrecruitments::mails.interviewer-assigned
- 面接官リストの変更検出はmutateFormDataBeforeSaveで行われる
- 自分自身を面接官としてアサインした場合は通知されない（ノイズ軽減）
- 既存の面接官が削除されても削除通知は送信されない（追加のみ通知）
