コンテンツにスキップ

データモデル

概念モデル図

erDiagram
  users ||--o{ projects : "作成する"
  users ||--o{ project_interviewers : "面接官として参加する"
  users ||--o{ reservations : "面接を担当する"
  projects ||--o{ project_candidates : "候補者を持つ"
  projects ||--o{ project_interviewers : "面接官を持つ"
  projects ||--o{ email_templates : "テンプレートを持つ"
  projects ||--o{ import_logs : "インポート履歴を持つ"
  candidates ||--o{ project_candidates : "参加する"
  project_candidates ||--o| reservations : "確定予約を持つ"
  project_candidates ||--o{ scheduling_tokens : "調整トークンを持つ"
  project_candidates ||--o{ candidate_available_dates : "希望日程を持つ"
  project_candidates ||--o{ email_logs : "送信履歴を持つ"
  project_candidates ||--o{ status_histories : "ステータス履歴を持つ"
  email_templates ||--o{ email_logs : "利用される"

エンティティ概要

コア

エンティティ名 物理名 説明
ユーザー users 管理画面のユーザー。Google アカウントに 1 対 1 で対応し、面接官もここに含まれる
プロジェクト projects 1 回のインタビュー企画。面接条件・スコアリングルール・アンケートインポート設定・アレンジ設定を持つ
候補者 candidates 個人そのもの。プロジェクトをまたいで一意(external_user_id)
プロジェクト候補者 project_candidates 候補者のプロジェクトへの参加。ステータス・スコア・選定区分・回答内容を持つ
プロジェクト面接官 project_interviewers プロジェクトと面接官(ユーザー)の紐付け

日程調整

エンティティ名 物理名 説明
調整トークン scheduling_tokens 候補者向け公開ページへのアクセストークン。有効期限を持つ
候補者希望日程 candidate_available_dates 候補者が送信した希望枠。送信のたびに全置換される
予約 reservations 確定した面接。プロジェクト候補者につき最大 1 件(UNIQUE)
ステータス履歴 status_histories 候補者ステータスの遷移記録

メール

エンティティ名 物理名 説明
メールテンプレート email_templates 種別つきのテンプレート。project_id が NULL ならシステム共通
メール送信ログ email_logs 送信済みメールの件名・本文・結果

インポートと調査メタキャッシュ

エンティティ名 物理名 説明
インポートログ import_logs TSV / アンケートインポートの実行履歴と件数・エラー内訳
調査メタ databricks_surveys 調査のメタデータキャッシュ。日次バッチで Databricks から更新する

主要なビジネスルール

候補者とプロジェクト候補者の分離

  • 個人としての候補者(candidates)と、プロジェクトへの参加(project_candidates)を分離している
  • candidates.external_user_id は全体で UNIQUE。同じ人物が複数プロジェクトに参加しても candidates は 1 レコード
  • project_candidates は (project_id, candidate_id) の組で UNIQUE(uk_project_candidate)。同一プロジェクトへの二重登録は不可
  • 回答内容(survey_responses)・属性(attributes)・スコア・選定区分はプロジェクトごとに持つ

予約

  • reservations.project_candidate_id は UNIQUE。1 人の候補者につきプロジェクト内で確定予約は最大 1 件
  • キャンセルはレコード削除ではなく status = 'cancelled' への更新
  • interviewer_id は users を onDelete: restrict で参照するため、予約が残るユーザーは削除できない

ステータス遷移

  • project_candidates.status の遷移は許可された組み合わせのみ(機能 のステータス遷移図を参照)
  • 遷移のたびに status_histories に 1 行追加される
  • completed と declined は終端。bounced からは contacted へ、cancelled からは not_contacted へ戻せる

カスケード削除

projects を削除すると、project_candidates / project_interviewers / email_templates / import_logs が連鎖削除される。project_candidates の削除はさらに email_logs / scheduling_tokens / candidate_available_dates / reservations / status_histories に連鎖する。

調査メタキャッシュ

  • databricks_surveys は外部データのキャッシュであり、アプリケーション側のテーブルとは外部キーで結ばれていない
  • 回答本体は Postgres に持たない。 Databricks の cs.cs_dm.dm_answers_<survey_id> から直接読む(Databricks 連携)
  • 回答は panel_id + 設問文で 1 行という縦持ち形式。設問 ID が存在しないため設問文そのものが識別子になる
  • 候補者への取り込みは、この縦持ちデータを横持ちに畳んで project_candidates.survey_responses に格納する

個人情報の保持

  • 個人情報(candidates の氏名・メール・電話)は保持期間(既定 3 ヶ月)超過後に pii-cleanup バッチで匿名化される
  • 集計のため project_candidates などの関連レコードは残す