Files
pikasTech-HWLAB/internal/userbilling/migrations/0004_redeem_subscription_payment.sql
T
2026-06-14 21:21:01 +08:00

81 lines
3.4 KiB
SQL

CREATE TABLE IF NOT EXISTS hwlab_redeem_codes (
id TEXT PRIMARY KEY,
code_hash TEXT NOT NULL UNIQUE,
code_prefix TEXT NOT NULL,
display_name TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'active',
credit_amount BIGINT NOT NULL,
reason TEXT NOT NULL DEFAULT 'redeem',
max_redemptions INTEGER NOT NULL DEFAULT 1,
per_user_limit INTEGER NOT NULL DEFAULT 1,
redeemed_count INTEGER NOT NULL DEFAULT 0,
expires_at TIMESTAMPTZ,
created_by_user_id TEXT,
created_by_username TEXT,
disabled_at TIMESTAMPTZ,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CHECK (status IN ('active', 'disabled', 'expired')),
CHECK (credit_amount > 0),
CHECK (max_redemptions > 0),
CHECK (per_user_limit > 0),
CHECK (redeemed_count >= 0)
);
CREATE INDEX IF NOT EXISTS hwlab_redeem_codes_status_created_idx ON hwlab_redeem_codes(status, created_at DESC);
CREATE INDEX IF NOT EXISTS hwlab_redeem_codes_prefix_idx ON hwlab_redeem_codes(code_prefix);
CREATE TABLE IF NOT EXISTS hwlab_redeem_redemptions (
id TEXT PRIMARY KEY,
code_id TEXT NOT NULL REFERENCES hwlab_redeem_codes(id) ON DELETE CASCADE,
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
ledger_id TEXT REFERENCES hwlab_credit_ledger(id) ON DELETE SET NULL,
credit_amount BIGINT NOT NULL,
status TEXT NOT NULL DEFAULT 'applied',
idempotency_key TEXT UNIQUE,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CHECK (credit_amount > 0),
CHECK (status IN ('applied', 'rejected'))
);
CREATE INDEX IF NOT EXISTS hwlab_redeem_redemptions_code_created_idx ON hwlab_redeem_redemptions(code_id, created_at DESC);
CREATE INDEX IF NOT EXISTS hwlab_redeem_redemptions_user_created_idx ON hwlab_redeem_redemptions(user_id, created_at DESC);
CREATE TABLE IF NOT EXISTS hwlab_user_subscriptions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
plan_id TEXT NOT NULL REFERENCES hwlab_billing_plans(id),
status TEXT NOT NULL DEFAULT 'active',
source TEXT NOT NULL DEFAULT 'manual',
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CHECK (status IN ('active', 'trialing', 'past_due', 'canceled', 'disabled')),
CHECK (source IN ('manual', 'redeem', 'payment_placeholder', 'system'))
);
CREATE INDEX IF NOT EXISTS hwlab_user_subscriptions_user_status_idx ON hwlab_user_subscriptions(user_id, status, created_at DESC);
CREATE TABLE IF NOT EXISTS hwlab_payment_orders (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
provider TEXT NOT NULL DEFAULT 'unconfigured',
status TEXT NOT NULL DEFAULT 'unconfigured',
credit_amount BIGINT NOT NULL DEFAULT 0,
amount_minor BIGINT NOT NULL DEFAULT 0,
currency TEXT NOT NULL DEFAULT 'CNY',
reason TEXT NOT NULL DEFAULT '',
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CHECK (status IN ('unconfigured', 'created', 'pending', 'paid', 'failed', 'cancelled', 'refunded')),
CHECK (credit_amount >= 0),
CHECK (amount_minor >= 0)
);
CREATE INDEX IF NOT EXISTS hwlab_payment_orders_user_created_idx ON hwlab_payment_orders(user_id, created_at DESC);