142 lines
7.0 KiB
SQL
142 lines
7.0 KiB
SQL
-- IT0 Billing Tables (public schema)
|
|
-- Phase 2: Subscription management + invoicing
|
|
|
|
-- Invoice number sequence
|
|
CREATE SEQUENCE IF NOT EXISTS billing_invoice_number_seq START 1000;
|
|
|
|
-- Plans
|
|
CREATE TABLE IF NOT EXISTS billing_plans (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(50) NOT NULL UNIQUE, -- free, pro, enterprise
|
|
display_name VARCHAR(100) NOT NULL,
|
|
monthly_price_usd_cents INTEGER NOT NULL DEFAULT 0,
|
|
monthly_price_cny INTEGER NOT NULL DEFAULT 0, -- in fen (1/100 yuan)
|
|
included_tokens_per_month BIGINT NOT NULL DEFAULT 100000,
|
|
overage_rate_cents_per_m_token INTEGER NOT NULL DEFAULT 0, -- per million tokens
|
|
max_servers INTEGER NOT NULL DEFAULT 5, -- -1 = unlimited
|
|
max_users INTEGER NOT NULL DEFAULT 3,
|
|
max_standing_orders INTEGER NOT NULL DEFAULT 10,
|
|
hard_limit_percent INTEGER NOT NULL DEFAULT 100, -- 0 = no hard limit
|
|
trial_days INTEGER NOT NULL DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Subscriptions
|
|
CREATE TABLE IF NOT EXISTS billing_subscriptions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id VARCHAR(20) NOT NULL REFERENCES it0_shared.tenants(id),
|
|
plan_id UUID NOT NULL REFERENCES billing_plans(id),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'trialing',
|
|
current_period_start TIMESTAMPTZ NOT NULL,
|
|
current_period_end TIMESTAMPTZ NOT NULL,
|
|
trial_ends_at TIMESTAMPTZ,
|
|
cancel_at_period_end BOOLEAN NOT NULL DEFAULT FALSE,
|
|
cancelled_at TIMESTAMPTZ,
|
|
next_plan_id UUID REFERENCES billing_plans(id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_subs_tenant ON billing_subscriptions(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_billing_subs_status ON billing_subscriptions(status);
|
|
CREATE INDEX IF NOT EXISTS idx_billing_subs_period_end ON billing_subscriptions(current_period_end);
|
|
|
|
-- Invoices
|
|
CREATE TABLE IF NOT EXISTS billing_invoices (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id VARCHAR(20) NOT NULL REFERENCES it0_shared.tenants(id),
|
|
subscription_id UUID REFERENCES billing_subscriptions(id),
|
|
invoice_number VARCHAR(50) NOT NULL UNIQUE,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'open', -- open, paid, void, past_due, uncollectible
|
|
currency VARCHAR(3) NOT NULL DEFAULT 'USD',
|
|
subtotal_cents INTEGER NOT NULL DEFAULT 0,
|
|
tax_cents INTEGER NOT NULL DEFAULT 0,
|
|
total_cents INTEGER NOT NULL DEFAULT 0,
|
|
amount_due_cents INTEGER NOT NULL DEFAULT 0,
|
|
period_start TIMESTAMPTZ NOT NULL,
|
|
period_end TIMESTAMPTZ NOT NULL,
|
|
due_date TIMESTAMPTZ NOT NULL,
|
|
paid_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_invoices_tenant ON billing_invoices(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_billing_invoices_status ON billing_invoices(status);
|
|
|
|
-- Invoice Items
|
|
CREATE TABLE IF NOT EXISTS billing_invoice_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invoice_id UUID NOT NULL REFERENCES billing_invoices(id) ON DELETE CASCADE,
|
|
item_type VARCHAR(30) NOT NULL, -- subscription, overage, credit, adjustment
|
|
description TEXT NOT NULL,
|
|
quantity BIGINT NOT NULL DEFAULT 1,
|
|
unit_price INTEGER NOT NULL, -- cents
|
|
amount INTEGER NOT NULL, -- cents
|
|
currency VARCHAR(3) NOT NULL DEFAULT 'USD',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_items_invoice ON billing_invoice_items(invoice_id);
|
|
|
|
-- Payments
|
|
CREATE TABLE IF NOT EXISTS billing_payments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id VARCHAR(20) NOT NULL REFERENCES it0_shared.tenants(id),
|
|
invoice_id UUID NOT NULL REFERENCES billing_invoices(id),
|
|
provider VARCHAR(20) NOT NULL, -- stripe, alipay, wechat_pay, crypto
|
|
provider_payment_id VARCHAR(255) NOT NULL UNIQUE,
|
|
amount_cents INTEGER NOT NULL,
|
|
currency VARCHAR(3) NOT NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending, succeeded, failed, refunded
|
|
paid_at TIMESTAMPTZ,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_payments_tenant ON billing_payments(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_billing_payments_provider_id ON billing_payments(provider_payment_id);
|
|
|
|
-- Payment Methods
|
|
CREATE TABLE IF NOT EXISTS billing_payment_methods (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id VARCHAR(20) NOT NULL REFERENCES it0_shared.tenants(id),
|
|
provider VARCHAR(20) NOT NULL,
|
|
display_name VARCHAR(200) NOT NULL,
|
|
provider_customer_id VARCHAR(255),
|
|
details JSONB, -- masked card info, alipay account, etc. NO raw card numbers
|
|
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
|
expires_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_methods_tenant ON billing_payment_methods(tenant_id);
|
|
|
|
-- Monthly Usage Aggregates
|
|
CREATE TABLE IF NOT EXISTS billing_usage_aggregates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id VARCHAR(20) NOT NULL REFERENCES it0_shared.tenants(id),
|
|
year INTEGER NOT NULL,
|
|
month INTEGER NOT NULL, -- 1-12
|
|
period_start TIMESTAMPTZ NOT NULL,
|
|
period_end TIMESTAMPTZ NOT NULL,
|
|
total_input_tokens BIGINT NOT NULL DEFAULT 0,
|
|
total_output_tokens BIGINT NOT NULL DEFAULT 0,
|
|
total_tokens BIGINT NOT NULL DEFAULT 0,
|
|
total_cost_usd NUMERIC(12, 6) NOT NULL DEFAULT 0,
|
|
task_count INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE(tenant_id, year, month)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_billing_usage_tenant_period ON billing_usage_aggregates(tenant_id, year, month);
|
|
|
|
-- Add max_standing_orders column to tenants if missing
|
|
ALTER TABLE it0_shared.tenants ADD COLUMN IF NOT EXISTS max_standing_orders INTEGER NOT NULL DEFAULT 10;
|
|
ALTER TABLE it0_shared.tenants ADD COLUMN IF NOT EXISTS max_agent_tokens_per_month BIGINT NOT NULL DEFAULT 100000;
|