Files
descrybe/apps/api/sql/schema/001_platform.sql
T

168 lines
5.4 KiB
SQL
Raw Normal View History

-- +goose Up
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE companies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
language TEXT NOT NULL DEFAULT 'en',
merge_products_by_gtin BOOLEAN NOT NULL DEFAULT false,
legacy_company_id TEXT UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT NOT NULL UNIQUE,
name TEXT,
password_hash TEXT,
must_set_password BOOLEAN NOT NULL DEFAULT true,
email_verified_at TIMESTAMPTZ,
is_platform_admin BOOLEAN NOT NULL DEFAULT false,
is_active BOOLEAN NOT NULL DEFAULT true,
legacy_user_id TEXT UNIQUE,
last_login_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE memberships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role TEXT NOT NULL DEFAULT 'member' CHECK (role IN ('admin', 'member')),
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (company_id, user_id)
);
CREATE INDEX memberships_user_id_idx ON memberships(user_id);
CREATE INDEX memberships_company_id_idx ON memberships(company_id);
CREATE TABLE invites (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
email TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'member' CHECK (role IN ('admin', 'member')),
token TEXT NOT NULL UNIQUE,
invited_by UUID REFERENCES users(id) ON DELETE SET NULL,
expires_at TIMESTAMPTZ NOT NULL,
accepted_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX invites_company_email_idx ON invites(company_id, email);
CREATE TABLE sessions (
token TEXT PRIMARY KEY,
data BYTEA NOT NULL,
expiry TIMESTAMPTZ NOT NULL
);
CREATE INDEX sessions_expiry_idx ON sessions(expiry);
CREATE TABLE api_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT,
key_hash TEXT NOT NULL UNIQUE,
key_prefix TEXT NOT NULL,
last_used_at TIMESTAMPTZ,
revoked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX api_keys_company_id_idx ON api_keys(company_id);
CREATE TABLE company_settings (
company_id UUID PRIMARY KEY REFERENCES companies(id) ON DELETE CASCADE,
settings JSONB NOT NULL DEFAULT '{}'::jsonb,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE plans (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
monthly_credits INT NOT NULL,
yearly_credits INT,
max_products INT,
is_custom BOOLEAN NOT NULL DEFAULT false,
term TEXT NOT NULL DEFAULT 'monthly',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE company_plans (
id BIGSERIAL PRIMARY KEY,
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
plan_id BIGINT NOT NULL REFERENCES plans(id),
is_active BOOLEAN NOT NULL DEFAULT true,
billing_cycle_start TIMESTAMPTZ NOT NULL,
next_billing_date TIMESTAMPTZ NOT NULL,
contract_start_date TIMESTAMPTZ,
contract_end_date TIMESTAMPTZ,
custom_monthly_credits INT,
total_credits_allocated INT,
custom_max_products INT,
contract_reference TEXT,
notes TEXT,
is_trial BOOLEAN NOT NULL DEFAULT false,
trial_ends_at TIMESTAMPTZ,
trial_credits INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX company_plans_company_id_idx ON company_plans(company_id);
CREATE TABLE billing_cycles (
id BIGSERIAL PRIMARY KEY,
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
start_date TIMESTAMPTZ NOT NULL,
end_date TIMESTAMPTZ NOT NULL,
credits_used INT NOT NULL DEFAULT 0,
products_processed INT NOT NULL DEFAULT 0,
invoice_amount INT,
invoice_notes TEXT,
is_invoiced BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX billing_cycles_company_id_idx ON billing_cycles(company_id);
CREATE TABLE credit_balances (
company_id UUID PRIMARY KEY REFERENCES companies(id) ON DELETE CASCADE,
total_credits INT NOT NULL DEFAULT 0,
used_credits INT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE processing_costs (
id BIGSERIAL PRIMARY KEY,
feature_name TEXT NOT NULL UNIQUE,
cost_per_unit INT NOT NULL,
description TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- +goose Down
DROP TABLE IF EXISTS processing_costs;
DROP TABLE IF EXISTS credit_balances;
DROP TABLE IF EXISTS billing_cycles;
DROP TABLE IF EXISTS company_plans;
DROP TABLE IF EXISTS plans;
DROP TABLE IF EXISTS company_settings;
DROP TABLE IF EXISTS api_keys;
DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS invites;
DROP TABLE IF EXISTS memberships;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS companies;