-- rCal module schema CREATE SCHEMA IF NOT EXISTS rcal; CREATE TABLE IF NOT EXISTS rcal.users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), did TEXT UNIQUE NOT NULL, username TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS rcal.calendar_sources ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, source_type TEXT NOT NULL CHECK (source_type IN ('MANUAL','ICS','CALDAV','GOOGLE','OUTLOOK','APPLE','OBSIDIAN')), url TEXT, color TEXT DEFAULT '#6366f1', is_active BOOLEAN DEFAULT TRUE, is_visible BOOLEAN DEFAULT TRUE, sync_interval_minutes INT DEFAULT 60, last_synced_at TIMESTAMPTZ, owner_id UUID REFERENCES rcal.users(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS rcal.locations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, granularity INT NOT NULL DEFAULT 5, lat DOUBLE PRECISION, lng DOUBLE PRECISION, parent_id UUID REFERENCES rcal.locations(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS rcal.events ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL, description TEXT, start_time TIMESTAMPTZ NOT NULL, end_time TIMESTAMPTZ, all_day BOOLEAN DEFAULT FALSE, timezone TEXT DEFAULT 'UTC', rrule TEXT, status TEXT DEFAULT 'CONFIRMED' CHECK (status IN ('TENTATIVE','CONFIRMED','CANCELLED')), visibility TEXT DEFAULT 'DEFAULT' CHECK (visibility IN ('PUBLIC','PRIVATE','DEFAULT')), source_id UUID REFERENCES rcal.calendar_sources(id) ON DELETE SET NULL, location_id UUID REFERENCES rcal.locations(id) ON DELETE SET NULL, location_name TEXT, coordinates POINT, location_granularity INT, is_virtual BOOLEAN DEFAULT FALSE, virtual_url TEXT, virtual_platform TEXT, r_tool_source TEXT, r_tool_entity_id TEXT, attendees TEXT[] DEFAULT '{}', attendee_count INT DEFAULT 0, metadata JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_rcal_events_time ON rcal.events(start_time, end_time); CREATE INDEX IF NOT EXISTS idx_rcal_events_source ON rcal.events(source_id); CREATE INDEX IF NOT EXISTS idx_rcal_events_rtool ON rcal.events(r_tool_source, r_tool_entity_id); CREATE INDEX IF NOT EXISTS idx_rcal_locations_parent ON rcal.locations(parent_id); CREATE INDEX IF NOT EXISTS idx_rcal_sources_owner ON rcal.calendar_sources(owner_id);