foodsnap/supabase/migrations/20260120_professional_schema.sql

190 lines
6 KiB
SQL

-- =============================================
-- MIGRATION: PROFESSIONAL SAAS MODULE
-- Description: Creates tables for Professionals, Students, Assessments, and Workouts.
-- =============================================
-- 1. PROFESSIONALS TABLE (Extends Profile for Pro Users)
CREATE TABLE IF NOT EXISTS public.professionals (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
business_name TEXT,
cref_crn TEXT, -- License number
bio TEXT,
specialties TEXT[],
logo_url TEXT,
primary_color TEXT DEFAULT '#059669', -- Brand Color
contacts JSONB DEFAULT '{}'::jsonb, -- { "whatsapp": "...", "instagram": "..." }
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Enable RLS
ALTER TABLE public.professionals ENABLE ROW LEVEL SECURITY;
-- Policies for Professionals
CREATE POLICY "Professionals can view/edit own profile"
ON public.professionals
FOR ALL
USING (auth.uid() = id)
WITH CHECK (auth.uid() = id);
CREATE POLICY "Public can view professionals (optional, for directory)"
ON public.professionals
FOR SELECT
USING (true);
-- 2. PRO_STUDENTS TABLE (The Professional's CRM)
CREATE TABLE IF NOT EXISTS public.pro_students (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
professional_id UUID REFERENCES public.professionals(id) ON DELETE CASCADE NOT NULL,
name TEXT NOT NULL,
email TEXT,
phone TEXT,
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'pending')),
-- Optional: Link to a real app user if they convert
linked_user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
goals TEXT,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Enable RLS
ALTER TABLE public.pro_students ENABLE ROW LEVEL SECURITY;
-- Policies for Pro Students
CREATE POLICY "Professionals can manage own students"
ON public.pro_students
FOR ALL
USING (auth.uid() = professional_id)
WITH CHECK (auth.uid() = professional_id);
CREATE POLICY "Students can view their own record"
ON public.pro_students
FOR SELECT
USING (auth.uid() = linked_user_id);
-- 3. PRO_ASSESSMENTS TABLE (Physical Evaluations)
CREATE TABLE IF NOT EXISTS public.pro_assessments (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
professional_id UUID REFERENCES public.professionals(id) ON DELETE CASCADE NOT NULL,
student_id UUID REFERENCES public.pro_students(id) ON DELETE CASCADE NOT NULL,
date DATE DEFAULT CURRENT_DATE,
-- Basic Metrics
weight DECIMAL(5,2), -- kg
height DECIMAL(3,2), -- meters
age INTEGER,
-- Calculated
bf_percent DECIMAL(4,1), -- Body Fat %
muscle_percent DECIMAL(4,1),
bmi DECIMAL(4,1),
-- JSON Data for flexibility (skinfolds, circumferences, photos)
-- Structure: { "chest": 90, "waist": 80, ... }
measurements JSONB DEFAULT '{}'::jsonb,
-- Structure: { "method": "pollock7", "folds": { ... } }
methodology JSONB DEFAULT '{}'::jsonb,
-- Structure: ["url1", "url2"]
photos TEXT[],
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Enable RLS
ALTER TABLE public.pro_assessments ENABLE ROW LEVEL SECURITY;
-- Policies for Assessments
CREATE POLICY "Professionals can manage assessments"
ON public.pro_assessments
FOR ALL
USING (auth.uid() = professional_id)
WITH CHECK (auth.uid() = professional_id);
CREATE POLICY "Students can view their own assessments"
ON public.pro_assessments
FOR SELECT
USING (
EXISTS (
SELECT 1 FROM public.pro_students
WHERE id = pro_assessments.student_id
AND linked_user_id = auth.uid()
)
);
-- 4. PRO_WORKOUTS TABLE (Workout Library)
CREATE TABLE IF NOT EXISTS public.pro_workouts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
professional_id UUID REFERENCES public.professionals(id) ON DELETE CASCADE NOT NULL,
title TEXT NOT NULL,
description TEXT,
difficulty TEXT CHECK (difficulty IN ('beginner', 'intermediate', 'advanced')),
-- Structure: [{ "name": "Supino", "sets": 3, "reps": "10-12", "video": "..." }]
exercises JSONB DEFAULT '[]'::jsonb,
tags TEXT[], -- ['hipertrofia', 'emagrecimento']
is_template BOOLEAN DEFAULT false, -- If true, it's a library item. If false, assigned to a specific student?
-- Actually, let's keep it simple: Workouts are templates or assigned.
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Enable RLS
ALTER TABLE public.pro_workouts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Professionals can manage own workouts"
ON public.pro_workouts
FOR ALL
USING (auth.uid() = professional_id)
WITH CHECK (auth.uid() = professional_id);
-- 5. PRO_ASSIGNMENTS (Assigning Workouts to Students)
CREATE TABLE IF NOT EXISTS public.pro_assignments (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
professional_id UUID REFERENCES public.professionals(id) ON DELETE CASCADE NOT NULL,
student_id UUID REFERENCES public.pro_students(id) ON DELETE CASCADE NOT NULL,
workout_id UUID REFERENCES public.pro_workouts(id) ON DELETE CASCADE NOT NULL,
start_date DATE DEFAULT CURRENT_DATE,
end_date DATE,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Enable RLS
ALTER TABLE public.pro_assignments ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Professionals can manage assignments"
ON public.pro_assignments
FOR ALL
USING (auth.uid() = professional_id)
WITH CHECK (auth.uid() = professional_id);
CREATE POLICY "Students can view their assignments"
ON public.pro_assignments
FOR SELECT
USING (
EXISTS (
SELECT 1 FROM public.pro_students
WHERE id = pro_assignments.student_id
AND linked_user_id = auth.uid()
)
);