-- crm_full_20260505.sql -- PGŽ Sport — Salesforce-Lite CRM (Accounts/Contacts/Leads/Opportunities/Activities/Cases) -- Author: dradulic@outlook.com / damir@rinet.one -- Date: 2026-05-05 BEGIN; -- 1) ACCOUNTS ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS pgz_sport.crm_accounts ( id BIGSERIAL PRIMARY KEY, naziv TEXT NOT NULL, type TEXT NOT NULL DEFAULT 'klub' CHECK (type IN ('klub','savez','sponzor','drzava','drugo')), klub_id BIGINT REFERENCES pgz_sport.klubovi(id) ON DELETE SET NULL, savez_id BIGINT REFERENCES pgz_sport.savezi(id) ON DELETE SET NULL, oib TEXT, email TEXT, telefon TEXT, web TEXT, adresa TEXT, grad TEXT, industry TEXT, napomene TEXT, owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 2) CONTACTS ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS pgz_sport.crm_contacts ( id BIGSERIAL PRIMARY KEY, account_id BIGINT REFERENCES pgz_sport.crm_accounts(id) ON DELETE SET NULL, clan_id BIGINT REFERENCES pgz_sport.clanovi(id) ON DELETE SET NULL, ime TEXT NOT NULL, prezime TEXT NOT NULL, funkcija TEXT, email TEXT, telefon TEXT, mobitel TEXT, napomene TEXT, owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 3) LEADS --------------------------------------------------------------- CREATE TABLE IF NOT EXISTS pgz_sport.crm_leads ( id BIGSERIAL PRIMARY KEY, ime TEXT, prezime TEXT, organizacija TEXT, email TEXT, telefon TEXT, izvor TEXT, status TEXT NOT NULL DEFAULT 'new' CHECK (status IN ('new','contacted','qualified','lost','converted')), napomene TEXT, owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, converted_account_id BIGINT REFERENCES pgz_sport.crm_accounts(id) ON DELETE SET NULL, converted_contact_id BIGINT REFERENCES pgz_sport.crm_contacts(id) ON DELETE SET NULL, converted_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 4) OPPORTUNITIES ------------------------------------------------------- CREATE TABLE IF NOT EXISTS pgz_sport.crm_opportunities ( id BIGSERIAL PRIMARY KEY, account_id BIGINT REFERENCES pgz_sport.crm_accounts(id) ON DELETE CASCADE, contact_id BIGINT REFERENCES pgz_sport.crm_contacts(id) ON DELETE SET NULL, naziv TEXT NOT NULL, type TEXT DEFAULT 'financiranje' CHECK (type IN ('financiranje','sponzorstvo','grant','natjecanje','drugo')), stage TEXT NOT NULL DEFAULT 'prospecting' CHECK (stage IN ('prospecting','qualification','proposal','negotiation','closed_won','closed_lost')), amount_eur NUMERIC(14,2), probability INT DEFAULT 20 CHECK (probability BETWEEN 0 AND 100), close_date DATE, napomene TEXT, owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- 5) ACTIVITIES ---------------------------------------------------------- CREATE TABLE IF NOT EXISTS pgz_sport.crm_activities ( id BIGSERIAL PRIMARY KEY, type TEXT NOT NULL CHECK (type IN ('call','meeting','email','task','note')), subject TEXT NOT NULL, body TEXT, account_id BIGINT REFERENCES pgz_sport.crm_accounts(id) ON DELETE CASCADE, contact_id BIGINT REFERENCES pgz_sport.crm_contacts(id) ON DELETE SET NULL, opportunity_id BIGINT REFERENCES pgz_sport.crm_opportunities(id) ON DELETE SET NULL, lead_id BIGINT REFERENCES pgz_sport.crm_leads(id) ON DELETE SET NULL, due_at TIMESTAMPTZ, completed_at TIMESTAMPTZ, owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, created_at TIMESTAMPTZ DEFAULT now() ); -- 6) CASES --------------------------------------------------------------- CREATE TABLE IF NOT EXISTS pgz_sport.crm_cases ( id BIGSERIAL PRIMARY KEY, account_id BIGINT REFERENCES pgz_sport.crm_accounts(id) ON DELETE CASCADE, contact_id BIGINT REFERENCES pgz_sport.crm_contacts(id) ON DELETE SET NULL, subject TEXT NOT NULL, description TEXT, status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open','in_progress','waiting','resolved','closed')), priority TEXT NOT NULL DEFAULT 'normal' CHECK (priority IN ('low','normal','high','urgent')), owner_user_id BIGINT REFERENCES pgz_sport.users(id) ON DELETE SET NULL, resolved_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); -- Indexes CREATE INDEX IF NOT EXISTS crm_contacts_account ON pgz_sport.crm_contacts(account_id); CREATE INDEX IF NOT EXISTS crm_opp_stage ON pgz_sport.crm_opportunities(stage); CREATE INDEX IF NOT EXISTS crm_opp_account ON pgz_sport.crm_opportunities(account_id); CREATE INDEX IF NOT EXISTS crm_opp_close ON pgz_sport.crm_opportunities(close_date); CREATE INDEX IF NOT EXISTS crm_act_account ON pgz_sport.crm_activities(account_id); CREATE INDEX IF NOT EXISTS crm_act_due ON pgz_sport.crm_activities(due_at); CREATE INDEX IF NOT EXISTS crm_act_open ON pgz_sport.crm_activities(completed_at) WHERE completed_at IS NULL; CREATE INDEX IF NOT EXISTS crm_cases_status ON pgz_sport.crm_cases(status); CREATE INDEX IF NOT EXISTS crm_leads_status ON pgz_sport.crm_leads(status); CREATE INDEX IF NOT EXISTS crm_accounts_type ON pgz_sport.crm_accounts(type); COMMIT;