Files
Aether/crates/aether-data/schema/generated/postgres/baseline/005_wallet_billing.sql
2026-05-19 10:18:25 +08:00

349 lines
19 KiB
SQL

-- Generated by aether-data-schema from schema/logical/*.toml.
-- Do not edit generated files directly; edit logical schema or explicit overrides instead.
CREATE TABLE IF NOT EXISTS public.wallets (
id character varying(64) NOT NULL,
user_id character varying(64),
api_key_id character varying(64),
balance double precision DEFAULT 0 NOT NULL,
gift_balance double precision DEFAULT 0 NOT NULL,
limit_mode character varying(64) DEFAULT 'finite' NOT NULL,
currency character varying(16) DEFAULT 'USD' NOT NULL,
status character varying(64) DEFAULT 'active' NOT NULL,
total_recharged double precision DEFAULT 0 NOT NULL,
total_consumed double precision DEFAULT 0 NOT NULL,
total_refunded double precision DEFAULT 0 NOT NULL,
total_adjusted double precision DEFAULT 0 NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.wallets ADD CONSTRAINT wallets_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.wallets ADD CONSTRAINT wallets_user_id_key UNIQUE (user_id);
ALTER TABLE ONLY public.wallets ADD CONSTRAINT wallets_api_key_id_key UNIQUE (api_key_id);
CREATE INDEX IF NOT EXISTS wallets_api_key_id_idx ON public.wallets USING btree (api_key_id);
CREATE INDEX IF NOT EXISTS wallets_user_id_idx ON public.wallets USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.wallet_transactions (
id character varying(64) NOT NULL,
wallet_id character varying(64) NOT NULL,
category character varying(64) NOT NULL,
reason_code character varying(64) NOT NULL,
amount double precision NOT NULL,
balance_before double precision NOT NULL,
balance_after double precision NOT NULL,
recharge_balance_before double precision NOT NULL,
recharge_balance_after double precision NOT NULL,
gift_balance_before double precision NOT NULL,
gift_balance_after double precision NOT NULL,
link_type character varying(64),
link_id character varying(128),
operator_id character varying(64),
description text,
created_at bigint NOT NULL
);
ALTER TABLE ONLY public.wallet_transactions ADD CONSTRAINT wallet_transactions_pkey PRIMARY KEY (id);
CREATE INDEX IF NOT EXISTS idx_wallet_tx_wallet_created ON public.wallet_transactions USING btree (wallet_id, created_at);
CREATE INDEX IF NOT EXISTS idx_wallet_tx_category_created ON public.wallet_transactions USING btree (category, created_at);
CREATE INDEX IF NOT EXISTS idx_wallet_tx_reason_created ON public.wallet_transactions USING btree (reason_code, created_at);
CREATE INDEX IF NOT EXISTS idx_wallet_tx_link ON public.wallet_transactions USING btree (link_type, link_id);
CREATE INDEX IF NOT EXISTS ix_wallet_transactions_operator_id ON public.wallet_transactions USING btree (operator_id);
CREATE TABLE IF NOT EXISTS public.wallet_daily_usage_ledgers (
id character varying(64) NOT NULL,
wallet_id character varying(64) NOT NULL,
billing_date character varying(16) NOT NULL,
billing_timezone character varying(64) NOT NULL,
total_cost_usd double precision DEFAULT 0 NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT 0 NOT NULL,
output_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_tokens bigint DEFAULT 0 NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
first_finalized_at bigint,
last_finalized_at bigint,
aggregated_at bigint NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.wallet_daily_usage_ledgers ADD CONSTRAINT wallet_daily_usage_ledgers_pkey PRIMARY KEY (id);
CREATE INDEX IF NOT EXISTS idx_wallet_daily_usage_wallet_date ON public.wallet_daily_usage_ledgers USING btree (wallet_id, billing_timezone, billing_date);
CREATE TABLE IF NOT EXISTS public.payment_orders (
id character varying(64) NOT NULL,
order_no character varying(128) NOT NULL,
wallet_id character varying(64) NOT NULL,
user_id character varying(64),
amount_usd double precision NOT NULL,
pay_amount double precision,
pay_currency character varying(16),
exchange_rate double precision,
refunded_amount_usd double precision DEFAULT 0 NOT NULL,
refundable_amount_usd double precision DEFAULT 0 NOT NULL,
payment_method character varying(64) NOT NULL,
payment_provider character varying(64),
payment_channel character varying(64),
order_kind character varying(64) DEFAULT 'wallet_recharge' NOT NULL,
product_id character varying(64),
product_snapshot jsonb,
fulfillment_status character varying(64) DEFAULT 'pending' NOT NULL,
fulfillment_error text,
gateway_order_id character varying(128),
gateway_response jsonb,
status character varying(64) DEFAULT 'pending' NOT NULL,
created_at bigint NOT NULL,
paid_at bigint,
credited_at bigint,
expires_at bigint
);
ALTER TABLE ONLY public.payment_orders ADD CONSTRAINT payment_orders_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.payment_orders ADD CONSTRAINT uq_payment_orders_order_no UNIQUE (order_no);
CREATE INDEX IF NOT EXISTS idx_payment_orders_wallet_created ON public.payment_orders USING btree (wallet_id, created_at);
CREATE INDEX IF NOT EXISTS idx_payment_orders_user_created ON public.payment_orders USING btree (user_id, created_at);
CREATE INDEX IF NOT EXISTS idx_payment_orders_status ON public.payment_orders USING btree (status);
CREATE INDEX IF NOT EXISTS idx_payment_orders_gateway_order_id ON public.payment_orders USING btree (gateway_order_id);
CREATE INDEX IF NOT EXISTS idx_payment_orders_kind_status ON public.payment_orders USING btree (order_kind, status);
CREATE INDEX IF NOT EXISTS idx_payment_orders_product ON public.payment_orders USING btree (product_id);
CREATE TABLE IF NOT EXISTS public.user_invite_codes (
user_id character varying(64) NOT NULL,
invite_code character varying(64) NOT NULL,
active boolean DEFAULT true NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
ALTER TABLE ONLY public.user_invite_codes ADD CONSTRAINT user_invite_codes_pkey PRIMARY KEY (user_id);
ALTER TABLE ONLY public.user_invite_codes ADD CONSTRAINT user_invite_codes_invite_code_key UNIQUE (invite_code);
ALTER TABLE ONLY public.user_invite_codes ADD CONSTRAINT user_invite_codes_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS public.user_referrals (
id character varying(64) NOT NULL,
inviter_user_id character varying(64) NOT NULL,
invitee_user_id character varying(64) NOT NULL,
invite_code_snapshot character varying(64) NOT NULL,
source_json jsonb,
first_paid_order_id character varying(64),
first_paid_at timestamp with time zone,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
ALTER TABLE ONLY public.user_referrals ADD CONSTRAINT user_referrals_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.user_referrals ADD CONSTRAINT user_referrals_invitee_user_id_key UNIQUE (invitee_user_id);
CREATE INDEX IF NOT EXISTS idx_user_referrals_inviter ON public.user_referrals USING btree (inviter_user_id, created_at);
CREATE INDEX IF NOT EXISTS idx_user_referrals_created ON public.user_referrals USING btree (created_at);
CREATE INDEX IF NOT EXISTS idx_user_referrals_invite_code ON public.user_referrals USING btree (invite_code_snapshot);
ALTER TABLE ONLY public.user_referrals ADD CONSTRAINT user_referrals_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.user_referrals ADD CONSTRAINT user_referrals_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.user_referrals ADD CONSTRAINT user_referrals_first_paid_order_fkey FOREIGN KEY (first_paid_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
CREATE TABLE IF NOT EXISTS public.referral_rewards (
id character varying(64) NOT NULL,
referral_id character varying(64) NOT NULL,
inviter_user_id character varying(64) NOT NULL,
invitee_user_id character varying(64) NOT NULL,
reward_type character varying(32) NOT NULL,
trigger_point character varying(64) NOT NULL,
source_order_id character varying(64),
idempotency_key character varying(128) NOT NULL,
amount_usd double precision NOT NULL,
status character varying(32) DEFAULT 'pending' NOT NULL,
wallet_transaction_id character varying(64),
reversed_amount_usd double precision DEFAULT 0 NOT NULL,
pending_reversal_amount_usd double precision DEFAULT 0 NOT NULL,
failure_reason text,
admin_operator_id character varying(64),
admin_note text,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_idempotency_key_key UNIQUE (idempotency_key);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_inviter_status ON public.referral_rewards USING btree (inviter_user_id, status, created_at);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_inviter_created ON public.referral_rewards USING btree (inviter_user_id, created_at);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_created ON public.referral_rewards USING btree (created_at);
CREATE INDEX IF NOT EXISTS idx_referral_rewards_source_order ON public.referral_rewards USING btree (source_order_id);
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_referral_id_fkey FOREIGN KEY (referral_id) REFERENCES public.user_referrals(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.referral_rewards ADD CONSTRAINT referral_rewards_source_order_fkey FOREIGN KEY (source_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
CREATE TABLE IF NOT EXISTS public.payment_gateway_configs (
provider character varying(64) NOT NULL,
enabled boolean DEFAULT false NOT NULL,
endpoint_url character varying(512) NOT NULL,
callback_base_url character varying(512),
merchant_id character varying(128) NOT NULL,
merchant_key_encrypted text,
pay_currency character varying(16) DEFAULT 'CNY' NOT NULL,
usd_exchange_rate double precision DEFAULT 7.2 NOT NULL,
min_recharge_usd double precision DEFAULT 1 NOT NULL,
channels_json jsonb,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.payment_gateway_configs ADD CONSTRAINT payment_gateway_configs_pkey PRIMARY KEY (provider);
CREATE TABLE IF NOT EXISTS public.payment_callbacks (
id character varying(64) NOT NULL,
payment_order_id character varying(64),
payment_method character varying(64) NOT NULL,
callback_key character varying(128) NOT NULL,
order_no character varying(128),
gateway_order_id character varying(128),
payload_hash character varying(128),
signature_valid boolean DEFAULT false NOT NULL,
status character varying(64) DEFAULT 'received' NOT NULL,
payload jsonb,
error_message text,
created_at bigint NOT NULL,
processed_at bigint
);
ALTER TABLE ONLY public.payment_callbacks ADD CONSTRAINT payment_callbacks_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.payment_callbacks ADD CONSTRAINT uq_payment_callbacks_callback_key UNIQUE (callback_key);
CREATE INDEX IF NOT EXISTS idx_payment_callbacks_order ON public.payment_callbacks USING btree (order_no);
CREATE INDEX IF NOT EXISTS idx_payment_callbacks_gateway_order ON public.payment_callbacks USING btree (gateway_order_id);
CREATE INDEX IF NOT EXISTS idx_payment_callbacks_created ON public.payment_callbacks USING btree (created_at);
CREATE INDEX IF NOT EXISTS ix_payment_callbacks_payment_order_id ON public.payment_callbacks USING btree (payment_order_id);
CREATE TABLE IF NOT EXISTS public.billing_plans (
id character varying(64) NOT NULL,
title character varying(128) NOT NULL,
description text,
price_amount double precision NOT NULL,
price_currency character varying(16) DEFAULT 'CNY' NOT NULL,
duration_unit character varying(32) NOT NULL,
duration_value bigint NOT NULL,
enabled boolean DEFAULT true NOT NULL,
sort_order bigint DEFAULT 0 NOT NULL,
max_active_per_user bigint DEFAULT 1 NOT NULL,
purchase_limit_scope character varying(32) DEFAULT 'active_period' NOT NULL,
entitlements_json jsonb NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.billing_plans ADD CONSTRAINT billing_plans_pkey PRIMARY KEY (id);
CREATE INDEX IF NOT EXISTS idx_billing_plans_enabled_sort ON public.billing_plans USING btree (enabled, sort_order);
CREATE TABLE IF NOT EXISTS public.user_plan_entitlements (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
plan_id character varying(64) NOT NULL,
payment_order_id character varying(64) NOT NULL,
status character varying(64) DEFAULT 'active' NOT NULL,
starts_at bigint NOT NULL,
expires_at bigint NOT NULL,
entitlements_snapshot jsonb NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.user_plan_entitlements ADD CONSTRAINT user_plan_entitlements_pkey PRIMARY KEY (id);
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_user_active ON public.user_plan_entitlements USING btree (user_id, status, expires_at);
CREATE INDEX IF NOT EXISTS idx_user_plan_entitlements_order ON public.user_plan_entitlements USING btree (payment_order_id);
CREATE TABLE IF NOT EXISTS public.entitlement_usage_ledgers (
id character varying(64) NOT NULL,
user_entitlement_id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
request_id character varying(128) NOT NULL,
amount_usd double precision NOT NULL,
balance_before double precision NOT NULL,
balance_after double precision NOT NULL,
usage_date character varying(16) NOT NULL,
created_at bigint NOT NULL
);
ALTER TABLE ONLY public.entitlement_usage_ledgers ADD CONSTRAINT entitlement_usage_ledgers_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.entitlement_usage_ledgers ADD CONSTRAINT uq_entitlement_usage_request UNIQUE (user_entitlement_id, request_id);
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_user_date ON public.entitlement_usage_ledgers USING btree (user_id, usage_date);
CREATE INDEX IF NOT EXISTS idx_entitlement_usage_entitlement_date ON public.entitlement_usage_ledgers USING btree (user_entitlement_id, usage_date);
CREATE TABLE IF NOT EXISTS public.refund_requests (
id character varying(64) NOT NULL,
refund_no character varying(128) NOT NULL,
wallet_id character varying(64) NOT NULL,
user_id character varying(64),
payment_order_id character varying(64),
source_type character varying(64) NOT NULL,
source_id character varying(128),
refund_mode character varying(64) NOT NULL,
amount_usd double precision NOT NULL,
status character varying(64) DEFAULT 'pending_approval' NOT NULL,
reason text,
requested_by character varying(64),
approved_by character varying(64),
processed_by character varying(64),
gateway_refund_id character varying(128),
payout_method character varying(64),
payout_reference character varying(255),
payout_proof jsonb,
failure_reason text,
idempotency_key character varying(128),
created_at bigint NOT NULL,
updated_at bigint NOT NULL,
processed_at bigint,
completed_at bigint
);
ALTER TABLE ONLY public.refund_requests ADD CONSTRAINT refund_requests_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.refund_requests ADD CONSTRAINT uq_refund_requests_refund_no UNIQUE (refund_no);
ALTER TABLE ONLY public.refund_requests ADD CONSTRAINT uq_refund_requests_idempotency_key UNIQUE (idempotency_key);
CREATE INDEX IF NOT EXISTS idx_refund_wallet_created ON public.refund_requests USING btree (wallet_id, created_at);
CREATE INDEX IF NOT EXISTS idx_refund_user_created ON public.refund_requests USING btree (user_id, created_at);
CREATE INDEX IF NOT EXISTS idx_refund_status ON public.refund_requests USING btree (status);
CREATE INDEX IF NOT EXISTS ix_refund_requests_payment_order_id ON public.refund_requests USING btree (payment_order_id);
CREATE INDEX IF NOT EXISTS ix_refund_requests_requested_by ON public.refund_requests USING btree (requested_by);
CREATE INDEX IF NOT EXISTS ix_refund_requests_approved_by ON public.refund_requests USING btree (approved_by);
CREATE INDEX IF NOT EXISTS ix_refund_requests_processed_by ON public.refund_requests USING btree (processed_by);
CREATE TABLE IF NOT EXISTS public.redeem_code_batches (
id character varying(64) NOT NULL,
name character varying(255) NOT NULL,
amount_usd double precision NOT NULL,
currency character varying(16) DEFAULT 'USD' NOT NULL,
balance_bucket character varying(64) DEFAULT 'gift' NOT NULL,
total_count integer NOT NULL,
status character varying(64) DEFAULT 'active' NOT NULL,
description text,
created_by character varying(64),
expires_at bigint,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.redeem_code_batches ADD CONSTRAINT redeem_code_batches_pkey PRIMARY KEY (id);
CREATE INDEX IF NOT EXISTS idx_redeem_code_batches_status ON public.redeem_code_batches USING btree (status, created_at);
CREATE TABLE IF NOT EXISTS public.redeem_codes (
id character varying(64) NOT NULL,
batch_id character varying(64) NOT NULL,
code_hash character varying(128) NOT NULL,
code_prefix character varying(16) NOT NULL,
code_suffix character varying(16) NOT NULL,
status character varying(64) DEFAULT 'active' NOT NULL,
redeemed_by_user_id character varying(64),
redeemed_wallet_id character varying(64),
redeemed_payment_order_id character varying(64),
redeemed_at bigint,
disabled_by character varying(64),
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
ALTER TABLE ONLY public.redeem_codes ADD CONSTRAINT redeem_codes_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.redeem_codes ADD CONSTRAINT uq_redeem_codes_code_hash UNIQUE (code_hash);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_batch_created ON public.redeem_codes USING btree (batch_id, created_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_status ON public.redeem_codes USING btree (status, updated_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_redeemed_user ON public.redeem_codes USING btree (redeemed_by_user_id, redeemed_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_redeemed_order ON public.redeem_codes USING btree (redeemed_payment_order_id);