153 lines
6.1 KiB
SQL
153 lines
6.1 KiB
SQL
-- CreateEnum: AFF Log Types (if not exists)
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'AffLogType') THEN
|
|
CREATE TYPE "AffLogType" AS ENUM ('new_purchase', 'renew', 'convert');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- CreateEnum: AFF Withdrawal Status (if not exists)
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'AffWithdrawalStatus') THEN
|
|
CREATE TYPE "AffWithdrawalStatus" AS ENUM ('pending', 'approved', 'rejected');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AlterTable: Add AFF fields to users
|
|
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "aff_balance" DECIMAL(10,2) NOT NULL DEFAULT 0;
|
|
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "aff_activated_at" TIMESTAMP(3);
|
|
|
|
-- CreateTable: AffCode (优惠码)
|
|
CREATE TABLE IF NOT EXISTS "aff_codes" (
|
|
"id" SERIAL NOT NULL,
|
|
"code" TEXT NOT NULL,
|
|
"user_id" INTEGER NOT NULL,
|
|
"package_plan_id" INTEGER NOT NULL,
|
|
"discount_rate" DECIMAL(5,4) NOT NULL DEFAULT 0.05,
|
|
"commission_rate" DECIMAL(5,4) NOT NULL DEFAULT 0.05,
|
|
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
"used_count" INTEGER NOT NULL DEFAULT 0,
|
|
"total_earnings" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "aff_codes_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable: AffBinding (实例与优惠码绑定)
|
|
CREATE TABLE IF NOT EXISTS "aff_bindings" (
|
|
"id" SERIAL NOT NULL,
|
|
"instance_id" INTEGER NOT NULL,
|
|
"aff_code_id" INTEGER NOT NULL,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "aff_bindings_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable: AffLog (AFF余额变动日志)
|
|
CREATE TABLE IF NOT EXISTS "aff_logs" (
|
|
"id" SERIAL NOT NULL,
|
|
"user_id" INTEGER NOT NULL,
|
|
"aff_code_id" INTEGER,
|
|
"instance_id" INTEGER,
|
|
"type" "AffLogType" NOT NULL,
|
|
"amount" DECIMAL(10,2) NOT NULL,
|
|
"original_amount" DECIMAL(10,2),
|
|
"balance_before" DECIMAL(10,2) NOT NULL,
|
|
"balance_after" DECIMAL(10,2) NOT NULL,
|
|
"remark" TEXT,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "aff_logs_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable: AffWithdrawal (AFF余额转化申请)
|
|
CREATE TABLE IF NOT EXISTS "aff_withdrawals" (
|
|
"id" SERIAL NOT NULL,
|
|
"user_id" INTEGER NOT NULL,
|
|
"amount" DECIMAL(10,2) NOT NULL,
|
|
"status" "AffWithdrawalStatus" NOT NULL DEFAULT 'pending',
|
|
"reject_reason" TEXT,
|
|
"reviewed_by" INTEGER,
|
|
"reviewed_at" TIMESTAMP(3),
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "aff_withdrawals_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex: Unique code
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "aff_codes_code_key" ON "aff_codes"("code");
|
|
|
|
-- CreateIndex: User can only have one code per plan
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "aff_codes_user_id_package_plan_id_key" ON "aff_codes"("user_id", "package_plan_id");
|
|
|
|
-- CreateIndex: AffCode indexes
|
|
CREATE INDEX IF NOT EXISTS "aff_codes_user_id_idx" ON "aff_codes"("user_id");
|
|
CREATE INDEX IF NOT EXISTS "aff_codes_package_plan_id_idx" ON "aff_codes"("package_plan_id");
|
|
|
|
-- CreateIndex: AffBinding - one instance can only bind one code
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "aff_bindings_instance_id_key" ON "aff_bindings"("instance_id");
|
|
CREATE INDEX IF NOT EXISTS "aff_bindings_aff_code_id_idx" ON "aff_bindings"("aff_code_id");
|
|
|
|
-- CreateIndex: AffLog indexes
|
|
CREATE INDEX IF NOT EXISTS "aff_logs_user_id_created_at_idx" ON "aff_logs"("user_id", "created_at" DESC);
|
|
CREATE INDEX IF NOT EXISTS "aff_logs_aff_code_id_idx" ON "aff_logs"("aff_code_id");
|
|
|
|
-- CreateIndex: AffWithdrawal indexes
|
|
CREATE INDEX IF NOT EXISTS "aff_withdrawals_user_id_status_idx" ON "aff_withdrawals"("user_id", "status");
|
|
CREATE INDEX IF NOT EXISTS "aff_withdrawals_status_created_at_idx" ON "aff_withdrawals"("status", "created_at");
|
|
|
|
-- AddForeignKey: AffCode -> User
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_codes_user_id_fkey') THEN
|
|
ALTER TABLE "aff_codes" ADD CONSTRAINT "aff_codes_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffCode -> PackagePlan
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_codes_package_plan_id_fkey') THEN
|
|
ALTER TABLE "aff_codes" ADD CONSTRAINT "aff_codes_package_plan_id_fkey" FOREIGN KEY ("package_plan_id") REFERENCES "package_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffBinding -> Instance
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_bindings_instance_id_fkey') THEN
|
|
ALTER TABLE "aff_bindings" ADD CONSTRAINT "aff_bindings_instance_id_fkey" FOREIGN KEY ("instance_id") REFERENCES "instances"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffBinding -> AffCode
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_bindings_aff_code_id_fkey') THEN
|
|
ALTER TABLE "aff_bindings" ADD CONSTRAINT "aff_bindings_aff_code_id_fkey" FOREIGN KEY ("aff_code_id") REFERENCES "aff_codes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffLog -> User
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_logs_user_id_fkey') THEN
|
|
ALTER TABLE "aff_logs" ADD CONSTRAINT "aff_logs_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffLog -> AffCode (SetNull on delete)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_logs_aff_code_id_fkey') THEN
|
|
ALTER TABLE "aff_logs" ADD CONSTRAINT "aff_logs_aff_code_id_fkey" FOREIGN KEY ("aff_code_id") REFERENCES "aff_codes"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- AddForeignKey: AffWithdrawal -> User
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'aff_withdrawals_user_id_fkey') THEN
|
|
ALTER TABLE "aff_withdrawals" ADD CONSTRAINT "aff_withdrawals_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
END IF;
|
|
END $$;
|