2026-07-03 15:12:20 +08:00

286 lines
13 KiB
SQL

CREATE TABLE IF NOT EXISTS "performance_survey_employee_profiles" (
"id" TEXT PRIMARY KEY,
"dingtalk_user_id" TEXT,
"ding_email" TEXT,
"job_number" TEXT,
"flower_name" TEXT,
"real_name" TEXT,
"display_name" TEXT NOT NULL,
"department_name" TEXT,
"department_path" TEXT,
"position_title" TEXT,
"position_level" TEXT,
"level_type" TEXT,
"is_leadership" BOOLEAN NOT NULL DEFAULT FALSE,
"manager_dingtalk_user_id" TEXT,
"manager_job_number" TEXT,
"manager_name" TEXT,
"employment_status" TEXT,
"work_place" TEXT,
"source_payload" JSONB,
"synced_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_employee_profiles_dingtalk_user_id_key"
ON "performance_survey_employee_profiles" ("dingtalk_user_id");
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_employee_profiles_job_number_key"
ON "performance_survey_employee_profiles" ("job_number");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_display_name_idx"
ON "performance_survey_employee_profiles" ("display_name");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_ding_email_idx"
ON "performance_survey_employee_profiles" ("ding_email");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_department_name_idx"
ON "performance_survey_employee_profiles" ("department_name");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_position_level_idx"
ON "performance_survey_employee_profiles" ("position_level");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_level_type_idx"
ON "performance_survey_employee_profiles" ("level_type");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_is_leadership_idx"
ON "performance_survey_employee_profiles" ("is_leadership");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_manager_dingtalk_user_id_idx"
ON "performance_survey_employee_profiles" ("manager_dingtalk_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_employee_profiles_employment_status_idx"
ON "performance_survey_employee_profiles" ("employment_status");
CREATE TABLE IF NOT EXISTS "performance_survey_department_profiles" (
"id" TEXT PRIMARY KEY,
"name" TEXT NOT NULL,
"parent_name" TEXT,
"source_dept_id" TEXT,
"sort_order" INTEGER NOT NULL DEFAULT 0,
"employee_count" INTEGER NOT NULL DEFAULT 0,
"synced_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_department_profiles_name_key"
ON "performance_survey_department_profiles" ("name");
CREATE INDEX IF NOT EXISTS "performance_survey_department_profiles_parent_name_idx"
ON "performance_survey_department_profiles" ("parent_name");
CREATE INDEX IF NOT EXISTS "performance_survey_department_profiles_source_dept_id_idx"
ON "performance_survey_department_profiles" ("source_dept_id");
CREATE TABLE IF NOT EXISTS "performance_survey_templates" (
"id" TEXT PRIMARY KEY,
"code" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"survey_type" TEXT NOT NULL DEFAULT 'person_period',
"weight" DOUBLE PRECISION NOT NULL DEFAULT 1,
"questions" JSONB NOT NULL,
"score_bands" JSONB NOT NULL,
"is_active" BOOLEAN NOT NULL DEFAULT TRUE,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_templates_code_key"
ON "performance_survey_templates" ("code");
CREATE INDEX IF NOT EXISTS "performance_survey_templates_survey_type_idx"
ON "performance_survey_templates" ("survey_type");
CREATE INDEX IF NOT EXISTS "performance_survey_templates_is_active_idx"
ON "performance_survey_templates" ("is_active");
CREATE TABLE IF NOT EXISTS "performance_surveys" (
"id" TEXT PRIMARY KEY,
"title" TEXT NOT NULL,
"description" TEXT,
"survey_kind" TEXT NOT NULL DEFAULT 'person_period',
"template_code" TEXT NOT NULL,
"template_snapshot" JSONB NOT NULL,
"status" TEXT NOT NULL DEFAULT 'draft',
"creator_user_id" TEXT NOT NULL,
"creator_name" TEXT NOT NULL,
"creator_employee_id" TEXT,
"department_name" TEXT,
"due_at" TIMESTAMP(3),
"opened_at" TIMESTAMP(3),
"closed_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS "performance_surveys_status_idx"
ON "performance_surveys" ("status");
CREATE INDEX IF NOT EXISTS "performance_surveys_survey_kind_idx"
ON "performance_surveys" ("survey_kind");
CREATE INDEX IF NOT EXISTS "performance_surveys_template_code_idx"
ON "performance_surveys" ("template_code");
CREATE INDEX IF NOT EXISTS "performance_surveys_creator_user_id_idx"
ON "performance_surveys" ("creator_user_id");
CREATE INDEX IF NOT EXISTS "performance_surveys_department_name_idx"
ON "performance_surveys" ("department_name");
CREATE INDEX IF NOT EXISTS "performance_surveys_due_at_idx"
ON "performance_surveys" ("due_at");
CREATE TABLE IF NOT EXISTS "performance_survey_targets" (
"id" TEXT PRIMARY KEY,
"survey_id" TEXT NOT NULL,
"target_type" TEXT NOT NULL DEFAULT 'employee',
"employee_profile_id" TEXT,
"target_name" TEXT NOT NULL,
"target_snapshot" JSONB NOT NULL,
"sort_order" INTEGER NOT NULL DEFAULT 0,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "performance_survey_targets_survey_id_fkey"
FOREIGN KEY ("survey_id") REFERENCES "performance_surveys"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_targets_employee_profile_id_fkey"
FOREIGN KEY ("employee_profile_id") REFERENCES "performance_survey_employee_profiles"("id")
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE INDEX IF NOT EXISTS "performance_survey_targets_survey_id_idx"
ON "performance_survey_targets" ("survey_id");
CREATE INDEX IF NOT EXISTS "performance_survey_targets_target_type_idx"
ON "performance_survey_targets" ("target_type");
CREATE INDEX IF NOT EXISTS "performance_survey_targets_employee_profile_id_idx"
ON "performance_survey_targets" ("employee_profile_id");
CREATE TABLE IF NOT EXISTS "performance_survey_assignments" (
"id" TEXT PRIMARY KEY,
"survey_id" TEXT NOT NULL,
"target_id" TEXT NOT NULL,
"evaluator_employee_id" TEXT,
"evaluator_user_id" TEXT,
"evaluator_dingtalk_user_id" TEXT,
"evaluator_key" TEXT NOT NULL,
"evaluator_name" TEXT NOT NULL,
"evaluator_snapshot" JSONB NOT NULL,
"status" TEXT NOT NULL DEFAULT 'pending',
"submitted_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "performance_survey_assignments_survey_id_fkey"
FOREIGN KEY ("survey_id") REFERENCES "performance_surveys"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_assignments_target_id_fkey"
FOREIGN KEY ("target_id") REFERENCES "performance_survey_targets"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_assignments_evaluator_employee_id_fkey"
FOREIGN KEY ("evaluator_employee_id") REFERENCES "performance_survey_employee_profiles"("id")
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_assignment_target_evaluator_key"
ON "performance_survey_assignments" ("target_id", "evaluator_key");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_survey_id_idx"
ON "performance_survey_assignments" ("survey_id");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_target_id_idx"
ON "performance_survey_assignments" ("target_id");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_evaluator_employee_id_idx"
ON "performance_survey_assignments" ("evaluator_employee_id");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_evaluator_user_id_idx"
ON "performance_survey_assignments" ("evaluator_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_evaluator_dingtalk_user_id_idx"
ON "performance_survey_assignments" ("evaluator_dingtalk_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_evaluator_key_idx"
ON "performance_survey_assignments" ("evaluator_key");
CREATE INDEX IF NOT EXISTS "performance_survey_assignments_status_idx"
ON "performance_survey_assignments" ("status");
CREATE TABLE IF NOT EXISTS "performance_survey_responses" (
"id" TEXT PRIMARY KEY,
"survey_id" TEXT NOT NULL,
"target_id" TEXT NOT NULL,
"assignment_id" TEXT NOT NULL,
"respondent_user_id" TEXT NOT NULL,
"respondent_employee_id" TEXT,
"respondent_name" TEXT NOT NULL,
"respondent_snapshot" JSONB NOT NULL,
"scores" JSONB NOT NULL,
"comment" TEXT,
"total_score" DOUBLE PRECISION NOT NULL,
"achievement_score" DOUBLE PRECISION NOT NULL,
"kpi_score" DOUBLE PRECISION NOT NULL,
"weighted_score" DOUBLE PRECISION NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "performance_survey_responses_survey_id_fkey"
FOREIGN KEY ("survey_id") REFERENCES "performance_surveys"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_responses_target_id_fkey"
FOREIGN KEY ("target_id") REFERENCES "performance_survey_targets"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_responses_assignment_id_fkey"
FOREIGN KEY ("assignment_id") REFERENCES "performance_survey_assignments"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_responses_respondent_employee_id_fkey"
FOREIGN KEY ("respondent_employee_id") REFERENCES "performance_survey_employee_profiles"("id")
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_responses_assignment_id_key"
ON "performance_survey_responses" ("assignment_id");
CREATE INDEX IF NOT EXISTS "performance_survey_responses_survey_id_idx"
ON "performance_survey_responses" ("survey_id");
CREATE INDEX IF NOT EXISTS "performance_survey_responses_target_id_idx"
ON "performance_survey_responses" ("target_id");
CREATE INDEX IF NOT EXISTS "performance_survey_responses_respondent_user_id_idx"
ON "performance_survey_responses" ("respondent_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_responses_respondent_employee_id_idx"
ON "performance_survey_responses" ("respondent_employee_id");
CREATE INDEX IF NOT EXISTS "performance_survey_responses_created_at_idx"
ON "performance_survey_responses" ("created_at");
CREATE TABLE IF NOT EXISTS "performance_survey_notifications" (
"id" TEXT PRIMARY KEY,
"survey_id" TEXT,
"target_id" TEXT,
"assignment_id" TEXT,
"recipient_employee_id" TEXT,
"recipient_user_id" TEXT,
"dingtalk_user_id" TEXT,
"recipient_name" TEXT NOT NULL,
"event_type" TEXT NOT NULL,
"business_key" TEXT NOT NULL,
"title" TEXT NOT NULL,
"content" TEXT NOT NULL,
"action_url" TEXT,
"status" TEXT NOT NULL DEFAULT 'pending',
"attempt_count" INTEGER NOT NULL DEFAULT 0,
"max_attempts" INTEGER NOT NULL DEFAULT 5,
"next_retry_at" TIMESTAMP(3),
"last_status_code" INTEGER,
"last_response_body" TEXT,
"last_error" TEXT,
"provider_message_id" TEXT,
"sent_at" TIMESTAMP(3),
"completed_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "performance_survey_notifications_survey_id_fkey"
FOREIGN KEY ("survey_id") REFERENCES "performance_surveys"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_notifications_target_id_fkey"
FOREIGN KEY ("target_id") REFERENCES "performance_survey_targets"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_notifications_assignment_id_fkey"
FOREIGN KEY ("assignment_id") REFERENCES "performance_survey_assignments"("id")
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "performance_survey_notifications_recipient_employee_id_fkey"
FOREIGN KEY ("recipient_employee_id") REFERENCES "performance_survey_employee_profiles"("id")
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "performance_survey_notification_event_key"
ON "performance_survey_notifications" ("event_type", "business_key");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_survey_id_idx"
ON "performance_survey_notifications" ("survey_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_target_id_idx"
ON "performance_survey_notifications" ("target_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_assignment_id_idx"
ON "performance_survey_notifications" ("assignment_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_recipient_employee_id_idx"
ON "performance_survey_notifications" ("recipient_employee_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_recipient_user_id_idx"
ON "performance_survey_notifications" ("recipient_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_dingtalk_user_id_idx"
ON "performance_survey_notifications" ("dingtalk_user_id");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_status_next_retry_idx"
ON "performance_survey_notifications" ("status", "next_retry_at");
CREATE INDEX IF NOT EXISTS "performance_survey_notifications_created_at_idx"
ON "performance_survey_notifications" ("created_at");