Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
75 lines
3.7 KiB
SQL
75 lines
3.7 KiB
SQL
-- +goose Up
|
|
-- Sales contact leads + admin-prepared payment quotes (custom/Enterprise deals).
|
|
|
|
CREATE TABLE sales_leads (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL,
|
|
email TEXT NOT NULL,
|
|
company_name TEXT,
|
|
phone TEXT,
|
|
message TEXT NOT NULL,
|
|
estimated_skus INT,
|
|
source TEXT NOT NULL DEFAULT 'pricing'
|
|
CHECK (char_length(source) BETWEEN 1 AND 64),
|
|
status TEXT NOT NULL DEFAULT 'new'
|
|
CHECK (status IN ('new', 'contacted', 'quoted', 'won', 'closed')),
|
|
company_id UUID REFERENCES companies(id) ON DELETE SET NULL,
|
|
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
admin_notes TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
CONSTRAINT sales_leads_name_len CHECK (char_length(btrim(name)) BETWEEN 1 AND 200),
|
|
CONSTRAINT sales_leads_email_len CHECK (char_length(btrim(email)) BETWEEN 3 AND 320),
|
|
CONSTRAINT sales_leads_message_len CHECK (char_length(btrim(message)) BETWEEN 1 AND 10000),
|
|
CONSTRAINT sales_leads_company_name_len CHECK (company_name IS NULL OR char_length(company_name) <= 200),
|
|
CONSTRAINT sales_leads_phone_len CHECK (phone IS NULL OR char_length(phone) <= 40),
|
|
CONSTRAINT sales_leads_admin_notes_len CHECK (admin_notes IS NULL OR char_length(admin_notes) <= 10000),
|
|
CONSTRAINT sales_leads_estimated_skus_chk CHECK (estimated_skus IS NULL OR estimated_skus >= 0)
|
|
);
|
|
|
|
CREATE INDEX sales_leads_status_created_idx ON sales_leads (status, created_at DESC);
|
|
CREATE INDEX sales_leads_email_idx ON sales_leads (lower(email), created_at DESC);
|
|
CREATE INDEX sales_leads_company_idx ON sales_leads (company_id) WHERE company_id IS NOT NULL;
|
|
|
|
CREATE TABLE sales_quotes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
lead_id UUID NOT NULL REFERENCES sales_leads(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
plan_id BIGINT REFERENCES plans(id) ON DELETE SET NULL,
|
|
plan_name TEXT NOT NULL,
|
|
monthly_credits INT NOT NULL DEFAULT 0,
|
|
max_products INT,
|
|
currency TEXT NOT NULL DEFAULT 'usd',
|
|
total_amount_cents INT NOT NULL,
|
|
installment_count INT NOT NULL DEFAULT 1,
|
|
installment_interval TEXT NOT NULL DEFAULT 'month'
|
|
CHECK (installment_interval IN ('month', 'quarter', 'year')),
|
|
installment_amount_cents INT NOT NULL,
|
|
term_months INT,
|
|
stripe_product_id TEXT,
|
|
stripe_price_id TEXT,
|
|
stripe_checkout_session_id TEXT,
|
|
checkout_url TEXT,
|
|
status TEXT NOT NULL DEFAULT 'draft'
|
|
CHECK (status IN ('draft', 'ready', 'sent', 'paid', 'canceled')),
|
|
created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
paid_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
CONSTRAINT sales_quotes_plan_name_len CHECK (char_length(btrim(plan_name)) BETWEEN 1 AND 120),
|
|
CONSTRAINT sales_quotes_currency_len CHECK (char_length(currency) BETWEEN 3 AND 10),
|
|
CONSTRAINT sales_quotes_total_chk CHECK (total_amount_cents > 0),
|
|
CONSTRAINT sales_quotes_installment_count_chk CHECK (installment_count BETWEEN 1 AND 60),
|
|
CONSTRAINT sales_quotes_installment_amount_chk CHECK (installment_amount_cents > 0),
|
|
CONSTRAINT sales_quotes_monthly_credits_chk CHECK (monthly_credits >= 0),
|
|
CONSTRAINT sales_quotes_max_products_chk CHECK (max_products IS NULL OR max_products >= 0),
|
|
CONSTRAINT sales_quotes_term_months_chk CHECK (term_months IS NULL OR term_months BETWEEN 1 AND 120)
|
|
);
|
|
|
|
CREATE INDEX sales_quotes_lead_idx ON sales_quotes (lead_id, created_at DESC);
|
|
CREATE INDEX sales_quotes_company_status_idx ON sales_quotes (company_id, status, created_at DESC);
|
|
CREATE INDEX sales_quotes_status_idx ON sales_quotes (status, created_at DESC);
|
|
|
|
-- +goose Down
|
|
DROP TABLE IF EXISTS sales_quotes;
|
|
DROP TABLE IF EXISTS sales_leads; |