Mega push vol 7 mvp lesgoooo
This commit is contained in:
258
supabase/migrations/026_department_dashboards.sql
Normal file
258
supabase/migrations/026_department_dashboards.sql
Normal file
@@ -0,0 +1,258 @@
|
||||
-- Department Dashboards: composable workspace for event departments
|
||||
-- Each department gets a dashboard with configurable module panels
|
||||
|
||||
-- ============================================================
|
||||
-- 1. Module types enum
|
||||
-- ============================================================
|
||||
CREATE TYPE module_type AS ENUM (
|
||||
'kanban',
|
||||
'files',
|
||||
'checklist',
|
||||
'notes',
|
||||
'schedule',
|
||||
'contacts'
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. Layout presets enum
|
||||
-- ============================================================
|
||||
CREATE TYPE layout_preset AS ENUM (
|
||||
'single',
|
||||
'split',
|
||||
'grid',
|
||||
'focus_sidebar',
|
||||
'custom'
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 3. Department Dashboards
|
||||
-- ============================================================
|
||||
CREATE TABLE department_dashboards (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
layout layout_preset NOT NULL DEFAULT 'split',
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now(),
|
||||
UNIQUE(department_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dept_dashboards_dept ON department_dashboards(department_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 4. Dashboard Panels (modules placed on a dashboard)
|
||||
-- ============================================================
|
||||
CREATE TABLE dashboard_panels (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
dashboard_id UUID NOT NULL REFERENCES department_dashboards(id) ON DELETE CASCADE,
|
||||
module module_type NOT NULL,
|
||||
position INT NOT NULL DEFAULT 0,
|
||||
width TEXT NOT NULL DEFAULT 'half' CHECK (width IN ('full', 'half', 'third', 'two_thirds')),
|
||||
config JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
UNIQUE(dashboard_id, position)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dashboard_panels_dashboard ON dashboard_panels(dashboard_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. Checklists (scoped to department)
|
||||
-- ============================================================
|
||||
CREATE TABLE department_checklists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL DEFAULT 'Checklist',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dept_checklists_dept ON department_checklists(department_id);
|
||||
|
||||
CREATE TABLE department_checklist_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
checklist_id UUID NOT NULL REFERENCES department_checklists(id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
is_completed BOOLEAN NOT NULL DEFAULT false,
|
||||
assigned_to UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
due_date TIMESTAMPTZ,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dept_checklist_items_checklist ON department_checklist_items(checklist_id);
|
||||
CREATE INDEX idx_dept_checklist_items_assigned ON department_checklist_items(assigned_to);
|
||||
|
||||
-- ============================================================
|
||||
-- 6. Department Notes (simple rich text notes)
|
||||
-- ============================================================
|
||||
CREATE TABLE department_notes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL DEFAULT 'Untitled Note',
|
||||
content TEXT DEFAULT '',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_dept_notes_dept ON department_notes(department_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 7. Add enabled_modules to event_departments
|
||||
-- ============================================================
|
||||
ALTER TABLE event_departments
|
||||
ADD COLUMN enabled_modules module_type[] NOT NULL DEFAULT ARRAY['kanban'::module_type, 'files'::module_type, 'checklist'::module_type];
|
||||
|
||||
-- ============================================================
|
||||
-- 8. RLS Policies
|
||||
-- ============================================================
|
||||
ALTER TABLE department_dashboards ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE dashboard_panels ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE department_checklists ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE department_checklist_items ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE department_notes ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Helper: check if user is org member for a department
|
||||
-- (department → event → org → org_members)
|
||||
|
||||
-- Department Dashboards
|
||||
CREATE POLICY "Org members can view department dashboards" ON department_dashboards FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_dashboards.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage department dashboards" ON department_dashboards FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_dashboards.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Dashboard Panels
|
||||
CREATE POLICY "Org members can view dashboard panels" ON dashboard_panels FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM department_dashboards dd
|
||||
JOIN event_departments ed ON dd.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE dd.id = dashboard_panels.dashboard_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage dashboard panels" ON dashboard_panels FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM department_dashboards dd
|
||||
JOIN event_departments ed ON dd.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE dd.id = dashboard_panels.dashboard_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Department Checklists
|
||||
CREATE POLICY "Org members can view department checklists" ON department_checklists FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_checklists.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage department checklists" ON department_checklists FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_checklists.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Department Checklist Items
|
||||
CREATE POLICY "Org members can view dept checklist items" ON department_checklist_items FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM department_checklists dc
|
||||
JOIN event_departments ed ON dc.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE dc.id = department_checklist_items.checklist_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage dept checklist items" ON department_checklist_items FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM department_checklists dc
|
||||
JOIN event_departments ed ON dc.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE dc.id = department_checklist_items.checklist_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Department Notes
|
||||
CREATE POLICY "Org members can view department notes" ON department_notes FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_notes.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage department notes" ON department_notes FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = department_notes.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- ============================================================
|
||||
-- 9. Enable realtime
|
||||
-- ============================================================
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE department_checklists;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE department_checklist_items;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE department_notes;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE dashboard_panels;
|
||||
|
||||
-- ============================================================
|
||||
-- 10. Auto-create dashboard when department is created
|
||||
-- ============================================================
|
||||
CREATE OR REPLACE FUNCTION public.create_department_dashboard()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
dash_id UUID;
|
||||
mod module_type;
|
||||
pos INT := 0;
|
||||
BEGIN
|
||||
-- Create dashboard
|
||||
INSERT INTO public.department_dashboards (department_id, layout)
|
||||
VALUES (NEW.id, 'split')
|
||||
RETURNING id INTO dash_id;
|
||||
|
||||
-- Create panels for each enabled module
|
||||
FOREACH mod IN ARRAY NEW.enabled_modules LOOP
|
||||
INSERT INTO public.dashboard_panels (dashboard_id, module, position, width)
|
||||
VALUES (dash_id, mod, pos, CASE WHEN pos = 0 THEN 'half' ELSE 'half' END);
|
||||
pos := pos + 1;
|
||||
END LOOP;
|
||||
|
||||
-- Auto-create a default checklist if checklist module is enabled
|
||||
IF 'checklist' = ANY(NEW.enabled_modules) THEN
|
||||
INSERT INTO public.department_checklists (department_id, title, sort_order)
|
||||
VALUES (NEW.id, 'General', 0);
|
||||
END IF;
|
||||
|
||||
-- Auto-create a default note if notes module is enabled
|
||||
IF 'notes' = ANY(NEW.enabled_modules) THEN
|
||||
INSERT INTO public.department_notes (department_id, title, content, sort_order)
|
||||
VALUES (NEW.id, 'Meeting Notes', '', 0);
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
CREATE TRIGGER on_department_created_setup_dashboard
|
||||
AFTER INSERT ON event_departments
|
||||
FOR EACH ROW EXECUTE FUNCTION public.create_department_dashboard();
|
||||
11
supabase/migrations/027_remove_default_seeds.sql
Normal file
11
supabase/migrations/027_remove_default_seeds.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- Remove auto-seeding of departments and roles on event creation.
|
||||
-- These will now be offered as suggestions in the UI instead.
|
||||
|
||||
-- Drop the existing trigger and function
|
||||
DROP TRIGGER IF EXISTS on_event_created_seed_defaults ON events;
|
||||
DROP FUNCTION IF EXISTS public.seed_event_defaults();
|
||||
|
||||
-- Delete all existing seeded departments and roles
|
||||
-- (cascades will clean up member-department assignments, dashboards, panels, checklists, notes)
|
||||
DELETE FROM event_departments;
|
||||
DELETE FROM event_roles;
|
||||
214
supabase/migrations/028_schedule_and_contacts.sql
Normal file
214
supabase/migrations/028_schedule_and_contacts.sql
Normal file
@@ -0,0 +1,214 @@
|
||||
-- Schedule/Timeline + Contacts/Vendor Directory for department dashboards
|
||||
-- These are self-contained modules that can be added to any department dashboard
|
||||
|
||||
-- ============================================================
|
||||
-- 1. Schedule Stages (rooms/areas where things happen)
|
||||
-- ============================================================
|
||||
CREATE TABLE schedule_stages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
color TEXT DEFAULT '#6366f1',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. Schedule Blocks (time blocks in the program)
|
||||
-- ============================================================
|
||||
CREATE TABLE schedule_blocks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
stage_id UUID REFERENCES schedule_stages(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
start_time TIMESTAMPTZ NOT NULL,
|
||||
end_time TIMESTAMPTZ NOT NULL,
|
||||
color TEXT DEFAULT '#6366f1',
|
||||
speaker TEXT,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 3. Contacts / Vendor Directory
|
||||
-- ============================================================
|
||||
CREATE TABLE department_contacts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
role TEXT,
|
||||
company TEXT,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
website TEXT,
|
||||
notes TEXT,
|
||||
category TEXT DEFAULT 'general',
|
||||
color TEXT DEFAULT '#00A3E0',
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- 4. Indexes
|
||||
-- ============================================================
|
||||
CREATE INDEX idx_schedule_stages_dept ON schedule_stages(department_id);
|
||||
CREATE INDEX idx_schedule_blocks_dept ON schedule_blocks(department_id);
|
||||
CREATE INDEX idx_schedule_blocks_stage ON schedule_blocks(stage_id);
|
||||
CREATE INDEX idx_schedule_blocks_time ON schedule_blocks(start_time, end_time);
|
||||
CREATE INDEX idx_department_contacts_dept ON department_contacts(department_id);
|
||||
CREATE INDEX idx_department_contacts_category ON department_contacts(category);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. RLS Policies
|
||||
-- ============================================================
|
||||
ALTER TABLE schedule_stages ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE schedule_blocks ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE department_contacts ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Schedule stages: org members can read, editors can write
|
||||
CREATE POLICY "schedule_stages_select" ON schedule_stages FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_stages.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_stages_insert" ON schedule_stages FOR INSERT
|
||||
WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_stages.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_stages_update" ON schedule_stages FOR UPDATE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_stages.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_stages_delete" ON schedule_stages FOR DELETE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_stages.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
-- Schedule blocks: same pattern
|
||||
CREATE POLICY "schedule_blocks_select" ON schedule_blocks FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_blocks.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_blocks_insert" ON schedule_blocks FOR INSERT
|
||||
WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_blocks.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_blocks_update" ON schedule_blocks FOR UPDATE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_blocks.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "schedule_blocks_delete" ON schedule_blocks FOR DELETE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = schedule_blocks.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
-- Contacts: same pattern
|
||||
CREATE POLICY "department_contacts_select" ON department_contacts FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = department_contacts.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "department_contacts_insert" ON department_contacts FOR INSERT
|
||||
WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = department_contacts.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "department_contacts_update" ON department_contacts FOR UPDATE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = department_contacts.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "department_contacts_delete" ON department_contacts FOR DELETE
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON e.id = ed.event_id
|
||||
JOIN org_members om ON om.org_id = e.org_id
|
||||
WHERE ed.id = department_contacts.department_id
|
||||
AND om.user_id = auth.uid()
|
||||
AND om.role IN ('owner', 'admin', 'editor')
|
||||
)
|
||||
);
|
||||
202
supabase/migrations/029_budget_and_sponsors.sql
Normal file
202
supabase/migrations/029_budget_and_sponsors.sql
Normal file
@@ -0,0 +1,202 @@
|
||||
-- Budget/Finance and Sponsors & Partners modules
|
||||
-- Adds new module types and creates tables for both
|
||||
|
||||
-- ============================================================
|
||||
-- 1. Extend module_type enum
|
||||
-- ============================================================
|
||||
ALTER TYPE module_type ADD VALUE IF NOT EXISTS 'budget';
|
||||
ALTER TYPE module_type ADD VALUE IF NOT EXISTS 'sponsors';
|
||||
|
||||
-- ============================================================
|
||||
-- 2. Budget Categories
|
||||
-- ============================================================
|
||||
CREATE TABLE budget_categories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
color TEXT DEFAULT '#6366f1',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_budget_categories_dept ON budget_categories(department_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 3. Budget Items (income or expense line items)
|
||||
-- ============================================================
|
||||
CREATE TABLE budget_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
category_id UUID REFERENCES budget_categories(id) ON DELETE SET NULL,
|
||||
description TEXT NOT NULL,
|
||||
item_type TEXT NOT NULL DEFAULT 'expense' CHECK (item_type IN ('income', 'expense')),
|
||||
planned_amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
actual_amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
notes TEXT,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_budget_items_dept ON budget_items(department_id);
|
||||
CREATE INDEX idx_budget_items_category ON budget_items(category_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 4. Sponsor Tiers (e.g. Platinum, Gold, Silver)
|
||||
-- ============================================================
|
||||
CREATE TABLE sponsor_tiers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
amount NUMERIC(12,2) DEFAULT 0,
|
||||
color TEXT DEFAULT '#F59E0B',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sponsor_tiers_dept ON sponsor_tiers(department_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. Sponsors
|
||||
-- ============================================================
|
||||
CREATE TABLE sponsors (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||
tier_id UUID REFERENCES sponsor_tiers(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
contact_name TEXT,
|
||||
contact_email TEXT,
|
||||
contact_phone TEXT,
|
||||
website TEXT,
|
||||
logo_url TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'prospect' CHECK (status IN ('prospect', 'contacted', 'confirmed', 'declined', 'active')),
|
||||
amount NUMERIC(12,2) DEFAULT 0,
|
||||
notes TEXT,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sponsors_dept ON sponsors(department_id);
|
||||
CREATE INDEX idx_sponsors_tier ON sponsors(tier_id);
|
||||
CREATE INDEX idx_sponsors_status ON sponsors(status);
|
||||
|
||||
-- ============================================================
|
||||
-- 6. Sponsor Deliverables (what we owe each sponsor)
|
||||
-- ============================================================
|
||||
CREATE TABLE sponsor_deliverables (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
sponsor_id UUID NOT NULL REFERENCES sponsors(id) ON DELETE CASCADE,
|
||||
description TEXT NOT NULL,
|
||||
is_completed BOOLEAN NOT NULL DEFAULT false,
|
||||
due_date TIMESTAMPTZ,
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sponsor_deliverables_sponsor ON sponsor_deliverables(sponsor_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 7. RLS Policies
|
||||
-- ============================================================
|
||||
ALTER TABLE budget_categories ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE budget_items ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sponsor_tiers ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sponsors ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sponsor_deliverables ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Budget Categories
|
||||
CREATE POLICY "Org members can view budget categories" ON budget_categories FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = budget_categories.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage budget categories" ON budget_categories FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = budget_categories.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Budget Items
|
||||
CREATE POLICY "Org members can view budget items" ON budget_items FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = budget_items.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage budget items" ON budget_items FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = budget_items.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Sponsor Tiers
|
||||
CREATE POLICY "Org members can view sponsor tiers" ON sponsor_tiers FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = sponsor_tiers.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage sponsor tiers" ON sponsor_tiers FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = sponsor_tiers.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Sponsors
|
||||
CREATE POLICY "Org members can view sponsors" ON sponsors FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = sponsors.department_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage sponsors" ON sponsors FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM event_departments ed
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE ed.id = sponsors.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- Sponsor Deliverables
|
||||
CREATE POLICY "Org members can view sponsor deliverables" ON sponsor_deliverables FOR SELECT
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM sponsors s
|
||||
JOIN event_departments ed ON s.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE s.id = sponsor_deliverables.sponsor_id AND om.user_id = auth.uid()
|
||||
));
|
||||
|
||||
CREATE POLICY "Editors can manage sponsor deliverables" ON sponsor_deliverables FOR ALL
|
||||
USING (EXISTS (
|
||||
SELECT 1 FROM sponsors s
|
||||
JOIN event_departments ed ON s.department_id = ed.id
|
||||
JOIN events e ON ed.event_id = e.id
|
||||
JOIN org_members om ON e.org_id = om.org_id
|
||||
WHERE s.id = sponsor_deliverables.sponsor_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
||||
));
|
||||
|
||||
-- ============================================================
|
||||
-- 8. Enable realtime
|
||||
-- ============================================================
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE budget_items;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE sponsors;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE sponsor_deliverables;
|
||||
8
supabase/migrations/030_platform_admin.sql
Normal file
8
supabase/migrations/030_platform_admin.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- Platform admin flag on profiles
|
||||
-- Only platform admins can access the /admin dashboard
|
||||
|
||||
ALTER TABLE profiles
|
||||
ADD COLUMN is_platform_admin BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- Set the initial platform admin (update this UUID to match your user)
|
||||
-- This will be set via the admin API or manually in the DB
|
||||
Reference in New Issue
Block a user