diff --git a/db/migrations/0009_first_hellfire_club.sql b/db/migrations/0009_first_hellfire_club.sql new file mode 100644 index 00000000..43475c31 --- /dev/null +++ b/db/migrations/0009_first_hellfire_club.sql @@ -0,0 +1,21 @@ +CREATE TABLE "file_extraction_cache" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "file_hash" varchar(64) NOT NULL, + "file_type" varchar(100) NOT NULL, + "file_name" varchar(255), + "file_size" varchar(20) NOT NULL, + "extracted_text" text NOT NULL, + "extraction_type" varchar(50), + "hit_count" varchar(10) DEFAULT '0' NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "file_extraction_cache_file_hash_unique" UNIQUE("file_hash") +); +--> statement-breakpoint +ALTER TABLE "interviews" DROP CONSTRAINT "interviews_humeChatId_unique";--> statement-breakpoint +ALTER TABLE "interviews" DROP CONSTRAINT "interviews_requestId_unique";--> statement-breakpoint +ALTER TABLE "interviews" ALTER COLUMN "chat_group_id" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "interviews" ALTER COLUMN "hume_chat_id" DROP NOT NULL;--> statement-breakpoint +CREATE INDEX "file_extraction_cache_file_hash_idx" ON "file_extraction_cache" USING btree ("file_hash");--> statement-breakpoint +CREATE INDEX "file_extraction_cache_created_at_idx" ON "file_extraction_cache" USING btree ("created_at");--> statement-breakpoint +CREATE INDEX "file_extraction_cache_extraction_type_idx" ON "file_extraction_cache" USING btree ("extraction_type"); \ No newline at end of file diff --git a/db/migrations/meta/0009_snapshot.json b/db/migrations/meta/0009_snapshot.json new file mode 100644 index 00000000..3b7fb9a1 --- /dev/null +++ b/db/migrations/meta/0009_snapshot.json @@ -0,0 +1,2577 @@ +{ + "id": "08a6f8d2-f678-40c4-bf09-783a40709664", + "prevId": "a3ef2029-3952-4f08-9df0-f807fdd0dfab", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.candidate_details": { + "name": "candidate_details", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "current_role": { + "name": "current_role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "professional_summary": { + "name": "professional_summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linkedin_url": { + "name": "linkedin_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "portfolio_url": { + "name": "portfolio_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "other_urls": { + "name": "other_urls", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "candidate_details_job_id_idx": { + "name": "candidate_details_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "candidate_details_job_id_jobs_id_fk": { + "name": "candidate_details_job_id_jobs_id_fk", + "tableFrom": "candidate_details", + "tableTo": "jobs", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.changelogs": { + "name": "changelogs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "date": { + "name": "date", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "likes": { + "name": "likes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "changelogs_date_idx": { + "name": "changelogs_date_idx", + "columns": [ + { + "expression": "date", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.countries": { + "name": "countries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "iso_code": { + "name": "iso_code", + "type": "varchar(2)", + "primaryKey": false, + "notNull": true + }, + "continent": { + "name": "continent", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "countries_iso_code_idx": { + "name": "countries_iso_code_idx", + "columns": [ + { + "expression": "iso_code", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "countries_isoCode_unique": { + "name": "countries_isoCode_unique", + "nullsNotDistinct": false, + "columns": [ + "iso_code" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.customisations": { + "name": "customisations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "phone": { + "name": "phone", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "custom_instructions": { + "name": "custom_instructions", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "customisations_user_id_idx": { + "name": "customisations_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "customisations_user_id_users_id_fk": { + "name": "customisations_user_id_users_id_fk", + "tableFrom": "customisations", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deleted_users": { + "name": "deleted_users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "email_hash": { + "name": "email_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "clerk_user_id": { + "name": "clerk_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "has_used_free_minutes": { + "name": "has_used_free_minutes", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "deleted_users_email_hash_idx": { + "name": "deleted_users_email_hash_idx", + "columns": [ + { + "expression": "email_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.feature_request_likes": { + "name": "feature_request_likes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "feature_request_id": { + "name": "feature_request_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "feature_request_likes_user_id_idx": { + "name": "feature_request_likes_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "feature_request_likes_feature_request_id_idx": { + "name": "feature_request_likes_feature_request_id_idx", + "columns": [ + { + "expression": "feature_request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "feature_request_likes_user_feature_request_uidx": { + "name": "feature_request_likes_user_feature_request_uidx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "feature_request_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "feature_request_likes_user_id_users_id_fk": { + "name": "feature_request_likes_user_id_users_id_fk", + "tableFrom": "feature_request_likes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "feature_request_likes_feature_request_id_feature_requests_id_fk": { + "name": "feature_request_likes_feature_request_id_feature_requests_id_fk", + "tableFrom": "feature_request_likes", + "tableTo": "feature_requests", + "columnsFrom": [ + "feature_request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.feature_requests": { + "name": "feature_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "feature_request_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'submitted'" + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "feature_requests_user_id_idx": { + "name": "feature_requests_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "feature_requests_user_id_users_id_fk": { + "name": "feature_requests_user_id_users_id_fk", + "tableFrom": "feature_requests", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.file_extraction_cache": { + "name": "file_extraction_cache", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "file_hash": { + "name": "file_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "file_type": { + "name": "file_type", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "file_name": { + "name": "file_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "file_size": { + "name": "file_size", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "extracted_text": { + "name": "extracted_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "extraction_type": { + "name": "extraction_type", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "hit_count": { + "name": "hit_count", + "type": "varchar(10)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "file_extraction_cache_file_hash_idx": { + "name": "file_extraction_cache_file_hash_idx", + "columns": [ + { + "expression": "file_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "file_extraction_cache_created_at_idx": { + "name": "file_extraction_cache_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "file_extraction_cache_extraction_type_idx": { + "name": "file_extraction_cache_extraction_type_idx", + "columns": [ + { + "expression": "extraction_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "file_extraction_cache_file_hash_unique": { + "name": "file_extraction_cache_file_hash_unique", + "nullsNotDistinct": false, + "columns": [ + "file_hash" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.images": { + "name": "images", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "prompt_id": { + "name": "prompt_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "cloudinary_public_id": { + "name": "cloudinary_public_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "format": { + "name": "format", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "original_filename": { + "name": "original_filename", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "images_prompt_id_idx": { + "name": "images_prompt_id_idx", + "columns": [ + { + "expression": "prompt_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "images_cloudinary_public_id_idx": { + "name": "images_cloudinary_public_id_idx", + "columns": [ + { + "expression": "cloudinary_public_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "images_prompt_id_users_id_fk": { + "name": "images_prompt_id_users_id_fk", + "tableFrom": "images", + "tableTo": "users", + "columnsFrom": [ + "prompt_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "images_cloudinaryPublicId_unique": { + "name": "images_cloudinaryPublicId_unique", + "nullsNotDistinct": false, + "columns": [ + "cloudinary_public_id" + ] + }, + "images_url_unique": { + "name": "images_url_unique", + "nullsNotDistinct": false, + "columns": [ + "url" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.interviews": { + "name": "interviews", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "custom_session_id": { + "name": "custom_session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transcript": { + "name": "transcript", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chat_group_id": { + "name": "chat_group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "hume_chat_id": { + "name": "hume_chat_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 15 + }, + "type": { + "name": "type", + "type": "interview_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'behavioral'" + }, + "key_questions": { + "name": "key_questions", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "actual_time": { + "name": "actual_time", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "interviews_job_id_idx": { + "name": "interviews_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "interviews_job_created_idx": { + "name": "interviews_job_created_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "interviews_job_id_jobs_id_fk": { + "name": "interviews_job_id_jobs_id_fk", + "tableFrom": "interviews", + "tableTo": "jobs", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitations": { + "name": "invitations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_deleted": { + "name": "is_deleted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "invitations_organization_id_idx": { + "name": "invitations_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitations_email_idx": { + "name": "invitations_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitations_status_idx": { + "name": "invitations_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitations_organization_id_organizations_id_fk": { + "name": "invitations_organization_id_organizations_id_fk", + "tableFrom": "invitations", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_descriptions": { + "name": "job_descriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "company": { + "name": "company", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "required_qualifications": { + "name": "required_qualifications", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "required_experience": { + "name": "required_experience", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "required_skills": { + "name": "required_skills", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "preferred_qualifications": { + "name": "preferred_qualifications", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "preferred_skills": { + "name": "preferred_skills", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "responsibilities": { + "name": "responsibilities", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "benefits": { + "name": "benefits", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "location": { + "name": "location", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "employment_type": { + "name": "employment_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "seniority": { + "name": "seniority", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "industry": { + "name": "industry", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_technologies": { + "name": "key_technologies", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "keywords": { + "name": "keywords", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_descriptions_job_id_idx": { + "name": "job_descriptions_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_descriptions_job_id_jobs_id_fk": { + "name": "job_descriptions_job_id_jobs_id_fk", + "tableFrom": "job_descriptions", + "tableTo": "jobs", + "columnsFrom": [ + "job_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jobs": { + "name": "jobs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "submitted_cv_text": { + "name": "submitted_cv_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "job_description_text": { + "name": "job_description_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "additional_info": { + "name": "additional_info", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "candidate": { + "name": "candidate", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "company": { + "name": "company", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "completed": { + "name": "completed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "jobs_user_id_idx": { + "name": "jobs_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "jobs_user_id_users_id_fk": { + "name": "jobs_user_id_users_id_fk", + "tableFrom": "jobs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_members": { + "name": "organization_members", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_members_organization_id_idx": { + "name": "organization_members_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_members_user_id_idx": { + "name": "organization_members_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_members_active_idx": { + "name": "organization_members_active_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_members_organization_id_organizations_id_fk": { + "name": "organization_members_organization_id_organizations_id_fk", + "tableFrom": "organization_members", + "tableTo": "organizations", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "organization_members_user_id_users_id_fk": { + "name": "organization_members_user_id_users_id_fk", + "tableFrom": "organization_members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organizations": { + "name": "organizations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(1000)", + "primaryKey": false, + "notNull": false + }, + "website": { + "name": "website", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "industry": { + "name": "industry", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "size": { + "name": "size", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "is_deleted": { + "name": "is_deleted", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organizations_name_idx": { + "name": "organizations_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organizations_is_deleted_idx": { + "name": "organizations_is_deleted_idx", + "columns": [ + { + "expression": "is_deleted", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.page_settings": { + "name": "page_settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "report_id": { + "name": "report_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "paper_size": { + "name": "paper_size", + "type": "paper_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "heading_font": { + "name": "heading_font", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "body_font": { + "name": "body_font", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "margin_size": { + "name": "margin_size", + "type": "margin_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "layout": { + "name": "layout", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "page_settings_report_id_idx": { + "name": "page_settings_report_id_idx", + "columns": [ + { + "expression": "report_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_settings_report_id_reports_id_fk": { + "name": "page_settings_report_id_reports_id_fk", + "tableFrom": "page_settings", + "tableTo": "reports", + "columnsFrom": [ + "report_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.question_analysis": { + "name": "question_analysis", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "report_id": { + "name": "report_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "question": { + "name": "question", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "analysis": { + "name": "analysis", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "score": { + "name": "score", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "is_key_question": { + "name": "is_key_question", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "question_analysis_report_id_idx": { + "name": "question_analysis_report_id_idx", + "columns": [ + { + "expression": "report_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "question_analysis_report_id_reports_id_fk": { + "name": "question_analysis_report_id_reports_id_fk", + "tableFrom": "question_analysis", + "tableTo": "reports", + "columnsFrom": [ + "report_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reports": { + "name": "reports", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "interview_id": { + "name": "interview_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "general_assessment": { + "name": "general_assessment", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "overall_score": { + "name": "overall_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "fitness_for_role": { + "name": "fitness_for_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "fitness_for_role_score": { + "name": "fitness_for_role_score", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "speaking_skills": { + "name": "speaking_skills", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "speaking_skills_score": { + "name": "speaking_skills_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "communication_skills": { + "name": "communication_skills", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "communication_skills_score": { + "name": "communication_skills_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "problem_solving_skills": { + "name": "problem_solving_skills", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "problem_solving_skills_score": { + "name": "problem_solving_skills_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "technical_knowledge": { + "name": "technical_knowledge", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "technical_knowledge_score": { + "name": "technical_knowledge_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "teamwork": { + "name": "teamwork", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "teamwork_score": { + "name": "teamwork_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "adaptability": { + "name": "adaptability", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adaptability_score": { + "name": "adaptability_score", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "areas_of_strength": { + "name": "areas_of_strength", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "areas_for_improvement": { + "name": "areas_for_improvement", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "interview_audio_url": { + "name": "interview_audio_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actionable_next_steps": { + "name": "actionable_next_steps", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_completed": { + "name": "is_completed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reports_interview_id_idx": { + "name": "reports_interview_id_idx", + "columns": [ + { + "expression": "interview_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reports_is_completed_idx": { + "name": "reports_is_completed_idx", + "columns": [ + { + "expression": "is_completed", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reports_interview_id_interviews_id_fk": { + "name": "reports_interview_id_interviews_id_fk", + "tableFrom": "reports", + "tableTo": "interviews", + "columnsFrom": [ + "interview_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reviews": { + "name": "reviews", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "rating": { + "name": "rating", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "comment": { + "name": "comment", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "image_url": { + "name": "image_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "twitter_username": { + "name": "twitter_username", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "linkedin_url": { + "name": "linkedin_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "show_on_landing": { + "name": "show_on_landing", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "processed_at": { + "name": "processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reviews_user_id_idx": { + "name": "reviews_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reviews_show_on_landing_idx": { + "name": "reviews_show_on_landing_idx", + "columns": [ + { + "expression": "show_on_landing", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reviews_is_published_idx": { + "name": "reviews_is_published_idx", + "columns": [ + { + "expression": "is_published", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reviews_user_id_users_id_fk": { + "name": "reviews_user_id_users_id_fk", + "tableFrom": "reviews", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.statistics": { + "name": "statistics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "interviews_count": { + "name": "interviews_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "minutes_count": { + "name": "minutes_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "users_count": { + "name": "users_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "firstname": { + "name": "firstname", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "lastname": { + "name": "lastname", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_interval": { + "name": "stripe_subscription_interval", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "stripe_price_id": { + "name": "stripe_price_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "stripe_plan_id": { + "name": "stripe_plan_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "trial_used": { + "name": "trial_used", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_deleted": { + "name": "is_deleted", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "clerk_user_id": { + "name": "clerk_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "minutes": { + "name": "minutes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 2 + } + }, + "indexes": { + "users_username_idx": { + "name": "users_username_idx", + "columns": [ + { + "expression": "username", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_stripe_customer_id_idx": { + "name": "users_stripe_customer_id_idx", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_email_idx": { + "name": "users_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_clerk_user_id_idx": { + "name": "users_clerk_user_id_idx", + "columns": [ + { + "expression": "clerk_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.feature_request_status": { + "name": "feature_request_status", + "schema": "public", + "values": [ + "submitted", + "triaged", + "in_progress", + "completed", + "declined" + ] + }, + "public.interview_type": { + "name": "interview_type", + "schema": "public", + "values": [ + "behavioral", + "situational", + "technical", + "case_study", + "competency_based", + "stress", + "cultural_fit" + ] + }, + "public.invitation_status": { + "name": "invitation_status", + "schema": "public", + "values": [ + "pending", + "accepted", + "rejected", + "expired", + "revoked" + ] + }, + "public.margin_size": { + "name": "margin_size", + "schema": "public", + "values": [ + "Normal", + "Narrow", + "Wide" + ] + }, + "public.paper_size": { + "name": "paper_size", + "schema": "public", + "values": [ + "A4", + "Letter", + "Legal" + ] + }, + "public.role": { + "name": "role", + "schema": "public", + "values": [ + "user", + "admin", + "recruiter" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/db/migrations/meta/_journal.json b/db/migrations/meta/_journal.json index 9082d601..c3da8277 100644 --- a/db/migrations/meta/_journal.json +++ b/db/migrations/meta/_journal.json @@ -64,6 +64,13 @@ "when": 1752614927837, "tag": "0008_daffy_susan_delgado", "breakpoints": true + }, + { + "idx": 9, + "version": "7", + "when": 1760290327482, + "tag": "0009_first_hellfire_club", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/db/schema/interviews.ts b/db/schema/interviews.ts index 3e20c85e..2c0f61e2 100644 --- a/db/schema/interviews.ts +++ b/db/schema/interviews.ts @@ -26,9 +26,9 @@ export const interviews = pgTable( .notNull(), customSessionId: p.text(), transcript: p.text(), - chatGroupId: p.text().notNull(), - humeChatId: p.text().notNull().unique(), - requestId: p.text().unique(), + chatGroupId: p.text(), + humeChatId: p.text(), + requestId: p.text(), duration: p.integer().notNull().default(15), type: interviewTypeEnum().notNull().default("behavioral"), keyQuestions: p.text().array(), diff --git a/functions/generate-missing-audio/index.ts b/functions/generate-missing-audio/index.ts index 6a0d5dfb..c48d8c5c 100644 --- a/functions/generate-missing-audio/index.ts +++ b/functions/generate-missing-audio/index.ts @@ -49,6 +49,15 @@ export const handler = Sentry.wrapHandler(async () => { } for (const report of reportsToProcess) { + // Skip if interview doesn't have Hume chat ID (shouldn't happen for completed interviews) + if (!report.interview.humeChatId) { + logger.warn( + { reportId: report.id }, + "Skipping audio reconstruction - missing humeChatId" + ); + continue; + } + logger.info({ reportId: report.id }, "Requesting audio reconstruction"); try { const reconstructionResponse = await requestChatAudioReconstruction( diff --git a/src/app/api/interviews/route.ts b/src/app/api/interviews/route.ts index 0edb4fd2..07822d56 100644 --- a/src/app/api/interviews/route.ts +++ b/src/app/api/interviews/route.ts @@ -35,19 +35,8 @@ export const POST = withAuth( }); } - if (!chatGroupId) { - logger.warn("Missing required field: chatGroupId"); - return NextResponse.json(formatErrorEntity("Missing required field: chatGroupId"), { - status: 400, - }); - } - - if (!humeChatId) { - logger.warn("Missing required field: humeChatId"); - return NextResponse.json(formatErrorEntity("Missing required field: humeChatId"), { - status: 400, - }); - } + // Note: chatGroupId and humeChatId are now optional on creation + // They get populated when the Hume connection is established on the interview page // Decode hash ID to numeric const jobId = idHandler.safeDecode(jobIdString); @@ -57,19 +46,22 @@ export const POST = withAuth( }); } - const existingInterview = await db.query.interviews.findFirst({ - where: and(eq(interviews.humeChatId, humeChatId)), - }); + // Only check for existing interview if humeChatId is provided + if (humeChatId) { + const existingInterview = await db.query.interviews.findFirst({ + where: and(eq(interviews.humeChatId, humeChatId)), + }); - if (existingInterview) { - logger.info({ jobId }, "Interview already exists"); + if (existingInterview) { + logger.info({ jobId }, "Interview already exists"); - // Encode all IDs before sending to client - const encodedInterview = encodeInterview(existingInterview); + // Encode all IDs before sending to client + const encodedInterview = encodeInterview(existingInterview); - return NextResponse.json(formatEntity(encodedInterview, "interview"), { - status: 200, - }); + return NextResponse.json(formatEntity(encodedInterview, "interview"), { + status: 200, + }); + } } const [newInterview] = await db diff --git a/src/components/interview-placeholder.tsx b/src/components/interview-placeholder.tsx index 4a052842..9e25ec74 100644 --- a/src/components/interview-placeholder.tsx +++ b/src/components/interview-placeholder.tsx @@ -12,7 +12,7 @@ import { getRepository } from "@/lib/data/repositoryFactory"; import { clientIdHandler } from "@/lib/utils/clientIdHandler"; import { useVoice } from "@humeai/voice-react"; import * as Sentry from "@sentry/nextjs"; -import { useMutation } from "@tanstack/react-query"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; import { motion } from "framer-motion"; import { Home, Layout, MessageCircle, X } from "lucide-react"; import Link from "next/link"; @@ -30,7 +30,7 @@ export function InterviewPlaceholder({ accessToken, configId }: InterviewPlaceho const [showModal, setShowModal] = useState(false); const params = useParams(); const jobId = params.jobId as string; - const { connect, status, chatMetadata } = useVoice(); + const queryClient = useQueryClient(); const { data: job, isLoading, error } = useJob(jobId); const { data: user, isLoading: isUserLoading } = useUser(); const router = useRouter(); @@ -83,12 +83,23 @@ export function InterviewPlaceholder({ accessToken, configId }: InterviewPlaceho keyQuestions: keyQuestions.data, type: interviewToBeCreated.type, duration: interviewToBeCreated.duration, + // Hume metadata will be populated later when connection is established }); }, onSuccess: (interview) => { - router.push( - `/dashboard/jobs/${jobId}/interviews/${clientIdHandler.formatId(interview?.data.id)}` - ); + // Pre-populate React Query cache to avoid redundant fetches on redirect + const interviewId = clientIdHandler.formatId(interview?.data.id); + + // Cache the newly created interview + queryClient.setQueryData(["interview", interviewId], interview); + + // Cache the job data we already have + if (job) { + queryClient.setQueryData(["job", jobId], job); + } + + // Redirect - interview page will use cached data instantly + router.push(`/dashboard/jobs/${jobId}/interviews/${interviewId}`); }, onError: (error) => { toast.error("Error creating interview. Please try again."); @@ -99,34 +110,22 @@ export function InterviewPlaceholder({ accessToken, configId }: InterviewPlaceho }, }); - useEffect(() => { - if (chatMetadata?.chatGroupId && chatMetadata.chatId) { - createInterview({ + const handleStartInterview = async () => { + // Don't connect here - just create the interview and redirect + // The interview page will handle the connection with proper context + try { + await createInterview({ jobId: params.jobId as string, - chatGroupId: chatMetadata?.chatGroupId || "", - customSessionId: chatMetadata?.customSessionId || "", - requestId: chatMetadata?.requestId || "", - humeChatId: chatMetadata?.chatId || "", type: interviewToBeCreated.type, duration: interviewToBeCreated.duration, + // Hume metadata will be populated later when connection is established }); - } - }, [chatMetadata, createInterview, params.jobId, interviewToBeCreated]); - - const handleStartInterview = async () => { - if (status.value !== "connected") { - try { - await connect({ - auth: { type: "accessToken", value: accessToken || "" }, - configId, - }); - } catch (error) { - Sentry.withScope((scope) => { - scope.setContext("params", params); - Sentry.captureException(error); - }); - toast.error("Error connecting to voice. Please try again."); - } + } catch (error) { + Sentry.withScope((scope) => { + scope.setContext("params", params); + Sentry.captureException(error); + }); + toast.error("Error starting interview. Please try again."); } }; @@ -294,7 +293,7 @@ export function InterviewPlaceholder({ accessToken, configId }: InterviewPlaceho isOpen={showModal} onClose={() => setShowModal(false)} onStart={handleStartInterview} - isLoading={status.value === "connecting" || isCreatingInterview} + isLoading={isCreatingInterview} duration={interviewToBeCreated?.duration} availableMinutes={user?.minutes} /> diff --git a/src/components/interview/interview-controller.tsx b/src/components/interview/interview-controller.tsx index 497b3027..f7c4bb21 100644 --- a/src/components/interview/interview-controller.tsx +++ b/src/components/interview/interview-controller.tsx @@ -64,6 +64,7 @@ export const InterviewController = React.memo(function InterviewController() { } = useVoice(); const interviewStartedRef = useRef(false); + const chatMetadataSavedRef = useRef(false); // Set unmounted flag on component unmount useEffect(() => { @@ -184,6 +185,28 @@ export const InterviewController = React.memo(function InterviewController() { }, }); + // Save chat metadata once when first connected + useEffect(() => { + if ( + chatMetadata?.chatGroupId && + chatMetadata.chatId && + !chatMetadataSavedRef.current && + activeInterview + ) { + chatMetadataSavedRef.current = true; + + // Update the interview with chat metadata + partialInterviewMutation.mutate({ + ...activeInterview, + jobId: params.jobId as string, + chatGroupId: chatMetadata.chatGroupId, + customSessionId: chatMetadata.customSessionId || null, + requestId: chatMetadata.requestId || null, + humeChatId: chatMetadata.chatId, + }); + } + }, [chatMetadata, activeInterview, params.jobId, partialInterviewMutation]); + // Usage tracking mutation const decrementMutation = useMutation({ mutationFn: async () => { diff --git a/src/hooks/useCustomisedSystemPrompt.tsx b/src/hooks/useCustomisedSystemPrompt.tsx index 2e313a6a..5c4b9dfc 100644 --- a/src/hooks/useCustomisedSystemPrompt.tsx +++ b/src/hooks/useCustomisedSystemPrompt.tsx @@ -32,6 +32,7 @@ export default function useCustomisedSystemPrompt({ return await interviewRepo.getById(interviewId); }, enabled: !!interviewId, + staleTime: 30000, // Cache valid for 30s, allows instant load from cache while background refetch happens }); const systemPrompt = useMemo(() => { diff --git a/src/hooks/useJob.ts b/src/hooks/useJob.ts index 7d63f2ff..e6b4f4f7 100644 --- a/src/hooks/useJob.ts +++ b/src/hooks/useJob.ts @@ -18,5 +18,6 @@ export function useJob(jobId: string) { const job = await jobsRepo.getById(jobId); return job; }, + staleTime: 30000, // Cache valid for 30s, allows instant load from cache while background refetch happens }); }