-- Migration 011: Create project sessions and related media tables -- ProjectSession: active work session during a project -- During session: task completions, notes, photos, videos -- Project work session CREATE TABLE project_sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE, customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE, scope_id UUID NOT NULL REFERENCES project_scopes(id) ON DELETE RESTRICT, -- Optional location (projects may or may not have a location) account_id UUID REFERENCES accounts(id) ON DELETE SET NULL, account_address_id UUID REFERENCES account_addresses(id) ON DELETE SET NULL, date DATE NOT NULL, start TIMESTAMPTZ NOT NULL, "end" TIMESTAMPTZ, created_by_id UUID NOT NULL REFERENCES team_profiles(id) ON DELETE RESTRICT, closed_by_id UUID REFERENCES team_profiles(id) ON DELETE SET NULL, -- Constraint: end must be after start (or null for active sessions) CONSTRAINT project_session_end_gt_start_or_null CHECK ("end" IS NULL OR "end" > start) ); -- Project task completion record CREATE TABLE project_task_completions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE, task_id UUID NOT NULL REFERENCES project_scope_tasks(id) ON DELETE CASCADE, -- Optional location context account_id UUID REFERENCES accounts(id) ON DELETE SET NULL, account_address_id UUID REFERENCES account_addresses(id) ON DELETE SET NULL, completed_by_id UUID NOT NULL REFERENCES team_profiles(id) ON DELETE RESTRICT, completed_at TIMESTAMPTZ NOT NULL, notes TEXT ); -- M2M: Session to task completions CREATE TABLE project_session_completed_tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), session_id UUID NOT NULL REFERENCES project_sessions(id) ON DELETE CASCADE, task_completion_id UUID NOT NULL REFERENCES project_task_completions(id) ON DELETE CASCADE, UNIQUE (session_id, task_completion_id) ); -- Session notes CREATE TABLE project_session_notes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), session_id UUID NOT NULL REFERENCES project_sessions(id) ON DELETE CASCADE, content TEXT NOT NULL, author_id UUID REFERENCES team_profiles(id) ON DELETE SET NULL, internal BOOLEAN NOT NULL DEFAULT FALSE ); -- Session images CREATE TABLE project_session_images ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), session_id UUID NOT NULL REFERENCES project_sessions(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, image VARCHAR(100) NOT NULL, thumbnail VARCHAR(100), content_type VARCHAR(100) NOT NULL, width INTEGER NOT NULL CHECK (width >= 0), height INTEGER NOT NULL CHECK (height >= 0), uploaded_by_team_profile_id UUID REFERENCES team_profiles(id) ON DELETE SET NULL, notes TEXT NOT NULL DEFAULT '', internal BOOLEAN NOT NULL DEFAULT FALSE ); -- Session videos CREATE TABLE project_session_videos ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), session_id UUID NOT NULL REFERENCES project_sessions(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, video VARCHAR(100) NOT NULL, thumbnail VARCHAR(100), content_type VARCHAR(100) NOT NULL, width INTEGER NOT NULL CHECK (width >= 0), height INTEGER NOT NULL CHECK (height >= 0), duration_seconds INTEGER NOT NULL CHECK (duration_seconds >= 0), file_size_bytes BIGINT NOT NULL CHECK (file_size_bytes >= 0), uploaded_by_team_profile_id UUID REFERENCES team_profiles(id) ON DELETE SET NULL, notes TEXT NOT NULL DEFAULT '', internal BOOLEAN NOT NULL DEFAULT FALSE ); -- Indexes CREATE INDEX idx_project_sessions_project ON project_sessions(project_id); CREATE INDEX idx_project_sessions_date ON project_sessions(date); CREATE INDEX idx_project_sessions_created_by ON project_sessions(created_by_id); CREATE INDEX idx_project_task_completions_project ON project_task_completions(project_id); CREATE INDEX idx_project_task_completions_task ON project_task_completions(task_id); CREATE INDEX idx_project_session_notes_session ON project_session_notes(session_id); CREATE INDEX idx_project_session_images_session ON project_session_images(session_id); CREATE INDEX idx_project_session_videos_session ON project_session_videos(session_id);