diff --git a/SESSION_SUMMARY.md b/SESSION_SUMMARY.md index 209f109..d829c43 100644 --- a/SESSION_SUMMARY.md +++ b/SESSION_SUMMARY.md @@ -249,3 +249,5 @@ docker compose restart api ## Session Date Session completed with focus on MQTT debugging and enhanced logging for troubleshooting auto-recording functionality. + + diff --git a/camera-management-api/test_mqtt_simple.py b/camera-management-api/test_mqtt_simple.py index 54939e9..c43e9dc 100755 --- a/camera-management-api/test_mqtt_simple.py +++ b/camera-management-api/test_mqtt_simple.py @@ -160,3 +160,5 @@ if __name__ == "__main__": main() + + diff --git a/management-dashboard-web-app/supabase/.temp/cli-latest b/management-dashboard-web-app/supabase/.temp/cli-latest index 65f2e19..11335d2 100755 --- a/management-dashboard-web-app/supabase/.temp/cli-latest +++ b/management-dashboard-web-app/supabase/.temp/cli-latest @@ -1 +1 @@ -v2.54.10 \ No newline at end of file +v2.54.11 \ No newline at end of file diff --git a/management-dashboard-web-app/supabase/migrations/00001_extensions_and_utilities.sql b/management-dashboard-web-app/supabase/migrations/00001_extensions_and_utilities.sql new file mode 100644 index 0000000..1ac44d3 --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00001_extensions_and_utilities.sql @@ -0,0 +1,86 @@ +-- Extensions and Utility Functions +-- This migration creates required extensions and utility functions used across the database + +-- ============================================= +-- 1. EXTENSIONS +-- ============================================= + +-- Enable UUID generation +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- Enable password hashing +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +-- ============================================= +-- 2. UTILITY FUNCTIONS +-- ============================================= + +-- Function to handle updated_at timestamp +CREATE OR REPLACE FUNCTION public.handle_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Helper function to get current user's roles +CREATE OR REPLACE FUNCTION public.get_user_roles() +RETURNS TEXT[] AS $$ +BEGIN + RETURN ARRAY( + SELECT r.name + FROM public.user_roles ur + JOIN public.roles r ON ur.role_id = r.id + WHERE ur.user_id = auth.uid() + ); +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + +-- Helper function to get current user's first role (for backward compatibility) +CREATE OR REPLACE FUNCTION public.get_user_role() +RETURNS TEXT AS $$ +BEGIN + -- Return the first role found (for backward compatibility) + RETURN ( + SELECT r.name + FROM public.user_roles ur + JOIN public.roles r ON ur.role_id = r.id + WHERE ur.user_id = auth.uid() + LIMIT 1 + ); +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + +-- Helper function to check if user is admin +CREATE OR REPLACE FUNCTION public.is_admin() +RETURNS BOOLEAN AS $$ +BEGIN + RETURN 'admin' = ANY(public.get_user_roles()); +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + +-- Helper function to check if user has specific role +CREATE OR REPLACE FUNCTION public.has_role(role_name TEXT) +RETURNS BOOLEAN AS $$ +BEGIN + RETURN role_name = ANY(public.get_user_roles()); +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + +-- Helper function to check if user can manage experiments +CREATE OR REPLACE FUNCTION public.can_manage_experiments() +RETURNS BOOLEAN AS $$ +BEGIN + RETURN EXISTS ( + SELECT 1 + FROM public.user_roles ur + JOIN public.roles r ON ur.role_id = r.id + WHERE ur.user_id = auth.uid() + AND r.name IN ('admin', 'conductor') + ); +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + + + diff --git a/management-dashboard-web-app/supabase/migrations/20250101000001_user_management.sql b/management-dashboard-web-app/supabase/migrations/00002_users_and_roles.sql similarity index 65% rename from management-dashboard-web-app/supabase/migrations/20250101000001_user_management.sql rename to management-dashboard-web-app/supabase/migrations/00002_users_and_roles.sql index 9c68f9e..128b438 100644 --- a/management-dashboard-web-app/supabase/migrations/20250101000001_user_management.sql +++ b/management-dashboard-web-app/supabase/migrations/00002_users_and_roles.sql @@ -1,21 +1,10 @@ --- User Management and Authentication --- This migration creates user-related tables, roles, and authentication structures +-- Users and Roles +-- This migration creates user-related tables with clean separation -- ============================================= --- 1. EXTENSIONS +-- 1. ROLES TABLE -- ============================================= --- Enable UUID generation -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; - --- Enable password hashing -CREATE EXTENSION IF NOT EXISTS "pgcrypto"; - --- ============================================= --- 2. USER MANAGEMENT --- ============================================= - --- Create roles table CREATE TABLE IF NOT EXISTS public.roles ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name TEXT NOT NULL UNIQUE, @@ -24,7 +13,10 @@ CREATE TABLE IF NOT EXISTS public.roles ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); --- Create user profiles table +-- ============================================= +-- 2. USER PROFILES TABLE +-- ============================================= + CREATE TABLE IF NOT EXISTS public.user_profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, email TEXT NOT NULL UNIQUE, @@ -35,7 +27,10 @@ CREATE TABLE IF NOT EXISTS public.user_profiles ( updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); --- Create user roles junction table +-- ============================================= +-- 3. USER ROLES JUNCTION TABLE +-- ============================================= + CREATE TABLE IF NOT EXISTS public.user_roles ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, @@ -45,77 +40,6 @@ CREATE TABLE IF NOT EXISTS public.user_roles ( UNIQUE(user_id, role_id) ); --- ============================================= --- 3. UTILITY FUNCTIONS --- ============================================= - --- Function to handle updated_at timestamp -CREATE OR REPLACE FUNCTION public.handle_updated_at() -RETURNS TRIGGER AS $$ -BEGIN - NEW.updated_at = NOW(); - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Helper function to get current user's roles -CREATE OR REPLACE FUNCTION public.get_user_roles() -RETURNS TEXT[] AS $$ -BEGIN - RETURN ARRAY( - SELECT r.name - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to get current user's first role (for backward compatibility) -CREATE OR REPLACE FUNCTION public.get_user_role() -RETURNS TEXT AS $$ -BEGIN - -- Return the first role found (for backward compatibility) - RETURN ( - SELECT r.name - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - LIMIT 1 - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user is admin -CREATE OR REPLACE FUNCTION public.is_admin() -RETURNS BOOLEAN AS $$ -BEGIN - RETURN 'admin' = ANY(public.get_user_roles()); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user has specific role -CREATE OR REPLACE FUNCTION public.has_role(role_name TEXT) -RETURNS BOOLEAN AS $$ -BEGIN - RETURN role_name = ANY(public.get_user_roles()); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user can manage experiments -CREATE OR REPLACE FUNCTION public.can_manage_experiments() -RETURNS BOOLEAN AS $$ -BEGIN - RETURN EXISTS ( - SELECT 1 - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - AND r.name IN ('admin', 'conductor') - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - -- ============================================= -- 4. INDEXES FOR PERFORMANCE -- ============================================= @@ -134,6 +58,12 @@ CREATE TRIGGER set_updated_at_user_profiles FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at(); +-- Create trigger for updated_at on roles +CREATE TRIGGER set_updated_at_roles + BEFORE UPDATE ON public.roles + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + -- ============================================= -- 6. GRANT PERMISSIONS -- ============================================= @@ -186,4 +116,3 @@ CREATE POLICY "User roles are deletable by authenticated users" ON public.user_r - diff --git a/management-dashboard-web-app/supabase/migrations/00003_machine_types.sql b/management-dashboard-web-app/supabase/migrations/00003_machine_types.sql new file mode 100644 index 0000000..ccc67c6 --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00003_machine_types.sql @@ -0,0 +1,62 @@ +-- Machine Types +-- This migration creates the machine types table + +-- ============================================= +-- 1. MACHINE TYPES TABLE +-- ============================================= + +CREATE TABLE IF NOT EXISTS public.machine_types ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + name TEXT NOT NULL UNIQUE, + description TEXT, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + created_by UUID NOT NULL REFERENCES public.user_profiles(id) +); + +-- ============================================= +-- 2. INDEXES FOR PERFORMANCE +-- ============================================= + +CREATE INDEX IF NOT EXISTS idx_machine_types_name ON public.machine_types(name); + +-- ============================================= +-- 3. TRIGGERS +-- ============================================= + +-- Create trigger for updated_at on machine_types +CREATE TRIGGER set_updated_at_machine_types + BEFORE UPDATE ON public.machine_types + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + +-- ============================================= +-- 4. GRANT PERMISSIONS +-- ============================================= + +GRANT ALL ON public.machine_types TO authenticated; + +-- ============================================= +-- 5. ENABLE ROW LEVEL SECURITY +-- ============================================= + +ALTER TABLE public.machine_types ENABLE ROW LEVEL SECURITY; + +-- ============================================= +-- 6. CREATE RLS POLICIES +-- ============================================= + +CREATE POLICY "Machine types are viewable by authenticated users" ON public.machine_types + FOR SELECT USING (auth.role() = 'authenticated'); + +CREATE POLICY "Machine types are insertable by authenticated users" ON public.machine_types + FOR INSERT WITH CHECK (auth.role() = 'authenticated'); + +CREATE POLICY "Machine types are updatable by authenticated users" ON public.machine_types + FOR UPDATE USING (auth.role() = 'authenticated'); + +CREATE POLICY "Machine types are deletable by authenticated users" ON public.machine_types + FOR DELETE USING (auth.role() = 'authenticated'); + + + diff --git a/management-dashboard-web-app/supabase/migrations/20250101000002_machine_types_and_phases.sql b/management-dashboard-web-app/supabase/migrations/00004_experiment_phases.sql similarity index 60% rename from management-dashboard-web-app/supabase/migrations/20250101000002_machine_types_and_phases.sql rename to management-dashboard-web-app/supabase/migrations/00004_experiment_phases.sql index 9b7aed8..6a734e8 100644 --- a/management-dashboard-web-app/supabase/migrations/20250101000002_machine_types_and_phases.sql +++ b/management-dashboard-web-app/supabase/migrations/00004_experiment_phases.sql @@ -1,25 +1,10 @@ --- Machine Types and Experiment Phases --- This migration creates machine types and experiment phase definitions +-- Experiment Phases +-- This migration creates the experiment phases table -- ============================================= --- 1. MACHINE TYPES +-- 1. EXPERIMENT PHASES TABLE -- ============================================= --- Create machine types table -CREATE TABLE IF NOT EXISTS public.machine_types ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - name TEXT NOT NULL UNIQUE, - description TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id) -); - --- ============================================= --- 2. EXPERIMENT PHASES --- ============================================= - --- Create experiment phases table CREATE TABLE IF NOT EXISTS public.experiment_phases ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name TEXT NOT NULL UNIQUE, @@ -43,23 +28,16 @@ CREATE TABLE IF NOT EXISTS public.experiment_phases ( ); -- ============================================= --- 3. INDEXES FOR PERFORMANCE +-- 2. INDEXES FOR PERFORMANCE -- ============================================= -CREATE INDEX IF NOT EXISTS idx_machine_types_name ON public.machine_types(name); CREATE INDEX IF NOT EXISTS idx_experiment_phases_name ON public.experiment_phases(name); CREATE INDEX IF NOT EXISTS idx_experiment_phases_cracking_machine_type_id ON public.experiment_phases(cracking_machine_type_id); -- ============================================= --- 4. TRIGGERS +-- 3. TRIGGERS -- ============================================= --- Create trigger for updated_at on machine_types -CREATE TRIGGER set_updated_at_machine_types - BEFORE UPDATE ON public.machine_types - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -- Create trigger for updated_at on experiment_phases CREATE TRIGGER set_updated_at_experiment_phases BEFORE UPDATE ON public.experiment_phases @@ -67,37 +45,21 @@ CREATE TRIGGER set_updated_at_experiment_phases EXECUTE FUNCTION public.handle_updated_at(); -- ============================================= --- 5. GRANT PERMISSIONS +-- 4. GRANT PERMISSIONS -- ============================================= -GRANT ALL ON public.machine_types TO authenticated; GRANT ALL ON public.experiment_phases TO authenticated; -- ============================================= --- 6. ENABLE ROW LEVEL SECURITY +-- 5. ENABLE ROW LEVEL SECURITY -- ============================================= -ALTER TABLE public.machine_types ENABLE ROW LEVEL SECURITY; ALTER TABLE public.experiment_phases ENABLE ROW LEVEL SECURITY; -- ============================================= --- 7. CREATE RLS POLICIES +-- 6. CREATE RLS POLICIES -- ============================================= --- Create RLS policies for machine_types -CREATE POLICY "Machine types are viewable by authenticated users" ON public.machine_types - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Machine types are insertable by authenticated users" ON public.machine_types - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Machine types are updatable by authenticated users" ON public.machine_types - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Machine types are deletable by authenticated users" ON public.machine_types - FOR DELETE USING (auth.role() = 'authenticated'); - --- Create RLS policies for experiment_phases CREATE POLICY "Experiment phases are viewable by authenticated users" ON public.experiment_phases FOR SELECT USING (auth.role() = 'authenticated'); @@ -112,4 +74,3 @@ CREATE POLICY "Experiment phases are deletable by authenticated users" ON public - diff --git a/management-dashboard-web-app/supabase/migrations/00005_experiments.sql b/management-dashboard-web-app/supabase/migrations/00005_experiments.sql new file mode 100644 index 0000000..1b57373 --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00005_experiments.sql @@ -0,0 +1,67 @@ +-- Experiments +-- This migration creates the experiments table + +-- ============================================= +-- 1. EXPERIMENTS TABLE +-- ============================================= + +CREATE TABLE IF NOT EXISTS public.experiments ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + experiment_number INTEGER NOT NULL, + reps_required INTEGER NOT NULL CHECK (reps_required > 0), + weight_per_repetition_lbs DOUBLE PRECISION NOT NULL DEFAULT 5.0 CHECK (weight_per_repetition_lbs > 0), + results_status TEXT NOT NULL DEFAULT 'valid' CHECK (results_status IN ('valid', 'invalid')), + completion_status BOOLEAN NOT NULL DEFAULT false, + phase_id UUID NOT NULL REFERENCES public.experiment_phases(id) ON DELETE SET NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + created_by UUID NOT NULL REFERENCES public.user_profiles(id) +); + +-- ============================================= +-- 2. INDEXES FOR PERFORMANCE +-- ============================================= + +CREATE INDEX IF NOT EXISTS idx_experiments_phase_id ON public.experiments(phase_id); +CREATE INDEX IF NOT EXISTS idx_experiments_experiment_number ON public.experiments(experiment_number); +CREATE INDEX IF NOT EXISTS idx_experiments_created_by ON public.experiments(created_by); +CREATE INDEX IF NOT EXISTS idx_experiments_id ON public.experiments(id); + +-- ============================================= +-- 3. TRIGGERS +-- ============================================= + +-- Create trigger for updated_at on experiments +CREATE TRIGGER set_updated_at_experiments + BEFORE UPDATE ON public.experiments + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + +-- ============================================= +-- 4. GRANT PERMISSIONS +-- ============================================= + +GRANT ALL ON public.experiments TO authenticated; + +-- ============================================= +-- 5. ENABLE ROW LEVEL SECURITY +-- ============================================= + +ALTER TABLE public.experiments ENABLE ROW LEVEL SECURITY; + +-- ============================================= +-- 6. CREATE RLS POLICIES +-- ============================================= + +CREATE POLICY "Experiments are viewable by authenticated users" ON public.experiments + FOR SELECT USING (auth.role() = 'authenticated'); + +CREATE POLICY "Experiments are insertable by authenticated users" ON public.experiments + FOR INSERT WITH CHECK (auth.role() = 'authenticated'); + +CREATE POLICY "Experiments are updatable by authenticated users" ON public.experiments + FOR UPDATE USING (auth.role() = 'authenticated'); + +CREATE POLICY "Experiments are deletable by authenticated users" ON public.experiments + FOR DELETE USING (auth.role() = 'authenticated'); + diff --git a/management-dashboard-web-app/supabase/migrations/00006_experiment_repetitions.sql b/management-dashboard-web-app/supabase/migrations/00006_experiment_repetitions.sql new file mode 100644 index 0000000..e5ed5cf --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00006_experiment_repetitions.sql @@ -0,0 +1,67 @@ +-- Experiment Repetitions +-- This migration creates the experiment repetitions table + +-- ============================================= +-- 1. EXPERIMENT REPETITIONS TABLE +-- ============================================= + +CREATE TABLE IF NOT EXISTS public.experiment_repetitions ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, + repetition_number INTEGER NOT NULL CHECK (repetition_number > 0), + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed', 'cancelled')), + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + created_by UUID NOT NULL REFERENCES public.user_profiles(id), + + -- Ensure unique repetition numbers per experiment + UNIQUE(experiment_id, repetition_number) +); + +-- ============================================= +-- 2. INDEXES FOR PERFORMANCE +-- ============================================= + +CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_experiment_id ON public.experiment_repetitions(experiment_id); +CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_created_by ON public.experiment_repetitions(created_by); + +-- ============================================= +-- 3. TRIGGERS +-- ============================================= + +-- Create trigger for updated_at on experiment_repetitions +CREATE TRIGGER set_updated_at_experiment_repetitions + BEFORE UPDATE ON public.experiment_repetitions + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + +-- ============================================= +-- 4. GRANT PERMISSIONS +-- ============================================= + +GRANT ALL ON public.experiment_repetitions TO authenticated; + +-- ============================================= +-- 5. ENABLE ROW LEVEL SECURITY +-- ============================================= + +ALTER TABLE public.experiment_repetitions ENABLE ROW LEVEL SECURITY; + +-- ============================================= +-- 6. CREATE RLS POLICIES +-- ============================================= + +CREATE POLICY "Experiment repetitions are viewable by authenticated users" ON public.experiment_repetitions + FOR SELECT USING (auth.role() = 'authenticated'); + +CREATE POLICY "Experiment repetitions are insertable by authenticated users" ON public.experiment_repetitions + FOR INSERT WITH CHECK (auth.role() = 'authenticated'); + +CREATE POLICY "Experiment repetitions are updatable by authenticated users" ON public.experiment_repetitions + FOR UPDATE USING (auth.role() = 'authenticated'); + +CREATE POLICY "Experiment repetitions are deletable by authenticated users" ON public.experiment_repetitions + FOR DELETE USING (auth.role() = 'authenticated'); + + + diff --git a/management-dashboard-web-app/supabase/migrations/00007_cracker_parameters.sql b/management-dashboard-web-app/supabase/migrations/00007_cracker_parameters.sql new file mode 100644 index 0000000..6657b59 --- /dev/null +++ b/management-dashboard-web-app/supabase/migrations/00007_cracker_parameters.sql @@ -0,0 +1,88 @@ +-- Cracker Parameters +-- This migration creates machine-specific parameter tables (must be created before cracking table) + +-- ============================================= +-- 1. JC CRACKER PARAMETERS TABLE +-- ============================================= + +CREATE TABLE IF NOT EXISTS public.jc_cracker_parameters ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + plate_contact_frequency_hz DOUBLE PRECISION NOT NULL CHECK (plate_contact_frequency_hz > 0), + throughput_rate_pecans_sec DOUBLE PRECISION NOT NULL CHECK (throughput_rate_pecans_sec > 0), + crush_amount_in DOUBLE PRECISION NOT NULL CHECK (crush_amount_in >= 0), + entry_exit_height_diff_in DOUBLE PRECISION NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- ============================================= +-- 2. MEYER CRACKER PARAMETERS TABLE +-- ============================================= + +CREATE TABLE IF NOT EXISTS public.meyer_cracker_parameters ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + motor_speed_hz DOUBLE PRECISION NOT NULL CHECK (motor_speed_hz > 0), + jig_displacement_inches DOUBLE PRECISION NOT NULL, + spring_stiffness_nm DOUBLE PRECISION NOT NULL CHECK (spring_stiffness_nm > 0), + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- ============================================= +-- 3. TRIGGERS +-- ============================================= + +CREATE TRIGGER set_updated_at_jc_cracker_parameters + BEFORE UPDATE ON public.jc_cracker_parameters + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + +CREATE TRIGGER set_updated_at_meyer_cracker_parameters + BEFORE UPDATE ON public.meyer_cracker_parameters + FOR EACH ROW + EXECUTE FUNCTION public.handle_updated_at(); + +-- ============================================= +-- 4. GRANT PERMISSIONS +-- ============================================= + +GRANT ALL ON public.jc_cracker_parameters TO authenticated; +GRANT ALL ON public.meyer_cracker_parameters TO authenticated; + +-- ============================================= +-- 5. ENABLE ROW LEVEL SECURITY +-- ============================================= + +ALTER TABLE public.jc_cracker_parameters ENABLE ROW LEVEL SECURITY; +ALTER TABLE public.meyer_cracker_parameters ENABLE ROW LEVEL SECURITY; + +-- ============================================= +-- 6. CREATE RLS POLICIES +-- ============================================= + +CREATE POLICY "JC Cracker parameters are viewable by authenticated users" ON public.jc_cracker_parameters + FOR SELECT USING (auth.role() = 'authenticated'); + +CREATE POLICY "JC Cracker parameters are insertable by authenticated users" ON public.jc_cracker_parameters + FOR INSERT WITH CHECK (auth.role() = 'authenticated'); + +CREATE POLICY "JC Cracker parameters are updatable by authenticated users" ON public.jc_cracker_parameters + FOR UPDATE USING (auth.role() = 'authenticated'); + +CREATE POLICY "JC Cracker parameters are deletable by authenticated users" ON public.jc_cracker_parameters + FOR DELETE USING (auth.role() = 'authenticated'); + +CREATE POLICY "Meyer Cracker parameters are viewable by authenticated users" ON public.meyer_cracker_parameters + FOR SELECT USING (auth.role() = 'authenticated'); + +CREATE POLICY "Meyer Cracker parameters are insertable by authenticated users" ON public.meyer_cracker_parameters + FOR INSERT WITH CHECK (auth.role() = 'authenticated'); + +CREATE POLICY "Meyer Cracker parameters are updatable by authenticated users" ON public.meyer_cracker_parameters + FOR UPDATE USING (auth.role() = 'authenticated'); + +CREATE POLICY "Meyer Cracker parameters are deletable by authenticated users" ON public.meyer_cracker_parameters + FOR DELETE USING (auth.role() = 'authenticated'); + + + diff --git a/management-dashboard-web-app/supabase/migrations/20250101000004_data_entry_tables.sql b/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql similarity index 71% rename from management-dashboard-web-app/supabase/migrations/20250101000004_data_entry_tables.sql rename to management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql index e439c0a..e7633cb 100644 --- a/management-dashboard-web-app/supabase/migrations/20250101000004_data_entry_tables.sql +++ b/management-dashboard-web-app/supabase/migrations/00008_phase_data_tables.sql @@ -1,18 +1,17 @@ --- Data Entry Tables --- This migration creates the phase-specific data entry tables (soaking, airdrying, cracking, shelling) +-- Phase Data Tables +-- This migration creates phase-specific data entry tables (soaking, airdrying, cracking, shelling) -- ============================================= -- 1. SOAKING TABLE -- ============================================= --- Create soaking table CREATE TABLE IF NOT EXISTS public.soaking ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, - soaking_duration_hours DOUBLE PRECISION NOT NULL CHECK (soaking_duration_hours > 0), + soaking_duration_minutes INTEGER NOT NULL CHECK (soaking_duration_minutes > 0), scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_end_time TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), @@ -28,7 +27,6 @@ CREATE TABLE IF NOT EXISTS public.soaking ( -- 2. AIRDRYING TABLE -- ============================================= --- Create airdrying table CREATE TABLE IF NOT EXISTS public.airdrying ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, @@ -51,14 +49,11 @@ CREATE TABLE IF NOT EXISTS public.airdrying ( -- 3. CRACKING TABLE -- ============================================= --- Create cracking table CREATE TABLE IF NOT EXISTS public.cracking ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, machine_type_id UUID NOT NULL REFERENCES public.machine_types(id), - jc_cracker_parameters_id UUID REFERENCES public.jc_cracker_parameters(id) ON DELETE SET NULL, - meyer_cracker_parameters_id UUID REFERENCES public.meyer_cracker_parameters(id) ON DELETE SET NULL, scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, actual_start_time TIMESTAMP WITH TIME ZONE, actual_end_time TIMESTAMP WITH TIME ZONE, @@ -68,19 +63,13 @@ CREATE TABLE IF NOT EXISTS public.cracking ( -- Ensure only one cracking per experiment or repetition CONSTRAINT unique_cracking_per_experiment UNIQUE (experiment_id), - CONSTRAINT unique_cracking_per_repetition UNIQUE (repetition_id), - -- Ensure exactly one cracker parameter set is specified - CONSTRAINT check_exactly_one_cracker_params CHECK ( - (jc_cracker_parameters_id IS NOT NULL AND meyer_cracker_parameters_id IS NULL) OR - (jc_cracker_parameters_id IS NULL AND meyer_cracker_parameters_id IS NOT NULL) - ) + CONSTRAINT unique_cracking_per_repetition UNIQUE (repetition_id) ); -- ============================================= -- 4. SHELLING TABLE -- ============================================= --- Create shelling table CREATE TABLE IF NOT EXISTS public.shelling ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, @@ -98,38 +87,7 @@ CREATE TABLE IF NOT EXISTS public.shelling ( ); -- ============================================= --- 5. MACHINE-SPECIFIC PARAMETER TABLES --- ============================================= - --- Create JC Cracker parameters table -CREATE TABLE IF NOT EXISTS public.jc_cracker_parameters ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - plate_contact_frequency_hz DOUBLE PRECISION NOT NULL CHECK (plate_contact_frequency_hz > 0), - throughput_rate_pecans_sec DOUBLE PRECISION NOT NULL CHECK (throughput_rate_pecans_sec > 0), - crush_amount_in DOUBLE PRECISION NOT NULL CHECK (crush_amount_in >= 0), - entry_exit_height_diff_in DOUBLE PRECISION NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -); - --- Create Meyer Cracker parameters table -CREATE TABLE IF NOT EXISTS public.meyer_cracker_parameters ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - motor_speed_hz DOUBLE PRECISION NOT NULL CHECK (motor_speed_hz > 0), - jig_displacement_inches DOUBLE PRECISION NOT NULL, - spring_stiffness_nm DOUBLE PRECISION NOT NULL CHECK (spring_stiffness_nm > 0), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -); - --- ============================================= --- 6. EXPERIMENTS TABLE DOES NOT NEED FOREIGN KEYS TO PHASE TABLES --- ============================================= --- Phase tables reference experiments via experiment_id --- Experiments inherit phase configuration from experiment_phases via phase_id - --- ============================================= --- 7. INDEXES FOR PERFORMANCE +-- 5. INDEXES FOR PERFORMANCE -- ============================================= -- Create indexes for experiment_id references @@ -154,25 +112,18 @@ CREATE INDEX IF NOT EXISTS idx_cracking_created_by ON public.cracking(created_by CREATE INDEX IF NOT EXISTS idx_shelling_created_by ON public.shelling(created_by); -- ============================================= --- 8. TRIGGERS FOR AUTOMATIC TIMESTAMP CALCULATIONS +-- 6. TRIGGER FUNCTIONS FOR AUTOMATIC TIMESTAMP CALCULATIONS -- ============================================= -- Function to calculate scheduled end time for soaking CREATE OR REPLACE FUNCTION calculate_soaking_scheduled_end_time() RETURNS TRIGGER AS $$ BEGIN - NEW.scheduled_end_time = NEW.scheduled_start_time + (NEW.soaking_duration_hours || ' hours')::INTERVAL; + NEW.scheduled_end_time = NEW.scheduled_start_time + (NEW.soaking_duration_minutes || ' minutes')::INTERVAL; RETURN NEW; END; $$ LANGUAGE plpgsql; --- Trigger for soaking scheduled end time -DROP TRIGGER IF EXISTS trigger_calculate_soaking_scheduled_end_time ON public.soaking; -CREATE TRIGGER trigger_calculate_soaking_scheduled_end_time - BEFORE INSERT OR UPDATE ON public.soaking - FOR EACH ROW - EXECUTE FUNCTION calculate_soaking_scheduled_end_time(); - -- Function to calculate scheduled end time for airdrying CREATE OR REPLACE FUNCTION calculate_airdrying_scheduled_end_time() RETURNS TRIGGER AS $$ @@ -182,13 +133,6 @@ BEGIN END; $$ LANGUAGE plpgsql; --- Trigger for airdrying scheduled end time -DROP TRIGGER IF EXISTS trigger_calculate_airdrying_scheduled_end_time ON public.airdrying; -CREATE TRIGGER trigger_calculate_airdrying_scheduled_end_time - BEFORE INSERT OR UPDATE ON public.airdrying - FOR EACH ROW - EXECUTE FUNCTION calculate_airdrying_scheduled_end_time(); - -- Function to set airdrying scheduled start time based on soaking end time CREATE OR REPLACE FUNCTION set_airdrying_scheduled_start_time() RETURNS TRIGGER AS $$ @@ -205,13 +149,6 @@ BEGIN END; $$ LANGUAGE plpgsql; --- Trigger for airdrying scheduled start time -DROP TRIGGER IF EXISTS trigger_set_airdrying_scheduled_start_time ON public.airdrying; -CREATE TRIGGER trigger_set_airdrying_scheduled_start_time - BEFORE INSERT ON public.airdrying - FOR EACH ROW - EXECUTE FUNCTION set_airdrying_scheduled_start_time(); - -- Function to set cracking scheduled start time based on airdrying end time CREATE OR REPLACE FUNCTION set_cracking_scheduled_start_time() RETURNS TRIGGER AS $$ @@ -228,18 +165,36 @@ BEGIN END; $$ LANGUAGE plpgsql; --- Trigger for cracking scheduled start time +-- ============================================= +-- 7. TRIGGERS +-- ============================================= + +-- Triggers for automatic timestamp calculations +DROP TRIGGER IF EXISTS trigger_calculate_soaking_scheduled_end_time ON public.soaking; +CREATE TRIGGER trigger_calculate_soaking_scheduled_end_time + BEFORE INSERT OR UPDATE ON public.soaking + FOR EACH ROW + EXECUTE FUNCTION calculate_soaking_scheduled_end_time(); + +DROP TRIGGER IF EXISTS trigger_calculate_airdrying_scheduled_end_time ON public.airdrying; +CREATE TRIGGER trigger_calculate_airdrying_scheduled_end_time + BEFORE INSERT OR UPDATE ON public.airdrying + FOR EACH ROW + EXECUTE FUNCTION calculate_airdrying_scheduled_end_time(); + +DROP TRIGGER IF EXISTS trigger_set_airdrying_scheduled_start_time ON public.airdrying; +CREATE TRIGGER trigger_set_airdrying_scheduled_start_time + BEFORE INSERT ON public.airdrying + FOR EACH ROW + EXECUTE FUNCTION set_airdrying_scheduled_start_time(); + DROP TRIGGER IF EXISTS trigger_set_cracking_scheduled_start_time ON public.cracking; CREATE TRIGGER trigger_set_cracking_scheduled_start_time BEFORE INSERT ON public.cracking FOR EACH ROW EXECUTE FUNCTION set_cracking_scheduled_start_time(); --- ============================================= --- 9. TRIGGERS FOR UPDATED_AT --- ============================================= - --- Create triggers for updated_at on all phase tables +-- Triggers for updated_at on all phase tables CREATE TRIGGER set_updated_at_soaking BEFORE UPDATE ON public.soaking FOR EACH ROW @@ -260,40 +215,26 @@ CREATE TRIGGER set_updated_at_shelling FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at(); -CREATE TRIGGER set_updated_at_jc_cracker_parameters - BEFORE UPDATE ON public.jc_cracker_parameters - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_meyer_cracker_parameters - BEFORE UPDATE ON public.meyer_cracker_parameters - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -- ============================================= --- 10. GRANT PERMISSIONS +-- 8. GRANT PERMISSIONS -- ============================================= GRANT ALL ON public.soaking TO authenticated; GRANT ALL ON public.airdrying TO authenticated; GRANT ALL ON public.cracking TO authenticated; GRANT ALL ON public.shelling TO authenticated; -GRANT ALL ON public.jc_cracker_parameters TO authenticated; -GRANT ALL ON public.meyer_cracker_parameters TO authenticated; -- ============================================= --- 11. ENABLE ROW LEVEL SECURITY +-- 9. ENABLE ROW LEVEL SECURITY -- ============================================= ALTER TABLE public.soaking ENABLE ROW LEVEL SECURITY; ALTER TABLE public.airdrying ENABLE ROW LEVEL SECURITY; ALTER TABLE public.cracking ENABLE ROW LEVEL SECURITY; ALTER TABLE public.shelling ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.jc_cracker_parameters ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.meyer_cracker_parameters ENABLE ROW LEVEL SECURITY; -- ============================================= --- 12. CREATE RLS POLICIES +-- 10. CREATE RLS POLICIES -- ============================================= -- Create RLS policies for phase tables @@ -345,31 +286,3 @@ CREATE POLICY "Shelling data is updatable by authenticated users" ON public.shel CREATE POLICY "Shelling data is deletable by authenticated users" ON public.shelling FOR DELETE USING (auth.role() = 'authenticated'); --- RLS policies for machine parameter tables -CREATE POLICY "JC Cracker parameters are viewable by authenticated users" ON public.jc_cracker_parameters - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are insertable by authenticated users" ON public.jc_cracker_parameters - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are updatable by authenticated users" ON public.jc_cracker_parameters - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are deletable by authenticated users" ON public.jc_cracker_parameters - FOR DELETE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are viewable by authenticated users" ON public.meyer_cracker_parameters - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are insertable by authenticated users" ON public.meyer_cracker_parameters - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are updatable by authenticated users" ON public.meyer_cracker_parameters - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are deletable by authenticated users" ON public.meyer_cracker_parameters - FOR DELETE USING (auth.role() = 'authenticated'); - - - - diff --git a/management-dashboard-web-app/supabase/migrations/20250101000005_conductor_availability_and_scheduling.sql b/management-dashboard-web-app/supabase/migrations/00009_conductor_availability.sql similarity index 52% rename from management-dashboard-web-app/supabase/migrations/20250101000005_conductor_availability_and_scheduling.sql rename to management-dashboard-web-app/supabase/migrations/00009_conductor_availability.sql index f483529..70a4a04 100644 --- a/management-dashboard-web-app/supabase/migrations/20250101000005_conductor_availability_and_scheduling.sql +++ b/management-dashboard-web-app/supabase/migrations/00009_conductor_availability.sql @@ -1,11 +1,10 @@ --- Conductor Availability and Scheduling --- This migration creates tables for conductor availability management and experiment scheduling +-- Conductor Availability +-- This migration creates the conductor availability table -- ============================================= -- 1. CONDUCTOR AVAILABILITY TABLE -- ============================================= --- Create conductor_availability table CREATE TABLE IF NOT EXISTS public.conductor_availability ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, @@ -25,41 +24,9 @@ CREATE TABLE IF NOT EXISTS public.conductor_availability ( ); -- ============================================= --- 2. EXPERIMENT PHASE ASSIGNMENTS TABLE +-- 2. INDEXES FOR PERFORMANCE -- ============================================= --- Create experiment_phase_assignments table for scheduling conductors to experiment phases -CREATE TABLE IF NOT EXISTS public.experiment_phase_assignments ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_number INTEGER NOT NULL, - experiment_phase_id UUID NOT NULL, - repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - conductor_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, - phase_name TEXT NOT NULL CHECK (phase_name IN ('pre-soaking', 'air-drying', 'cracking', 'shelling')), - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL, - status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'in-progress', 'completed', 'cancelled')), - notes TEXT, -- Optional notes about the assignment - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Foreign key to experiments using composite key - FOREIGN KEY (experiment_number, experiment_phase_id) - REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE, - - -- Ensure scheduled_end_time is after scheduled_start_time - CONSTRAINT valid_scheduled_time_range CHECK (scheduled_end_time > scheduled_start_time), - - -- Ensure unique assignment per conductor per phase per repetition - CONSTRAINT unique_conductor_phase_assignment UNIQUE (repetition_id, conductor_id, phase_name) -); - --- ============================================= --- 3. INDEXES FOR PERFORMANCE --- ============================================= - --- Conductor availability indexes CREATE INDEX IF NOT EXISTS idx_conductor_availability_user_id ON public.conductor_availability(user_id); CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_from ON public.conductor_availability(available_from); CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_to ON public.conductor_availability(available_to); @@ -67,17 +34,8 @@ CREATE INDEX IF NOT EXISTS idx_conductor_availability_status ON public.conductor CREATE INDEX IF NOT EXISTS idx_conductor_availability_created_by ON public.conductor_availability(created_by); CREATE INDEX IF NOT EXISTS idx_conductor_availability_time_range ON public.conductor_availability(available_from, available_to); --- Experiment phase assignments indexes -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_experiment_composite ON public.experiment_phase_assignments(experiment_number, experiment_phase_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_repetition_id ON public.experiment_phase_assignments(repetition_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_conductor_id ON public.experiment_phase_assignments(conductor_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_phase_name ON public.experiment_phase_assignments(phase_name); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_status ON public.experiment_phase_assignments(status); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_scheduled_start ON public.experiment_phase_assignments(scheduled_start_time); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_created_by ON public.experiment_phase_assignments(created_by); - -- ============================================= --- 4. FUNCTIONS FOR OVERLAP PREVENTION +-- 3. FUNCTIONS FOR OVERLAP PREVENTION -- ============================================= -- Function to check for overlapping availabilities @@ -111,10 +69,6 @@ BEGIN END; $$ LANGUAGE plpgsql; --- ============================================= --- 5. HELPER FUNCTIONS --- ============================================= - -- Function to get available conductors for a specific time range CREATE OR REPLACE FUNCTION public.get_available_conductors( start_time TIMESTAMP WITH TIME ZONE, @@ -167,7 +121,7 @@ END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- ============================================= --- 6. TRIGGERS +-- 4. TRIGGERS -- ============================================= -- Create trigger for updated_at on conductor_availability @@ -176,12 +130,6 @@ CREATE TRIGGER set_updated_at_conductor_availability FOR EACH ROW EXECUTE FUNCTION public.handle_updated_at(); --- Create trigger for updated_at on experiment_phase_assignments -CREATE TRIGGER set_updated_at_experiment_phase_assignments - BEFORE UPDATE ON public.experiment_phase_assignments - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -- Create trigger to prevent overlapping availabilities CREATE TRIGGER trigger_check_availability_overlap BEFORE INSERT OR UPDATE ON public.conductor_availability @@ -189,24 +137,21 @@ CREATE TRIGGER trigger_check_availability_overlap EXECUTE FUNCTION public.check_availability_overlap(); -- ============================================= --- 7. GRANT PERMISSIONS +-- 5. GRANT PERMISSIONS -- ============================================= GRANT ALL ON public.conductor_availability TO authenticated; -GRANT ALL ON public.experiment_phase_assignments TO authenticated; -- ============================================= --- 8. ENABLE ROW LEVEL SECURITY +-- 6. ENABLE ROW LEVEL SECURITY -- ============================================= ALTER TABLE public.conductor_availability ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_phase_assignments ENABLE ROW LEVEL SECURITY; -- ============================================= --- 9. CREATE RLS POLICIES +-- 7. CREATE RLS POLICIES -- ============================================= --- Conductor availability policies CREATE POLICY "conductor_availability_select_policy" ON public.conductor_availability FOR SELECT TO authenticated @@ -243,61 +188,5 @@ CREATE POLICY "conductor_availability_delete_policy" ON public.conductor_availab user_id = auth.uid() OR public.is_admin() ); --- Experiment phase assignments policies -CREATE POLICY "experiment_phase_assignments_select_policy" ON public.experiment_phase_assignments - FOR SELECT - TO authenticated - USING ( - -- Conductors can view their own assignments, admins can view all - conductor_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "experiment_phase_assignments_insert_policy" ON public.experiment_phase_assignments - FOR INSERT - TO authenticated - WITH CHECK ( - -- Only admins and conductors can create assignments - public.can_manage_experiments() - ); - -CREATE POLICY "experiment_phase_assignments_update_policy" ON public.experiment_phase_assignments - FOR UPDATE - TO authenticated - USING ( - -- Conductors can update their own assignments, admins can update any - conductor_id = auth.uid() OR public.is_admin() - ) - WITH CHECK ( - -- Conductors can update their own assignments, admins can update any - conductor_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "experiment_phase_assignments_delete_policy" ON public.experiment_phase_assignments - FOR DELETE - TO authenticated - USING ( - -- Only admins can delete assignments - public.is_admin() - ); - --- ============================================= --- 10. COMMENTS FOR DOCUMENTATION --- ============================================= - -COMMENT ON TABLE public.conductor_availability IS 'Stores conductor availability windows for experiment scheduling'; -COMMENT ON TABLE public.experiment_phase_assignments IS 'Assigns conductors to specific experiment repetition phases with scheduled times'; - -COMMENT ON COLUMN public.conductor_availability.available_from IS 'Start time of availability window'; -COMMENT ON COLUMN public.conductor_availability.available_to IS 'End time of availability window'; -COMMENT ON COLUMN public.conductor_availability.notes IS 'Optional notes about the availability period'; -COMMENT ON COLUMN public.conductor_availability.status IS 'Status of the availability (active or cancelled)'; - -COMMENT ON COLUMN public.experiment_phase_assignments.phase_name IS 'Experiment phase being assigned (pre-soaking, air-drying, cracking, shelling)'; -COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_start_time IS 'Planned start time for the phase'; -COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_end_time IS 'Planned end time for the phase'; -COMMENT ON COLUMN public.experiment_phase_assignments.status IS 'Current status of the assignment'; -COMMENT ON COLUMN public.experiment_phase_assignments.notes IS 'Optional notes about the assignment'; - - diff --git a/management-dashboard-web-app/supabase/migrations/20250101000006_views_and_final_setup.sql b/management-dashboard-web-app/supabase/migrations/00011_views.sql similarity index 78% rename from management-dashboard-web-app/supabase/migrations/20250101000006_views_and_final_setup.sql rename to management-dashboard-web-app/supabase/migrations/00011_views.sql index e0e9fc4..a7f1cc0 100644 --- a/management-dashboard-web-app/supabase/migrations/20250101000006_views_and_final_setup.sql +++ b/management-dashboard-web-app/supabase/migrations/00011_views.sql @@ -1,5 +1,5 @@ --- Views and Final Setup --- This migration creates views for easier querying and finalizes the database setup +-- Views +-- This migration creates views for easier querying (must run last after all tables are created) -- ============================================= -- 1. CREATE VIEWS FOR EASIER QUERYING @@ -15,10 +15,6 @@ SELECT e.results_status, e.completion_status, e.phase_id, - e.soaking_id, - e.airdrying_id, - e.cracking_id, - e.shelling_id, e.created_at, e.updated_at, e.created_by, @@ -28,42 +24,47 @@ SELECT ep.has_airdrying, ep.has_cracking, ep.has_shelling, + s.id as soaking_id, s.scheduled_start_time as soaking_scheduled_start, s.actual_start_time as soaking_actual_start, - s.soaking_duration_hours, + s.soaking_duration_minutes, s.scheduled_end_time as soaking_scheduled_end, s.actual_end_time as soaking_actual_end, + ad.id as airdrying_id, ad.scheduled_start_time as airdrying_scheduled_start, ad.actual_start_time as airdrying_actual_start, ad.duration_minutes as airdrying_duration, ad.scheduled_end_time as airdrying_scheduled_end, ad.actual_end_time as airdrying_actual_end, + c.id as cracking_id, c.scheduled_start_time as cracking_scheduled_start, c.actual_start_time as cracking_actual_start, c.actual_end_time as cracking_actual_end, mt.name as machine_type_name, + sh.id as shelling_id, sh.scheduled_start_time as shelling_scheduled_start, sh.actual_start_time as shelling_actual_start, sh.actual_end_time as shelling_actual_end FROM public.experiments e LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON e.soaking_id = s.id -LEFT JOIN public.airdrying ad ON e.airdrying_id = ad.id -LEFT JOIN public.cracking c ON e.cracking_id = c.id +LEFT JOIN public.soaking s ON s.experiment_id = e.id +LEFT JOIN public.airdrying ad ON ad.experiment_id = e.id +LEFT JOIN public.cracking c ON c.experiment_id = e.id LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON e.shelling_id = sh.id; +LEFT JOIN public.shelling sh ON sh.experiment_id = e.id; -- View for repetitions with phase information CREATE OR REPLACE VIEW public.repetitions_with_phases AS SELECT er.id, - er.experiment_number, - er.experiment_phase_id, + er.experiment_id, er.repetition_number, er.status, er.created_at, er.updated_at, er.created_by, + e.experiment_number, + e.phase_id, e.weight_per_repetition_lbs, ep.name as phase_name, ep.has_soaking, @@ -72,7 +73,7 @@ SELECT ep.has_shelling, s.scheduled_start_time as soaking_scheduled_start, s.actual_start_time as soaking_actual_start, - s.soaking_duration_hours, + s.soaking_duration_minutes, s.scheduled_end_time as soaking_scheduled_end, s.actual_end_time as soaking_actual_end, ad.scheduled_start_time as airdrying_scheduled_start, @@ -88,7 +89,7 @@ SELECT sh.actual_start_time as shelling_actual_start, sh.actual_end_time as shelling_actual_end FROM public.experiment_repetitions er -JOIN public.experiments e ON er.experiment_number = e.experiment_number AND er.experiment_phase_id = e.phase_id +JOIN public.experiments e ON er.experiment_id = e.id LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id LEFT JOIN public.soaking s ON er.id = s.repetition_id LEFT JOIN public.airdrying ad ON er.id = ad.repetition_id @@ -96,37 +97,6 @@ LEFT JOIN public.cracking c ON er.id = c.repetition_id LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id LEFT JOIN public.shelling sh ON er.id = sh.repetition_id; --- View for conductor assignments with experiment details -CREATE OR REPLACE VIEW public.conductor_assignments_with_details AS -SELECT - epa.id, - epa.experiment_number, - epa.experiment_phase_id, - epa.repetition_id, - epa.conductor_id, - epa.phase_name, - epa.scheduled_start_time, - epa.scheduled_end_time, - epa.status, - epa.notes, - epa.created_at, - epa.updated_at, - epa.created_by, - e.reps_required, - e.weight_per_repetition_lbs, - ep.name as experiment_phase_name, - ep.description as phase_description, - up.email as conductor_email, - up.first_name as conductor_first_name, - up.last_name as conductor_last_name, - er.repetition_number, - er.status as repetition_status -FROM public.experiment_phase_assignments epa -JOIN public.experiments e ON epa.experiment_number = e.experiment_number AND epa.experiment_phase_id = e.phase_id -JOIN public.experiment_phases ep ON e.phase_id = ep.id -JOIN public.user_profiles up ON epa.conductor_id = up.id -JOIN public.experiment_repetitions er ON epa.repetition_id = er.id; - -- View for available conductors with their roles CREATE OR REPLACE VIEW public.available_conductors AS SELECT @@ -148,20 +118,18 @@ AND r.name = 'conductor'; GRANT SELECT ON public.experiments_with_phases TO authenticated; GRANT SELECT ON public.repetitions_with_phases TO authenticated; -GRANT SELECT ON public.conductor_assignments_with_details TO authenticated; GRANT SELECT ON public.available_conductors TO authenticated; -- ============================================= --- 3. FINAL COMMENTS FOR DOCUMENTATION +-- 3. COMMENTS FOR DOCUMENTATION -- ============================================= COMMENT ON VIEW public.experiments_with_phases IS 'Comprehensive view of experiments with all phase information and timing details'; COMMENT ON VIEW public.repetitions_with_phases IS 'View of experiment repetitions with associated phase data'; -COMMENT ON VIEW public.conductor_assignments_with_details IS 'Detailed view of conductor assignments with experiment and conductor information'; COMMENT ON VIEW public.available_conductors IS 'View of currently available conductors with their profile information'; -- ============================================= --- 4. CREATE SAMPLE DATA FUNCTIONS (OPTIONAL) +-- 4. SAMPLE DATA FUNCTIONS (OPTIONAL) -- ============================================= -- Function to create sample roles @@ -214,3 +182,4 @@ $$ LANGUAGE plpgsql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION public.create_sample_roles() TO authenticated; GRANT EXECUTE ON FUNCTION public.create_sample_machine_types() TO authenticated; GRANT EXECUTE ON FUNCTION public.create_sample_experiment_phases() TO authenticated; + diff --git a/management-dashboard-web-app/supabase/migrations/20250101000003_experiments_and_repetitions.sql b/management-dashboard-web-app/supabase/migrations/20250101000003_experiments_and_repetitions.sql deleted file mode 100644 index 6f67de6..0000000 --- a/management-dashboard-web-app/supabase/migrations/20250101000003_experiments_and_repetitions.sql +++ /dev/null @@ -1,115 +0,0 @@ --- Experiments and Repetitions --- This migration creates the experiments and experiment repetitions tables with composite primary key - --- ============================================= --- 1. EXPERIMENTS --- ============================================= - --- Create experiments table with composite primary key (experiment_number, phase_id) -CREATE TABLE IF NOT EXISTS public.experiments ( - id UUID DEFAULT uuid_generate_v4(), - experiment_number INTEGER NOT NULL, - reps_required INTEGER NOT NULL CHECK (reps_required > 0), - weight_per_repetition_lbs DOUBLE PRECISION NOT NULL DEFAULT 5.0 CHECK (weight_per_repetition_lbs > 0), - results_status TEXT NOT NULL DEFAULT 'valid' CHECK (results_status IN ('valid', 'invalid')), - completion_status BOOLEAN NOT NULL DEFAULT false, - phase_id UUID NOT NULL REFERENCES public.experiment_phases(id) ON DELETE SET NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Composite primary key allows each phase to have its own experiment numbering starting from 1 - PRIMARY KEY (experiment_number, phase_id) -); - --- ============================================= --- 2. EXPERIMENT REPETITIONS --- ============================================= - --- Create experiment repetitions table -CREATE TABLE IF NOT EXISTS public.experiment_repetitions ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_number INTEGER NOT NULL CHECK (repetition_number > 0), - status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed', 'cancelled')), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure unique repetition numbers per experiment - UNIQUE(experiment_id, repetition_number) -); - --- ============================================= --- 3. INDEXES FOR PERFORMANCE --- ============================================= - -CREATE INDEX IF NOT EXISTS idx_experiments_phase_id ON public.experiments(phase_id); -CREATE INDEX IF NOT EXISTS idx_experiments_experiment_number ON public.experiments(experiment_number); -CREATE INDEX IF NOT EXISTS idx_experiments_created_by ON public.experiments(created_by); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_experiment_id ON public.experiment_repetitions(experiment_id); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_created_by ON public.experiment_repetitions(created_by); - --- ============================================= --- 4. TRIGGERS --- ============================================= - --- Create trigger for updated_at on experiments -CREATE TRIGGER set_updated_at_experiments - BEFORE UPDATE ON public.experiments - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- Create trigger for updated_at on experiment_repetitions -CREATE TRIGGER set_updated_at_experiment_repetitions - BEFORE UPDATE ON public.experiment_repetitions - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- ============================================= --- 5. GRANT PERMISSIONS --- ============================================= - -GRANT ALL ON public.experiments TO authenticated; -GRANT ALL ON public.experiment_repetitions TO authenticated; - --- ============================================= --- 6. ENABLE ROW LEVEL SECURITY --- ============================================= - -ALTER TABLE public.experiments ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_repetitions ENABLE ROW LEVEL SECURITY; - --- ============================================= --- 7. CREATE RLS POLICIES --- ============================================= - --- Create RLS policies for experiments -CREATE POLICY "Experiments are viewable by authenticated users" ON public.experiments - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Experiments are insertable by authenticated users" ON public.experiments - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Experiments are updatable by authenticated users" ON public.experiments - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Experiments are deletable by authenticated users" ON public.experiments - FOR DELETE USING (auth.role() = 'authenticated'); - --- Create RLS policies for experiment_repetitions -CREATE POLICY "Experiment repetitions are viewable by authenticated users" ON public.experiment_repetitions - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Experiment repetitions are insertable by authenticated users" ON public.experiment_repetitions - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Experiment repetitions are updatable by authenticated users" ON public.experiment_repetitions - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Experiment repetitions are deletable by authenticated users" ON public.experiment_repetitions - FOR DELETE USING (auth.role() = 'authenticated'); - - - - diff --git a/management-dashboard-web-app/supabase/migrations/20250103000001_fix_soaking_duration_column.sql b/management-dashboard-web-app/supabase/migrations/20250103000001_fix_soaking_duration_column.sql deleted file mode 100644 index f74b871..0000000 --- a/management-dashboard-web-app/supabase/migrations/20250103000001_fix_soaking_duration_column.sql +++ /dev/null @@ -1,133 +0,0 @@ --- Fix soaking duration column to use minutes instead of hours --- This aligns the database schema with frontend expectations and seed data - -BEGIN; - --- 1) Add new soaking_duration_minutes column -ALTER TABLE public.soaking ADD COLUMN IF NOT EXISTS soaking_duration_minutes INTEGER; - --- 2) Backfill soaking_duration_minutes from soaking_duration_hours -UPDATE public.soaking -SET soaking_duration_minutes = ROUND(soaking_duration_hours * 60) -WHERE soaking_duration_minutes IS NULL; - --- 3) Make soaking_duration_minutes NOT NULL -ALTER TABLE public.soaking ALTER COLUMN soaking_duration_minutes SET NOT NULL; - --- 4) Add check constraint for positive values -ALTER TABLE public.soaking ADD CONSTRAINT check_soaking_duration_minutes_positive - CHECK (soaking_duration_minutes > 0); - --- 5) Drop and recreate views to use the new column (must be done before dropping old column) -DROP VIEW IF EXISTS public.experiments_with_phases; -DROP VIEW IF EXISTS public.repetitions_with_phases; - -CREATE VIEW public.experiments_with_phases AS -SELECT - e.id, - e.experiment_number, - e.reps_required, - e.weight_per_repetition_lbs, - e.results_status, - e.completion_status, - e.phase_id, - e.soaking_id, - e.airdrying_id, - e.cracking_id, - e.shelling_id, - e.created_at, - e.updated_at, - e.created_by, - ep.name as phase_name, - ep.description as phase_description, - ep.has_soaking, - ep.has_airdrying, - ep.has_cracking, - ep.has_shelling, - s.scheduled_start_time as soaking_scheduled_start, - s.actual_start_time as soaking_actual_start, - s.soaking_duration_minutes, - s.scheduled_end_time as soaking_scheduled_end, - s.actual_end_time as soaking_actual_end, - ad.scheduled_start_time as airdrying_scheduled_start, - ad.actual_start_time as airdrying_actual_start, - ad.duration_minutes as airdrying_duration, - ad.scheduled_end_time as airdrying_scheduled_end, - ad.actual_end_time as airdrying_actual_end, - c.scheduled_start_time as cracking_scheduled_start, - c.actual_start_time as cracking_actual_start, - c.actual_end_time as cracking_actual_end, - mt.name as machine_type_name, - sh.scheduled_start_time as shelling_scheduled_start, - sh.actual_start_time as shelling_actual_start, - sh.actual_end_time as shelling_actual_end -FROM public.experiments e -LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON e.soaking_id = s.id -LEFT JOIN public.airdrying ad ON e.airdrying_id = ad.id -LEFT JOIN public.cracking c ON e.cracking_id = c.id -LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON e.shelling_id = sh.id; - -CREATE VIEW public.repetitions_with_phases AS -SELECT - er.id, - er.experiment_number, - er.experiment_phase_id, - er.repetition_number, - er.status, - er.created_at, - er.updated_at, - er.created_by, - e.weight_per_repetition_lbs, - ep.name as phase_name, - ep.has_soaking, - ep.has_airdrying, - ep.has_cracking, - ep.has_shelling, - s.scheduled_start_time as soaking_scheduled_start, - s.actual_start_time as soaking_actual_start, - s.soaking_duration_minutes, - s.scheduled_end_time as soaking_scheduled_end, - s.actual_end_time as soaking_actual_end, - ad.scheduled_start_time as airdrying_scheduled_start, - ad.actual_start_time as airdrying_actual_start, - ad.duration_minutes as airdrying_duration, - ad.scheduled_end_time as airdrying_scheduled_end, - ad.actual_end_time as airdrying_actual_end, - c.scheduled_start_time as cracking_scheduled_start, - c.actual_start_time as cracking_actual_start, - c.actual_end_time as cracking_actual_end, - mt.name as machine_type_name, - sh.scheduled_start_time as shelling_scheduled_start, - sh.actual_start_time as shelling_actual_start, - sh.actual_end_time as shelling_actual_end -FROM public.experiment_repetitions er -JOIN public.experiments e ON er.experiment_number = e.experiment_number AND er.experiment_phase_id = e.phase_id -LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON er.id = s.repetition_id -LEFT JOIN public.airdrying ad ON er.id = ad.repetition_id -LEFT JOIN public.cracking c ON er.id = c.repetition_id -LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON er.id = sh.repetition_id; - --- 6) Update the trigger function to use minutes -CREATE OR REPLACE FUNCTION calculate_soaking_scheduled_end_time() -RETURNS TRIGGER AS $$ -BEGIN - NEW.scheduled_end_time = NEW.scheduled_start_time + (NEW.soaking_duration_minutes || ' minutes')::INTERVAL; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- 7) Update the trigger to use the new column -DROP TRIGGER IF EXISTS trigger_calculate_soaking_scheduled_end_time ON public.soaking; -CREATE TRIGGER trigger_calculate_soaking_scheduled_end_time - BEFORE INSERT OR UPDATE ON public.soaking - FOR EACH ROW - EXECUTE FUNCTION calculate_soaking_scheduled_end_time(); - --- 8) Drop the old soaking_duration_hours column -ALTER TABLE public.soaking DROP COLUMN IF EXISTS soaking_duration_hours; - -COMMIT; diff --git a/management-dashboard-web-app/supabase/migrations/20250925_change_experiments_pk.sql b/management-dashboard-web-app/supabase/migrations/20250925_change_experiments_pk.sql deleted file mode 100644 index 043d9d4..0000000 --- a/management-dashboard-web-app/supabase/migrations/20250925_change_experiments_pk.sql +++ /dev/null @@ -1,44 +0,0 @@ --- Change experiments primary key to (id, experiment_number) --- Preserve uniqueness on (experiment_number, phase_id) for legacy FKs --- Ensure experiments.id is unique so existing FKs to id remain valid - -BEGIN; - --- 1) Ensure experiments.id is unique for FKs to reference -DO $$ -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM pg_constraint WHERE conname = 'experiments_id_key' - ) THEN - ALTER TABLE public.experiments - ADD CONSTRAINT experiments_id_key UNIQUE (id); - END IF; -END $$; - --- 2) Ensure (experiment_number, phase_id) remains unique before dropping PK -DO $$ -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM pg_constraint WHERE conname = 'experiments_experiment_number_phase_id_key' - ) THEN - ALTER TABLE public.experiments - ADD CONSTRAINT experiments_experiment_number_phase_id_key UNIQUE (experiment_number, phase_id); - END IF; -END $$; - --- 3) Do NOT drop the existing primary key because dependent FKs reference it. --- Instead, add a UNIQUE constraint on (id, experiment_number) to satisfy --- application-level requirements without breaking dependencies. -DO $$ -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM pg_constraint WHERE conname = 'experiments_id_experiment_number_key' - ) THEN - ALTER TABLE public.experiments - ADD CONSTRAINT experiments_id_experiment_number_key UNIQUE (id, experiment_number); - END IF; -END $$; - -COMMIT; - - diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250101000001_complete_schema.sql b/management-dashboard-web-app/supabase/migrations_backup/20250101000001_complete_schema.sql deleted file mode 100644 index b8e139f..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250101000001_complete_schema.sql +++ /dev/null @@ -1,785 +0,0 @@ --- Complete Database Schema for USDA Vision Pecan Experiments System --- This migration creates the entire database schema from scratch - --- Enable necessary extensions -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; - --- ============================================= --- 1. ROLES AND USER MANAGEMENT --- ============================================= - --- Create roles table -CREATE TABLE IF NOT EXISTS public.roles ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - name TEXT UNIQUE NOT NULL CHECK (name IN ('admin', 'conductor', 'analyst', 'data recorder')), - description TEXT NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -); - --- Create user_profiles table to extend auth.users -CREATE TABLE IF NOT EXISTS public.user_profiles ( - id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, - email TEXT NOT NULL, - status TEXT DEFAULT 'active' CHECK (status IN ('active', 'disabled')), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -); - --- Create user_roles junction table for many-to-many relationship -CREATE TABLE IF NOT EXISTS public.user_roles ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, - role_id UUID NOT NULL REFERENCES public.roles(id) ON DELETE CASCADE, - assigned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - assigned_by UUID REFERENCES public.user_profiles(id), - UNIQUE(user_id, role_id) -); - --- ============================================= --- 2. EXPERIMENT PHASES --- ============================================= - --- Create experiment_phases table -CREATE TABLE IF NOT EXISTS public.experiment_phases ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - name TEXT NOT NULL UNIQUE, - description TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id) -); - --- ============================================= --- 3. EXPERIMENTS --- ============================================= - --- Create experiments table -CREATE TABLE IF NOT EXISTS public.experiments ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_number INTEGER UNIQUE NOT NULL, - reps_required INTEGER NOT NULL CHECK (reps_required > 0), - soaking_duration_hr FLOAT NOT NULL CHECK (soaking_duration_hr >= 0), - air_drying_time_min INTEGER NOT NULL CHECK (air_drying_time_min >= 0), - plate_contact_frequency_hz FLOAT NOT NULL CHECK (plate_contact_frequency_hz > 0), - throughput_rate_pecans_sec FLOAT NOT NULL CHECK (throughput_rate_pecans_sec > 0), - crush_amount_in FLOAT NOT NULL CHECK (crush_amount_in >= 0), - entry_exit_height_diff_in FLOAT NOT NULL, - results_status TEXT NOT NULL DEFAULT 'valid' CHECK (results_status IN ('valid', 'invalid')), - completion_status BOOLEAN NOT NULL DEFAULT false, - phase_id UUID REFERENCES public.experiment_phases(id) ON DELETE SET NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id) -); - --- ============================================= --- 4. EXPERIMENT REPETITIONS --- ============================================= - --- Create experiment_repetitions table -CREATE TABLE IF NOT EXISTS public.experiment_repetitions ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_number INTEGER NOT NULL CHECK (repetition_number > 0), - scheduled_date TIMESTAMP WITH TIME ZONE, - schedule_status TEXT NOT NULL DEFAULT 'pending schedule' - CHECK (schedule_status IN ('pending schedule', 'scheduled', 'canceled', 'aborted')), - completion_status BOOLEAN NOT NULL DEFAULT false, - is_locked BOOLEAN NOT NULL DEFAULT false, - locked_at TIMESTAMP WITH TIME ZONE, - locked_by UUID REFERENCES public.user_profiles(id), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure unique repetition numbers per experiment - CONSTRAINT unique_repetition_per_experiment UNIQUE (experiment_id, repetition_number) -); - --- ============================================= --- 5. DATA ENTRY SYSTEM --- ============================================= - --- Create experiment_phase_drafts table for phase-specific draft management -CREATE TABLE IF NOT EXISTS public.experiment_phase_drafts ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - user_id UUID NOT NULL REFERENCES public.user_profiles(id), - phase_name TEXT NOT NULL CHECK (phase_name IN ('pre-soaking', 'air-drying', 'cracking', 'shelling')), - status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'submitted', 'withdrawn')), - draft_name TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - submitted_at TIMESTAMP WITH TIME ZONE, - withdrawn_at TIMESTAMP WITH TIME ZONE -); - --- Create experiment_phase_data table for phase-specific measurements -CREATE TABLE IF NOT EXISTS public.experiment_phase_data ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - phase_draft_id UUID NOT NULL REFERENCES public.experiment_phase_drafts(id) ON DELETE CASCADE, - phase_name TEXT NOT NULL CHECK (phase_name IN ('pre-soaking', 'air-drying', 'cracking', 'shelling')), - - -- Pre-soaking phase data - batch_initial_weight_lbs FLOAT CHECK (batch_initial_weight_lbs >= 0), - initial_shell_moisture_pct FLOAT CHECK (initial_shell_moisture_pct >= 0 AND initial_shell_moisture_pct <= 100), - initial_kernel_moisture_pct FLOAT CHECK (initial_kernel_moisture_pct >= 0 AND initial_kernel_moisture_pct <= 100), - soaking_start_time TIMESTAMP WITH TIME ZONE, - - -- Air-drying phase data - airdrying_start_time TIMESTAMP WITH TIME ZONE, - post_soak_weight_lbs FLOAT CHECK (post_soak_weight_lbs >= 0), - post_soak_kernel_moisture_pct FLOAT CHECK (post_soak_kernel_moisture_pct >= 0 AND post_soak_kernel_moisture_pct <= 100), - post_soak_shell_moisture_pct FLOAT CHECK (post_soak_shell_moisture_pct >= 0 AND post_soak_shell_moisture_pct <= 100), - avg_pecan_diameter_in FLOAT CHECK (avg_pecan_diameter_in >= 0), - - -- Cracking phase data - cracking_start_time TIMESTAMP WITH TIME ZONE, - - -- Shelling phase data - shelling_start_time TIMESTAMP WITH TIME ZONE, - bin_1_weight_lbs FLOAT CHECK (bin_1_weight_lbs >= 0), - bin_2_weight_lbs FLOAT CHECK (bin_2_weight_lbs >= 0), - bin_3_weight_lbs FLOAT CHECK (bin_3_weight_lbs >= 0), - discharge_bin_weight_lbs FLOAT CHECK (discharge_bin_weight_lbs >= 0), - bin_1_full_yield_oz FLOAT CHECK (bin_1_full_yield_oz >= 0), - bin_2_full_yield_oz FLOAT CHECK (bin_2_full_yield_oz >= 0), - bin_3_full_yield_oz FLOAT CHECK (bin_3_full_yield_oz >= 0), - bin_1_half_yield_oz FLOAT CHECK (bin_1_half_yield_oz >= 0), - bin_2_half_yield_oz FLOAT CHECK (bin_2_half_yield_oz >= 0), - bin_3_half_yield_oz FLOAT CHECK (bin_3_half_yield_oz >= 0), - - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - - -- Constraint: One record per phase draft - CONSTRAINT unique_phase_per_draft UNIQUE (phase_draft_id, phase_name) -); - --- Create pecan_diameter_measurements table for individual diameter measurements -CREATE TABLE IF NOT EXISTS public.pecan_diameter_measurements ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - phase_data_id UUID NOT NULL REFERENCES public.experiment_phase_data(id) ON DELETE CASCADE, - measurement_number INTEGER NOT NULL CHECK (measurement_number >= 1 AND measurement_number <= 10), - diameter_in FLOAT NOT NULL CHECK (diameter_in >= 0), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - - -- Constraint: Unique measurement number per phase data - CONSTRAINT unique_measurement_per_phase UNIQUE (phase_data_id, measurement_number) -); - --- ============================================= --- 6. INDEXES FOR PERFORMANCE --- ============================================= - --- User management indexes -CREATE INDEX IF NOT EXISTS idx_user_profiles_email ON public.user_profiles(email); -CREATE INDEX IF NOT EXISTS idx_user_profiles_status ON public.user_profiles(status); -CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON public.user_roles(user_id); -CREATE INDEX IF NOT EXISTS idx_user_roles_role_id ON public.user_roles(role_id); - --- Experiment phases indexes -CREATE INDEX IF NOT EXISTS idx_experiment_phases_name ON public.experiment_phases(name); -CREATE INDEX IF NOT EXISTS idx_experiment_phases_created_by ON public.experiment_phases(created_by); - --- Experiments indexes -CREATE INDEX IF NOT EXISTS idx_experiments_experiment_number ON public.experiments(experiment_number); -CREATE INDEX IF NOT EXISTS idx_experiments_created_by ON public.experiments(created_by); -CREATE INDEX IF NOT EXISTS idx_experiments_results_status ON public.experiments(results_status); -CREATE INDEX IF NOT EXISTS idx_experiments_completion_status ON public.experiments(completion_status); -CREATE INDEX IF NOT EXISTS idx_experiments_created_at ON public.experiments(created_at); -CREATE INDEX IF NOT EXISTS idx_experiments_phase_id ON public.experiments(phase_id); - --- Experiment repetitions indexes -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_experiment_id ON public.experiment_repetitions(experiment_id); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_schedule_status ON public.experiment_repetitions(schedule_status); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_completion_status ON public.experiment_repetitions(completion_status); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_scheduled_date ON public.experiment_repetitions(scheduled_date); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_created_by ON public.experiment_repetitions(created_by); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_created_at ON public.experiment_repetitions(created_at); -CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_is_locked ON public.experiment_repetitions(is_locked); - --- Data entry system indexes -CREATE INDEX IF NOT EXISTS idx_experiment_phase_drafts_experiment_id ON public.experiment_phase_drafts(experiment_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_drafts_repetition_id ON public.experiment_phase_drafts(repetition_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_drafts_user_id ON public.experiment_phase_drafts(user_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_drafts_phase_name ON public.experiment_phase_drafts(phase_name); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_drafts_status ON public.experiment_phase_drafts(status); - -CREATE INDEX IF NOT EXISTS idx_experiment_phase_data_draft_id ON public.experiment_phase_data(phase_draft_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_data_phase_name ON public.experiment_phase_data(phase_name); - -CREATE INDEX IF NOT EXISTS idx_pecan_diameter_measurements_phase_data_id ON public.pecan_diameter_measurements(phase_data_id); - --- ============================================= --- 7. TRIGGERS AND FUNCTIONS --- ============================================= - --- Create updated_at trigger function -CREATE OR REPLACE FUNCTION public.handle_updated_at() -RETURNS TRIGGER AS $$ -BEGIN - NEW.updated_at = NOW(); - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Create triggers for updated_at -CREATE TRIGGER set_updated_at_roles - BEFORE UPDATE ON public.roles - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_user_profiles - BEFORE UPDATE ON public.user_profiles - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_experiment_phases - BEFORE UPDATE ON public.experiment_phases - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_experiments - BEFORE UPDATE ON public.experiments - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_experiment_repetitions - BEFORE UPDATE ON public.experiment_repetitions - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_experiment_phase_drafts - BEFORE UPDATE ON public.experiment_phase_drafts - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_experiment_phase_data - BEFORE UPDATE ON public.experiment_phase_data - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- Function to validate repetition number doesn't exceed experiment's reps_required -CREATE OR REPLACE FUNCTION validate_repetition_number() -RETURNS TRIGGER AS $$ -DECLARE - max_reps INTEGER; -BEGIN - -- Get the reps_required for this experiment - SELECT reps_required INTO max_reps - FROM public.experiments - WHERE id = NEW.experiment_id; - - -- Check if repetition number exceeds the limit - IF NEW.repetition_number > max_reps THEN - RAISE EXCEPTION 'Repetition number % exceeds maximum allowed repetitions % for experiment', - NEW.repetition_number, max_reps; - END IF; - - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Create trigger to validate repetition number -CREATE TRIGGER trigger_validate_repetition_number - BEFORE INSERT OR UPDATE ON public.experiment_repetitions - FOR EACH ROW - EXECUTE FUNCTION validate_repetition_number(); - --- Function to handle phase draft status changes -CREATE OR REPLACE FUNCTION public.handle_phase_draft_status_change() -RETURNS TRIGGER AS $$ -BEGIN - -- Set submitted_at when status changes to 'submitted' - IF NEW.status = 'submitted' AND OLD.status != 'submitted' THEN - NEW.submitted_at = NOW(); - NEW.withdrawn_at = NULL; - END IF; - - -- Set withdrawn_at when status changes to 'withdrawn' - IF NEW.status = 'withdrawn' AND OLD.status = 'submitted' THEN - NEW.withdrawn_at = NOW(); - END IF; - - -- Clear timestamps when status changes back to 'draft' - IF NEW.status = 'draft' AND OLD.status IN ('submitted', 'withdrawn') THEN - NEW.submitted_at = NULL; - NEW.withdrawn_at = NULL; - END IF; - - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - -CREATE TRIGGER set_timestamps_experiment_phase_drafts - BEFORE UPDATE ON public.experiment_phase_drafts - FOR EACH ROW - EXECUTE FUNCTION public.handle_phase_draft_status_change(); - --- ============================================= --- 8. HELPER FUNCTIONS --- ============================================= - --- Helper function to get current user's roles -CREATE OR REPLACE FUNCTION public.get_user_roles() -RETURNS TEXT[] AS $$ -BEGIN - RETURN ARRAY( - SELECT r.name - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to get current user's first role (for backward compatibility) -CREATE OR REPLACE FUNCTION public.get_user_role() -RETURNS TEXT AS $$ -BEGIN - -- Return the first role found (for backward compatibility) - RETURN ( - SELECT r.name - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - LIMIT 1 - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user is admin -CREATE OR REPLACE FUNCTION public.is_admin() -RETURNS BOOLEAN AS $$ -BEGIN - RETURN 'admin' = ANY(public.get_user_roles()); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user has specific role -CREATE OR REPLACE FUNCTION public.has_role(role_name TEXT) -RETURNS BOOLEAN AS $$ -BEGIN - RETURN role_name = ANY(public.get_user_roles()); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Helper function to check if user can manage experiments -CREATE OR REPLACE FUNCTION public.can_manage_experiments() -RETURNS BOOLEAN AS $$ -BEGIN - RETURN EXISTS ( - SELECT 1 - FROM public.user_roles ur - JOIN public.roles r ON ur.role_id = r.id - WHERE ur.user_id = auth.uid() - AND r.name IN ('admin', 'conductor') - ); -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Function to generate secure temporary password -CREATE OR REPLACE FUNCTION public.generate_temp_password() -RETURNS TEXT AS $$ -DECLARE - chars TEXT := 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'; - result TEXT := ''; - i INTEGER; -BEGIN - FOR i IN 1..12 LOOP - result := result || substr(chars, floor(random() * length(chars) + 1)::integer, 1); - END LOOP; - RETURN result; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Function to create user with roles (for admin use) -CREATE OR REPLACE FUNCTION public.create_user_with_roles( - user_email TEXT, - role_names TEXT[], - temp_password TEXT DEFAULT NULL -) -RETURNS JSON AS $$ -DECLARE - new_user_id UUID; - role_record RECORD; - generated_password TEXT; - result JSON; - role_count INTEGER; -BEGIN - -- Only admins can create users - IF NOT public.is_admin() THEN - RAISE EXCEPTION 'Only administrators can create users'; - END IF; - - -- Validate that at least one role is provided - IF array_length(role_names, 1) IS NULL OR array_length(role_names, 1) = 0 THEN - RAISE EXCEPTION 'At least one role must be assigned to the user'; - END IF; - - -- Validate that all provided roles exist - SELECT COUNT(*) INTO role_count - FROM public.roles - WHERE name = ANY(role_names); - - IF role_count != array_length(role_names, 1) THEN - RAISE EXCEPTION 'One or more specified roles do not exist'; - END IF; - - -- Check if user already exists - IF EXISTS (SELECT 1 FROM auth.users WHERE email = user_email) THEN - RAISE EXCEPTION 'User with email % already exists', user_email; - END IF; - - -- Generate password if not provided - IF temp_password IS NULL THEN - generated_password := public.generate_temp_password(); - ELSE - generated_password := temp_password; - END IF; - - -- Generate new user ID - new_user_id := uuid_generate_v4(); - - -- Insert into auth.users (simulating user creation) - INSERT INTO auth.users ( - instance_id, - id, - aud, - role, - email, - encrypted_password, - email_confirmed_at, - created_at, - updated_at, - confirmation_token, - email_change, - email_change_token_new, - recovery_token - ) VALUES ( - '00000000-0000-0000-0000-000000000000', - new_user_id, - 'authenticated', - 'authenticated', - user_email, - crypt(generated_password, gen_salt('bf')), - NOW(), - NOW(), - NOW(), - '', - '', - '', - '' - ); - - -- Insert user profile - INSERT INTO public.user_profiles (id, email, status) - VALUES (new_user_id, user_email, 'active'); - - -- Assign roles through the user_roles junction table - FOR role_record IN - SELECT id FROM public.roles WHERE name = ANY(role_names) - LOOP - INSERT INTO public.user_roles (user_id, role_id, assigned_by) - VALUES (new_user_id, role_record.id, auth.uid()); - END LOOP; - - -- Return result - result := json_build_object( - 'user_id', new_user_id, - 'email', user_email, - 'temp_password', generated_password, - 'roles', role_names, - 'status', 'active' - ); - - RETURN result; - -EXCEPTION - WHEN OTHERS THEN - -- Clean up any partial inserts - DELETE FROM public.user_roles WHERE user_id = new_user_id; - DELETE FROM public.user_profiles WHERE id = new_user_id; - DELETE FROM auth.users WHERE id = new_user_id; - RAISE; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- ============================================= --- 9. ROW LEVEL SECURITY (RLS) --- ============================================= - --- Enable RLS on all tables -ALTER TABLE public.roles ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.user_profiles ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.user_roles ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_phases ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiments ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_repetitions ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_phase_drafts ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_phase_data ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.pecan_diameter_measurements ENABLE ROW LEVEL SECURITY; - --- Roles table policies -CREATE POLICY "Anyone can read roles" ON public.roles - FOR SELECT USING (true); - -CREATE POLICY "Only admins can insert roles" ON public.roles - FOR INSERT WITH CHECK (public.is_admin()); - -CREATE POLICY "Only admins can update roles" ON public.roles - FOR UPDATE USING (public.is_admin()); - -CREATE POLICY "Only admins can delete roles" ON public.roles - FOR DELETE USING (public.is_admin()); - --- User profiles policies -CREATE POLICY "Users can read own profile, admins can read all" ON public.user_profiles - FOR SELECT USING ( - auth.uid() = id OR public.is_admin() - ); - -CREATE POLICY "Only admins can insert user profiles" ON public.user_profiles - FOR INSERT WITH CHECK (public.is_admin()); - -CREATE POLICY "Users can update own profile, admins can update any" ON public.user_profiles - FOR UPDATE USING ( - auth.uid() = id OR public.is_admin() - ); - -CREATE POLICY "Only admins can delete user profiles" ON public.user_profiles - FOR DELETE USING (public.is_admin()); - --- User roles policies -CREATE POLICY "Users can read own roles, admins can read all" ON public.user_roles - FOR SELECT USING ( - user_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "Only admins can assign roles" ON public.user_roles - FOR INSERT WITH CHECK (public.is_admin()); - -CREATE POLICY "Only admins can update role assignments" ON public.user_roles - FOR UPDATE USING (public.is_admin()); - -CREATE POLICY "Only admins can remove role assignments" ON public.user_roles - FOR DELETE USING (public.is_admin()); - --- Experiment phases policies -CREATE POLICY "experiment_phases_select_policy" ON public.experiment_phases - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "experiment_phases_insert_policy" ON public.experiment_phases - FOR INSERT - TO authenticated - WITH CHECK (public.can_manage_experiments()); - -CREATE POLICY "experiment_phases_update_policy" ON public.experiment_phases - FOR UPDATE - TO authenticated - USING (public.can_manage_experiments()) - WITH CHECK (public.can_manage_experiments()); - -CREATE POLICY "experiment_phases_delete_policy" ON public.experiment_phases - FOR DELETE - TO authenticated - USING (public.is_admin()); - --- Experiments policies -CREATE POLICY "experiments_select_policy" ON public.experiments - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "experiments_insert_policy" ON public.experiments - FOR INSERT - TO authenticated - WITH CHECK (public.can_manage_experiments()); - -CREATE POLICY "experiments_update_policy" ON public.experiments - FOR UPDATE - TO authenticated - USING (public.can_manage_experiments()) - WITH CHECK (public.can_manage_experiments()); - -CREATE POLICY "experiments_delete_policy" ON public.experiments - FOR DELETE - TO authenticated - USING (public.is_admin()); - --- Experiment repetitions policies -CREATE POLICY "Users can view experiment repetitions" ON public.experiment_repetitions - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "Users can create experiment repetitions" ON public.experiment_repetitions - FOR INSERT WITH CHECK ( - experiment_id IN ( - SELECT id FROM public.experiments - WHERE created_by = auth.uid() - ) - OR public.is_admin() - ); - -CREATE POLICY "Users can update experiment repetitions" ON public.experiment_repetitions - FOR UPDATE USING ( - experiment_id IN ( - SELECT id FROM public.experiments - WHERE created_by = auth.uid() - ) - OR public.is_admin() - ); - -CREATE POLICY "Users can delete experiment repetitions" ON public.experiment_repetitions - FOR DELETE USING ( - experiment_id IN ( - SELECT id FROM public.experiments - WHERE created_by = auth.uid() - ) - OR public.is_admin() - ); - --- Experiment phase drafts policies -CREATE POLICY "experiment_phase_drafts_select_policy" ON public.experiment_phase_drafts - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "experiment_phase_drafts_insert_policy" ON public.experiment_phase_drafts - FOR INSERT - TO authenticated - WITH CHECK (user_id = auth.uid()); - -CREATE POLICY "experiment_phase_drafts_update_policy" ON public.experiment_phase_drafts - FOR UPDATE - TO authenticated - USING ( - (user_id = auth.uid() AND NOT EXISTS ( - SELECT 1 FROM public.experiment_repetitions - WHERE id = repetition_id AND is_locked = true - )) OR public.is_admin() - ) - WITH CHECK ( - (user_id = auth.uid() AND NOT EXISTS ( - SELECT 1 FROM public.experiment_repetitions - WHERE id = repetition_id AND is_locked = true - )) OR public.is_admin() - ); - -CREATE POLICY "experiment_phase_drafts_delete_policy" ON public.experiment_phase_drafts - FOR DELETE - TO authenticated - USING ( - (user_id = auth.uid() AND status = 'draft' AND NOT EXISTS ( - SELECT 1 FROM public.experiment_repetitions - WHERE id = repetition_id AND is_locked = true - )) OR public.is_admin() - ); - --- Experiment phase data policies -CREATE POLICY "experiment_phase_data_select_policy" ON public.experiment_phase_data - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "experiment_phase_data_insert_policy" ON public.experiment_phase_data - FOR INSERT - TO authenticated - WITH CHECK ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_drafts epd - WHERE epd.id = phase_draft_id AND epd.user_id = auth.uid() - ) - ); - -CREATE POLICY "experiment_phase_data_update_policy" ON public.experiment_phase_data - FOR UPDATE - TO authenticated - USING ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_drafts epd - WHERE epd.id = phase_draft_id AND epd.user_id = auth.uid() - ) - ) - WITH CHECK ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_drafts epd - WHERE epd.id = phase_draft_id AND epd.user_id = auth.uid() - ) - ); - -CREATE POLICY "experiment_phase_data_delete_policy" ON public.experiment_phase_data - FOR DELETE - TO authenticated - USING ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_drafts epd - WHERE epd.id = phase_draft_id AND epd.user_id = auth.uid() AND epd.status = 'draft' - ) - ); - --- Pecan diameter measurements policies -CREATE POLICY "pecan_diameter_measurements_select_policy" ON public.pecan_diameter_measurements - FOR SELECT - TO authenticated - USING (true); - -CREATE POLICY "pecan_diameter_measurements_insert_policy" ON public.pecan_diameter_measurements - FOR INSERT - TO authenticated - WITH CHECK ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_data epd - JOIN public.experiment_phase_drafts epdr ON epd.phase_draft_id = epdr.id - WHERE epd.id = phase_data_id AND epdr.user_id = auth.uid() - ) - ); - -CREATE POLICY "pecan_diameter_measurements_update_policy" ON public.pecan_diameter_measurements - FOR UPDATE - TO authenticated - USING ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_data epd - JOIN public.experiment_phase_drafts epdr ON epd.phase_draft_id = epdr.id - WHERE epd.id = phase_data_id AND epdr.user_id = auth.uid() - ) - ) - WITH CHECK ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_data epd - JOIN public.experiment_phase_drafts epdr ON epd.phase_draft_id = epdr.id - WHERE epd.id = phase_data_id AND epdr.user_id = auth.uid() - ) - ); - -CREATE POLICY "pecan_diameter_measurements_delete_policy" ON public.pecan_diameter_measurements - FOR DELETE - TO authenticated - USING ( - EXISTS ( - SELECT 1 FROM public.experiment_phase_data epd - JOIN public.experiment_phase_drafts epdr ON epd.phase_draft_id = epdr.id - WHERE epd.id = phase_data_id AND epdr.user_id = auth.uid() AND epdr.status = 'draft' - ) - ); - --- ============================================= --- 10. COMMENTS FOR DOCUMENTATION --- ============================================= - -COMMENT ON TABLE public.roles IS 'System roles for user access control'; -COMMENT ON TABLE public.user_profiles IS 'Extended user profiles linked to auth.users'; -COMMENT ON TABLE public.user_roles IS 'Many-to-many relationship between users and roles'; -COMMENT ON TABLE public.experiment_phases IS 'Groups experiments into logical phases for better organization and navigation'; -COMMENT ON TABLE public.experiments IS 'Stores experiment definitions for pecan processing with parameters and status tracking'; -COMMENT ON TABLE public.experiment_repetitions IS 'Individual repetitions of experiment blueprints that can be scheduled and executed'; -COMMENT ON TABLE public.experiment_phase_drafts IS 'Phase-specific draft records for experiment data entry with status tracking'; -COMMENT ON TABLE public.experiment_phase_data IS 'Phase-specific measurement data for experiments'; -COMMENT ON TABLE public.pecan_diameter_measurements IS 'Individual pecan diameter measurements (up to 10 per phase)'; diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250102000001_add_conductor_availability.sql b/management-dashboard-web-app/supabase/migrations_backup/20250102000001_add_conductor_availability.sql deleted file mode 100644 index 96c6f0d..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250102000001_add_conductor_availability.sql +++ /dev/null @@ -1,341 +0,0 @@ --- Add Conductor Availability and Experiment Phase Assignment Tables --- This migration adds tables for conductor availability management and future experiment scheduling - --- ============================================= --- 1. CONDUCTOR AVAILABILITY TABLE --- ============================================= - --- Create conductor_availability table -CREATE TABLE IF NOT EXISTS public.conductor_availability ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, - available_from TIMESTAMP WITH TIME ZONE NOT NULL, - available_to TIMESTAMP WITH TIME ZONE NOT NULL, - notes TEXT, -- Optional notes about the availability - status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'cancelled')), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure available_to is after available_from - CONSTRAINT valid_time_range CHECK (available_to > available_from), - - -- Ensure availability is in the future (can be modified if needed for past records) - CONSTRAINT future_availability CHECK (available_from >= NOW() - INTERVAL '1 day') -); - --- ============================================= --- 2. EXPERIMENT PHASE ASSIGNMENTS TABLE (Future Scheduling) --- ============================================= - --- Create experiment_phase_assignments table for scheduling conductors to experiment phases -CREATE TABLE IF NOT EXISTS public.experiment_phase_assignments ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - conductor_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE, - phase_name TEXT NOT NULL CHECK (phase_name IN ('pre-soaking', 'air-drying', 'cracking', 'shelling')), - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL, - status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'in-progress', 'completed', 'cancelled')), - notes TEXT, -- Optional notes about the assignment - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure scheduled_end_time is after scheduled_start_time - CONSTRAINT valid_scheduled_time_range CHECK (scheduled_end_time > scheduled_start_time), - - -- Ensure unique assignment per conductor per phase per repetition - CONSTRAINT unique_conductor_phase_assignment UNIQUE (repetition_id, conductor_id, phase_name) -); - --- ============================================= --- 3. INDEXES FOR PERFORMANCE --- ============================================= - --- Conductor availability indexes -CREATE INDEX IF NOT EXISTS idx_conductor_availability_user_id ON public.conductor_availability(user_id); -CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_from ON public.conductor_availability(available_from); -CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_to ON public.conductor_availability(available_to); -CREATE INDEX IF NOT EXISTS idx_conductor_availability_status ON public.conductor_availability(status); -CREATE INDEX IF NOT EXISTS idx_conductor_availability_created_by ON public.conductor_availability(created_by); -CREATE INDEX IF NOT EXISTS idx_conductor_availability_time_range ON public.conductor_availability(available_from, available_to); - --- Experiment phase assignments indexes -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_experiment_id ON public.experiment_phase_assignments(experiment_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_repetition_id ON public.experiment_phase_assignments(repetition_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_conductor_id ON public.experiment_phase_assignments(conductor_id); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_phase_name ON public.experiment_phase_assignments(phase_name); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_status ON public.experiment_phase_assignments(status); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_scheduled_start ON public.experiment_phase_assignments(scheduled_start_time); -CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_created_by ON public.experiment_phase_assignments(created_by); - --- ============================================= --- 4. FUNCTIONS FOR OVERLAP PREVENTION --- ============================================= - --- Function to check for overlapping availabilities -CREATE OR REPLACE FUNCTION public.check_availability_overlap() -RETURNS TRIGGER AS $$ -DECLARE - overlap_count INTEGER; -BEGIN - -- Check for overlapping availabilities for the same user - SELECT COUNT(*) INTO overlap_count - FROM public.conductor_availability - WHERE user_id = NEW.user_id - AND id != COALESCE(NEW.id, '00000000-0000-0000-0000-000000000000'::UUID) - AND status = 'active' - AND ( - -- New availability starts during an existing one - (NEW.available_from >= available_from AND NEW.available_from < available_to) OR - -- New availability ends during an existing one - (NEW.available_to > available_from AND NEW.available_to <= available_to) OR - -- New availability completely contains an existing one - (NEW.available_from <= available_from AND NEW.available_to >= available_to) OR - -- Existing availability completely contains the new one - (available_from <= NEW.available_from AND available_to >= NEW.available_to) - ); - - IF overlap_count > 0 THEN - RAISE EXCEPTION 'Availability overlaps with existing availability for user %. Please adjust the time range or cancel the conflicting availability.', NEW.user_id; - END IF; - - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Function to automatically adjust overlapping availabilities (alternative approach) -CREATE OR REPLACE FUNCTION public.adjust_overlapping_availability() -RETURNS TRIGGER AS $$ -DECLARE - overlapping_record RECORD; -BEGIN - -- Find overlapping availabilities and adjust them - FOR overlapping_record IN - SELECT id, available_from, available_to - FROM public.conductor_availability - WHERE user_id = NEW.user_id - AND id != COALESCE(NEW.id, '00000000-0000-0000-0000-000000000000'::UUID) - AND status = 'active' - AND ( - (NEW.available_from >= available_from AND NEW.available_from < available_to) OR - (NEW.available_to > available_from AND NEW.available_to <= available_to) OR - (NEW.available_from <= available_from AND NEW.available_to >= available_to) OR - (available_from <= NEW.available_from AND available_to >= NEW.available_to) - ) - LOOP - -- Adjust the overlapping record to end where the new one starts - IF overlapping_record.available_from < NEW.available_from AND overlapping_record.available_to > NEW.available_from THEN - UPDATE public.conductor_availability - SET available_to = NEW.available_from, - updated_at = NOW() - WHERE id = overlapping_record.id; - END IF; - - -- If the overlapping record starts after the new one, adjust it to start where the new one ends - IF overlapping_record.available_from < NEW.available_to AND overlapping_record.available_to > NEW.available_to THEN - UPDATE public.conductor_availability - SET available_from = NEW.available_to, - updated_at = NOW() - WHERE id = overlapping_record.id; - END IF; - - -- If the overlapping record is completely contained within the new one, cancel it - IF overlapping_record.available_from >= NEW.available_from AND overlapping_record.available_to <= NEW.available_to THEN - UPDATE public.conductor_availability - SET status = 'cancelled', - updated_at = NOW() - WHERE id = overlapping_record.id; - END IF; - END LOOP; - - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- ============================================= --- 5. TRIGGERS --- ============================================= - --- Create trigger for updated_at on conductor_availability -CREATE TRIGGER set_updated_at_conductor_availability - BEFORE UPDATE ON public.conductor_availability - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- Create trigger for updated_at on experiment_phase_assignments -CREATE TRIGGER set_updated_at_experiment_phase_assignments - BEFORE UPDATE ON public.experiment_phase_assignments - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- Create trigger to prevent overlapping availabilities (strict approach) -CREATE TRIGGER trigger_check_availability_overlap - BEFORE INSERT OR UPDATE ON public.conductor_availability - FOR EACH ROW - EXECUTE FUNCTION public.check_availability_overlap(); - --- Alternative trigger to automatically adjust overlapping availabilities (uncomment if preferred) --- CREATE TRIGGER trigger_adjust_overlapping_availability --- BEFORE INSERT OR UPDATE ON public.conductor_availability --- FOR EACH ROW --- EXECUTE FUNCTION public.adjust_overlapping_availability(); - --- ============================================= --- 6. HELPER FUNCTIONS --- ============================================= - --- Function to get available conductors for a specific time range -CREATE OR REPLACE FUNCTION public.get_available_conductors( - start_time TIMESTAMP WITH TIME ZONE, - end_time TIMESTAMP WITH TIME ZONE -) -RETURNS TABLE ( - user_id UUID, - email TEXT, - available_from TIMESTAMP WITH TIME ZONE, - available_to TIMESTAMP WITH TIME ZONE -) AS $$ -BEGIN - RETURN QUERY - SELECT - ca.user_id, - up.email, - ca.available_from, - ca.available_to - FROM public.conductor_availability ca - JOIN public.user_profiles up ON ca.user_id = up.id - JOIN public.user_roles ur ON up.id = ur.user_id - JOIN public.roles r ON ur.role_id = r.id - WHERE ca.status = 'active' - AND r.name = 'conductor' - AND ca.available_from <= start_time - AND ca.available_to >= end_time - ORDER BY up.email; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- Function to check if a conductor is available for a specific time range -CREATE OR REPLACE FUNCTION public.is_conductor_available( - conductor_user_id UUID, - start_time TIMESTAMP WITH TIME ZONE, - end_time TIMESTAMP WITH TIME ZONE -) -RETURNS BOOLEAN AS $$ -DECLARE - availability_count INTEGER; -BEGIN - SELECT COUNT(*) INTO availability_count - FROM public.conductor_availability - WHERE user_id = conductor_user_id - AND status = 'active' - AND available_from <= start_time - AND available_to >= end_time; - - RETURN availability_count > 0; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- ============================================= --- 7. ROW LEVEL SECURITY (RLS) --- ============================================= - --- Enable RLS on new tables -ALTER TABLE public.conductor_availability ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.experiment_phase_assignments ENABLE ROW LEVEL SECURITY; - --- Conductor availability policies -CREATE POLICY "conductor_availability_select_policy" ON public.conductor_availability - FOR SELECT - TO authenticated - USING ( - -- Users can view their own availability, admins can view all - user_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "conductor_availability_insert_policy" ON public.conductor_availability - FOR INSERT - TO authenticated - WITH CHECK ( - -- Users can create their own availability, admins can create for anyone - (user_id = auth.uid() AND created_by = auth.uid()) OR public.is_admin() - ); - -CREATE POLICY "conductor_availability_update_policy" ON public.conductor_availability - FOR UPDATE - TO authenticated - USING ( - -- Users can update their own availability, admins can update any - user_id = auth.uid() OR public.is_admin() - ) - WITH CHECK ( - -- Users can update their own availability, admins can update any - user_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "conductor_availability_delete_policy" ON public.conductor_availability - FOR DELETE - TO authenticated - USING ( - -- Users can delete their own availability, admins can delete any - user_id = auth.uid() OR public.is_admin() - ); - --- Experiment phase assignments policies -CREATE POLICY "experiment_phase_assignments_select_policy" ON public.experiment_phase_assignments - FOR SELECT - TO authenticated - USING ( - -- Conductors can view their own assignments, admins can view all - conductor_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "experiment_phase_assignments_insert_policy" ON public.experiment_phase_assignments - FOR INSERT - TO authenticated - WITH CHECK ( - -- Only admins and conductors can create assignments - public.can_manage_experiments() - ); - -CREATE POLICY "experiment_phase_assignments_update_policy" ON public.experiment_phase_assignments - FOR UPDATE - TO authenticated - USING ( - -- Conductors can update their own assignments, admins can update any - conductor_id = auth.uid() OR public.is_admin() - ) - WITH CHECK ( - -- Conductors can update their own assignments, admins can update any - conductor_id = auth.uid() OR public.is_admin() - ); - -CREATE POLICY "experiment_phase_assignments_delete_policy" ON public.experiment_phase_assignments - FOR DELETE - TO authenticated - USING ( - -- Only admins can delete assignments - public.is_admin() - ); - --- ============================================= --- 8. COMMENTS FOR DOCUMENTATION --- ============================================= - -COMMENT ON TABLE public.conductor_availability IS 'Stores conductor availability windows for experiment scheduling'; -COMMENT ON TABLE public.experiment_phase_assignments IS 'Assigns conductors to specific experiment repetition phases with scheduled times'; - -COMMENT ON COLUMN public.conductor_availability.available_from IS 'Start time of availability window'; -COMMENT ON COLUMN public.conductor_availability.available_to IS 'End time of availability window'; -COMMENT ON COLUMN public.conductor_availability.notes IS 'Optional notes about the availability period'; -COMMENT ON COLUMN public.conductor_availability.status IS 'Status of the availability (active or cancelled)'; - -COMMENT ON COLUMN public.experiment_phase_assignments.phase_name IS 'Experiment phase being assigned (pre-soaking, air-drying, cracking, shelling)'; -COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_start_time IS 'Planned start time for the phase'; -COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_end_time IS 'Planned end time for the phase'; -COMMENT ON COLUMN public.experiment_phase_assignments.status IS 'Current status of the assignment'; -COMMENT ON COLUMN public.experiment_phase_assignments.notes IS 'Optional notes about the assignment'; - - diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250102000002_restructure_experiment_phases.sql b/management-dashboard-web-app/supabase/migrations_backup/20250102000002_restructure_experiment_phases.sql deleted file mode 100644 index fbb702b..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250102000002_restructure_experiment_phases.sql +++ /dev/null @@ -1,474 +0,0 @@ --- Migration: Restructure experiment phases and add machine types --- This migration restructures the experiment system to support separate phase tables --- and machine-specific parameters - --- ============================================= --- 1. MACHINE TYPES --- ============================================= - --- Create machine types table -CREATE TABLE IF NOT EXISTS public.machine_types ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - name TEXT NOT NULL UNIQUE, - description TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id) -); - --- Machine types will be inserted in seed.sql after user profiles are created - --- ============================================= --- 2. UPDATE EXPERIMENT_PHASES TABLE --- ============================================= - --- Add phase selection columns to experiment_phases -ALTER TABLE public.experiment_phases -ADD COLUMN IF NOT EXISTS has_soaking BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN IF NOT EXISTS has_airdrying BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN IF NOT EXISTS has_cracking BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN IF NOT EXISTS has_shelling BOOLEAN NOT NULL DEFAULT false; - --- Add constraint to ensure at least one phase is selected -ALTER TABLE public.experiment_phases -ADD CONSTRAINT check_at_least_one_phase -CHECK (has_soaking = true OR has_airdrying = true OR has_cracking = true OR has_shelling = true); - --- ============================================= --- 3. CREATE PHASE-SPECIFIC TABLES --- ============================================= - --- Create soaking table -CREATE TABLE IF NOT EXISTS public.soaking ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_start_time TIMESTAMP WITH TIME ZONE, - soaking_duration_minutes INTEGER NOT NULL CHECK (soaking_duration_minutes > 0), - scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_end_time TIMESTAMP WITH TIME ZONE, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure only one soaking per experiment or repetition - CONSTRAINT unique_soaking_per_experiment UNIQUE (experiment_id), - CONSTRAINT unique_soaking_per_repetition UNIQUE (repetition_id) -); - --- Create airdrying table -CREATE TABLE IF NOT EXISTS public.airdrying ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_start_time TIMESTAMP WITH TIME ZONE, - duration_minutes INTEGER NOT NULL CHECK (duration_minutes > 0), - scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_end_time TIMESTAMP WITH TIME ZONE, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure only one airdrying per experiment or repetition - CONSTRAINT unique_airdrying_per_experiment UNIQUE (experiment_id), - CONSTRAINT unique_airdrying_per_repetition UNIQUE (repetition_id) -); - --- Create cracking table -CREATE TABLE IF NOT EXISTS public.cracking ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - machine_type_id UUID NOT NULL REFERENCES public.machine_types(id), - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_start_time TIMESTAMP WITH TIME ZONE, - actual_end_time TIMESTAMP WITH TIME ZONE, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure only one cracking per experiment or repetition - CONSTRAINT unique_cracking_per_experiment UNIQUE (experiment_id), - CONSTRAINT unique_cracking_per_repetition UNIQUE (repetition_id) -); - --- Create shelling table -CREATE TABLE IF NOT EXISTS public.shelling ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE, - repetition_id UUID REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE, - scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL, - actual_start_time TIMESTAMP WITH TIME ZONE, - actual_end_time TIMESTAMP WITH TIME ZONE, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - created_by UUID NOT NULL REFERENCES public.user_profiles(id), - - -- Ensure only one shelling per experiment or repetition - CONSTRAINT unique_shelling_per_experiment UNIQUE (experiment_id), - CONSTRAINT unique_shelling_per_repetition UNIQUE (repetition_id) -); - --- ============================================= --- 4. MACHINE-SPECIFIC PARAMETER TABLES --- ============================================= - --- Create JC Cracker parameters table -CREATE TABLE IF NOT EXISTS public.jc_cracker_parameters ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - cracking_id UUID NOT NULL REFERENCES public.cracking(id) ON DELETE CASCADE, - plate_contact_frequency_hz DOUBLE PRECISION NOT NULL CHECK (plate_contact_frequency_hz > 0), - throughput_rate_pecans_sec DOUBLE PRECISION NOT NULL CHECK (throughput_rate_pecans_sec > 0), - crush_amount_in DOUBLE PRECISION NOT NULL CHECK (crush_amount_in >= 0), - entry_exit_height_diff_in DOUBLE PRECISION NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - - -- Ensure only one parameter set per cracking - CONSTRAINT unique_jc_params_per_cracking UNIQUE (cracking_id) -); - --- Create Meyer Cracker parameters table -CREATE TABLE IF NOT EXISTS public.meyer_cracker_parameters ( - id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), - cracking_id UUID NOT NULL REFERENCES public.cracking(id) ON DELETE CASCADE, - motor_speed_hz DOUBLE PRECISION NOT NULL CHECK (motor_speed_hz > 0), - jig_displacement_inches DOUBLE PRECISION NOT NULL CHECK (jig_displacement_inches >= 0), - spring_stiffness_nm DOUBLE PRECISION NOT NULL CHECK (spring_stiffness_nm > 0), - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - - -- Ensure only one parameter set per cracking - CONSTRAINT unique_meyer_params_per_cracking UNIQUE (cracking_id) -); - --- ============================================= --- 5. UPDATE EXPERIMENTS TABLE --- ============================================= - --- Add weight_per_repetition column -ALTER TABLE public.experiments -ADD COLUMN IF NOT EXISTS weight_per_repetition_lbs DOUBLE PRECISION NOT NULL DEFAULT 0 CHECK (weight_per_repetition_lbs > 0); - --- Remove phase-specific parameters (these will be moved to phase tables) --- Note: We'll keep these columns for now to avoid data loss, but they should be deprecated --- Make old columns nullable to support new schema experiments -ALTER TABLE public.experiments -ALTER COLUMN soaking_duration_hr DROP NOT NULL, -ALTER COLUMN air_drying_time_min DROP NOT NULL, -ALTER COLUMN plate_contact_frequency_hz DROP NOT NULL, -ALTER COLUMN throughput_rate_pecans_sec DROP NOT NULL, -ALTER COLUMN crush_amount_in DROP NOT NULL, -ALTER COLUMN entry_exit_height_diff_in DROP NOT NULL; - --- ============================================= --- 6. ADD FOREIGN KEY CONSTRAINTS --- ============================================= - --- Add foreign key constraints to experiments table for phase associations -ALTER TABLE public.experiments -ADD COLUMN IF NOT EXISTS soaking_id UUID REFERENCES public.soaking(id) ON DELETE SET NULL, -ADD COLUMN IF NOT EXISTS airdrying_id UUID REFERENCES public.airdrying(id) ON DELETE SET NULL, -ADD COLUMN IF NOT EXISTS cracking_id UUID REFERENCES public.cracking(id) ON DELETE SET NULL, -ADD COLUMN IF NOT EXISTS shelling_id UUID REFERENCES public.shelling(id) ON DELETE SET NULL; - --- ============================================= --- 7. CREATE INDEXES FOR PERFORMANCE --- ============================================= - --- Create indexes for better query performance -CREATE INDEX IF NOT EXISTS idx_soaking_experiment_id ON public.soaking(experiment_id); -CREATE INDEX IF NOT EXISTS idx_soaking_repetition_id ON public.soaking(repetition_id); -CREATE INDEX IF NOT EXISTS idx_airdrying_experiment_id ON public.airdrying(experiment_id); -CREATE INDEX IF NOT EXISTS idx_airdrying_repetition_id ON public.airdrying(repetition_id); -CREATE INDEX IF NOT EXISTS idx_cracking_experiment_id ON public.cracking(experiment_id); -CREATE INDEX IF NOT EXISTS idx_cracking_repetition_id ON public.cracking(repetition_id); -CREATE INDEX IF NOT EXISTS idx_cracking_machine_type_id ON public.cracking(machine_type_id); -CREATE INDEX IF NOT EXISTS idx_shelling_experiment_id ON public.shelling(experiment_id); -CREATE INDEX IF NOT EXISTS idx_shelling_repetition_id ON public.shelling(repetition_id); - --- ============================================= --- 8. CREATE TRIGGERS FOR AUTOMATIC TIMESTAMP CALCULATIONS --- ============================================= - --- Function to calculate scheduled end time for soaking -CREATE OR REPLACE FUNCTION calculate_soaking_scheduled_end_time() -RETURNS TRIGGER AS $$ -BEGIN - NEW.scheduled_end_time = NEW.scheduled_start_time + (NEW.soaking_duration_minutes || ' minutes')::INTERVAL; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Trigger for soaking scheduled end time -DROP TRIGGER IF EXISTS trigger_calculate_soaking_scheduled_end_time ON public.soaking; -CREATE TRIGGER trigger_calculate_soaking_scheduled_end_time - BEFORE INSERT OR UPDATE ON public.soaking - FOR EACH ROW - EXECUTE FUNCTION calculate_soaking_scheduled_end_time(); - --- Function to calculate scheduled end time for airdrying -CREATE OR REPLACE FUNCTION calculate_airdrying_scheduled_end_time() -RETURNS TRIGGER AS $$ -BEGIN - NEW.scheduled_end_time = NEW.scheduled_start_time + (NEW.duration_minutes || ' minutes')::INTERVAL; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Trigger for airdrying scheduled end time -DROP TRIGGER IF EXISTS trigger_calculate_airdrying_scheduled_end_time ON public.airdrying; -CREATE TRIGGER trigger_calculate_airdrying_scheduled_end_time - BEFORE INSERT OR UPDATE ON public.airdrying - FOR EACH ROW - EXECUTE FUNCTION calculate_airdrying_scheduled_end_time(); - --- Function to set airdrying scheduled start time based on soaking end time -CREATE OR REPLACE FUNCTION set_airdrying_scheduled_start_time() -RETURNS TRIGGER AS $$ -BEGIN - -- If this is a new airdrying record and no scheduled_start_time is provided, - -- try to get it from the associated soaking's scheduled_end_time - IF NEW.scheduled_start_time IS NULL THEN - SELECT s.scheduled_end_time INTO NEW.scheduled_start_time - FROM public.soaking s - WHERE s.experiment_id = NEW.experiment_id - LIMIT 1; - END IF; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Trigger for airdrying scheduled start time -DROP TRIGGER IF EXISTS trigger_set_airdrying_scheduled_start_time ON public.airdrying; -CREATE TRIGGER trigger_set_airdrying_scheduled_start_time - BEFORE INSERT ON public.airdrying - FOR EACH ROW - EXECUTE FUNCTION set_airdrying_scheduled_start_time(); - --- Function to set cracking scheduled start time based on airdrying end time -CREATE OR REPLACE FUNCTION set_cracking_scheduled_start_time() -RETURNS TRIGGER AS $$ -BEGIN - -- If this is a new cracking record and no scheduled_start_time is provided, - -- try to get it from the associated airdrying's scheduled_end_time - IF NEW.scheduled_start_time IS NULL THEN - SELECT a.scheduled_end_time INTO NEW.scheduled_start_time - FROM public.airdrying a - WHERE a.experiment_id = NEW.experiment_id - LIMIT 1; - END IF; - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Trigger for cracking scheduled start time -DROP TRIGGER IF EXISTS trigger_set_cracking_scheduled_start_time ON public.cracking; -CREATE TRIGGER trigger_set_cracking_scheduled_start_time - BEFORE INSERT ON public.cracking - FOR EACH ROW - EXECUTE FUNCTION set_cracking_scheduled_start_time(); - --- ============================================= --- 9. CREATE VIEWS FOR EASIER QUERYING --- ============================================= - --- View for experiments with all phase information -CREATE OR REPLACE VIEW public.experiments_with_phases AS -SELECT - e.id, - e.experiment_number, - e.reps_required, - e.weight_per_repetition_lbs, - e.results_status, - e.completion_status, - e.phase_id, - e.soaking_id, - e.airdrying_id, - e.cracking_id, - e.shelling_id, - e.created_at, - e.updated_at, - e.created_by, - ep.name as phase_name, - ep.description as phase_description, - ep.has_soaking, - ep.has_airdrying, - ep.has_cracking, - ep.has_shelling, - s.scheduled_start_time as soaking_scheduled_start, - s.actual_start_time as soaking_actual_start, - s.soaking_duration_minutes, - s.scheduled_end_time as soaking_scheduled_end, - s.actual_end_time as soaking_actual_end, - ad.scheduled_start_time as airdrying_scheduled_start, - ad.actual_start_time as airdrying_actual_start, - ad.duration_minutes as airdrying_duration, - ad.scheduled_end_time as airdrying_scheduled_end, - ad.actual_end_time as airdrying_actual_end, - c.scheduled_start_time as cracking_scheduled_start, - c.actual_start_time as cracking_actual_start, - c.actual_end_time as cracking_actual_end, - mt.name as machine_type_name, - sh.scheduled_start_time as shelling_scheduled_start, - sh.actual_start_time as shelling_actual_start, - sh.actual_end_time as shelling_actual_end -FROM public.experiments e -LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON e.soaking_id = s.id -LEFT JOIN public.airdrying ad ON e.airdrying_id = ad.id -LEFT JOIN public.cracking c ON e.cracking_id = c.id -LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON e.shelling_id = sh.id; - --- View for repetitions with phase information -CREATE OR REPLACE VIEW public.repetitions_with_phases AS -SELECT - er.*, - e.experiment_number, - e.weight_per_repetition_lbs, - ep.name as phase_name, - ep.has_soaking, - ep.has_airdrying, - ep.has_cracking, - ep.has_shelling, - s.id as soaking_id, - s.scheduled_start_time as soaking_scheduled_start, - s.actual_start_time as soaking_actual_start, - s.soaking_duration_minutes, - s.scheduled_end_time as soaking_scheduled_end, - s.actual_end_time as soaking_actual_end, - ad.id as airdrying_id, - ad.scheduled_start_time as airdrying_scheduled_start, - ad.actual_start_time as airdrying_actual_start, - ad.duration_minutes as airdrying_duration, - ad.scheduled_end_time as airdrying_scheduled_end, - ad.actual_end_time as airdrying_actual_end, - c.id as cracking_id, - c.scheduled_start_time as cracking_scheduled_start, - c.actual_start_time as cracking_actual_start, - c.actual_end_time as cracking_actual_end, - mt.name as machine_type_name, - sh.id as shelling_id, - sh.scheduled_start_time as shelling_scheduled_start, - sh.actual_start_time as shelling_actual_start, - sh.actual_end_time as shelling_actual_end -FROM public.experiment_repetitions er -JOIN public.experiments e ON er.experiment_id = e.id -LEFT JOIN public.experiment_phases ep ON e.phase_id = ep.id -LEFT JOIN public.soaking s ON er.id = s.repetition_id -LEFT JOIN public.airdrying ad ON er.id = ad.repetition_id -LEFT JOIN public.cracking c ON er.id = c.repetition_id -LEFT JOIN public.machine_types mt ON c.machine_type_id = mt.id -LEFT JOIN public.shelling sh ON er.id = sh.repetition_id; - --- ============================================= --- 10. GRANT PERMISSIONS --- ============================================= - --- Grant permissions for new tables -GRANT ALL ON public.machine_types TO authenticated; -GRANT ALL ON public.soaking TO authenticated; -GRANT ALL ON public.airdrying TO authenticated; -GRANT ALL ON public.cracking TO authenticated; -GRANT ALL ON public.shelling TO authenticated; -GRANT ALL ON public.jc_cracker_parameters TO authenticated; -GRANT ALL ON public.meyer_cracker_parameters TO authenticated; - --- Grant permissions for views -GRANT SELECT ON public.experiments_with_phases TO authenticated; -GRANT SELECT ON public.repetitions_with_phases TO authenticated; - --- ============================================= --- 11. UPDATE RLS POLICIES --- ============================================= - --- Enable RLS on new tables -ALTER TABLE public.machine_types ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.soaking ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.airdrying ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.cracking ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.shelling ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.jc_cracker_parameters ENABLE ROW LEVEL SECURITY; -ALTER TABLE public.meyer_cracker_parameters ENABLE ROW LEVEL SECURITY; - --- Create RLS policies for machine_types (read-only for all authenticated users) -CREATE POLICY "Machine types are viewable by authenticated users" ON public.machine_types - FOR SELECT USING (auth.role() = 'authenticated'); - --- Create RLS policies for phase tables (similar to experiments) -CREATE POLICY "Soaking data is viewable by authenticated users" ON public.soaking - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Soaking data is insertable by authenticated users" ON public.soaking - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Soaking data is updatable by authenticated users" ON public.soaking - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Soaking data is deletable by authenticated users" ON public.soaking - FOR DELETE USING (auth.role() = 'authenticated'); - --- Similar policies for other phase tables -CREATE POLICY "Airdrying data is viewable by authenticated users" ON public.airdrying - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Airdrying data is insertable by authenticated users" ON public.airdrying - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Airdrying data is updatable by authenticated users" ON public.airdrying - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Airdrying data is deletable by authenticated users" ON public.airdrying - FOR DELETE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Cracking data is viewable by authenticated users" ON public.cracking - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Cracking data is insertable by authenticated users" ON public.cracking - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Cracking data is updatable by authenticated users" ON public.cracking - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Cracking data is deletable by authenticated users" ON public.cracking - FOR DELETE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Shelling data is viewable by authenticated users" ON public.shelling - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Shelling data is insertable by authenticated users" ON public.shelling - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Shelling data is updatable by authenticated users" ON public.shelling - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Shelling data is deletable by authenticated users" ON public.shelling - FOR DELETE USING (auth.role() = 'authenticated'); - --- RLS policies for machine parameter tables -CREATE POLICY "JC Cracker parameters are viewable by authenticated users" ON public.jc_cracker_parameters - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are insertable by authenticated users" ON public.jc_cracker_parameters - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are updatable by authenticated users" ON public.jc_cracker_parameters - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "JC Cracker parameters are deletable by authenticated users" ON public.jc_cracker_parameters - FOR DELETE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are viewable by authenticated users" ON public.meyer_cracker_parameters - FOR SELECT USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are insertable by authenticated users" ON public.meyer_cracker_parameters - FOR INSERT WITH CHECK (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are updatable by authenticated users" ON public.meyer_cracker_parameters - FOR UPDATE USING (auth.role() = 'authenticated'); - -CREATE POLICY "Meyer Cracker parameters are deletable by authenticated users" ON public.meyer_cracker_parameters - FOR DELETE USING (auth.role() = 'authenticated'); diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250103000001_add_password_reset_function.sql b/management-dashboard-web-app/supabase/migrations_backup/20250103000001_add_password_reset_function.sql deleted file mode 100644 index c7bb98b..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250103000001_add_password_reset_function.sql +++ /dev/null @@ -1,49 +0,0 @@ --- Add password reset function for admin use --- This migration adds a function to reset user passwords back to the default "password123" - --- Function to reset user password (admin only) -CREATE OR REPLACE FUNCTION public.reset_user_password( - target_user_id UUID -) -RETURNS JSON AS $$ -DECLARE - user_email TEXT; - result JSON; -BEGIN - -- Only admins can reset passwords - IF NOT public.is_admin() THEN - RAISE EXCEPTION 'Only administrators can reset user passwords'; - END IF; - - -- Check if target user exists - SELECT email INTO user_email - FROM public.user_profiles - WHERE id = target_user_id; - - IF user_email IS NULL THEN - RAISE EXCEPTION 'User not found'; - END IF; - - -- Update the password in auth.users table - UPDATE auth.users - SET - encrypted_password = crypt('password123', gen_salt('bf')), - updated_at = NOW() - WHERE id = target_user_id; - - -- Return result - result := json_build_object( - 'user_id', target_user_id, - 'email', user_email, - 'new_password', 'password123', - 'reset_at', NOW() - ); - - RETURN result; - -EXCEPTION - WHEN OTHERS THEN - RAISE; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250103000002_add_user_names.sql b/management-dashboard-web-app/supabase/migrations_backup/20250103000002_add_user_names.sql deleted file mode 100644 index 46d2b71..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250103000002_add_user_names.sql +++ /dev/null @@ -1,12 +0,0 @@ --- Add first_name and last_name fields to user_profiles table --- This migration adds name fields to store user's first and last names - --- Add first_name and last_name columns to user_profiles table -ALTER TABLE public.user_profiles -ADD COLUMN first_name TEXT, -ADD COLUMN last_name TEXT; - --- Add comments for documentation -COMMENT ON COLUMN public.user_profiles.first_name IS 'User first name'; -COMMENT ON COLUMN public.user_profiles.last_name IS 'User last name'; - diff --git a/management-dashboard-web-app/supabase/migrations_backup/20250103000003_add_change_password_function.sql b/management-dashboard-web-app/supabase/migrations_backup/20250103000003_add_change_password_function.sql deleted file mode 100644 index 5942e5c..0000000 --- a/management-dashboard-web-app/supabase/migrations_backup/20250103000003_add_change_password_function.sql +++ /dev/null @@ -1,62 +0,0 @@ --- Add change password function for users --- This migration adds a function to allow users to change their own password - --- Function to change user password (user can only change their own password) -CREATE OR REPLACE FUNCTION public.change_user_password( - current_password TEXT, - new_password TEXT -) -RETURNS JSON AS $$ -DECLARE - user_id UUID; - user_email TEXT; - result JSON; -BEGIN - -- Get current user ID - user_id := auth.uid(); - - IF user_id IS NULL THEN - RAISE EXCEPTION 'User not authenticated'; - END IF; - - -- Get user email - SELECT email INTO user_email - FROM public.user_profiles - WHERE id = user_id; - - IF user_email IS NULL THEN - RAISE EXCEPTION 'User profile not found'; - END IF; - - -- Verify current password - IF NOT EXISTS ( - SELECT 1 - FROM auth.users - WHERE id = user_id - AND encrypted_password = crypt(current_password, encrypted_password) - ) THEN - RAISE EXCEPTION 'Current password is incorrect'; - END IF; - - -- Update the password in auth.users table - UPDATE auth.users - SET - encrypted_password = crypt(new_password, gen_salt('bf')), - updated_at = NOW() - WHERE id = user_id; - - -- Return result - result := json_build_object( - 'user_id', user_id, - 'email', user_email, - 'password_changed_at', NOW() - ); - - RETURN result; - -EXCEPTION - WHEN OTHERS THEN - RAISE; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - diff --git a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments.sql b/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments.sql deleted file mode 100644 index 2261176..0000000 --- a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments.sql +++ /dev/null @@ -1,364 +0,0 @@ --- Phase 2 JC Experiments Seed Data (Corrected) --- This file contains all Phase 2 JC experiments from phase_2_JC_experimental_run_sheet.csv --- Each experiment has 3 repetitions, and each row represents one repetition --- Updated to match the actual CSV data with correct experiment numbers and parameters - --- ============================================= --- INSERT PHASE 2 JC EXPERIMENTS --- ============================================= - --- First, insert unique experiments (based on experiment_number from CSV: 0-19) -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Phase 2 JC Experiments 0-19 (matching CSV data) -(0, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(1, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create soaking records for Phase 2 JC experiments (0-19) with data from CSV -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number + 1) * INTERVAL '1 day', - CASE e.experiment_number - WHEN 0 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 1 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 2 THEN 38 * 60 -- 38 hours = 2280 minutes - WHEN 3 THEN 11 * 60 -- 11 hours = 660 minutes - WHEN 4 THEN 13 * 60 -- 13 hours = 780 minutes - WHEN 5 THEN 30 * 60 -- 30 hours = 1800 minutes - WHEN 6 THEN 10 * 60 -- 10 hours = 600 minutes - WHEN 7 THEN 15 * 60 -- 15 hours = 900 minutes - WHEN 8 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 9 THEN 32 * 60 -- 32 hours = 1920 minutes - WHEN 10 THEN 26 * 60 -- 26 hours = 1560 minutes - WHEN 11 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 12 THEN 28 * 60 -- 28 hours = 1680 minutes - WHEN 13 THEN 21 * 60 -- 21 hours = 1260 minutes - WHEN 14 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 15 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 16 THEN 20 * 60 -- 20 hours = 1200 minutes - WHEN 17 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 18 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 19 THEN 11 * 60 -- 11 hours = 660 minutes - END, - NOW() + (e.experiment_number + 1) * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 0 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 1 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 2 THEN 38 * 60 * INTERVAL '1 minute' -- 38 hours = 2280 minutes - WHEN 3 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - WHEN 4 THEN 13 * 60 * INTERVAL '1 minute' -- 13 hours = 780 minutes - WHEN 5 THEN 30 * 60 * INTERVAL '1 minute' -- 30 hours = 1800 minutes - WHEN 6 THEN 10 * 60 * INTERVAL '1 minute' -- 10 hours = 600 minutes - WHEN 7 THEN 15 * 60 * INTERVAL '1 minute' -- 15 hours = 900 minutes - WHEN 8 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 9 THEN 32 * 60 * INTERVAL '1 minute' -- 32 hours = 1920 minutes - WHEN 10 THEN 26 * 60 * INTERVAL '1 minute' -- 26 hours = 1560 minutes - WHEN 11 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 12 THEN 28 * 60 * INTERVAL '1 minute' -- 28 hours = 1680 minutes - WHEN 13 THEN 21 * 60 * INTERVAL '1 minute' -- 21 hours = 1260 minutes - WHEN 14 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 15 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 16 THEN 20 * 60 * INTERVAL '1 minute' -- 20 hours = 1200 minutes - WHEN 17 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 18 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 19 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 0 AND 19 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create airdrying records for Phase 2 JC experiments (0-19) with data from CSV -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number + 1) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 0 THEN 19 -- 19 minutes - WHEN 1 THEN 27 -- 27 minutes - WHEN 2 THEN 10 -- 10 minutes - WHEN 3 THEN 36 -- 36 minutes - WHEN 4 THEN 41 -- 41 minutes - WHEN 5 THEN 33 -- 33 minutes - WHEN 6 THEN 22 -- 22 minutes - WHEN 7 THEN 30 -- 30 minutes - WHEN 8 THEN 12 -- 12 minutes - WHEN 9 THEN 26 -- 26 minutes - WHEN 10 THEN 60 -- 60 minutes - WHEN 11 THEN 59 -- 59 minutes - WHEN 12 THEN 59 -- 59 minutes - WHEN 13 THEN 59 -- 59 minutes - WHEN 14 THEN 59 -- 59 minutes - WHEN 15 THEN 60 -- 60 minutes - WHEN 16 THEN 59 -- 59 minutes - WHEN 17 THEN 60 -- 60 minutes - WHEN 18 THEN 49 -- 49 minutes - WHEN 19 THEN 25 -- 25 minutes - END, - NOW() + (e.experiment_number + 1) * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 0 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 1 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 2 THEN 10 * INTERVAL '1 minute' -- 10 minutes - WHEN 3 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 4 THEN 41 * INTERVAL '1 minute' -- 41 minutes - WHEN 5 THEN 33 * INTERVAL '1 minute' -- 33 minutes - WHEN 6 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 7 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 8 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 9 THEN 26 * INTERVAL '1 minute' -- 26 minutes - WHEN 10 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 11 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 12 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 13 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 14 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 15 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 16 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 17 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 18 THEN 49 * INTERVAL '1 minute' -- 49 minutes - WHEN 19 THEN 25 * INTERVAL '1 minute' -- 25 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 0 AND 19 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create cracking records for Phase 2 JC experiments (0-19) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'JC Cracker'), - NOW() + (e.experiment_number + 1) * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 0 AND 19 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE JC CRACKER PARAMETERS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create JC cracker parameters for Phase 2 JC experiments (0-19) with data from CSV -INSERT INTO public.jc_cracker_parameters ( - cracking_id, - plate_contact_frequency_hz, - throughput_rate_pecans_sec, - crush_amount_in, - entry_exit_height_diff_in -) -SELECT - c.id, - CASE e.experiment_number - WHEN 0 THEN 53.0 - WHEN 1 THEN 34.0 - WHEN 2 THEN 60.0 - WHEN 3 THEN 42.0 - WHEN 4 THEN 41.0 - WHEN 5 THEN 30.0 - WHEN 6 THEN 37.0 - WHEN 7 THEN 35.0 - WHEN 8 THEN 55.0 - WHEN 9 THEN 47.0 - WHEN 10 THEN 44.0 - WHEN 11 THEN 42.0 - WHEN 12 THEN 37.0 - WHEN 13 THEN 41.0 - WHEN 14 THEN 45.0 - WHEN 15 THEN 30.0 - WHEN 16 THEN 41.0 - WHEN 17 THEN 34.0 - WHEN 18 THEN 38.0 - WHEN 19 THEN 56.0 - END, - CASE e.experiment_number - WHEN 0 THEN 28.0 - WHEN 1 THEN 29.0 - WHEN 2 THEN 28.0 - WHEN 3 THEN 13.0 - WHEN 4 THEN 38.0 - WHEN 5 THEN 36.0 - WHEN 6 THEN 30.0 - WHEN 7 THEN 32.0 - WHEN 8 THEN 24.0 - WHEN 9 THEN 26.0 - WHEN 10 THEN 12.0 - WHEN 11 THEN 25.0 - WHEN 12 THEN 23.0 - WHEN 13 THEN 21.0 - WHEN 14 THEN 17.0 - WHEN 15 THEN 24.0 - WHEN 16 THEN 14.0 - WHEN 17 THEN 29.0 - WHEN 18 THEN 35.0 - WHEN 19 THEN 34.0 - END, - CASE e.experiment_number - WHEN 0 THEN 0.05 - WHEN 1 THEN 0.03 - WHEN 2 THEN 0.06 - WHEN 3 THEN 0.07 - WHEN 4 THEN 0.05 - WHEN 5 THEN 0.05 - WHEN 6 THEN 0.06 - WHEN 7 THEN 0.05 - WHEN 8 THEN 0.04 - WHEN 9 THEN 0.07 - WHEN 10 THEN 0.08 - WHEN 11 THEN 0.07 - WHEN 12 THEN 0.06 - WHEN 13 THEN 0.06 - WHEN 14 THEN 0.07 - WHEN 15 THEN 0.07 - WHEN 16 THEN 0.07 - WHEN 17 THEN 0.07 - WHEN 18 THEN 0.07 - WHEN 19 THEN 0.06 - END, - CASE e.experiment_number - WHEN 0 THEN -0.09 - WHEN 1 THEN 0.01 - WHEN 2 THEN -0.10 - WHEN 3 THEN -0.07 - WHEN 4 THEN 0.03 - WHEN 5 THEN -0.04 - WHEN 6 THEN 0.02 - WHEN 7 THEN -0.07 - WHEN 8 THEN 0.04 - WHEN 9 THEN 0.03 - WHEN 10 THEN -0.10 - WHEN 11 THEN -0.05 - WHEN 12 THEN -0.08 - WHEN 13 THEN -0.09 - WHEN 14 THEN -0.08 - WHEN 15 THEN 0.02 - WHEN 16 THEN 0.04 - WHEN 17 THEN -0.09 - WHEN 18 THEN -0.08 - WHEN 19 THEN -0.09 - END -FROM public.experiments e -JOIN public.cracking c ON c.experiment_id = e.id -WHERE e.experiment_number BETWEEN 0 AND 19 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Phase 2 JC experiments --- Each experiment needs 3 repetitions -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - completion_status, - created_by -) -SELECT - e.id, - rep_num, - false, - e.created_by -FROM public.experiments e -CROSS JOIN generate_series(1, 3) AS rep_num -WHERE e.experiment_number BETWEEN 0 AND 19 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; diff --git a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_old.sql b/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_old.sql deleted file mode 100644 index f3c2072..0000000 --- a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_old.sql +++ /dev/null @@ -1,364 +0,0 @@ --- Phase 2 JC Experiments Seed Data --- This file contains all Phase 2 JC experiments from phase_2_experimental_run_sheet.csv --- Each experiment has 3 repetitions, and each row represents one repetition --- Updated to use 1-based numbering per phase and composite primary key - --- ============================================= --- INSERT PHASE 2 JC EXPERIMENTS --- ============================================= - --- First, insert unique experiments (based on experiment_number) -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Phase 2 JC Experiments 1-20 (1-based numbering) -(1, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(20, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create soaking records for Phase 2 JC experiments (1-20) -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_hours, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day', - CASE e.experiment_number - WHEN 1 THEN 34 -- hours - WHEN 2 THEN 24 - WHEN 3 THEN 38 - WHEN 4 THEN 11 - WHEN 5 THEN 13 - WHEN 6 THEN 30 - WHEN 7 THEN 10 - WHEN 8 THEN 15 - WHEN 9 THEN 27 - WHEN 10 THEN 32 - WHEN 11 THEN 26 - WHEN 12 THEN 24 - WHEN 13 THEN 28 - WHEN 14 THEN 21 - WHEN 15 THEN 22 - WHEN 16 THEN 16 - WHEN 17 THEN 20 - WHEN 18 THEN 34 - WHEN 19 THEN 18 - WHEN 20 THEN 11 - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 1 THEN 34 * INTERVAL '1 hour' - WHEN 2 THEN 24 * INTERVAL '1 hour' - WHEN 3 THEN 38 * INTERVAL '1 hour' - WHEN 4 THEN 11 * INTERVAL '1 hour' - WHEN 5 THEN 13 * INTERVAL '1 hour' - WHEN 6 THEN 30 * INTERVAL '1 hour' - WHEN 7 THEN 10 * INTERVAL '1 hour' - WHEN 8 THEN 15 * INTERVAL '1 hour' - WHEN 9 THEN 27 * INTERVAL '1 hour' - WHEN 10 THEN 32 * INTERVAL '1 hour' - WHEN 11 THEN 26 * INTERVAL '1 hour' - WHEN 12 THEN 24 * INTERVAL '1 hour' - WHEN 13 THEN 28 * INTERVAL '1 hour' - WHEN 14 THEN 21 * INTERVAL '1 hour' - WHEN 15 THEN 22 * INTERVAL '1 hour' - WHEN 16 THEN 16 * INTERVAL '1 hour' - WHEN 17 THEN 20 * INTERVAL '1 hour' - WHEN 18 THEN 34 * INTERVAL '1 hour' - WHEN 19 THEN 18 * INTERVAL '1 hour' - WHEN 20 THEN 11 * INTERVAL '1 hour' - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create airdrying records for Phase 2 JC experiments (1-20) -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 1 THEN 19 -- 19 minutes - WHEN 2 THEN 27 -- 27 minutes - WHEN 3 THEN 10 -- 10 minutes - WHEN 4 THEN 36 -- 36 minutes - WHEN 5 THEN 41 -- 41 minutes - WHEN 6 THEN 33 -- 33 minutes - WHEN 7 THEN 22 -- 22 minutes - WHEN 8 THEN 30 -- 30 minutes - WHEN 9 THEN 12 -- 12 minutes - WHEN 10 THEN 26 -- 26 minutes - WHEN 11 THEN 60 -- 60 minutes - WHEN 12 THEN 59 -- 59 minutes - WHEN 13 THEN 59 -- 59 minutes - WHEN 14 THEN 59 -- 59 minutes - WHEN 15 THEN 60 -- 60 minutes - WHEN 16 THEN 59 -- 59 minutes - WHEN 17 THEN 60 -- 60 minutes - WHEN 18 THEN 49 -- 49 minutes - WHEN 19 THEN 25 -- 25 minutes - WHEN 20 THEN 25 -- 25 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 1 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 2 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 3 THEN 10 * INTERVAL '1 minute' -- 10 minutes - WHEN 4 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 5 THEN 41 * INTERVAL '1 minute' -- 41 minutes - WHEN 6 THEN 33 * INTERVAL '1 minute' -- 33 minutes - WHEN 7 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 8 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 9 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 10 THEN 26 * INTERVAL '1 minute' -- 26 minutes - WHEN 11 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 12 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 13 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 14 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 15 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 16 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 17 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 18 THEN 49 * INTERVAL '1 minute' -- 49 minutes - WHEN 19 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 20 THEN 25 * INTERVAL '1 minute' -- 25 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create cracking records for Phase 2 JC experiments (1-20) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'JC Cracker'), - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE JC CRACKER PARAMETERS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create JC cracker parameters for Phase 2 JC experiments (1-20) -INSERT INTO public.jc_cracker_parameters ( - cracking_id, - plate_contact_frequency_hz, - throughput_rate_pecans_sec, - crush_amount_in, - entry_exit_height_diff_in -) -SELECT - c.id, - CASE e.experiment_number - WHEN 1 THEN 53.0 - WHEN 2 THEN 34.0 - WHEN 3 THEN 60.0 - WHEN 4 THEN 42.0 - WHEN 5 THEN 41.0 - WHEN 6 THEN 30.0 - WHEN 7 THEN 37.0 - WHEN 8 THEN 35.0 - WHEN 9 THEN 55.0 - WHEN 10 THEN 47.0 - WHEN 11 THEN 44.0 - WHEN 12 THEN 42.0 - WHEN 13 THEN 37.0 - WHEN 14 THEN 41.0 - WHEN 15 THEN 45.0 - WHEN 16 THEN 30.0 - WHEN 17 THEN 41.0 - WHEN 18 THEN 34.0 - WHEN 19 THEN 38.0 - WHEN 20 THEN 56.0 - END, - CASE e.experiment_number - WHEN 1 THEN 28.0 - WHEN 2 THEN 29.0 - WHEN 3 THEN 28.0 - WHEN 4 THEN 13.0 - WHEN 5 THEN 38.0 - WHEN 6 THEN 36.0 - WHEN 7 THEN 30.0 - WHEN 8 THEN 32.0 - WHEN 9 THEN 24.0 - WHEN 10 THEN 26.0 - WHEN 11 THEN 12.0 - WHEN 12 THEN 25.0 - WHEN 13 THEN 23.0 - WHEN 14 THEN 21.0 - WHEN 15 THEN 17.0 - WHEN 16 THEN 24.0 - WHEN 17 THEN 14.0 - WHEN 18 THEN 29.0 - WHEN 19 THEN 35.0 - WHEN 20 THEN 34.0 - END, - CASE e.experiment_number - WHEN 1 THEN 0.05 - WHEN 2 THEN 0.03 - WHEN 3 THEN 0.06 - WHEN 4 THEN 0.07 - WHEN 5 THEN 0.05 - WHEN 6 THEN 0.05 - WHEN 7 THEN 0.06 - WHEN 8 THEN 0.05 - WHEN 9 THEN 0.04 - WHEN 10 THEN 0.07 - WHEN 11 THEN 0.08 - WHEN 12 THEN 0.07 - WHEN 13 THEN 0.06 - WHEN 14 THEN 0.06 - WHEN 15 THEN 0.07 - WHEN 16 THEN 0.07 - WHEN 17 THEN 0.07 - WHEN 18 THEN 0.07 - WHEN 19 THEN 0.07 - WHEN 20 THEN 0.06 - END, - CASE e.experiment_number - WHEN 1 THEN -0.09 - WHEN 2 THEN 0.01 - WHEN 3 THEN -0.10 - WHEN 4 THEN -0.07 - WHEN 5 THEN 0.03 - WHEN 6 THEN -0.04 - WHEN 7 THEN 0.02 - WHEN 8 THEN -0.07 - WHEN 9 THEN 0.04 - WHEN 10 THEN 0.03 - WHEN 11 THEN -0.10 - WHEN 12 THEN -0.05 - WHEN 13 THEN -0.08 - WHEN 14 THEN -0.09 - WHEN 15 THEN -0.08 - WHEN 16 THEN 0.02 - WHEN 17 THEN 0.04 - WHEN 18 THEN -0.09 - WHEN 19 THEN -0.08 - WHEN 20 THEN -0.09 - END -FROM public.experiments e -JOIN public.cracking c ON c.experiment_id = e.id -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Phase 2 JC experiments --- Each experiment needs 3 repetitions -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - status, - created_by -) -SELECT - e.id, - rep_num, - 'pending', - e.created_by -FROM public.experiments e -CROSS JOIN generate_series(1, 3) AS rep_num -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; diff --git a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_updated.sql b/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_updated.sql deleted file mode 100644 index 46f6748..0000000 --- a/management-dashboard-web-app/supabase/seed_04_phase2_jc_experiments_updated.sql +++ /dev/null @@ -1,384 +0,0 @@ --- Phase 2 JC Experiments Seed Data --- This file contains all Phase 2 JC experiments from phase_2_experimental_run_sheet.csv --- Each experiment has 3 repetitions, and each row represents one repetition --- Updated to use 1-based numbering per phase and composite primary key - --- ============================================= --- INSERT PHASE 2 JC EXPERIMENTS --- ============================================= - --- First, insert unique experiments (based on experiment_number) -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Phase 2 JC Experiments 1-20 (1-based numbering) -(1, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(20, 3, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create soaking records for Phase 2 JC experiments (1-20) -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day', - CASE e.experiment_number - WHEN 1 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 2 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 3 THEN 38 * 60 -- 38 hours = 2280 minutes - WHEN 4 THEN 11 * 60 -- 11 hours = 660 minutes - WHEN 5 THEN 13 * 60 -- 13 hours = 780 minutes - WHEN 6 THEN 30 * 60 -- 30 hours = 1800 minutes - WHEN 7 THEN 10 * 60 -- 10 hours = 600 minutes - WHEN 8 THEN 15 * 60 -- 15 hours = 900 minutes - WHEN 9 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 10 THEN 32 * 60 -- 32 hours = 1920 minutes - WHEN 11 THEN 26 * 60 -- 26 hours = 1560 minutes - WHEN 12 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 13 THEN 28 * 60 -- 28 hours = 1680 minutes - WHEN 14 THEN 21 * 60 -- 21 hours = 1260 minutes - WHEN 15 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 16 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 17 THEN 20 * 60 -- 20 hours = 1200 minutes - WHEN 18 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 19 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 20 THEN 11 * 60 -- 11 hours = 660 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 1 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 2 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 3 THEN 38 * 60 * INTERVAL '1 minute' -- 38 hours = 2280 minutes - WHEN 4 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - WHEN 5 THEN 13 * 60 * INTERVAL '1 minute' -- 13 hours = 780 minutes - WHEN 6 THEN 30 * 60 * INTERVAL '1 minute' -- 30 hours = 1800 minutes - WHEN 7 THEN 10 * 60 * INTERVAL '1 minute' -- 10 hours = 600 minutes - WHEN 8 THEN 15 * 60 * INTERVAL '1 minute' -- 15 hours = 900 minutes - WHEN 9 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 10 THEN 32 * 60 * INTERVAL '1 minute' -- 32 hours = 1920 minutes - WHEN 11 THEN 26 * 60 * INTERVAL '1 minute' -- 26 hours = 1560 minutes - WHEN 12 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 13 THEN 28 * 60 * INTERVAL '1 minute' -- 28 hours = 1680 minutes - WHEN 14 THEN 21 * 60 * INTERVAL '1 minute' -- 21 hours = 1260 minutes - WHEN 15 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 16 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 17 THEN 20 * 60 * INTERVAL '1 minute' -- 20 hours = 1200 minutes - WHEN 18 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 19 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 20 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create airdrying records for Phase 2 JC experiments (1-20) -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 1 THEN 19 -- 19 minutes - WHEN 2 THEN 27 -- 27 minutes - WHEN 3 THEN 10 -- 10 minutes - WHEN 4 THEN 36 -- 36 minutes - WHEN 5 THEN 41 -- 41 minutes - WHEN 6 THEN 33 -- 33 minutes - WHEN 7 THEN 22 -- 22 minutes - WHEN 8 THEN 30 -- 30 minutes - WHEN 9 THEN 12 -- 12 minutes - WHEN 10 THEN 26 -- 26 minutes - WHEN 11 THEN 60 -- 60 minutes - WHEN 12 THEN 59 -- 59 minutes - WHEN 13 THEN 59 -- 59 minutes - WHEN 14 THEN 59 -- 59 minutes - WHEN 15 THEN 60 -- 60 minutes - WHEN 16 THEN 59 -- 59 minutes - WHEN 17 THEN 60 -- 60 minutes - WHEN 18 THEN 49 -- 49 minutes - WHEN 19 THEN 25 -- 25 minutes - WHEN 20 THEN 25 -- 25 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 1 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 2 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 3 THEN 10 * INTERVAL '1 minute' -- 10 minutes - WHEN 4 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 5 THEN 41 * INTERVAL '1 minute' -- 41 minutes - WHEN 6 THEN 33 * INTERVAL '1 minute' -- 33 minutes - WHEN 7 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 8 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 9 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 10 THEN 26 * INTERVAL '1 minute' -- 26 minutes - WHEN 11 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 12 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 13 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 14 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 15 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 16 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 17 THEN 60 * INTERVAL '1 minute' -- 60 minutes - WHEN 18 THEN 49 * INTERVAL '1 minute' -- 49 minutes - WHEN 19 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 20 THEN 25 * INTERVAL '1 minute' -- 25 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create cracking records for Phase 2 JC experiments (1-20) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'JC Cracker'), - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE JC CRACKER PARAMETERS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create JC cracker parameters for Phase 2 JC experiments (1-20) --- First create the JC cracker parameters -INSERT INTO public.jc_cracker_parameters ( - plate_contact_frequency_hz, - throughput_rate_pecans_sec, - crush_amount_in, - entry_exit_height_diff_in -) -SELECT - CASE e.experiment_number - WHEN 1 THEN 53.0 - WHEN 2 THEN 34.0 - WHEN 3 THEN 60.0 - WHEN 4 THEN 42.0 - WHEN 5 THEN 41.0 - WHEN 6 THEN 30.0 - WHEN 7 THEN 37.0 - WHEN 8 THEN 35.0 - WHEN 9 THEN 55.0 - WHEN 10 THEN 47.0 - WHEN 11 THEN 44.0 - WHEN 12 THEN 42.0 - WHEN 13 THEN 37.0 - WHEN 14 THEN 41.0 - WHEN 15 THEN 45.0 - WHEN 16 THEN 30.0 - WHEN 17 THEN 41.0 - WHEN 18 THEN 34.0 - WHEN 19 THEN 38.0 - WHEN 20 THEN 56.0 - END, - CASE e.experiment_number - WHEN 1 THEN 28.0 - WHEN 2 THEN 29.0 - WHEN 3 THEN 28.0 - WHEN 4 THEN 13.0 - WHEN 5 THEN 38.0 - WHEN 6 THEN 36.0 - WHEN 7 THEN 30.0 - WHEN 8 THEN 32.0 - WHEN 9 THEN 24.0 - WHEN 10 THEN 26.0 - WHEN 11 THEN 12.0 - WHEN 12 THEN 25.0 - WHEN 13 THEN 23.0 - WHEN 14 THEN 21.0 - WHEN 15 THEN 17.0 - WHEN 16 THEN 24.0 - WHEN 17 THEN 14.0 - WHEN 18 THEN 29.0 - WHEN 19 THEN 35.0 - WHEN 20 THEN 34.0 - END, - CASE e.experiment_number - WHEN 1 THEN 0.05 - WHEN 2 THEN 0.03 - WHEN 3 THEN 0.06 - WHEN 4 THEN 0.07 - WHEN 5 THEN 0.05 - WHEN 6 THEN 0.05 - WHEN 7 THEN 0.06 - WHEN 8 THEN 0.05 - WHEN 9 THEN 0.04 - WHEN 10 THEN 0.07 - WHEN 11 THEN 0.08 - WHEN 12 THEN 0.07 - WHEN 13 THEN 0.06 - WHEN 14 THEN 0.06 - WHEN 15 THEN 0.07 - WHEN 16 THEN 0.07 - WHEN 17 THEN 0.07 - WHEN 18 THEN 0.07 - WHEN 19 THEN 0.07 - WHEN 20 THEN 0.06 - END, - CASE e.experiment_number - WHEN 1 THEN -0.09 - WHEN 2 THEN 0.01 - WHEN 3 THEN -0.10 - WHEN 4 THEN -0.07 - WHEN 5 THEN 0.03 - WHEN 6 THEN -0.04 - WHEN 7 THEN 0.02 - WHEN 8 THEN -0.07 - WHEN 9 THEN 0.04 - WHEN 10 THEN 0.03 - WHEN 11 THEN -0.10 - WHEN 12 THEN -0.05 - WHEN 13 THEN -0.08 - WHEN 14 THEN -0.09 - WHEN 15 THEN -0.08 - WHEN 16 THEN 0.02 - WHEN 17 THEN 0.04 - WHEN 18 THEN -0.09 - WHEN 19 THEN -0.08 - WHEN 20 THEN -0.09 - END -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - --- Now update the cracking records to reference the JC cracker parameters --- Match them by the order they were created -WITH parameter_mapping AS ( - SELECT - e.experiment_number, - jcp.id as param_id, - ROW_NUMBER() OVER (ORDER BY e.experiment_number) as exp_rn, - ROW_NUMBER() OVER (ORDER BY jcp.created_at) as param_rn - FROM public.experiments e - CROSS JOIN public.jc_cracker_parameters jcp - WHERE e.experiment_number BETWEEN 1 AND 20 - AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -) -UPDATE public.cracking c -SET jc_cracker_parameters_id = pm.param_id -FROM parameter_mapping pm -JOIN public.experiments e ON c.experiment_id = e.id -WHERE e.experiment_number = pm.experiment_number -AND pm.exp_rn = pm.param_rn -AND c.jc_cracker_parameters_id IS NULL; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR PHASE 2 JC EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Phase 2 JC experiments --- Each experiment needs 3 repetitions -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - status, - created_by -) -SELECT - e.id, - rep_num, - 'pending', - e.created_by -FROM public.experiments e -CROSS JOIN generate_series(1, 3) AS rep_num -WHERE e.experiment_number BETWEEN 1 AND 20 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Phase 2 of JC Experiments') -ON CONFLICT DO NOTHING; - diff --git a/management-dashboard-web-app/supabase/seed_05_meyer_experiments.sql b/management-dashboard-web-app/supabase/seed_05_meyer_experiments.sql deleted file mode 100644 index 929ebf0..0000000 --- a/management-dashboard-web-app/supabase/seed_05_meyer_experiments.sql +++ /dev/null @@ -1,540 +0,0 @@ --- Meyer Experiments Seed Data (Corrected) --- This file contains all 40 Meyer experiments from post_workshop_meyer_experiments.csv --- Each experiment has only 1 repetition required --- Updated to match the actual CSV data with correct experiment numbers and parameters - --- ============================================= --- INSERT MEYER EXPERIMENTS (Post Workshop) --- ============================================= - --- Insert Meyer experiments (experiments 1-40) with data from CSV -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Meyer Experiments 1-40 (matching CSV data) -(1, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(20, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(21, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(22, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(23, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(24, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(25, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(26, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(27, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(28, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(29, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(30, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(31, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(32, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(33, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(34, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(35, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(36, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(37, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(38, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(39, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(40, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create soaking records for Meyer experiments (1-40) with data from CSV -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + e.experiment_number * INTERVAL '1 day', - CASE e.experiment_number - WHEN 1 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 2 THEN 37 * 60 -- 37 hours = 2220 minutes - WHEN 3 THEN 36 * 60 -- 36 hours = 2160 minutes - WHEN 4 THEN 12 * 60 -- 12 hours = 720 minutes - WHEN 5 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 6 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 7 THEN 14 * 60 -- 14 hours = 840 minutes - WHEN 8 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 9 THEN 11 * 60 -- 11 hours = 660 minutes - WHEN 10 THEN 33 * 60 -- 33 hours = 1980 minutes - WHEN 11 THEN 23 * 60 -- 23 hours = 1380 minutes - WHEN 12 THEN 37 * 60 -- 37 hours = 2220 minutes - WHEN 13 THEN 15 * 60 -- 15 hours = 900 minutes - WHEN 14 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 15 THEN 36 * 60 -- 36 hours = 2160 minutes - WHEN 16 THEN 32 * 60 -- 32 hours = 1920 minutes - WHEN 17 THEN 28 * 60 -- 28 hours = 1680 minutes - WHEN 18 THEN 31 * 60 -- 31 hours = 1860 minutes - WHEN 19 THEN 20 * 60 -- 20 hours = 1200 minutes - WHEN 20 THEN 10 * 60 -- 10 hours = 600 minutes - WHEN 21 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 22 THEN 21 * 60 -- 21 hours = 1260 minutes - WHEN 23 THEN 42 * 60 -- 42 hours = 2520 minutes - WHEN 24 THEN 29 * 60 -- 29 hours = 1740 minutes - WHEN 25 THEN 54 * 60 -- 54 hours = 3240 minutes - WHEN 26 THEN 29 * 60 -- 29 hours = 1740 minutes - WHEN 27 THEN 30 * 60 -- 30 hours = 1800 minutes - WHEN 28 THEN 35 * 60 -- 35 hours = 2100 minutes - WHEN 29 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 30 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 31 THEN 17 * 60 -- 17 hours = 1020 minutes - WHEN 32 THEN 13 * 60 -- 13 hours = 780 minutes - WHEN 33 THEN 19 * 60 -- 19 hours = 1140 minutes - WHEN 34 THEN 38 * 60 -- 38 hours = 2280 minutes - WHEN 35 THEN 26 * 60 -- 26 hours = 1560 minutes - WHEN 36 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 37 THEN 12 * 60 -- 12 hours = 720 minutes - WHEN 38 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 39 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 40 THEN 24 * 60 -- 24 hours = 1440 minutes - END, - NOW() + e.experiment_number * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 1 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 2 THEN 37 * 60 * INTERVAL '1 minute' -- 37 hours = 2220 minutes - WHEN 3 THEN 36 * 60 * INTERVAL '1 minute' -- 36 hours = 2160 minutes - WHEN 4 THEN 12 * 60 * INTERVAL '1 minute' -- 12 hours = 720 minutes - WHEN 5 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 6 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 7 THEN 14 * 60 * INTERVAL '1 minute' -- 14 hours = 840 minutes - WHEN 8 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 9 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - WHEN 10 THEN 33 * 60 * INTERVAL '1 minute' -- 33 hours = 1980 minutes - WHEN 11 THEN 23 * 60 * INTERVAL '1 minute' -- 23 hours = 1380 minutes - WHEN 12 THEN 37 * 60 * INTERVAL '1 minute' -- 37 hours = 2220 minutes - WHEN 13 THEN 15 * 60 * INTERVAL '1 minute' -- 15 hours = 900 minutes - WHEN 14 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 15 THEN 36 * 60 * INTERVAL '1 minute' -- 36 hours = 2160 minutes - WHEN 16 THEN 32 * 60 * INTERVAL '1 minute' -- 32 hours = 1920 minutes - WHEN 17 THEN 28 * 60 * INTERVAL '1 minute' -- 28 hours = 1680 minutes - WHEN 18 THEN 31 * 60 * INTERVAL '1 minute' -- 31 hours = 1860 minutes - WHEN 19 THEN 20 * 60 * INTERVAL '1 minute' -- 20 hours = 1200 minutes - WHEN 20 THEN 10 * 60 * INTERVAL '1 minute' -- 10 hours = 600 minutes - WHEN 21 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 22 THEN 21 * 60 * INTERVAL '1 minute' -- 21 hours = 1260 minutes - WHEN 23 THEN 42 * 60 * INTERVAL '1 minute' -- 42 hours = 2520 minutes - WHEN 24 THEN 29 * 60 * INTERVAL '1 minute' -- 29 hours = 1740 minutes - WHEN 25 THEN 54 * 60 * INTERVAL '1 minute' -- 54 hours = 3240 minutes - WHEN 26 THEN 29 * 60 * INTERVAL '1 minute' -- 29 hours = 1740 minutes - WHEN 27 THEN 30 * 60 * INTERVAL '1 minute' -- 30 hours = 1800 minutes - WHEN 28 THEN 35 * 60 * INTERVAL '1 minute' -- 35 hours = 2100 minutes - WHEN 29 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 30 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 31 THEN 17 * 60 * INTERVAL '1 minute' -- 17 hours = 1020 minutes - WHEN 32 THEN 13 * 60 * INTERVAL '1 minute' -- 13 hours = 780 minutes - WHEN 33 THEN 19 * 60 * INTERVAL '1 minute' -- 19 hours = 1140 minutes - WHEN 34 THEN 38 * 60 * INTERVAL '1 minute' -- 38 hours = 2280 minutes - WHEN 35 THEN 26 * 60 * INTERVAL '1 minute' -- 26 hours = 1560 minutes - WHEN 36 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 37 THEN 12 * 60 * INTERVAL '1 minute' -- 12 hours = 720 minutes - WHEN 38 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 39 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 40 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create airdrying records for Meyer experiments (1-40) with data from CSV -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + e.experiment_number * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 1 THEN 28 -- 28 minutes - WHEN 2 THEN 17 -- 17 minutes - WHEN 3 THEN 50 -- 50 minutes - WHEN 4 THEN 30 -- 30 minutes - WHEN 5 THEN 19 -- 19 minutes - WHEN 6 THEN 40 -- 40 minutes - WHEN 7 THEN 59 -- 59 minutes - WHEN 8 THEN 32 -- 32 minutes - WHEN 9 THEN 31 -- 31 minutes - WHEN 10 THEN 12 -- 12 minutes - WHEN 11 THEN 36 -- 36 minutes - WHEN 12 THEN 35 -- 35 minutes - WHEN 13 THEN 15 -- 15 minutes - WHEN 14 THEN 22 -- 22 minutes - WHEN 15 THEN 15 -- 15 minutes - WHEN 16 THEN 48 -- 48 minutes - WHEN 17 THEN 38 -- 38 minutes - WHEN 18 THEN 51 -- 51 minutes - WHEN 19 THEN 57 -- 57 minutes - WHEN 20 THEN 27 -- 27 minutes - WHEN 21 THEN 43 -- 43 minutes - WHEN 22 THEN 42 -- 42 minutes - WHEN 23 THEN 21 -- 21 minutes - WHEN 24 THEN 46 -- 46 minutes - WHEN 25 THEN 54 -- 54 minutes - WHEN 26 THEN 54 -- 54 minutes - WHEN 27 THEN 48 -- 48 minutes - WHEN 28 THEN 53 -- 53 minutes - WHEN 29 THEN 39 -- 39 minutes - WHEN 30 THEN 38 -- 38 minutes - WHEN 31 THEN 25 -- 25 minutes - WHEN 32 THEN 22 -- 22 minutes - WHEN 33 THEN 11 -- 11 minutes - WHEN 34 THEN 32 -- 32 minutes - WHEN 35 THEN 18 -- 18 minutes - WHEN 36 THEN 52 -- 52 minutes - WHEN 37 THEN 56 -- 56 minutes - WHEN 38 THEN 45 -- 45 minutes - WHEN 39 THEN 25 -- 25 minutes - WHEN 40 THEN 13 -- 13 minutes - END, - NOW() + e.experiment_number * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 1 THEN 28 * INTERVAL '1 minute' -- 28 minutes - WHEN 2 THEN 17 * INTERVAL '1 minute' -- 17 minutes - WHEN 3 THEN 50 * INTERVAL '1 minute' -- 50 minutes - WHEN 4 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 5 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 6 THEN 40 * INTERVAL '1 minute' -- 40 minutes - WHEN 7 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 8 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 9 THEN 31 * INTERVAL '1 minute' -- 31 minutes - WHEN 10 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 11 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 12 THEN 35 * INTERVAL '1 minute' -- 35 minutes - WHEN 13 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 14 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 15 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 16 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 17 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 18 THEN 51 * INTERVAL '1 minute' -- 51 minutes - WHEN 19 THEN 57 * INTERVAL '1 minute' -- 57 minutes - WHEN 20 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 21 THEN 43 * INTERVAL '1 minute' -- 43 minutes - WHEN 22 THEN 42 * INTERVAL '1 minute' -- 42 minutes - WHEN 23 THEN 21 * INTERVAL '1 minute' -- 21 minutes - WHEN 24 THEN 46 * INTERVAL '1 minute' -- 46 minutes - WHEN 25 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 26 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 27 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 28 THEN 53 * INTERVAL '1 minute' -- 53 minutes - WHEN 29 THEN 39 * INTERVAL '1 minute' -- 39 minutes - WHEN 30 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 31 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 32 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 33 THEN 11 * INTERVAL '1 minute' -- 11 minutes - WHEN 34 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 35 THEN 18 * INTERVAL '1 minute' -- 18 minutes - WHEN 36 THEN 52 * INTERVAL '1 minute' -- 52 minutes - WHEN 37 THEN 56 * INTERVAL '1 minute' -- 56 minutes - WHEN 38 THEN 45 * INTERVAL '1 minute' -- 45 minutes - WHEN 39 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 40 THEN 13 * INTERVAL '1 minute' -- 13 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create cracking records for Meyer experiments (1-40) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'Meyer Cracker'), - NOW() + e.experiment_number * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE MEYER CRACKER PARAMETERS FOR MEYER EXPERIMENTS --- ============================================= - --- Create Meyer cracker parameters for Meyer experiments (1-40) with data from CSV -INSERT INTO public.meyer_cracker_parameters ( - cracking_id, - motor_speed_hz, - jig_displacement_inches, - spring_stiffness_nm -) -SELECT - c.id, - CASE e.experiment_number - WHEN 1 THEN 33.0 - WHEN 2 THEN 30.0 - WHEN 3 THEN 47.0 - WHEN 4 THEN 42.0 - WHEN 5 THEN 53.0 - WHEN 6 THEN 37.0 - WHEN 7 THEN 40.0 - WHEN 8 THEN 39.0 - WHEN 9 THEN 49.0 - WHEN 10 THEN 47.0 - WHEN 11 THEN 52.0 - WHEN 12 THEN 59.0 - WHEN 13 THEN 41.0 - WHEN 14 THEN 46.0 - WHEN 15 THEN 50.0 - WHEN 16 THEN 36.0 - WHEN 17 THEN 33.0 - WHEN 18 THEN 35.0 - WHEN 19 THEN 55.0 - WHEN 20 THEN 44.0 - WHEN 21 THEN 37.0 - WHEN 22 THEN 56.0 - WHEN 23 THEN 30.0 - WHEN 24 THEN 60.0 - WHEN 25 THEN 41.0 - WHEN 26 THEN 55.0 - WHEN 27 THEN 39.0 - WHEN 28 THEN 34.0 - WHEN 29 THEN 57.0 - WHEN 30 THEN 45.0 - WHEN 31 THEN 52.0 - WHEN 32 THEN 51.0 - WHEN 33 THEN 36.0 - WHEN 34 THEN 44.0 - WHEN 35 THEN 58.0 - WHEN 36 THEN 32.0 - WHEN 37 THEN 43.0 - WHEN 38 THEN 60.0 - WHEN 39 THEN 54.0 - WHEN 40 THEN 48.0 - END, - CASE e.experiment_number - WHEN 1 THEN -0.307 - WHEN 2 THEN -0.311 - WHEN 3 THEN -0.291 - WHEN 4 THEN -0.314 - WHEN 5 THEN -0.302 - WHEN 6 THEN -0.301 - WHEN 7 THEN -0.286 - WHEN 8 THEN -0.309 - WHEN 9 THEN -0.299 - WHEN 10 THEN -0.295 - WHEN 11 THEN -0.302 - WHEN 12 THEN -0.299 - WHEN 13 THEN -0.312 - WHEN 14 THEN -0.303 - WHEN 15 THEN -0.308 - WHEN 16 THEN -0.306 - WHEN 17 THEN -0.308 - WHEN 18 THEN -0.311 - WHEN 19 THEN -0.304 - WHEN 20 THEN -0.313 - WHEN 21 THEN -0.294 - WHEN 22 THEN -0.310 - WHEN 23 THEN -0.292 - WHEN 24 THEN -0.294 - WHEN 25 THEN -0.306 - WHEN 26 THEN -0.296 - WHEN 27 THEN -0.293 - WHEN 28 THEN -0.285 - WHEN 29 THEN -0.291 - WHEN 30 THEN -0.296 - WHEN 31 THEN -0.297 - WHEN 32 THEN -0.288 - WHEN 33 THEN -0.290 - WHEN 34 THEN -0.315 - WHEN 35 THEN -0.289 - WHEN 36 THEN -0.288 - WHEN 37 THEN -0.287 - WHEN 38 THEN -0.298 - WHEN 39 THEN -0.301 - WHEN 40 THEN -0.305 - END, - CASE e.experiment_number - WHEN 1 THEN 1800.0 - WHEN 2 THEN 2000.0 - WHEN 3 THEN 1800.0 - WHEN 4 THEN 2000.0 - WHEN 5 THEN 1800.0 - WHEN 6 THEN 2200.0 - WHEN 7 THEN 2000.0 - WHEN 8 THEN 1800.0 - WHEN 9 THEN 2200.0 - WHEN 10 THEN 2000.0 - WHEN 11 THEN 2000.0 - WHEN 12 THEN 1800.0 - WHEN 13 THEN 2000.0 - WHEN 14 THEN 1800.0 - WHEN 15 THEN 1800.0 - WHEN 16 THEN 2200.0 - WHEN 17 THEN 2200.0 - WHEN 18 THEN 1800.0 - WHEN 19 THEN 2000.0 - WHEN 20 THEN 2200.0 - WHEN 21 THEN 2000.0 - WHEN 22 THEN 2200.0 - WHEN 23 THEN 2200.0 - WHEN 24 THEN 2200.0 - WHEN 25 THEN 2000.0 - WHEN 26 THEN 1800.0 - WHEN 27 THEN 2200.0 - WHEN 28 THEN 2200.0 - WHEN 29 THEN 1800.0 - WHEN 30 THEN 2200.0 - WHEN 31 THEN 1800.0 - WHEN 32 THEN 2200.0 - WHEN 33 THEN 2000.0 - WHEN 34 THEN 1800.0 - WHEN 35 THEN 1800.0 - WHEN 36 THEN 1800.0 - WHEN 37 THEN 2200.0 - WHEN 38 THEN 2200.0 - WHEN 39 THEN 2000.0 - WHEN 40 THEN 2000.0 - END -FROM public.experiments e -JOIN public.cracking c ON c.experiment_id = e.id -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR MEYER EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Meyer experiments --- Each experiment needs only 1 repetition -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - completion_status, - created_by -) -SELECT - e.id, - 1, - false, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; diff --git a/management-dashboard-web-app/supabase/seed_05_meyer_experiments_old.sql b/management-dashboard-web-app/supabase/seed_05_meyer_experiments_old.sql deleted file mode 100644 index 54f34da..0000000 --- a/management-dashboard-web-app/supabase/seed_05_meyer_experiments_old.sql +++ /dev/null @@ -1,540 +0,0 @@ --- Meyer Experiments Seed Data --- This file contains all 40 Meyer experiments from meyer experiments.csv --- Each experiment has only 1 repetition required --- Updated to use 1-based numbering per phase and composite primary key - --- ============================================= --- INSERT MEYER EXPERIMENTS (Post Workshop) --- ============================================= - --- Insert Meyer experiments (experiments 1-40) -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Meyer Experiments 1-40 (1-based numbering) -(1, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(20, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(21, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(22, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(23, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(24, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(25, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(26, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(27, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(28, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(29, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(30, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(31, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(32, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(33, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(34, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(35, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(36, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(37, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(38, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(39, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(40, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create soaking records for Meyer experiments (1-40) -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_hours, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day', - CASE e.experiment_number - WHEN 1 THEN 27 -- hours - WHEN 2 THEN 37 - WHEN 3 THEN 36 - WHEN 4 THEN 12 - WHEN 5 THEN 34 - WHEN 6 THEN 18 - WHEN 7 THEN 14 - WHEN 8 THEN 18 - WHEN 9 THEN 11 - WHEN 10 THEN 33 - WHEN 11 THEN 23 - WHEN 12 THEN 37 - WHEN 13 THEN 15 - WHEN 14 THEN 24 - WHEN 15 THEN 36 - WHEN 16 THEN 32 - WHEN 17 THEN 28 - WHEN 18 THEN 31 - WHEN 19 THEN 20 - WHEN 20 THEN 10 - WHEN 21 THEN 16 - WHEN 22 THEN 21 - WHEN 23 THEN 42 - WHEN 24 THEN 29 - WHEN 25 THEN 54 - WHEN 26 THEN 29 - WHEN 27 THEN 30 - WHEN 28 THEN 35 - WHEN 29 THEN 27 - WHEN 30 THEN 27 - WHEN 31 THEN 17 - WHEN 32 THEN 13 - WHEN 33 THEN 19 - WHEN 34 THEN 38 - WHEN 35 THEN 26 - WHEN 36 THEN 22 - WHEN 37 THEN 12 - WHEN 38 THEN 16 - WHEN 39 THEN 22 - WHEN 40 THEN 24 - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 1 THEN 27 * INTERVAL '1 hour' - WHEN 2 THEN 37 * INTERVAL '1 hour' - WHEN 3 THEN 36 * INTERVAL '1 hour' - WHEN 4 THEN 12 * INTERVAL '1 hour' - WHEN 5 THEN 34 * INTERVAL '1 hour' - WHEN 6 THEN 18 * INTERVAL '1 hour' - WHEN 7 THEN 14 * INTERVAL '1 hour' - WHEN 8 THEN 18 * INTERVAL '1 hour' - WHEN 9 THEN 11 * INTERVAL '1 hour' - WHEN 10 THEN 33 * INTERVAL '1 hour' - WHEN 11 THEN 23 * INTERVAL '1 hour' - WHEN 12 THEN 37 * INTERVAL '1 hour' - WHEN 13 THEN 15 * INTERVAL '1 hour' - WHEN 14 THEN 24 * INTERVAL '1 hour' - WHEN 15 THEN 36 * INTERVAL '1 hour' - WHEN 16 THEN 32 * INTERVAL '1 hour' - WHEN 17 THEN 28 * INTERVAL '1 hour' - WHEN 18 THEN 31 * INTERVAL '1 hour' - WHEN 19 THEN 20 * INTERVAL '1 hour' - WHEN 20 THEN 10 * INTERVAL '1 hour' - WHEN 21 THEN 16 * INTERVAL '1 hour' - WHEN 22 THEN 21 * INTERVAL '1 hour' - WHEN 23 THEN 42 * INTERVAL '1 hour' - WHEN 24 THEN 29 * INTERVAL '1 hour' - WHEN 25 THEN 54 * INTERVAL '1 hour' - WHEN 26 THEN 29 * INTERVAL '1 hour' - WHEN 27 THEN 30 * INTERVAL '1 hour' - WHEN 28 THEN 35 * INTERVAL '1 hour' - WHEN 29 THEN 27 * INTERVAL '1 hour' - WHEN 30 THEN 27 * INTERVAL '1 hour' - WHEN 31 THEN 17 * INTERVAL '1 hour' - WHEN 32 THEN 13 * INTERVAL '1 hour' - WHEN 33 THEN 19 * INTERVAL '1 hour' - WHEN 34 THEN 38 * INTERVAL '1 hour' - WHEN 35 THEN 26 * INTERVAL '1 hour' - WHEN 36 THEN 22 * INTERVAL '1 hour' - WHEN 37 THEN 12 * INTERVAL '1 hour' - WHEN 38 THEN 16 * INTERVAL '1 hour' - WHEN 39 THEN 22 * INTERVAL '1 hour' - WHEN 40 THEN 24 * INTERVAL '1 hour' - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create airdrying records for Meyer experiments (1-40) -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 1 THEN 28 -- 28 minutes - WHEN 2 THEN 17 -- 17 minutes - WHEN 3 THEN 50 -- 50 minutes - WHEN 4 THEN 30 -- 30 minutes - WHEN 5 THEN 19 -- 19 minutes - WHEN 6 THEN 40 -- 40 minutes - WHEN 7 THEN 59 -- 59 minutes - WHEN 8 THEN 32 -- 32 minutes - WHEN 9 THEN 31 -- 31 minutes - WHEN 10 THEN 12 -- 12 minutes - WHEN 11 THEN 36 -- 36 minutes - WHEN 12 THEN 35 -- 35 minutes - WHEN 13 THEN 15 -- 15 minutes - WHEN 14 THEN 22 -- 22 minutes - WHEN 15 THEN 15 -- 15 minutes - WHEN 16 THEN 48 -- 48 minutes - WHEN 17 THEN 38 -- 38 minutes - WHEN 18 THEN 51 -- 51 minutes - WHEN 19 THEN 57 -- 57 minutes - WHEN 20 THEN 27 -- 27 minutes - WHEN 21 THEN 43 -- 43 minutes - WHEN 22 THEN 42 -- 42 minutes - WHEN 23 THEN 21 -- 21 minutes - WHEN 24 THEN 46 -- 46 minutes - WHEN 25 THEN 54 -- 54 minutes - WHEN 26 THEN 54 -- 54 minutes - WHEN 27 THEN 48 -- 48 minutes - WHEN 28 THEN 53 -- 53 minutes - WHEN 29 THEN 39 -- 39 minutes - WHEN 30 THEN 38 -- 38 minutes - WHEN 31 THEN 25 -- 25 minutes - WHEN 32 THEN 22 -- 22 minutes - WHEN 33 THEN 11 -- 11 minutes - WHEN 34 THEN 32 -- 32 minutes - WHEN 35 THEN 18 -- 18 minutes - WHEN 36 THEN 52 -- 52 minutes - WHEN 37 THEN 56 -- 56 minutes - WHEN 38 THEN 45 -- 45 minutes - WHEN 39 THEN 25 -- 25 minutes - WHEN 40 THEN 13 -- 13 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 1 THEN 28 * INTERVAL '1 minute' -- 28 minutes - WHEN 2 THEN 17 * INTERVAL '1 minute' -- 17 minutes - WHEN 3 THEN 50 * INTERVAL '1 minute' -- 50 minutes - WHEN 4 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 5 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 6 THEN 40 * INTERVAL '1 minute' -- 40 minutes - WHEN 7 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 8 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 9 THEN 31 * INTERVAL '1 minute' -- 31 minutes - WHEN 10 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 11 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 12 THEN 35 * INTERVAL '1 minute' -- 35 minutes - WHEN 13 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 14 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 15 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 16 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 17 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 18 THEN 51 * INTERVAL '1 minute' -- 51 minutes - WHEN 19 THEN 57 * INTERVAL '1 minute' -- 57 minutes - WHEN 20 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 21 THEN 43 * INTERVAL '1 minute' -- 43 minutes - WHEN 22 THEN 42 * INTERVAL '1 minute' -- 42 minutes - WHEN 23 THEN 21 * INTERVAL '1 minute' -- 21 minutes - WHEN 24 THEN 46 * INTERVAL '1 minute' -- 46 minutes - WHEN 25 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 26 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 27 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 28 THEN 53 * INTERVAL '1 minute' -- 53 minutes - WHEN 29 THEN 39 * INTERVAL '1 minute' -- 39 minutes - WHEN 30 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 31 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 32 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 33 THEN 11 * INTERVAL '1 minute' -- 11 minutes - WHEN 34 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 35 THEN 18 * INTERVAL '1 minute' -- 18 minutes - WHEN 36 THEN 52 * INTERVAL '1 minute' -- 52 minutes - WHEN 37 THEN 56 * INTERVAL '1 minute' -- 56 minutes - WHEN 38 THEN 45 * INTERVAL '1 minute' -- 45 minutes - WHEN 39 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 40 THEN 13 * INTERVAL '1 minute' -- 13 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create cracking records for Meyer experiments (1-40) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'Meyer Cracker'), - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE MEYER CRACKER PARAMETERS FOR MEYER EXPERIMENTS --- ============================================= - --- Create Meyer cracker parameters for Meyer experiments (1-40) -INSERT INTO public.meyer_cracker_parameters ( - cracking_id, - motor_speed_hz, - jig_displacement_inches, - spring_stiffness_nm -) -SELECT - c.id, - CASE e.experiment_number - WHEN 1 THEN 33.0 - WHEN 2 THEN 30.0 - WHEN 3 THEN 47.0 - WHEN 4 THEN 42.0 - WHEN 5 THEN 53.0 - WHEN 6 THEN 37.0 - WHEN 7 THEN 40.0 - WHEN 8 THEN 39.0 - WHEN 9 THEN 49.0 - WHEN 10 THEN 47.0 - WHEN 11 THEN 52.0 - WHEN 12 THEN 59.0 - WHEN 13 THEN 41.0 - WHEN 14 THEN 46.0 - WHEN 15 THEN 50.0 - WHEN 16 THEN 36.0 - WHEN 17 THEN 33.0 - WHEN 18 THEN 35.0 - WHEN 19 THEN 55.0 - WHEN 20 THEN 44.0 - WHEN 21 THEN 37.0 - WHEN 22 THEN 56.0 - WHEN 23 THEN 30.0 - WHEN 24 THEN 60.0 - WHEN 25 THEN 41.0 - WHEN 26 THEN 55.0 - WHEN 27 THEN 39.0 - WHEN 28 THEN 34.0 - WHEN 29 THEN 57.0 - WHEN 30 THEN 45.0 - WHEN 31 THEN 52.0 - WHEN 32 THEN 51.0 - WHEN 33 THEN 36.0 - WHEN 34 THEN 44.0 - WHEN 35 THEN 58.0 - WHEN 36 THEN 32.0 - WHEN 37 THEN 43.0 - WHEN 38 THEN 60.0 - WHEN 39 THEN 54.0 - WHEN 40 THEN 48.0 - END, - CASE e.experiment_number - WHEN 1 THEN -0.307 - WHEN 2 THEN -0.311 - WHEN 3 THEN -0.291 - WHEN 4 THEN -0.314 - WHEN 5 THEN -0.302 - WHEN 6 THEN -0.301 - WHEN 7 THEN -0.286 - WHEN 8 THEN -0.309 - WHEN 9 THEN -0.299 - WHEN 10 THEN -0.295 - WHEN 11 THEN -0.302 - WHEN 12 THEN -0.299 - WHEN 13 THEN -0.312 - WHEN 14 THEN -0.303 - WHEN 15 THEN -0.308 - WHEN 16 THEN -0.306 - WHEN 17 THEN -0.308 - WHEN 18 THEN -0.311 - WHEN 19 THEN -0.304 - WHEN 20 THEN -0.313 - WHEN 21 THEN -0.294 - WHEN 22 THEN -0.310 - WHEN 23 THEN -0.292 - WHEN 24 THEN -0.294 - WHEN 25 THEN -0.306 - WHEN 26 THEN -0.296 - WHEN 27 THEN -0.293 - WHEN 28 THEN -0.285 - WHEN 29 THEN -0.291 - WHEN 30 THEN -0.296 - WHEN 31 THEN -0.297 - WHEN 32 THEN -0.288 - WHEN 33 THEN -0.290 - WHEN 34 THEN -0.315 - WHEN 35 THEN -0.289 - WHEN 36 THEN -0.288 - WHEN 37 THEN -0.287 - WHEN 38 THEN -0.298 - WHEN 39 THEN -0.301 - WHEN 40 THEN -0.305 - END, - CASE e.experiment_number - WHEN 1 THEN 1800.0 - WHEN 2 THEN 2000.0 - WHEN 3 THEN 1800.0 - WHEN 4 THEN 2000.0 - WHEN 5 THEN 1800.0 - WHEN 6 THEN 2200.0 - WHEN 7 THEN 2000.0 - WHEN 8 THEN 1800.0 - WHEN 9 THEN 2200.0 - WHEN 10 THEN 2000.0 - WHEN 11 THEN 2000.0 - WHEN 12 THEN 1800.0 - WHEN 13 THEN 2000.0 - WHEN 14 THEN 1800.0 - WHEN 15 THEN 1800.0 - WHEN 16 THEN 2200.0 - WHEN 17 THEN 2200.0 - WHEN 18 THEN 1800.0 - WHEN 19 THEN 2000.0 - WHEN 20 THEN 2200.0 - WHEN 21 THEN 2000.0 - WHEN 22 THEN 2200.0 - WHEN 23 THEN 2200.0 - WHEN 24 THEN 2200.0 - WHEN 25 THEN 2000.0 - WHEN 26 THEN 1800.0 - WHEN 27 THEN 2200.0 - WHEN 28 THEN 2200.0 - WHEN 29 THEN 1800.0 - WHEN 30 THEN 2200.0 - WHEN 31 THEN 1800.0 - WHEN 32 THEN 2200.0 - WHEN 33 THEN 2000.0 - WHEN 34 THEN 1800.0 - WHEN 35 THEN 1800.0 - WHEN 36 THEN 1800.0 - WHEN 37 THEN 2200.0 - WHEN 38 THEN 2200.0 - WHEN 39 THEN 2000.0 - WHEN 40 THEN 2000.0 - END -FROM public.experiments e -JOIN public.cracking c ON c.experiment_id = e.id -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR MEYER EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Meyer experiments --- Each experiment needs only 1 repetition -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - status, - created_by -) -SELECT - e.id, - 1, - 'pending', - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; diff --git a/management-dashboard-web-app/supabase/seed_05_meyer_experiments_updated.sql b/management-dashboard-web-app/supabase/seed_05_meyer_experiments_updated.sql deleted file mode 100644 index d4dd2fb..0000000 --- a/management-dashboard-web-app/supabase/seed_05_meyer_experiments_updated.sql +++ /dev/null @@ -1,560 +0,0 @@ --- Meyer Experiments Seed Data --- This file contains all 40 Meyer experiments from meyer experiments.csv --- Each experiment has only 1 repetition required --- Updated to use 1-based numbering per phase and composite primary key - --- ============================================= --- INSERT MEYER EXPERIMENTS (Post Workshop) --- ============================================= - --- Insert Meyer experiments (experiments 1-40) -INSERT INTO public.experiments ( - experiment_number, - reps_required, - results_status, - completion_status, - phase_id, - created_by -) VALUES --- Meyer Experiments 1-40 (1-based numbering) -(1, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(2, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(3, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(4, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(5, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(6, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(7, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(8, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(9, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(10, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(11, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(12, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(13, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(14, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(15, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(16, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(17, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(18, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(19, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(20, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(21, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(22, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(23, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(24, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(25, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(26, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(27, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(28, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(29, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(30, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(31, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(32, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(33, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(34, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(35, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(36, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(37, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(38, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(39, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')), -(40, 1, 'valid', false, - (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments'), - (SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')) -ON CONFLICT (experiment_number, phase_id) DO NOTHING; - --- ============================================= --- CREATE SOAKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create soaking records for Meyer experiments (1-40) -INSERT INTO public.soaking ( - experiment_id, - scheduled_start_time, - soaking_duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day', - CASE e.experiment_number - WHEN 1 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 2 THEN 37 * 60 -- 37 hours = 2220 minutes - WHEN 3 THEN 36 * 60 -- 36 hours = 2160 minutes - WHEN 4 THEN 12 * 60 -- 12 hours = 720 minutes - WHEN 5 THEN 34 * 60 -- 34 hours = 2040 minutes - WHEN 6 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 7 THEN 14 * 60 -- 14 hours = 840 minutes - WHEN 8 THEN 18 * 60 -- 18 hours = 1080 minutes - WHEN 9 THEN 11 * 60 -- 11 hours = 660 minutes - WHEN 10 THEN 33 * 60 -- 33 hours = 1980 minutes - WHEN 11 THEN 23 * 60 -- 23 hours = 1380 minutes - WHEN 12 THEN 37 * 60 -- 37 hours = 2220 minutes - WHEN 13 THEN 15 * 60 -- 15 hours = 900 minutes - WHEN 14 THEN 24 * 60 -- 24 hours = 1440 minutes - WHEN 15 THEN 36 * 60 -- 36 hours = 2160 minutes - WHEN 16 THEN 32 * 60 -- 32 hours = 1920 minutes - WHEN 17 THEN 28 * 60 -- 28 hours = 1680 minutes - WHEN 18 THEN 31 * 60 -- 31 hours = 1860 minutes - WHEN 19 THEN 20 * 60 -- 20 hours = 1200 minutes - WHEN 20 THEN 10 * 60 -- 10 hours = 600 minutes - WHEN 21 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 22 THEN 21 * 60 -- 21 hours = 1260 minutes - WHEN 23 THEN 42 * 60 -- 42 hours = 2520 minutes - WHEN 24 THEN 29 * 60 -- 29 hours = 1740 minutes - WHEN 25 THEN 54 * 60 -- 54 hours = 3240 minutes - WHEN 26 THEN 29 * 60 -- 29 hours = 1740 minutes - WHEN 27 THEN 30 * 60 -- 30 hours = 1800 minutes - WHEN 28 THEN 35 * 60 -- 35 hours = 2100 minutes - WHEN 29 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 30 THEN 27 * 60 -- 27 hours = 1620 minutes - WHEN 31 THEN 17 * 60 -- 17 hours = 1020 minutes - WHEN 32 THEN 13 * 60 -- 13 hours = 780 minutes - WHEN 33 THEN 19 * 60 -- 19 hours = 1140 minutes - WHEN 34 THEN 38 * 60 -- 38 hours = 2280 minutes - WHEN 35 THEN 26 * 60 -- 26 hours = 1560 minutes - WHEN 36 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 37 THEN 12 * 60 -- 12 hours = 720 minutes - WHEN 38 THEN 16 * 60 -- 16 hours = 960 minutes - WHEN 39 THEN 22 * 60 -- 22 hours = 1320 minutes - WHEN 40 THEN 24 * 60 -- 24 hours = 1440 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + - CASE e.experiment_number - WHEN 1 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 2 THEN 37 * 60 * INTERVAL '1 minute' -- 37 hours = 2220 minutes - WHEN 3 THEN 36 * 60 * INTERVAL '1 minute' -- 36 hours = 2160 minutes - WHEN 4 THEN 12 * 60 * INTERVAL '1 minute' -- 12 hours = 720 minutes - WHEN 5 THEN 34 * 60 * INTERVAL '1 minute' -- 34 hours = 2040 minutes - WHEN 6 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 7 THEN 14 * 60 * INTERVAL '1 minute' -- 14 hours = 840 minutes - WHEN 8 THEN 18 * 60 * INTERVAL '1 minute' -- 18 hours = 1080 minutes - WHEN 9 THEN 11 * 60 * INTERVAL '1 minute' -- 11 hours = 660 minutes - WHEN 10 THEN 33 * 60 * INTERVAL '1 minute' -- 33 hours = 1980 minutes - WHEN 11 THEN 23 * 60 * INTERVAL '1 minute' -- 23 hours = 1380 minutes - WHEN 12 THEN 37 * 60 * INTERVAL '1 minute' -- 37 hours = 2220 minutes - WHEN 13 THEN 15 * 60 * INTERVAL '1 minute' -- 15 hours = 900 minutes - WHEN 14 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - WHEN 15 THEN 36 * 60 * INTERVAL '1 minute' -- 36 hours = 2160 minutes - WHEN 16 THEN 32 * 60 * INTERVAL '1 minute' -- 32 hours = 1920 minutes - WHEN 17 THEN 28 * 60 * INTERVAL '1 minute' -- 28 hours = 1680 minutes - WHEN 18 THEN 31 * 60 * INTERVAL '1 minute' -- 31 hours = 1860 minutes - WHEN 19 THEN 20 * 60 * INTERVAL '1 minute' -- 20 hours = 1200 minutes - WHEN 20 THEN 10 * 60 * INTERVAL '1 minute' -- 10 hours = 600 minutes - WHEN 21 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 22 THEN 21 * 60 * INTERVAL '1 minute' -- 21 hours = 1260 minutes - WHEN 23 THEN 42 * 60 * INTERVAL '1 minute' -- 42 hours = 2520 minutes - WHEN 24 THEN 29 * 60 * INTERVAL '1 minute' -- 29 hours = 1740 minutes - WHEN 25 THEN 54 * 60 * INTERVAL '1 minute' -- 54 hours = 3240 minutes - WHEN 26 THEN 29 * 60 * INTERVAL '1 minute' -- 29 hours = 1740 minutes - WHEN 27 THEN 30 * 60 * INTERVAL '1 minute' -- 30 hours = 1800 minutes - WHEN 28 THEN 35 * 60 * INTERVAL '1 minute' -- 35 hours = 2100 minutes - WHEN 29 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 30 THEN 27 * 60 * INTERVAL '1 minute' -- 27 hours = 1620 minutes - WHEN 31 THEN 17 * 60 * INTERVAL '1 minute' -- 17 hours = 1020 minutes - WHEN 32 THEN 13 * 60 * INTERVAL '1 minute' -- 13 hours = 780 minutes - WHEN 33 THEN 19 * 60 * INTERVAL '1 minute' -- 19 hours = 1140 minutes - WHEN 34 THEN 38 * 60 * INTERVAL '1 minute' -- 38 hours = 2280 minutes - WHEN 35 THEN 26 * 60 * INTERVAL '1 minute' -- 26 hours = 1560 minutes - WHEN 36 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 37 THEN 12 * 60 * INTERVAL '1 minute' -- 12 hours = 720 minutes - WHEN 38 THEN 16 * 60 * INTERVAL '1 minute' -- 16 hours = 960 minutes - WHEN 39 THEN 22 * 60 * INTERVAL '1 minute' -- 22 hours = 1320 minutes - WHEN 40 THEN 24 * 60 * INTERVAL '1 minute' -- 24 hours = 1440 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE AIRDRYING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create airdrying records for Meyer experiments (1-40) -INSERT INTO public.airdrying ( - experiment_id, - scheduled_start_time, - duration_minutes, - scheduled_end_time, - created_by -) -SELECT - e.id, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking - CASE e.experiment_number - WHEN 1 THEN 28 -- 28 minutes - WHEN 2 THEN 17 -- 17 minutes - WHEN 3 THEN 50 -- 50 minutes - WHEN 4 THEN 30 -- 30 minutes - WHEN 5 THEN 19 -- 19 minutes - WHEN 6 THEN 40 -- 40 minutes - WHEN 7 THEN 59 -- 59 minutes - WHEN 8 THEN 32 -- 32 minutes - WHEN 9 THEN 31 -- 31 minutes - WHEN 10 THEN 12 -- 12 minutes - WHEN 11 THEN 36 -- 36 minutes - WHEN 12 THEN 35 -- 35 minutes - WHEN 13 THEN 15 -- 15 minutes - WHEN 14 THEN 22 -- 22 minutes - WHEN 15 THEN 15 -- 15 minutes - WHEN 16 THEN 48 -- 48 minutes - WHEN 17 THEN 38 -- 38 minutes - WHEN 18 THEN 51 -- 51 minutes - WHEN 19 THEN 57 -- 57 minutes - WHEN 20 THEN 27 -- 27 minutes - WHEN 21 THEN 43 -- 43 minutes - WHEN 22 THEN 42 -- 42 minutes - WHEN 23 THEN 21 -- 21 minutes - WHEN 24 THEN 46 -- 46 minutes - WHEN 25 THEN 54 -- 54 minutes - WHEN 26 THEN 54 -- 54 minutes - WHEN 27 THEN 48 -- 48 minutes - WHEN 28 THEN 53 -- 53 minutes - WHEN 29 THEN 39 -- 39 minutes - WHEN 30 THEN 38 -- 38 minutes - WHEN 31 THEN 25 -- 25 minutes - WHEN 32 THEN 22 -- 22 minutes - WHEN 33 THEN 11 -- 11 minutes - WHEN 34 THEN 32 -- 32 minutes - WHEN 35 THEN 18 -- 18 minutes - WHEN 36 THEN 52 -- 52 minutes - WHEN 37 THEN 56 -- 56 minutes - WHEN 38 THEN 45 -- 45 minutes - WHEN 39 THEN 25 -- 25 minutes - WHEN 40 THEN 13 -- 13 minutes - END, - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days' + - CASE e.experiment_number - WHEN 1 THEN 28 * INTERVAL '1 minute' -- 28 minutes - WHEN 2 THEN 17 * INTERVAL '1 minute' -- 17 minutes - WHEN 3 THEN 50 * INTERVAL '1 minute' -- 50 minutes - WHEN 4 THEN 30 * INTERVAL '1 minute' -- 30 minutes - WHEN 5 THEN 19 * INTERVAL '1 minute' -- 19 minutes - WHEN 6 THEN 40 * INTERVAL '1 minute' -- 40 minutes - WHEN 7 THEN 59 * INTERVAL '1 minute' -- 59 minutes - WHEN 8 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 9 THEN 31 * INTERVAL '1 minute' -- 31 minutes - WHEN 10 THEN 12 * INTERVAL '1 minute' -- 12 minutes - WHEN 11 THEN 36 * INTERVAL '1 minute' -- 36 minutes - WHEN 12 THEN 35 * INTERVAL '1 minute' -- 35 minutes - WHEN 13 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 14 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 15 THEN 15 * INTERVAL '1 minute' -- 15 minutes - WHEN 16 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 17 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 18 THEN 51 * INTERVAL '1 minute' -- 51 minutes - WHEN 19 THEN 57 * INTERVAL '1 minute' -- 57 minutes - WHEN 20 THEN 27 * INTERVAL '1 minute' -- 27 minutes - WHEN 21 THEN 43 * INTERVAL '1 minute' -- 43 minutes - WHEN 22 THEN 42 * INTERVAL '1 minute' -- 42 minutes - WHEN 23 THEN 21 * INTERVAL '1 minute' -- 21 minutes - WHEN 24 THEN 46 * INTERVAL '1 minute' -- 46 minutes - WHEN 25 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 26 THEN 54 * INTERVAL '1 minute' -- 54 minutes - WHEN 27 THEN 48 * INTERVAL '1 minute' -- 48 minutes - WHEN 28 THEN 53 * INTERVAL '1 minute' -- 53 minutes - WHEN 29 THEN 39 * INTERVAL '1 minute' -- 39 minutes - WHEN 30 THEN 38 * INTERVAL '1 minute' -- 38 minutes - WHEN 31 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 32 THEN 22 * INTERVAL '1 minute' -- 22 minutes - WHEN 33 THEN 11 * INTERVAL '1 minute' -- 11 minutes - WHEN 34 THEN 32 * INTERVAL '1 minute' -- 32 minutes - WHEN 35 THEN 18 * INTERVAL '1 minute' -- 18 minutes - WHEN 36 THEN 52 * INTERVAL '1 minute' -- 52 minutes - WHEN 37 THEN 56 * INTERVAL '1 minute' -- 56 minutes - WHEN 38 THEN 45 * INTERVAL '1 minute' -- 45 minutes - WHEN 39 THEN 25 * INTERVAL '1 minute' -- 25 minutes - WHEN 40 THEN 13 * INTERVAL '1 minute' -- 13 minutes - END, - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE CRACKING PHASE RECORDS FOR MEYER EXPERIMENTS --- ============================================= - --- Create cracking records for Meyer experiments (1-40) -INSERT INTO public.cracking ( - experiment_id, - machine_type_id, - scheduled_start_time, - created_by -) -SELECT - e.id, - (SELECT id FROM public.machine_types WHERE name = 'Meyer Cracker'), - NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '3 days', -- Start 3 days after soaking - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- ============================================= --- CREATE MEYER CRACKER PARAMETERS FOR MEYER EXPERIMENTS --- ============================================= - --- Create Meyer cracker parameters for Meyer experiments (1-40) --- First create the Meyer cracker parameters -INSERT INTO public.meyer_cracker_parameters ( - motor_speed_hz, - jig_displacement_inches, - spring_stiffness_nm -) -SELECT - CASE e.experiment_number - WHEN 1 THEN 33.0 - WHEN 2 THEN 30.0 - WHEN 3 THEN 47.0 - WHEN 4 THEN 42.0 - WHEN 5 THEN 53.0 - WHEN 6 THEN 37.0 - WHEN 7 THEN 40.0 - WHEN 8 THEN 39.0 - WHEN 9 THEN 49.0 - WHEN 10 THEN 47.0 - WHEN 11 THEN 52.0 - WHEN 12 THEN 59.0 - WHEN 13 THEN 41.0 - WHEN 14 THEN 46.0 - WHEN 15 THEN 50.0 - WHEN 16 THEN 36.0 - WHEN 17 THEN 33.0 - WHEN 18 THEN 35.0 - WHEN 19 THEN 55.0 - WHEN 20 THEN 44.0 - WHEN 21 THEN 37.0 - WHEN 22 THEN 56.0 - WHEN 23 THEN 30.0 - WHEN 24 THEN 60.0 - WHEN 25 THEN 41.0 - WHEN 26 THEN 55.0 - WHEN 27 THEN 39.0 - WHEN 28 THEN 34.0 - WHEN 29 THEN 57.0 - WHEN 30 THEN 45.0 - WHEN 31 THEN 52.0 - WHEN 32 THEN 51.0 - WHEN 33 THEN 36.0 - WHEN 34 THEN 44.0 - WHEN 35 THEN 58.0 - WHEN 36 THEN 32.0 - WHEN 37 THEN 43.0 - WHEN 38 THEN 60.0 - WHEN 39 THEN 54.0 - WHEN 40 THEN 48.0 - END, - CASE e.experiment_number - WHEN 1 THEN -0.307 - WHEN 2 THEN -0.311 - WHEN 3 THEN -0.291 - WHEN 4 THEN -0.314 - WHEN 5 THEN -0.302 - WHEN 6 THEN -0.301 - WHEN 7 THEN -0.286 - WHEN 8 THEN -0.309 - WHEN 9 THEN -0.299 - WHEN 10 THEN -0.295 - WHEN 11 THEN -0.302 - WHEN 12 THEN -0.299 - WHEN 13 THEN -0.312 - WHEN 14 THEN -0.303 - WHEN 15 THEN -0.308 - WHEN 16 THEN -0.306 - WHEN 17 THEN -0.308 - WHEN 18 THEN -0.311 - WHEN 19 THEN -0.304 - WHEN 20 THEN -0.313 - WHEN 21 THEN -0.294 - WHEN 22 THEN -0.310 - WHEN 23 THEN -0.292 - WHEN 24 THEN -0.294 - WHEN 25 THEN -0.306 - WHEN 26 THEN -0.296 - WHEN 27 THEN -0.293 - WHEN 28 THEN -0.285 - WHEN 29 THEN -0.291 - WHEN 30 THEN -0.296 - WHEN 31 THEN -0.297 - WHEN 32 THEN -0.288 - WHEN 33 THEN -0.290 - WHEN 34 THEN -0.315 - WHEN 35 THEN -0.289 - WHEN 36 THEN -0.288 - WHEN 37 THEN -0.287 - WHEN 38 THEN -0.298 - WHEN 39 THEN -0.301 - WHEN 40 THEN -0.305 - END, - CASE e.experiment_number - WHEN 1 THEN 1800.0 - WHEN 2 THEN 2000.0 - WHEN 3 THEN 1800.0 - WHEN 4 THEN 2000.0 - WHEN 5 THEN 1800.0 - WHEN 6 THEN 2200.0 - WHEN 7 THEN 2000.0 - WHEN 8 THEN 1800.0 - WHEN 9 THEN 2200.0 - WHEN 10 THEN 2000.0 - WHEN 11 THEN 2000.0 - WHEN 12 THEN 1800.0 - WHEN 13 THEN 2000.0 - WHEN 14 THEN 1800.0 - WHEN 15 THEN 1800.0 - WHEN 16 THEN 2200.0 - WHEN 17 THEN 2200.0 - WHEN 18 THEN 1800.0 - WHEN 19 THEN 2000.0 - WHEN 20 THEN 2200.0 - WHEN 21 THEN 2000.0 - WHEN 22 THEN 2200.0 - WHEN 23 THEN 2200.0 - WHEN 24 THEN 2200.0 - WHEN 25 THEN 2000.0 - WHEN 26 THEN 1800.0 - WHEN 27 THEN 2200.0 - WHEN 28 THEN 2200.0 - WHEN 29 THEN 1800.0 - WHEN 30 THEN 2200.0 - WHEN 31 THEN 1800.0 - WHEN 32 THEN 2200.0 - WHEN 33 THEN 2000.0 - WHEN 34 THEN 1800.0 - WHEN 35 THEN 1800.0 - WHEN 36 THEN 1800.0 - WHEN 37 THEN 2200.0 - WHEN 38 THEN 2200.0 - WHEN 39 THEN 2000.0 - WHEN 40 THEN 2000.0 - END -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; - --- Now update the cracking records to reference the Meyer cracker parameters --- Match them by the order they were created -WITH parameter_mapping AS ( - SELECT - e.experiment_number, - mcp.id as param_id, - ROW_NUMBER() OVER (ORDER BY e.experiment_number) as exp_rn, - ROW_NUMBER() OVER (ORDER BY mcp.created_at) as param_rn - FROM public.experiments e - CROSS JOIN public.meyer_cracker_parameters mcp - WHERE e.experiment_number BETWEEN 1 AND 40 - AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -) -UPDATE public.cracking c -SET meyer_cracker_parameters_id = pm.param_id -FROM parameter_mapping pm -JOIN public.experiments e ON c.experiment_id = e.id -WHERE e.experiment_number = pm.experiment_number -AND pm.exp_rn = pm.param_rn -AND c.meyer_cracker_parameters_id IS NULL; - --- ============================================= --- CREATE EXPERIMENT REPETITIONS FOR MEYER EXPERIMENTS --- ============================================= - --- Create experiment repetitions for Meyer experiments --- Each experiment needs only 1 repetition -INSERT INTO public.experiment_repetitions ( - experiment_id, - repetition_number, - status, - created_by -) -SELECT - e.id, - 1, - 'pending', - e.created_by -FROM public.experiments e -WHERE e.experiment_number BETWEEN 1 AND 40 -AND e.phase_id = (SELECT id FROM public.experiment_phases WHERE name = 'Post Workshop Meyer Experiments') -ON CONFLICT DO NOTHING; -