nexus/migrations/20260101000011_create_project_sessions.sql
2026-01-26 11:58:04 -05:00

126 lines
4.8 KiB
SQL

-- 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);