-- CreateEnum CREATE TYPE "UserStatus" AS ENUM ('ACTIVE', 'DISABLED', 'DELETED'); -- CreateEnum CREATE TYPE "KycStatus" AS ENUM ('PENDING', 'SUBMITTED', 'VERIFIED', 'REJECTED'); -- CreateEnum CREATE TYPE "SmsVerificationType" AS ENUM ('REGISTER', 'LOGIN', 'RESET_PASSWORD', 'CHANGE_PHONE'); -- CreateEnum CREATE TYPE "SmsStatus" AS ENUM ('PENDING', 'SENT', 'DELIVERED', 'FAILED'); -- CreateEnum CREATE TYPE "LoginType" AS ENUM ('PASSWORD', 'SMS_CODE', 'LEGACY_MIGRATE'); -- CreateEnum CREATE TYPE "OutboxStatus" AS ENUM ('PENDING', 'PUBLISHED', 'FAILED'); -- CreateTable CREATE TABLE "users" ( "id" BIGSERIAL NOT NULL, "phone" TEXT NOT NULL, "password_hash" TEXT NOT NULL, "account_sequence" TEXT NOT NULL, "status" "UserStatus" NOT NULL DEFAULT 'ACTIVE', "kycStatus" "KycStatus" NOT NULL DEFAULT 'PENDING', "real_name" TEXT, "id_card_no" TEXT, "id_card_front" TEXT, "id_card_back" TEXT, "kyc_submitted_at" TIMESTAMP(3), "kyc_verified_at" TIMESTAMP(3), "kyc_reject_reason" TEXT, "login_fail_count" INTEGER NOT NULL DEFAULT 0, "locked_until" TIMESTAMP(3), "last_login_at" TIMESTAMP(3), "last_login_ip" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "users_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "synced_legacy_users" ( "id" BIGSERIAL NOT NULL, "legacy_id" BIGINT NOT NULL, "account_sequence" TEXT NOT NULL, "phone" TEXT NOT NULL, "password_hash" TEXT NOT NULL, "status" TEXT NOT NULL, "legacy_created_at" TIMESTAMP(3) NOT NULL, "migrated_to_v2" BOOLEAN NOT NULL DEFAULT false, "migrated_at" TIMESTAMP(3), "source_sequence_num" BIGINT NOT NULL, "synced_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "synced_legacy_users_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "refresh_tokens" ( "id" BIGSERIAL NOT NULL, "user_id" BIGINT NOT NULL, "token" TEXT NOT NULL, "device_info" TEXT, "ip_address" TEXT, "expires_at" TIMESTAMP(3) NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "revoked_at" TIMESTAMP(3), CONSTRAINT "refresh_tokens_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "sms_verifications" ( "id" BIGSERIAL NOT NULL, "phone" TEXT NOT NULL, "code" TEXT NOT NULL, "type" "SmsVerificationType" NOT NULL, "expires_at" TIMESTAMP(3) NOT NULL, "verified_at" TIMESTAMP(3), "attempts" INTEGER NOT NULL DEFAULT 0, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "sms_verifications_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "sms_logs" ( "id" BIGSERIAL NOT NULL, "user_id" BIGINT, "phone" TEXT NOT NULL, "type" "SmsVerificationType" NOT NULL, "content" TEXT, "status" "SmsStatus" NOT NULL DEFAULT 'PENDING', "provider" TEXT, "provider_id" TEXT, "error_msg" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "sms_logs_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "login_logs" ( "id" BIGSERIAL NOT NULL, "user_id" BIGINT, "phone" TEXT NOT NULL, "type" "LoginType" NOT NULL, "success" BOOLEAN NOT NULL, "fail_reason" TEXT, "ip_address" TEXT, "user_agent" TEXT, "device_info" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "login_logs_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "daily_sequence_counters" ( "id" BIGSERIAL NOT NULL, "date_key" TEXT NOT NULL, "last_seq" INTEGER NOT NULL DEFAULT 0, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "daily_sequence_counters_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "outbox_events" ( "id" BIGSERIAL NOT NULL, "aggregate_type" TEXT NOT NULL, "aggregate_id" TEXT NOT NULL, "event_type" TEXT NOT NULL, "payload" JSONB NOT NULL, "topic" TEXT NOT NULL, "key" TEXT NOT NULL, "status" "OutboxStatus" NOT NULL DEFAULT 'PENDING', "retry_count" INTEGER NOT NULL DEFAULT 0, "max_retries" INTEGER NOT NULL DEFAULT 3, "last_error" TEXT, "published_at" TIMESTAMP(3), "next_retry_at" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "outbox_events_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE UNIQUE INDEX "users_phone_key" ON "users"("phone"); -- CreateIndex CREATE UNIQUE INDEX "users_account_sequence_key" ON "users"("account_sequence"); -- CreateIndex CREATE INDEX "users_phone_idx" ON "users"("phone"); -- CreateIndex CREATE INDEX "users_account_sequence_idx" ON "users"("account_sequence"); -- CreateIndex CREATE INDEX "users_status_idx" ON "users"("status"); -- CreateIndex CREATE INDEX "users_kycStatus_idx" ON "users"("kycStatus"); -- CreateIndex CREATE UNIQUE INDEX "synced_legacy_users_legacy_id_key" ON "synced_legacy_users"("legacy_id"); -- CreateIndex CREATE UNIQUE INDEX "synced_legacy_users_account_sequence_key" ON "synced_legacy_users"("account_sequence"); -- CreateIndex CREATE INDEX "synced_legacy_users_phone_idx" ON "synced_legacy_users"("phone"); -- CreateIndex CREATE INDEX "synced_legacy_users_account_sequence_idx" ON "synced_legacy_users"("account_sequence"); -- CreateIndex CREATE INDEX "synced_legacy_users_migrated_to_v2_idx" ON "synced_legacy_users"("migrated_to_v2"); -- CreateIndex CREATE UNIQUE INDEX "refresh_tokens_token_key" ON "refresh_tokens"("token"); -- CreateIndex CREATE INDEX "refresh_tokens_user_id_idx" ON "refresh_tokens"("user_id"); -- CreateIndex CREATE INDEX "refresh_tokens_token_idx" ON "refresh_tokens"("token"); -- CreateIndex CREATE INDEX "refresh_tokens_expires_at_idx" ON "refresh_tokens"("expires_at"); -- CreateIndex CREATE INDEX "sms_verifications_phone_type_idx" ON "sms_verifications"("phone", "type"); -- CreateIndex CREATE INDEX "sms_verifications_expires_at_idx" ON "sms_verifications"("expires_at"); -- CreateIndex CREATE INDEX "sms_logs_phone_idx" ON "sms_logs"("phone"); -- CreateIndex CREATE INDEX "sms_logs_user_id_idx" ON "sms_logs"("user_id"); -- CreateIndex CREATE INDEX "sms_logs_created_at_idx" ON "sms_logs"("created_at"); -- CreateIndex CREATE INDEX "login_logs_user_id_idx" ON "login_logs"("user_id"); -- CreateIndex CREATE INDEX "login_logs_phone_idx" ON "login_logs"("phone"); -- CreateIndex CREATE INDEX "login_logs_created_at_idx" ON "login_logs"("created_at"); -- CreateIndex CREATE UNIQUE INDEX "daily_sequence_counters_date_key_key" ON "daily_sequence_counters"("date_key"); -- CreateIndex CREATE INDEX "outbox_events_status_idx" ON "outbox_events"("status"); -- CreateIndex CREATE INDEX "outbox_events_next_retry_at_idx" ON "outbox_events"("next_retry_at"); -- AddForeignKey ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "sms_logs" ADD CONSTRAINT "sms_logs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "login_logs" ADD CONSTRAINT "login_logs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;