feat: add v03 user billing service (#1128)
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
CREATE TABLE IF NOT EXISTS hwlab_users (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
display_name TEXT NOT NULL DEFAULT '',
|
||||
password_hash TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
role TEXT NOT NULL DEFAULT 'user',
|
||||
email_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK (status IN ('active', 'disabled', 'pending')),
|
||||
CHECK (role IN ('user', 'admin'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_user_sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS hwlab_user_sessions_user_id_idx ON hwlab_user_sessions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS hwlab_user_sessions_token_hash_idx ON hwlab_user_sessions(token_hash);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_api_keys (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
key_prefix TEXT NOT NULL,
|
||||
key_hash TEXT NOT NULL UNIQUE,
|
||||
scopes_json JSONB NOT NULL DEFAULT '["api"]'::jsonb,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
last_used_at TIMESTAMPTZ,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
CHECK (status IN ('active', 'revoked'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS hwlab_api_keys_user_id_idx ON hwlab_api_keys(user_id);
|
||||
CREATE INDEX IF NOT EXISTS hwlab_api_keys_key_hash_idx ON hwlab_api_keys(key_hash);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_credit_accounts (
|
||||
user_id TEXT PRIMARY KEY REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
balance_credits BIGINT NOT NULL DEFAULT 0,
|
||||
reserved_credits BIGINT NOT NULL DEFAULT 0,
|
||||
plan_id TEXT NOT NULL DEFAULT 'default',
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK (balance_credits >= 0),
|
||||
CHECK (reserved_credits >= 0)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_credit_ledger (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
delta_credits BIGINT NOT NULL,
|
||||
balance_after BIGINT NOT NULL,
|
||||
kind TEXT NOT NULL,
|
||||
reason TEXT NOT NULL DEFAULT '',
|
||||
idempotency_key TEXT UNIQUE,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS hwlab_credit_ledger_user_id_idx ON hwlab_credit_ledger(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_billing_reservations (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
service_id TEXT NOT NULL,
|
||||
estimated_credits BIGINT NOT NULL,
|
||||
estimated_tokens BIGINT NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'reserved',
|
||||
idempotency_key TEXT UNIQUE,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK (estimated_credits >= 0),
|
||||
CHECK (estimated_tokens >= 0),
|
||||
CHECK (status IN ('reserved', 'completed', 'cancelled', 'expired'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS hwlab_billing_reservations_user_id_idx ON hwlab_billing_reservations(user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS hwlab_usage_records (
|
||||
id TEXT PRIMARY KEY,
|
||||
reservation_id TEXT REFERENCES hwlab_billing_reservations(id) ON DELETE SET NULL,
|
||||
user_id TEXT NOT NULL REFERENCES hwlab_users(id) ON DELETE CASCADE,
|
||||
service_id TEXT NOT NULL,
|
||||
unit TEXT NOT NULL DEFAULT 'token',
|
||||
quantity BIGINT NOT NULL DEFAULT 0,
|
||||
credits BIGINT NOT NULL DEFAULT 0,
|
||||
idempotency_key TEXT UNIQUE,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK (quantity >= 0),
|
||||
CHECK (credits >= 0)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS hwlab_usage_records_user_id_idx ON hwlab_usage_records(user_id);
|
||||
CREATE INDEX IF NOT EXISTS hwlab_usage_records_service_id_idx ON hwlab_usage_records(service_id);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user