-- Event Team Management: departments, roles, and member-department assignments -- Supports real-world event teams where members have roles and belong to departments -- ============================================================ -- 1. Event Roles: customizable per-event position types -- ============================================================ CREATE TABLE event_roles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE, name TEXT NOT NULL, color TEXT NOT NULL DEFAULT '#6366f1', sort_order INT NOT NULL DEFAULT 0, is_default BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ DEFAULT now(), UNIQUE(event_id, name) ); CREATE INDEX idx_event_roles_event ON event_roles(event_id); -- ============================================================ -- 2. Event Departments: teams/areas within an event -- ============================================================ CREATE TABLE event_departments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE, name TEXT NOT NULL, color TEXT NOT NULL DEFAULT '#00A3E0', description TEXT, sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ DEFAULT now(), UNIQUE(event_id, name) ); CREATE INDEX idx_event_departments_event ON event_departments(event_id); -- ============================================================ -- 3. Evolve event_members: add role_id FK, keep role text as fallback -- ============================================================ ALTER TABLE event_members ADD COLUMN role_id UUID REFERENCES event_roles(id) ON DELETE SET NULL, ADD COLUMN notes TEXT; -- ============================================================ -- 4. Member-Department assignments (many-to-many) -- ============================================================ CREATE TABLE event_member_departments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_member_id UUID NOT NULL REFERENCES event_members(id) ON DELETE CASCADE, department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE, assigned_at TIMESTAMPTZ DEFAULT now(), UNIQUE(event_member_id, department_id) ); CREATE INDEX idx_emd_member ON event_member_departments(event_member_id); CREATE INDEX idx_emd_department ON event_member_departments(department_id); -- ============================================================ -- 5. RLS policies -- ============================================================ ALTER TABLE event_roles ENABLE ROW LEVEL SECURITY; ALTER TABLE event_departments ENABLE ROW LEVEL SECURITY; ALTER TABLE event_member_departments ENABLE ROW LEVEL SECURITY; -- Event roles: org members can view, editors+ can manage CREATE POLICY "Org members can view event roles" ON event_roles FOR SELECT USING (EXISTS ( SELECT 1 FROM events e JOIN org_members om ON e.org_id = om.org_id WHERE e.id = event_roles.event_id AND om.user_id = auth.uid() )); CREATE POLICY "Editors can manage event roles" ON event_roles FOR ALL USING (EXISTS ( SELECT 1 FROM events e JOIN org_members om ON e.org_id = om.org_id WHERE e.id = event_roles.event_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor') )); -- Event departments: org members can view, editors+ can manage CREATE POLICY "Org members can view event departments" ON event_departments FOR SELECT USING (EXISTS ( SELECT 1 FROM events e JOIN org_members om ON e.org_id = om.org_id WHERE e.id = event_departments.event_id AND om.user_id = auth.uid() )); CREATE POLICY "Editors can manage event departments" ON event_departments FOR ALL USING (EXISTS ( SELECT 1 FROM events e JOIN org_members om ON e.org_id = om.org_id WHERE e.id = event_departments.event_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor') )); -- Member-department assignments: org members can view, editors+ can manage CREATE POLICY "Org members can view member departments" ON event_member_departments FOR SELECT USING (EXISTS ( SELECT 1 FROM event_members em JOIN events e ON em.event_id = e.id JOIN org_members om ON e.org_id = om.org_id WHERE em.id = event_member_departments.event_member_id AND om.user_id = auth.uid() )); CREATE POLICY "Editors can manage member departments" ON event_member_departments FOR ALL USING (EXISTS ( SELECT 1 FROM event_members em JOIN events e ON em.event_id = e.id JOIN org_members om ON e.org_id = om.org_id WHERE em.id = event_member_departments.event_member_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor') )); -- ============================================================ -- 6. Auto-seed default roles when a new event is created -- ============================================================ CREATE OR REPLACE FUNCTION public.seed_event_defaults() RETURNS TRIGGER AS $$ BEGIN -- Default roles (generalized from real event data) INSERT INTO public.event_roles (event_id, name, color, sort_order, is_default) VALUES (NEW.id, 'Head Organizer', '#EF4444', 0, false), (NEW.id, 'Team Lead', '#8B5CF6', 1, false), (NEW.id, 'Organizer', '#F59E0B', 2, true), (NEW.id, 'Volunteer', '#10B981', 3, false), (NEW.id, 'Sponsor', '#00A3E0', 4, false); -- Default departments (generalized from real event data) INSERT INTO public.event_departments (event_id, name, color, sort_order) VALUES (NEW.id, 'Logistics', '#F59E0B', 0), (NEW.id, 'IT & Tech', '#6366F1', 1), (NEW.id, 'Marketing', '#EC4899', 2), (NEW.id, 'Finance', '#10B981', 3), (NEW.id, 'Program', '#8B5CF6', 4), (NEW.id, 'Sponsorship', '#00A3E0', 5), (NEW.id, 'Design', '#F97316', 6), (NEW.id, 'Volunteers', '#14B8A6', 7); RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; CREATE TRIGGER on_event_created_seed_defaults AFTER INSERT ON events FOR EACH ROW EXECUTE FUNCTION public.seed_event_defaults();