コンテンツにスキップ

データベース(コア)

プロジェクトと候補者を中心とした 5 テーブル。


users

概要

管理画面のユーザー。Google アカウントに 1 対 1 で対応する。面接官もこのテーブルのレコードとして表現される。

テーブル定義

論理名 物理名 カラム名 データ型 主キー リレーション ユニーク NULL許可 デフォルト値 備考
ユーザー users id integer ◯ auto-increment
google_id varchar(255) ◯ Google アカウントの一意 ID
email varchar(255) ◯
name varchar(255) 表示名
avatar_url varchar(500) ◯ Google プロフィール画像
role user_role 'member' admin / member / viewer
created_at timestamp now()
updated_at timestamp now()

インデックス

  • 主キー (id)
  • UNIQUE: google_id
  • UNIQUE: email
  • INDEX: idx_users_email (email)

注記

  • ユーザーの新規作成は Google OAuth コールバック時に自動で行われる(初回ログインで登録)
  • role の既定は member。viewer への降格や admin への昇格は現状 DB 直接更新
  • reservations.interviewer_id が onDelete: restrict で参照するため、予約が残るユーザーは削除できない

projects

概要

1 回のインタビュー企画。面接条件・スコアリングルール・アンケートインポート設定・アレンジフローの状態をすべて保持する。

テーブル定義

論理名 物理名 カラム名 データ型 主キー リレーション ユニーク NULL許可 デフォルト値 備考
プロジェクト projects id integer ◯ auto-increment
name varchar(255) プロジェクト名
description text ◯
status project_status 'draft' draft / active / completed / archived
interview_duration_minutes integer 60 面接 1 件の所要時間(分)
scheduling_range_start_days integer 1 調整可能期間の開始(今日から N 日後)
scheduling_range_end_days integer 14 調整可能期間の終了(今日から N 日後)
scoring_rules json ◯ ScoringRules 型
interview_type interview_type 'any' online_meet / online_zoom / offline / any
google_calendar_id varchar(255) ◯ プロジェクト専用カレンダー
survey_auto_import_enabled boolean false 自動インポートの有効化
survey_id varchar(50) ◯ 紐付けるアンケート ID(databricks_surveys.survey_id を論理参照)
survey_import_mapping json ◯ ImportMapping 型
survey_import_filter json ◯ ImportFilter 型
survey_last_imported_at timestamp ◯ 最終インポート日時
arrange_settings json ◯ ArrangeSettings 型(STEP1〜3)
created_by integer users:id(論理) 作成者
created_at timestamp now()
updated_at timestamp now()

リレーション

  • created_by → users.id:Drizzle の relations() 上でのみ定義されており、DB レベルの外部キー制約は張られていない
  • 子テーブル(onDelete: cascade):project_candidates / project_interviewers / email_templates / import_logs

インデックス

  • 主キー (id)
  • INDEX: idx_projects_status (status)
  • INDEX: idx_projects_created_by (created_by)

注記

  • arrange_settings はアレンジフローの状態を JSON カラム 1 個に丸ごと 保存する設計。STEP ごとにテーブルを分けていない
  • scoring_rules.max_score が指定されている場合、算出スコアの上限になる
  • 調整可能期間は絶対日付ではなく「今日からの相対日数」で保持する

candidates

概要

個人としての候補者。プロジェクトをまたいで一意であり、同じ人物が複数プロジェクトに参加しても 1 レコード。

テーブル定義

論理名 物理名 カラム名 データ型 主キー リレーション ユニーク NULL許可 デフォルト値 備考
候補者 candidates id integer ◯ auto-increment
external_user_id varchar(255) ◯ 外部システム(アンケート基盤)の回答者 ID
email varchar(255) 個人情報
phone varchar(50) ◯ 個人情報
name varchar(255) 個人情報
created_at timestamp now()
updated_at timestamp now()

インデックス

  • 主キー (id)
  • UNIQUE: external_user_id
  • INDEX: idx_candidates_email (email)

注記

  • email は UNIQUE ではない。同一メールアドレスの別回答者を許容するため、一意キーは external_user_id
  • email / phone / name は個人情報であり、保持期間(既定 3 ヶ月)超過後に pii-cleanup バッチで匿名化される
  • 匿名化後も project_candidates などの関連レコードは集計のため残る

project_candidates

概要

候補者のプロジェクトへの参加。ステータス・スコア・選定区分・回答内容といった「プロジェクト文脈の情報」をすべて持つ、システムの中心テーブル。

テーブル定義

論理名 物理名 カラム名 データ型 主キー リレーション ユニーク NULL許可 デフォルト値 備考
プロジェクト候補者 project_candidates id integer ◯ auto-increment
project_id integer projects:id (cascade)
candidate_id integer candidates:id (cascade)
attributes jsonb ◯ 属性(都道府県・年齢など)
survey_responses jsonb ◯ アンケート回答(横持ち)
score decimal(10,2) ◯ スコアリング結果
selection_type selection_type ◯ primary(本命)/ reserve(補欠)
segment_id varchar(255) ◯ arrange_settings.step2.segments[].id を参照する論理キー
memo text ◯ 自由記述メモ
priority varchar(1) ◯ 優先度(A / B / C)
status pc_status 'not_contacted' 10 値の enum
created_at timestamp now()
updated_at timestamp now()

リレーション

  • project_id → projects.id(onDelete: cascade)
  • candidate_id → candidates.id(onDelete: cascade)
  • 子テーブル(onDelete: cascade):email_logs / scheduling_tokens / candidate_available_dates / reservations / status_histories

インデックス

  • 主キー (id)
  • UNIQUE INDEX: uk_project_candidate (project_id, candidate_id)
  • INDEX: idx_pc_project_status (project_id, status)
  • INDEX: idx_pc_project_score (project_id, score)

注記

  • uk_project_candidate により、同一プロジェクトへの二重登録は不可
  • status の遷移は VALID_STATUS_TRANSITIONS に定義された組み合わせのみ許可される(機能 の遷移図を参照)。不正な遷移は InvalidStatusTransitionError
  • segment_id は他テーブルへの外部キーではなく、projects.arrange_settings 内のセグメント定義を指す文字列
  • attributes と survey_responses はどちらも jsonb。候補者一覧の responseFilter クエリはこの 2 つを対象に絞り込む

project_interviewers

概要

プロジェクトと面接官(ユーザー)の中間テーブル。

テーブル定義

論理名 物理名 カラム名 データ型 主キー リレーション ユニーク NULL許可 デフォルト値 備考
プロジェクト面接官 project_interviewers id integer ◯ auto-increment
project_id integer projects:id (cascade)
user_id integer users:id (cascade)
created_at timestamp now()

リレーション

  • project_id → projects.id(onDelete: cascade)
  • user_id → users.id(onDelete: cascade)

インデックス

  • 主キー (id)
  • UNIQUE INDEX: uk_project_user (project_id, user_id)

注記

  • メイン/サブの区別はこのテーブルではなく projects.arrange_settings.step1.mainInterviewerIds / subInterviewerIds に持つ
  • 空き枠算出はこのテーブルに登録された面接官の Google Calendar を参照する