first commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
-- 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 $$;
|
||||
Reference in New Issue
Block a user