new-site/api/migrations/001_core_tables.sql
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

84 lines
3 KiB
PL/PgSQL

-- 001_core_tables.sql
-- Core tables for Performance West API: subscribers, tickets, quotes, orders.
-- Run: psql $DATABASE_URL < migrations/001_core_tables.sql
BEGIN;
-- Mailing list subscribers
CREATE TABLE IF NOT EXISTS subscribers (
id SERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT,
company TEXT,
consent_text TEXT NOT NULL,
consent_at TIMESTAMPTZ NOT NULL DEFAULT now(),
ip_address TEXT,
confirmed BOOLEAN DEFAULT FALSE,
unsubscribed BOOLEAN DEFAULT FALSE,
source TEXT DEFAULT 'website',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_subscribers_email ON subscribers(email);
CREATE INDEX IF NOT EXISTS idx_subscribers_created ON subscribers(created_at DESC);
-- Support tickets (local fallback when Zammad is unavailable)
CREATE TABLE IF NOT EXISTS tickets (
id SERIAL PRIMARY KEY,
category TEXT NOT NULL CHECK (category IN (
'question', 'support', 'issue', 'service_request', 'quote'
)),
subject TEXT NOT NULL,
message TEXT NOT NULL,
email TEXT,
name TEXT,
page TEXT,
ip_address TEXT,
zammad_ticket_id TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_tickets_category ON tickets(category);
CREATE INDEX IF NOT EXISTS idx_tickets_created ON tickets(created_at DESC);
-- Quote requests (for custom-priced services)
CREATE TABLE IF NOT EXISTS quotes (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
company TEXT,
phone TEXT,
service_slug TEXT NOT NULL,
details TEXT,
status TEXT DEFAULT 'pending' CHECK (status IN (
'pending', 'sent', 'accepted', 'declined', 'expired'
)),
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_quotes_status ON quotes(status);
CREATE INDEX IF NOT EXISTS idx_quotes_email ON quotes(email);
-- Service orders (fixed-price and accepted quotes)
CREATE TABLE IF NOT EXISTS orders (
id SERIAL PRIMARY KEY,
order_number TEXT UNIQUE NOT NULL,
quote_id INTEGER REFERENCES quotes(id),
service_slug TEXT NOT NULL,
name TEXT NOT NULL,
email TEXT NOT NULL,
company TEXT,
status TEXT DEFAULT 'received' CHECK (status IN (
'received', 'processing', 'review', 'delivered', 'cancelled'
)),
amount_cents INTEGER,
created_at TIMESTAMPTZ DEFAULT now(),
delivered_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
CREATE INDEX IF NOT EXISTS idx_orders_number ON orders(order_number);
CREATE INDEX IF NOT EXISTS idx_orders_email ON orders(email);
COMMIT;