Remove deprecated CSV files and update experiment seeding scripts
- Deleted unused CSV files: 'meyer experiments.csv' and 'phase_2_experimental_run_sheet.csv'. - Updated SQL seed scripts to reflect changes in experiment data structure and ensure consistency with the latest experiment parameters. - Enhanced user role assignments in the seed data to include 'conductor' alongside 'data recorder'. - Adjusted experiment seeding logic to align with the corrected data from the CSV files.
This commit is contained in:
118
management-dashboard-web-app/SEED_DATA_CORRECTIONS.md
Normal file
118
management-dashboard-web-app/SEED_DATA_CORRECTIONS.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Seed Data Corrections
|
||||
|
||||
## Problem Identified
|
||||
|
||||
The "Schedule Experiment" component was showing "undefined" for soaking duration in the top right panel. This was caused by a mismatch between the database schema and frontend expectations:
|
||||
|
||||
- **Database**: Used `soaking_duration_hours` column
|
||||
- **Frontend**: Expected `soaking_duration_minutes` field
|
||||
- **Seed Files**: Were trying to insert into non-existent `soaking_duration_minutes` column
|
||||
|
||||
## Root Cause
|
||||
|
||||
1. The migration `20250101000004_data_entry_tables.sql` created the `soaking` table with `soaking_duration_hours` column
|
||||
2. The frontend TypeScript interfaces and UI code expected `soaking_duration_minutes`
|
||||
3. The seed files were updated to use `soaking_duration_minutes` but the database schema wasn't updated accordingly
|
||||
4. This caused the frontend to receive `undefined` when trying to access `soaking.soaking_duration_minutes`
|
||||
|
||||
## Solution Implemented
|
||||
|
||||
### 1. Database Schema Fix
|
||||
**File**: `supabase/migrations/20250103000001_fix_soaking_duration_column.sql`
|
||||
- Added `soaking_duration_minutes` INTEGER column
|
||||
- Backfilled data from `soaking_duration_hours * 60`
|
||||
- Updated trigger function to use minutes
|
||||
- Dropped the old `soaking_duration_hours` column
|
||||
|
||||
### 2. Views Update
|
||||
**File**: `supabase/migrations/20250103000002_update_views_for_soaking_minutes.sql`
|
||||
- Updated `experiments_with_phases` view to use `soaking_duration_minutes`
|
||||
- Updated `repetitions_with_phases` view to use `soaking_duration_minutes`
|
||||
|
||||
### 3. Corrected Seed Files
|
||||
|
||||
#### Phase 2 JC Experiments
|
||||
**File**: `supabase/seed_04_phase2_jc_experiments_corrected.sql`
|
||||
- **Experiment Numbers**: 0-19 (matching CSV data, not 1-20)
|
||||
- **Soaking Duration**: Converted from hours to minutes (e.g., 34 hours = 2040 minutes)
|
||||
- **Air Drying Duration**: Used exact values from CSV (19-60 minutes)
|
||||
- **JC Cracker Parameters**: All parameters match CSV data exactly
|
||||
- **Repetitions**: Each experiment has 3 repetitions as specified
|
||||
|
||||
#### Meyer Experiments
|
||||
**File**: `supabase/seed_05_meyer_experiments_corrected.sql`
|
||||
- **Experiment Numbers**: 1-40 (matching CSV data)
|
||||
- **Soaking Duration**: Converted from hours to minutes (e.g., 27 hours = 1620 minutes)
|
||||
- **Air Drying Duration**: Used exact values from CSV (11-56 minutes)
|
||||
- **Meyer Cracker Parameters**: All parameters match CSV data exactly
|
||||
- **Repetitions**: Each experiment has 1 repetition as specified
|
||||
|
||||
## Data Mapping from CSV
|
||||
|
||||
### Phase 2 JC Experiments (phase_2_JC_experimental_run_sheet.csv)
|
||||
- **Unique Experiments**: 20 (numbers 0-19)
|
||||
- **Repetitions per Experiment**: 3
|
||||
- **Soaking Duration Range**: 10-38 hours (600-2280 minutes)
|
||||
- **Air Drying Duration Range**: 10-60 minutes
|
||||
- **Machine Type**: JC Cracker
|
||||
|
||||
### Meyer Experiments (post_workshop_meyer_experiments.csv)
|
||||
- **Unique Experiments**: 40 (numbers 1-40)
|
||||
- **Repetitions per Experiment**: 1
|
||||
- **Soaking Duration Range**: 10-54 hours (600-3240 minutes)
|
||||
- **Air Drying Duration Range**: 11-56 minutes
|
||||
- **Machine Type**: Meyer Cracker
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
### New Migration Files
|
||||
1. `supabase/migrations/20250103000001_fix_soaking_duration_column.sql`
|
||||
2. `supabase/migrations/20250103000002_update_views_for_soaking_minutes.sql`
|
||||
|
||||
### New Seed Files
|
||||
1. `supabase/seed_04_phase2_jc_experiments_corrected.sql`
|
||||
2. `supabase/seed_05_meyer_experiments_corrected.sql`
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
1. **Run the migrations in order**:
|
||||
```sql
|
||||
-- First fix the column
|
||||
\i supabase/migrations/20250103000001_fix_soaking_duration_column.sql
|
||||
|
||||
-- Then update the views
|
||||
\i supabase/migrations/20250103000002_update_views_for_soaking_minutes.sql
|
||||
```
|
||||
|
||||
2. **Clear existing data and run corrected seeds**:
|
||||
```sql
|
||||
-- Clear existing data (optional, use with caution)
|
||||
DELETE FROM public.experiment_repetitions;
|
||||
DELETE FROM public.jc_cracker_parameters;
|
||||
DELETE FROM public.meyer_cracker_parameters;
|
||||
DELETE FROM public.cracking;
|
||||
DELETE FROM public.airdrying;
|
||||
DELETE FROM public.soaking;
|
||||
DELETE FROM public.experiments;
|
||||
|
||||
-- Run corrected seed files
|
||||
\i supabase/seed_04_phase2_jc_experiments_corrected.sql
|
||||
\i supabase/seed_05_meyer_experiments_corrected.sql
|
||||
```
|
||||
|
||||
## Expected Result
|
||||
|
||||
After applying these changes:
|
||||
- The "Schedule Experiment" component will show correct soaking durations in minutes
|
||||
- All experiment data will match the CSV source files exactly
|
||||
- The database schema will be consistent with frontend expectations
|
||||
- Phase timing calculations will work correctly
|
||||
|
||||
## Verification
|
||||
|
||||
To verify the fix:
|
||||
1. Check that `soaking.soaking_duration_minutes` is populated in the database
|
||||
2. Verify the Schedule Experiment UI shows durations like "2040min" instead of "undefined"
|
||||
3. Confirm experiment numbers match the CSV files (0-19 for JC, 1-40 for Meyer)
|
||||
4. Validate that all machine parameters match the CSV data
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
Motor Speed (Hz),Soaking Time (hr),Air Drying Time (min),Jig Displacement (in),Spring Stiffness (N/m)
|
||||
33,27,28,-0.307,1800
|
||||
30,37,17,-0.311,2000
|
||||
47,36,50,-0.291,1800
|
||||
42,12,30,-0.314,2000
|
||||
53,34,19,-0.302,1800
|
||||
37,18,40,-0.301,2200
|
||||
40,14,59,-0.286,2000
|
||||
39,18,32,-0.309,1800
|
||||
49,11,31,-0.299,2200
|
||||
47,33,12,-0.295,2000
|
||||
52,23,36,-0.302,2000
|
||||
59,37,35,-0.299,1800
|
||||
41,15,15,-0.312,2000
|
||||
46,24,22,-0.303,1800
|
||||
50,36,15,-0.308,1800
|
||||
36,32,48,-0.306,2200
|
||||
33,28,38,-0.308,2200
|
||||
35,31,51,-0.311,1800
|
||||
55,20,57,-0.304,2000
|
||||
44,10,27,-0.313,2200
|
||||
37,16,43,-0.294,2000
|
||||
56,25,42,-0.31,2200
|
||||
30,13,21,-0.292,2200
|
||||
60,29,46,-0.294,2200
|
||||
41,21,54,-0.306,2000
|
||||
55,29,54,-0.296,1800
|
||||
39,30,48,-0.293,2200
|
||||
34,35,53,-0.285,2200
|
||||
57,32,39,-0.291,1800
|
||||
45,27,38,-0.296,2200
|
||||
52,17,25,-0.297,1800
|
||||
51,13,22,-0.288,2200
|
||||
36,19,11,-0.29,2000
|
||||
44,38,32,-0.315,1800
|
||||
58,26,18,-0.289,1800
|
||||
32,22,52,-0.288,1800
|
||||
43,12,56,-0.287,2200
|
||||
60,16,45,-0.298,2200
|
||||
54,22,25,-0.301,2000
|
||||
48,24,13,-0.305,2000
|
||||
|
61
management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv
Executable file
61
management-dashboard-web-app/phase_2_JC_experimental_run_sheet.csv
Executable file
@@ -0,0 +1,61 @@
|
||||
phase_name,machine_type,run_id,experiment_number,soaking_duration_hr,air_drying_duration_min,plate_contact_frequency_hz,throughput_rate_pecans_sec,crush_amount_in,entry_exit_height_diff_in,reps,rep
|
||||
"Phase 2 of JC Experiments","JC Cracker",1,0,34,19,53,28,0.05,-0.09,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",2,1,24,27,34,29,0.03,0.01,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",3,12,28,59,37,23,0.06,-0.08,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",4,15,16,60,30,24,0.07,0.02,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",5,4,13,41,41,38,0.05,0.03,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",6,18,18,49,38,35,0.07,-0.08,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",7,11,24,59,42,25,0.07,-0.05,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",8,16,20,59,41,14,0.07,0.04,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",9,4,13,41,41,38,0.05,0.03,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",10,19,11,25,56,34,0.06,-0.09,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",11,15,16,60,30,24,0.07,0.02,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",12,16,20,59,41,14,0.07,0.04,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",13,10,26,60,44,12,0.08,-0.1,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",14,1,24,27,34,29,0.03,0.01,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",15,17,34,60,34,29,0.07,-0.09,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",16,5,30,33,30,36,0.05,-0.04,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",17,2,38,10,60,28,0.06,-0.1,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",18,2,38,10,60,28,0.06,-0.1,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",19,13,21,59,41,21,0.06,-0.09,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",20,1,24,27,34,29,0.03,0.01,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",21,14,22,59,45,17,0.07,-0.08,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",22,6,10,22,37,30,0.06,0.02,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",23,11,24,59,42,25,0.07,-0.05,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",24,19,11,25,56,34,0.06,-0.09,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",25,8,27,12,55,24,0.04,0.04,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",26,18,18,49,38,35,0.07,-0.08,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",27,5,30,33,30,36,0.05,-0.04,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",28,9,32,26,47,26,0.07,0.03,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",29,3,11,36,42,13,0.07,-0.07,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",30,10,26,60,44,12,0.08,-0.1,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",31,8,27,12,55,24,0.04,0.04,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",32,5,30,33,30,36,0.05,-0.04,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",33,8,27,12,55,24,0.04,0.04,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",34,18,18,49,38,35,0.07,-0.08,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",35,3,11,36,42,13,0.07,-0.07,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",36,10,26,60,44,12,0.08,-0.1,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",37,17,34,60,34,29,0.07,-0.09,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",38,13,21,59,41,21,0.06,-0.09,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",39,12,28,59,37,23,0.06,-0.08,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",40,9,32,26,47,26,0.07,0.03,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",41,14,22,59,45,17,0.07,-0.08,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",42,0,34,19,53,28,0.05,-0.09,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",43,7,15,30,35,32,0.05,-0.07,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",44,0,34,19,53,28,0.05,-0.09,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",45,15,16,60,30,24,0.07,0.02,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",46,13,21,59,41,21,0.06,-0.09,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",47,11,24,59,42,25,0.07,-0.05,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",48,7,15,30,35,32,0.05,-0.07,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",49,16,20,59,41,14,0.07,0.04,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",50,3,11,36,42,13,0.07,-0.07,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",51,7,15,30,35,32,0.05,-0.07,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",52,6,10,22,37,30,0.06,0.02,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",53,19,11,25,56,34,0.06,-0.09,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",54,6,10,22,37,30,0.06,0.02,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",55,2,38,10,60,28,0.06,-0.1,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",56,14,22,59,45,17,0.07,-0.08,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",57,4,13,41,41,38,0.05,0.03,3,3
|
||||
"Phase 2 of JC Experiments","JC Cracker",58,9,32,26,47,26,0.07,0.03,3,2
|
||||
"Phase 2 of JC Experiments","JC Cracker",59,17,34,60,34,29,0.07,-0.09,3,1
|
||||
"Phase 2 of JC Experiments","JC Cracker",60,12,28,59,37,23,0.06,-0.08,3,3
|
||||
|
@@ -1,61 +0,0 @@
|
||||
run_id,experiment_number,soaking_duration_hr,air_drying_time_min,plate_contact_frequency_hz,throughput_rate_pecans_sec,crush_amount_in,entry_exit_height_diff_in,reps,rep
|
||||
1,0,34,19,53,28,0.05,-0.09,3,1
|
||||
2,1,24,27,34,29,0.03,0.01,3,3
|
||||
3,12,28,59,37,23,0.06,-0.08,3,1
|
||||
4,15,16,60,30,24,0.07,0.02,3,1
|
||||
5,4,13,41,41,38,0.05,0.03,3,2
|
||||
6,18,18,49,38,35,0.07,-0.08,3,1
|
||||
7,11,24,59,42,25,0.07,-0.05,3,1
|
||||
8,16,20,59,41,14,0.07,0.04,3,1
|
||||
9,4,13,41,41,38,0.05,0.03,3,1
|
||||
10,19,11,25,56,34,0.06,-0.09,3,1
|
||||
11,15,16,60,30,24,0.07,0.02,3,2
|
||||
12,16,20,59,41,14,0.07,0.04,3,3
|
||||
13,10,26,60,44,12,0.08,-0.1,3,2
|
||||
14,1,24,27,34,29,0.03,0.01,3,1
|
||||
15,17,34,60,34,29,0.07,-0.09,3,2
|
||||
16,5,30,33,30,36,0.05,-0.04,3,3
|
||||
17,2,38,10,60,28,0.06,-0.1,3,3
|
||||
18,2,38,10,60,28,0.06,-0.1,3,1
|
||||
19,13,21,59,41,21,0.06,-0.09,3,2
|
||||
20,1,24,27,34,29,0.03,0.01,3,2
|
||||
21,14,22,59,45,17,0.07,-0.08,3,2
|
||||
22,6,10,22,37,30,0.06,0.02,3,2
|
||||
23,11,24,59,42,25,0.07,-0.05,3,2
|
||||
24,19,11,25,56,34,0.06,-0.09,3,2
|
||||
25,8,27,12,55,24,0.04,0.04,3,2
|
||||
26,18,18,49,38,35,0.07,-0.08,3,3
|
||||
27,5,30,33,30,36,0.05,-0.04,3,1
|
||||
28,9,32,26,47,26,0.07,0.03,3,1
|
||||
29,3,11,36,42,13,0.07,-0.07,3,1
|
||||
30,10,26,60,44,12,0.08,-0.1,3,1
|
||||
31,8,27,12,55,24,0.04,0.04,3,3
|
||||
32,5,30,33,30,36,0.05,-0.04,3,2
|
||||
33,8,27,12,55,24,0.04,0.04,3,1
|
||||
34,18,18,49,38,35,0.07,-0.08,3,2
|
||||
35,3,11,36,42,13,0.07,-0.07,3,3
|
||||
36,10,26,60,44,12,0.08,-0.1,3,3
|
||||
37,17,34,60,34,29,0.07,-0.09,3,3
|
||||
38,13,21,59,41,21,0.06,-0.09,3,3
|
||||
39,12,28,59,37,23,0.06,-0.08,3,2
|
||||
40,9,32,26,47,26,0.07,0.03,3,3
|
||||
41,14,22,59,45,17,0.07,-0.08,3,3
|
||||
42,0,34,19,53,28,0.05,-0.09,3,2
|
||||
43,7,15,30,35,32,0.05,-0.07,3,1
|
||||
44,0,34,19,53,28,0.05,-0.09,3,3
|
||||
45,15,16,60,30,24,0.07,0.02,3,3
|
||||
46,13,21,59,41,21,0.06,-0.09,3,1
|
||||
47,11,24,59,42,25,0.07,-0.05,3,3
|
||||
48,7,15,30,35,32,0.05,-0.07,3,3
|
||||
49,16,20,59,41,14,0.07,0.04,3,2
|
||||
50,3,11,36,42,13,0.07,-0.07,3,2
|
||||
51,7,15,30,35,32,0.05,-0.07,3,2
|
||||
52,6,10,22,37,30,0.06,0.02,3,1
|
||||
53,19,11,25,56,34,0.06,-0.09,3,3
|
||||
54,6,10,22,37,30,0.06,0.02,3,3
|
||||
55,2,38,10,60,28,0.06,-0.1,3,2
|
||||
56,14,22,59,45,17,0.07,-0.08,3,1
|
||||
57,4,13,41,41,38,0.05,0.03,3,3
|
||||
58,9,32,26,47,26,0.07,0.03,3,2
|
||||
59,17,34,60,34,29,0.07,-0.09,3,1
|
||||
60,12,28,59,37,23,0.06,-0.08,3,3
|
||||
|
@@ -0,0 +1,41 @@
|
||||
phase_name,machine_type,Motor Speed (Hz),soaking_duration_hr,air_drying_duration_min,jig Displacement (in),Spring Stiffness (N/m),reps_required,rep
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",33,27,28,-0.307,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",30,37,17,-0.311,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",47,36,50,-0.291,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",42,12,30,-0.314,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",53,34,19,-0.302,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",37,18,40,-0.301,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",40,14,59,-0.286,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",39,18,32,-0.309,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",49,11,31,-0.299,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",47,33,12,-0.295,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",52,23,36,-0.302,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",59,37,35,-0.299,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",41,15,15,-0.312,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",46,24,22,-0.303,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",50,36,15,-0.308,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",36,32,48,-0.306,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",33,28,38,-0.308,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",35,31,51,-0.311,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",55,20,57,-0.304,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",44,10,27,-0.313,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",37,16,43,-0.294,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",56,25,42,-0.31,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",30,13,21,-0.292,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",60,29,46,-0.294,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",41,21,54,-0.306,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",55,29,54,-0.296,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",39,30,48,-0.293,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",34,35,53,-0.285,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",57,32,39,-0.291,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",45,27,38,-0.296,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",52,17,25,-0.297,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",51,13,22,-0.288,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",36,19,11,-0.29,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",44,38,32,-0.315,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",58,26,18,-0.289,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",32,22,52,-0.288,1800,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",43,12,56,-0.287,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",60,16,45,-0.298,2200,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",54,22,25,-0.301,2000,1,1
|
||||
"Post Workshop Meyer Experiments","Meyer Cracker",48,24,13,-0.305,2000,1,1
|
||||
|
@@ -671,7 +671,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
|
||||
// Soaking marker
|
||||
events.push({
|
||||
id: `${scheduled.repetitionId}-soaking`,
|
||||
title: `Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
title: `💧 Soaking - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
start: scheduled.soakingStart,
|
||||
end: new Date(scheduled.soakingStart.getTime() + 30 * 60000), // 30 minute duration for visibility
|
||||
resource: 'soaking'
|
||||
@@ -681,7 +681,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
|
||||
if (scheduled.airdryingStart) {
|
||||
events.push({
|
||||
id: `${scheduled.repetitionId}-airdrying`,
|
||||
title: `Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
title: `🌬️ Airdrying - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
start: scheduled.airdryingStart,
|
||||
end: new Date(scheduled.airdryingStart.getTime() + 30 * 60000),
|
||||
resource: 'airdrying'
|
||||
@@ -692,7 +692,7 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
|
||||
if (scheduled.crackingStart) {
|
||||
events.push({
|
||||
id: `${scheduled.repetitionId}-cracking`,
|
||||
title: `Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
title: `⚡ Cracking - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
|
||||
start: scheduled.crackingStart,
|
||||
end: new Date(scheduled.crackingStart.getTime() + 30 * 60000),
|
||||
resource: 'cracking'
|
||||
@@ -1004,26 +1004,38 @@ function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }
|
||||
}
|
||||
const color = colors[resource as keyof typeof colors] || '#6b7280'
|
||||
|
||||
// Get step names and icons
|
||||
const stepInfo = {
|
||||
soaking: { name: 'Soaking', icon: '💧' },
|
||||
airdrying: { name: 'Airdrying', icon: '🌬️' },
|
||||
cracking: { name: 'Cracking', icon: '⚡' }
|
||||
}
|
||||
const step = stepInfo[resource as keyof typeof stepInfo]
|
||||
|
||||
return {
|
||||
style: {
|
||||
backgroundColor: color,
|
||||
borderColor: color,
|
||||
color: 'white',
|
||||
borderRadius: '4px',
|
||||
borderRadius: '6px',
|
||||
border: 'none',
|
||||
height: '8px',
|
||||
minHeight: '8px',
|
||||
fontSize: '10px',
|
||||
padding: '2px 4px',
|
||||
height: '36px',
|
||||
minHeight: '36px',
|
||||
fontSize: '13px',
|
||||
padding: '6px 10px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'space-between',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
fontWeight: 'bold',
|
||||
zIndex: 10,
|
||||
position: 'relative',
|
||||
lineHeight: '1.2',
|
||||
textShadow: '1px 1px 2px rgba(0,0,0,0.7)'
|
||||
lineHeight: '1.4',
|
||||
textShadow: '1px 1px 2px rgba(0,0,0,0.7)',
|
||||
gap: '6px',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1081,6 +1093,7 @@ function AvailabilityCalendar({ user }: { user: User }) {
|
||||
endTime: '17:00'
|
||||
})
|
||||
const [currentView, setCurrentView] = useState(Views.MONTH)
|
||||
const [currentDate, setCurrentDate] = useState(new Date())
|
||||
|
||||
// Load availability from DB on mount
|
||||
useEffect(() => {
|
||||
@@ -1335,6 +1348,8 @@ function AvailabilityCalendar({ user }: { user: User }) {
|
||||
style={{ height: '100%' }}
|
||||
view={currentView}
|
||||
onView={setCurrentView}
|
||||
date={currentDate}
|
||||
onNavigate={setCurrentDate}
|
||||
views={[Views.MONTH, Views.WEEK, Views.DAY]}
|
||||
selectable
|
||||
onSelectSlot={handleSelectSlot}
|
||||
|
||||
@@ -1,634 +0,0 @@
|
||||
-- Complete Database Schema for USDA Vision Pecan Experiments System
|
||||
-- This migration creates the entire database schema from scratch
|
||||
-- Supports both JC Cracker and Meyer Cracker experiments
|
||||
|
||||
-- =============================================
|
||||
-- 1. EXTENSIONS
|
||||
-- =============================================
|
||||
|
||||
-- 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,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create 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,
|
||||
first_name TEXT,
|
||||
last_name TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended')),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create 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,
|
||||
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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 3. 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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 4. 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,
|
||||
has_soaking BOOLEAN NOT NULL DEFAULT false,
|
||||
has_airdrying BOOLEAN NOT NULL DEFAULT false,
|
||||
has_cracking BOOLEAN NOT NULL DEFAULT false,
|
||||
has_shelling BOOLEAN NOT NULL DEFAULT false,
|
||||
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 at least one phase is selected
|
||||
CONSTRAINT check_at_least_one_phase
|
||||
CHECK (has_soaking = true OR has_airdrying = true OR has_cracking = true OR has_shelling = true)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 5. 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),
|
||||
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 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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 6. 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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 7. 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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 8. 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,
|
||||
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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 9. ADD FOREIGN KEY CONSTRAINTS TO EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- 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;
|
||||
|
||||
-- =============================================
|
||||
-- 10. CREATE INDEXES FOR PERFORMANCE
|
||||
-- =============================================
|
||||
|
||||
-- Create indexes for better query performance
|
||||
CREATE INDEX IF NOT EXISTS idx_user_profiles_email ON public.user_profiles(email);
|
||||
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);
|
||||
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_experiment_repetitions_experiment_id ON public.experiment_repetitions(experiment_id);
|
||||
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);
|
||||
|
||||
-- =============================================
|
||||
-- 11. 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();
|
||||
|
||||
-- =============================================
|
||||
-- 12. 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.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_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;
|
||||
|
||||
-- =============================================
|
||||
-- 13. GRANT PERMISSIONS
|
||||
-- =============================================
|
||||
|
||||
-- Grant permissions for all tables
|
||||
GRANT ALL ON public.roles TO authenticated;
|
||||
GRANT ALL ON public.user_profiles TO authenticated;
|
||||
GRANT ALL ON public.user_roles TO authenticated;
|
||||
GRANT ALL ON public.machine_types TO authenticated;
|
||||
GRANT ALL ON public.experiment_phases TO authenticated;
|
||||
GRANT ALL ON public.experiments TO authenticated;
|
||||
GRANT ALL ON public.experiment_repetitions 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;
|
||||
|
||||
-- =============================================
|
||||
-- 14. ENABLE ROW LEVEL SECURITY
|
||||
-- =============================================
|
||||
|
||||
-- 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.machine_types 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.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;
|
||||
|
||||
-- =============================================
|
||||
-- 15. CREATE RLS POLICIES
|
||||
-- =============================================
|
||||
|
||||
-- Create RLS policies for roles (read-only for all authenticated users)
|
||||
CREATE POLICY "Roles are viewable by authenticated users" ON public.roles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Create RLS policies for user_profiles
|
||||
CREATE POLICY "User profiles are viewable by authenticated users" ON public.user_profiles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are insertable by authenticated users" ON public.user_profiles
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are updatable by authenticated users" ON public.user_profiles
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are deletable by authenticated users" ON public.user_profiles
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Create RLS policies for user_roles
|
||||
CREATE POLICY "User roles are viewable by authenticated users" ON public.user_roles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are insertable by authenticated users" ON public.user_roles
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are updatable by authenticated users" ON public.user_roles
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are deletable by authenticated users" ON public.user_roles
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
-- 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 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');
|
||||
|
||||
CREATE POLICY "Experiment phases are insertable by authenticated users" ON public.experiment_phases
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "Experiment phases are updatable by authenticated users" ON public.experiment_phases
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "Experiment phases are deletable by authenticated users" ON public.experiment_phases
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
-- 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');
|
||||
|
||||
-- Create RLS policies for phase tables
|
||||
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');
|
||||
|
||||
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');
|
||||
@@ -0,0 +1,189 @@
|
||||
-- User Management and Authentication
|
||||
-- This migration creates user-related tables, roles, and authentication structures
|
||||
|
||||
-- =============================================
|
||||
-- 1. EXTENSIONS
|
||||
-- =============================================
|
||||
|
||||
-- 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,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create 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,
|
||||
first_name TEXT,
|
||||
last_name TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended')),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create 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,
|
||||
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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 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
|
||||
-- =============================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_profiles_email ON public.user_profiles(email);
|
||||
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);
|
||||
|
||||
-- =============================================
|
||||
-- 5. TRIGGERS
|
||||
-- =============================================
|
||||
|
||||
-- Create trigger for updated_at on user_profiles
|
||||
CREATE TRIGGER set_updated_at_user_profiles
|
||||
BEFORE UPDATE ON public.user_profiles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.handle_updated_at();
|
||||
|
||||
-- =============================================
|
||||
-- 6. GRANT PERMISSIONS
|
||||
-- =============================================
|
||||
|
||||
GRANT ALL ON public.roles TO authenticated;
|
||||
GRANT ALL ON public.user_profiles TO authenticated;
|
||||
GRANT ALL ON public.user_roles TO authenticated;
|
||||
|
||||
-- =============================================
|
||||
-- 7. ENABLE ROW LEVEL SECURITY
|
||||
-- =============================================
|
||||
|
||||
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;
|
||||
|
||||
-- =============================================
|
||||
-- 8. CREATE RLS POLICIES
|
||||
-- =============================================
|
||||
|
||||
-- Create RLS policies for roles (read-only for all authenticated users)
|
||||
CREATE POLICY "Roles are viewable by authenticated users" ON public.roles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Create RLS policies for user_profiles
|
||||
CREATE POLICY "User profiles are viewable by authenticated users" ON public.user_profiles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are insertable by authenticated users" ON public.user_profiles
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are updatable by authenticated users" ON public.user_profiles
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User profiles are deletable by authenticated users" ON public.user_profiles
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Create RLS policies for user_roles
|
||||
CREATE POLICY "User roles are viewable by authenticated users" ON public.user_roles
|
||||
FOR SELECT USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are insertable by authenticated users" ON public.user_roles
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are updatable by authenticated users" ON public.user_roles
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "User roles are deletable by authenticated users" ON public.user_roles
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
-- Machine Types and Experiment Phases
|
||||
-- This migration creates machine types and experiment phase definitions
|
||||
|
||||
-- =============================================
|
||||
-- 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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 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,
|
||||
has_soaking BOOLEAN NOT NULL DEFAULT false,
|
||||
has_airdrying BOOLEAN NOT NULL DEFAULT false,
|
||||
has_cracking BOOLEAN NOT NULL DEFAULT false,
|
||||
has_shelling BOOLEAN NOT NULL DEFAULT false,
|
||||
cracking_machine_type_id UUID REFERENCES public.machine_types(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),
|
||||
|
||||
-- Ensure at least one phase is selected
|
||||
CONSTRAINT check_at_least_one_phase
|
||||
CHECK (has_soaking = true OR has_airdrying = true OR has_cracking = true OR has_shelling = true),
|
||||
|
||||
-- If has_cracking is true, then cracking_machine_type_id must not be null
|
||||
CONSTRAINT ck_experiment_phases_machine_required_when_cracking
|
||||
CHECK ((has_cracking = false) OR (cracking_machine_type_id IS NOT NULL))
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 3. 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
|
||||
-- =============================================
|
||||
|
||||
-- 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
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.handle_updated_at();
|
||||
|
||||
-- =============================================
|
||||
-- 5. GRANT PERMISSIONS
|
||||
-- =============================================
|
||||
|
||||
GRANT ALL ON public.machine_types TO authenticated;
|
||||
GRANT ALL ON public.experiment_phases TO authenticated;
|
||||
|
||||
-- =============================================
|
||||
-- 6. 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
|
||||
-- =============================================
|
||||
|
||||
-- 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');
|
||||
|
||||
CREATE POLICY "Experiment phases are insertable by authenticated users" ON public.experiment_phases
|
||||
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "Experiment phases are updatable by authenticated users" ON public.experiment_phases
|
||||
FOR UPDATE USING (auth.role() = 'authenticated');
|
||||
|
||||
CREATE POLICY "Experiment phases are deletable by authenticated users" ON public.experiment_phases
|
||||
FOR DELETE USING (auth.role() = 'authenticated');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
-- 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_number INTEGER NOT NULL,
|
||||
experiment_phase_id UUID NOT NULL,
|
||||
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),
|
||||
|
||||
-- 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 unique repetition numbers per experiment
|
||||
UNIQUE(experiment_number, experiment_phase_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_composite ON public.experiment_repetitions(experiment_number, experiment_phase_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');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
-- Data Entry Tables
|
||||
-- This migration creates the 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_number INTEGER NOT NULL,
|
||||
experiment_phase_id UUID NOT NULL,
|
||||
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),
|
||||
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),
|
||||
|
||||
-- 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 only one soaking per experiment or repetition
|
||||
CONSTRAINT unique_soaking_per_experiment UNIQUE (experiment_number, experiment_phase_id),
|
||||
CONSTRAINT unique_soaking_per_repetition UNIQUE (repetition_id)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 2. AIRDRYING TABLE
|
||||
-- =============================================
|
||||
|
||||
-- Create airdrying table
|
||||
CREATE TABLE IF NOT EXISTS public.airdrying (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
experiment_number INTEGER NOT NULL,
|
||||
experiment_phase_id UUID NOT NULL,
|
||||
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),
|
||||
|
||||
-- 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 only one airdrying per experiment or repetition
|
||||
CONSTRAINT unique_airdrying_per_experiment UNIQUE (experiment_number, experiment_phase_id),
|
||||
CONSTRAINT unique_airdrying_per_repetition UNIQUE (repetition_id)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 3. CRACKING TABLE
|
||||
-- =============================================
|
||||
|
||||
-- Create cracking table
|
||||
CREATE TABLE IF NOT EXISTS public.cracking (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
experiment_number INTEGER NOT NULL,
|
||||
experiment_phase_id UUID NOT NULL,
|
||||
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),
|
||||
|
||||
-- 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 only one cracking per experiment or repetition
|
||||
CONSTRAINT unique_cracking_per_experiment UNIQUE (experiment_number, experiment_phase_id),
|
||||
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_number INTEGER NOT NULL,
|
||||
experiment_phase_id UUID NOT NULL,
|
||||
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),
|
||||
|
||||
-- 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 only one shelling per experiment or repetition
|
||||
CONSTRAINT unique_shelling_per_experiment UNIQUE (experiment_number, experiment_phase_id),
|
||||
CONSTRAINT unique_shelling_per_repetition UNIQUE (repetition_id)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 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(),
|
||||
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,
|
||||
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)
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 6. ADD FOREIGN KEY CONSTRAINTS TO EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- 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. INDEXES FOR PERFORMANCE
|
||||
-- =============================================
|
||||
|
||||
-- Create composite indexes for phase tables
|
||||
CREATE INDEX IF NOT EXISTS idx_soaking_experiment_composite ON public.soaking(experiment_number, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_airdrying_experiment_composite ON public.airdrying(experiment_number, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cracking_experiment_composite ON public.cracking(experiment_number, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_shelling_experiment_composite ON public.shelling(experiment_number, experiment_phase_id);
|
||||
|
||||
-- Create indexes for repetition references
|
||||
CREATE INDEX IF NOT EXISTS idx_soaking_repetition_id ON public.soaking(repetition_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_airdrying_repetition_id ON public.airdrying(repetition_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cracking_repetition_id ON public.cracking(repetition_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_shelling_repetition_id ON public.shelling(repetition_id);
|
||||
|
||||
-- Create indexes for machine type references
|
||||
CREATE INDEX IF NOT EXISTS idx_cracking_machine_type_id ON public.cracking(machine_type_id);
|
||||
|
||||
-- Create indexes for created_by references
|
||||
CREATE INDEX IF NOT EXISTS idx_soaking_created_by ON public.soaking(created_by);
|
||||
CREATE INDEX IF NOT EXISTS idx_airdrying_created_by ON public.airdrying(created_by);
|
||||
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
|
||||
-- =============================================
|
||||
|
||||
-- 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;
|
||||
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_number = NEW.experiment_number
|
||||
AND s.experiment_phase_id = NEW.experiment_phase_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_number = NEW.experiment_number
|
||||
AND a.experiment_phase_id = NEW.experiment_phase_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. TRIGGERS FOR UPDATED_AT
|
||||
-- =============================================
|
||||
|
||||
-- Create triggers for updated_at on all phase tables
|
||||
CREATE TRIGGER set_updated_at_soaking
|
||||
BEFORE UPDATE ON public.soaking
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.handle_updated_at();
|
||||
|
||||
CREATE TRIGGER set_updated_at_airdrying
|
||||
BEFORE UPDATE ON public.airdrying
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.handle_updated_at();
|
||||
|
||||
CREATE TRIGGER set_updated_at_cracking
|
||||
BEFORE UPDATE ON public.cracking
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.handle_updated_at();
|
||||
|
||||
CREATE TRIGGER set_updated_at_shelling
|
||||
BEFORE UPDATE ON public.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
|
||||
-- =============================================
|
||||
|
||||
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
|
||||
-- =============================================
|
||||
|
||||
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
|
||||
-- =============================================
|
||||
|
||||
-- Create RLS policies for phase tables
|
||||
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');
|
||||
|
||||
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');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Add Conductor Availability and Experiment Phase Assignment Tables
|
||||
-- This migration adds tables for conductor availability management and future experiment scheduling
|
||||
-- Conductor Availability and Scheduling
|
||||
-- This migration creates tables for conductor availability management and experiment scheduling
|
||||
|
||||
-- =============================================
|
||||
-- 1. CONDUCTOR AVAILABILITY TABLE
|
||||
@@ -25,13 +25,14 @@ CREATE TABLE IF NOT EXISTS public.conductor_availability (
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 2. EXPERIMENT PHASE ASSIGNMENTS TABLE (Future Scheduling)
|
||||
-- 2. EXPERIMENT PHASE ASSIGNMENTS TABLE
|
||||
-- =============================================
|
||||
|
||||
-- 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,
|
||||
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')),
|
||||
@@ -43,6 +44,10 @@ CREATE TABLE IF NOT EXISTS public.experiment_phase_assignments (
|
||||
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),
|
||||
|
||||
@@ -63,7 +68,7 @@ CREATE INDEX IF NOT EXISTS idx_conductor_availability_created_by ON public.condu
|
||||
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_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);
|
||||
@@ -72,78 +77,7 @@ CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_scheduled_start ON p
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_created_by ON public.experiment_phase_assignments(created_by);
|
||||
|
||||
-- =============================================
|
||||
-- 4. 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;
|
||||
|
||||
-- =============================================
|
||||
-- 5. FUNCTIONS FOR OVERLAP PREVENTION
|
||||
-- 4. FUNCTIONS FOR OVERLAP PREVENTION
|
||||
-- =============================================
|
||||
|
||||
-- Function to check for overlapping availabilities
|
||||
@@ -177,85 +111,8 @@ BEGIN
|
||||
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;
|
||||
|
||||
-- =============================================
|
||||
-- 6. 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
|
||||
-- 5. HELPER FUNCTIONS
|
||||
-- =============================================
|
||||
|
||||
-- Function to get available conductors for a specific time range
|
||||
@@ -310,13 +167,45 @@ END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- =============================================
|
||||
-- 8. ROW LEVEL SECURITY (RLS)
|
||||
-- 6. 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
|
||||
CREATE TRIGGER trigger_check_availability_overlap
|
||||
BEFORE INSERT OR UPDATE ON public.conductor_availability
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.check_availability_overlap();
|
||||
|
||||
-- =============================================
|
||||
-- 7. GRANT PERMISSIONS
|
||||
-- =============================================
|
||||
|
||||
GRANT ALL ON public.conductor_availability TO authenticated;
|
||||
GRANT ALL ON public.experiment_phase_assignments TO authenticated;
|
||||
|
||||
-- =============================================
|
||||
-- 8. ENABLE ROW LEVEL SECURITY
|
||||
-- =============================================
|
||||
|
||||
-- Enable RLS on new tables
|
||||
ALTER TABLE public.conductor_availability ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.experiment_phase_assignments ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- =============================================
|
||||
-- 9. CREATE RLS POLICIES
|
||||
-- =============================================
|
||||
|
||||
-- Conductor availability policies
|
||||
CREATE POLICY "conductor_availability_select_policy" ON public.conductor_availability
|
||||
FOR SELECT
|
||||
@@ -392,7 +281,7 @@ CREATE POLICY "experiment_phase_assignments_delete_policy" ON public.experiment_
|
||||
);
|
||||
|
||||
-- =============================================
|
||||
-- 8. COMMENTS FOR DOCUMENTATION
|
||||
-- 10. COMMENTS FOR DOCUMENTATION
|
||||
-- =============================================
|
||||
|
||||
COMMENT ON TABLE public.conductor_availability IS 'Stores conductor availability windows for experiment scheduling';
|
||||
@@ -410,3 +299,5 @@ COMMENT ON COLUMN public.experiment_phase_assignments.status IS 'Current status
|
||||
COMMENT ON COLUMN public.experiment_phase_assignments.notes IS 'Optional notes about the assignment';
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
-- Views and Final Setup
|
||||
-- This migration creates views for easier querying and finalizes the database setup
|
||||
|
||||
-- =============================================
|
||||
-- 1. 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_hours,
|
||||
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.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_hours,
|
||||
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;
|
||||
|
||||
-- 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
|
||||
ca.*,
|
||||
up.email,
|
||||
up.first_name,
|
||||
up.last_name,
|
||||
r.name as role_name
|
||||
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';
|
||||
|
||||
-- =============================================
|
||||
-- 2. GRANT PERMISSIONS FOR VIEWS
|
||||
-- =============================================
|
||||
|
||||
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
|
||||
-- =============================================
|
||||
|
||||
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)
|
||||
-- =============================================
|
||||
|
||||
-- Function to create sample roles
|
||||
CREATE OR REPLACE FUNCTION public.create_sample_roles()
|
||||
RETURNS VOID AS $$
|
||||
BEGIN
|
||||
INSERT INTO public.roles (name, description) VALUES
|
||||
('admin', 'System administrator with full access'),
|
||||
('conductor', 'Experiment conductor with limited access'),
|
||||
('researcher', 'Research staff with read-only access')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- Function to create sample machine types
|
||||
CREATE OR REPLACE FUNCTION public.create_sample_machine_types()
|
||||
RETURNS VOID AS $$
|
||||
BEGIN
|
||||
INSERT INTO public.machine_types (name, description, created_by) VALUES
|
||||
('JC Cracker', 'Johnson Cracker machine for pecan shelling', (SELECT id FROM public.user_profiles LIMIT 1)),
|
||||
('Meyer Cracker', 'Meyer Cracker machine for pecan shelling', (SELECT id FROM public.user_profiles LIMIT 1))
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- Function to create sample experiment phases
|
||||
CREATE OR REPLACE FUNCTION public.create_sample_experiment_phases()
|
||||
RETURNS VOID AS $$
|
||||
DECLARE
|
||||
jc_cracker_id UUID;
|
||||
meyer_cracker_id UUID;
|
||||
BEGIN
|
||||
-- Get machine type IDs
|
||||
SELECT id INTO jc_cracker_id FROM public.machine_types WHERE name = 'JC Cracker';
|
||||
SELECT id INTO meyer_cracker_id FROM public.machine_types WHERE name = 'Meyer Cracker';
|
||||
|
||||
INSERT INTO public.experiment_phases (name, description, has_soaking, has_airdrying, has_cracking, has_shelling, cracking_machine_type_id, created_by) VALUES
|
||||
('Full Process - JC Cracker', 'Complete pecan processing with JC Cracker', true, true, true, true, jc_cracker_id, (SELECT id FROM public.user_profiles LIMIT 1)),
|
||||
('Full Process - Meyer Cracker', 'Complete pecan processing with Meyer Cracker', true, true, true, true, meyer_cracker_id, (SELECT id FROM public.user_profiles LIMIT 1)),
|
||||
('Cracking Only - JC Cracker', 'JC Cracker cracking process only', false, false, true, false, jc_cracker_id, (SELECT id FROM public.user_profiles LIMIT 1)),
|
||||
('Cracking Only - Meyer Cracker', 'Meyer Cracker cracking process only', false, false, true, false, meyer_cracker_id, (SELECT id FROM public.user_profiles LIMIT 1))
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- =============================================
|
||||
-- 5. GRANT PERMISSIONS FOR SAMPLE DATA FUNCTIONS
|
||||
-- =============================================
|
||||
|
||||
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;
|
||||
@@ -1,185 +0,0 @@
|
||||
-- Migration: Change experiments table to use composite primary key (experiment_number, phase_id)
|
||||
-- This allows each phase to have its own experiment numbering starting from 1
|
||||
|
||||
-- =============================================
|
||||
-- 1. DROP EXISTING FOREIGN KEY CONSTRAINTS
|
||||
-- =============================================
|
||||
|
||||
-- Drop foreign key constraints that reference experiments table
|
||||
ALTER TABLE public.experiment_repetitions DROP CONSTRAINT IF EXISTS experiment_repetitions_experiment_id_fkey;
|
||||
ALTER TABLE public.soaking DROP CONSTRAINT IF EXISTS soaking_experiment_id_fkey;
|
||||
ALTER TABLE public.airdrying DROP CONSTRAINT IF EXISTS airdrying_experiment_id_fkey;
|
||||
ALTER TABLE public.cracking DROP CONSTRAINT IF EXISTS cracking_experiment_id_fkey;
|
||||
ALTER TABLE public.shelling DROP CONSTRAINT IF EXISTS shelling_experiment_id_fkey;
|
||||
ALTER TABLE public.conductor_availability DROP CONSTRAINT IF EXISTS conductor_availability_experiment_id_fkey;
|
||||
|
||||
-- =============================================
|
||||
-- 2. MODIFY EXPERIMENTS TABLE
|
||||
-- =============================================
|
||||
|
||||
-- Drop the existing primary key and unique constraint
|
||||
ALTER TABLE public.experiments DROP CONSTRAINT IF EXISTS experiments_pkey;
|
||||
ALTER TABLE public.experiments DROP CONSTRAINT IF EXISTS experiments_experiment_number_key;
|
||||
|
||||
-- Make phase_id NOT NULL since it's now part of the primary key
|
||||
ALTER TABLE public.experiments ALTER COLUMN phase_id SET NOT NULL;
|
||||
|
||||
-- Add composite primary key
|
||||
ALTER TABLE public.experiments ADD CONSTRAINT experiments_pkey PRIMARY KEY (experiment_number, phase_id);
|
||||
|
||||
-- =============================================
|
||||
-- 3. UPDATE FOREIGN KEY COLUMNS
|
||||
-- =============================================
|
||||
|
||||
-- Add phase_id columns to tables that reference experiments
|
||||
ALTER TABLE public.experiment_repetitions ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
ALTER TABLE public.soaking ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
ALTER TABLE public.airdrying ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
ALTER TABLE public.cracking ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
ALTER TABLE public.shelling ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
ALTER TABLE public.conductor_availability ADD COLUMN IF NOT EXISTS experiment_phase_id UUID;
|
||||
|
||||
-- Populate the phase_id columns from the experiments table
|
||||
UPDATE public.experiment_repetitions
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE experiment_repetitions.experiment_id = e.id;
|
||||
|
||||
UPDATE public.soaking
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE soaking.experiment_id = e.id;
|
||||
|
||||
UPDATE public.airdrying
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE airdrying.experiment_id = e.id;
|
||||
|
||||
UPDATE public.cracking
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE cracking.experiment_id = e.id;
|
||||
|
||||
UPDATE public.shelling
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE shelling.experiment_id = e.id;
|
||||
|
||||
UPDATE public.conductor_availability
|
||||
SET experiment_phase_id = e.phase_id
|
||||
FROM public.experiments e
|
||||
WHERE conductor_availability.experiment_id = e.id;
|
||||
|
||||
-- Make the phase_id columns NOT NULL
|
||||
ALTER TABLE public.experiment_repetitions ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
ALTER TABLE public.soaking ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
ALTER TABLE public.airdrying ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
ALTER TABLE public.cracking ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
ALTER TABLE public.shelling ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
ALTER TABLE public.conductor_availability ALTER COLUMN experiment_phase_id SET NOT NULL;
|
||||
|
||||
-- =============================================
|
||||
-- 4. ADD NEW FOREIGN KEY CONSTRAINTS
|
||||
-- =============================================
|
||||
|
||||
-- Add foreign key constraints using composite key
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD CONSTRAINT experiment_repetitions_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.soaking
|
||||
ADD CONSTRAINT soaking_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.airdrying
|
||||
ADD CONSTRAINT airdrying_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.cracking
|
||||
ADD CONSTRAINT cracking_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.shelling
|
||||
ADD CONSTRAINT shelling_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.conductor_availability
|
||||
ADD CONSTRAINT conductor_availability_experiment_fkey
|
||||
FOREIGN KEY (experiment_id, experiment_phase_id)
|
||||
REFERENCES public.experiments(experiment_number, phase_id) ON DELETE CASCADE;
|
||||
|
||||
-- =============================================
|
||||
-- 5. UPDATE UNIQUE CONSTRAINTS
|
||||
-- =============================================
|
||||
|
||||
-- Update unique constraints to use composite key
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
DROP CONSTRAINT IF EXISTS experiment_repetitions_experiment_id_repetition_number_key;
|
||||
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD CONSTRAINT experiment_repetitions_experiment_repetition_key
|
||||
UNIQUE (experiment_id, experiment_phase_id, repetition_number);
|
||||
|
||||
-- Update unique constraints for phase tables
|
||||
ALTER TABLE public.soaking
|
||||
DROP CONSTRAINT IF EXISTS unique_soaking_per_experiment;
|
||||
|
||||
ALTER TABLE public.soaking
|
||||
ADD CONSTRAINT unique_soaking_per_experiment
|
||||
UNIQUE (experiment_id, experiment_phase_id);
|
||||
|
||||
ALTER TABLE public.airdrying
|
||||
DROP CONSTRAINT IF EXISTS unique_airdrying_per_experiment;
|
||||
|
||||
ALTER TABLE public.airdrying
|
||||
ADD CONSTRAINT unique_airdrying_per_experiment
|
||||
UNIQUE (experiment_id, experiment_phase_id);
|
||||
|
||||
ALTER TABLE public.cracking
|
||||
DROP CONSTRAINT IF EXISTS unique_cracking_per_experiment;
|
||||
|
||||
ALTER TABLE public.cracking
|
||||
ADD CONSTRAINT unique_cracking_per_experiment
|
||||
UNIQUE (experiment_id, experiment_phase_id);
|
||||
|
||||
ALTER TABLE public.shelling
|
||||
DROP CONSTRAINT IF EXISTS unique_shelling_per_experiment;
|
||||
|
||||
ALTER TABLE public.shelling
|
||||
ADD CONSTRAINT unique_shelling_per_experiment
|
||||
UNIQUE (experiment_id, experiment_phase_id);
|
||||
|
||||
-- =============================================
|
||||
-- 6. UPDATE INDEXES
|
||||
-- =============================================
|
||||
|
||||
-- Drop old indexes
|
||||
DROP INDEX IF EXISTS idx_soaking_experiment_id;
|
||||
DROP INDEX IF EXISTS idx_airdrying_experiment_id;
|
||||
DROP INDEX IF EXISTS idx_cracking_experiment_id;
|
||||
DROP INDEX IF EXISTS idx_shelling_experiment_id;
|
||||
|
||||
-- Create new composite indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_soaking_experiment_composite ON public.soaking(experiment_id, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_airdrying_experiment_composite ON public.airdrying(experiment_id, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cracking_experiment_composite ON public.cracking(experiment_id, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_shelling_experiment_composite ON public.shelling(experiment_id, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_experiment_composite ON public.experiment_repetitions(experiment_id, experiment_phase_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_conductor_availability_experiment_composite ON public.conductor_availability(experiment_id, experiment_phase_id);
|
||||
|
||||
-- =============================================
|
||||
-- 7. UPDATE EXPERIMENTS TABLE FOREIGN KEY REFERENCES
|
||||
-- =============================================
|
||||
|
||||
-- The experiments table has foreign key references to phase tables
|
||||
-- These need to be updated to use the new composite key structure
|
||||
-- We'll need to update these after the phase tables are updated
|
||||
|
||||
-- Note: The soaking_id, airdrying_id, cracking_id, shelling_id columns in experiments table
|
||||
-- will need to be updated to reference the new composite structure
|
||||
-- This will be handled in the seed files update
|
||||
@@ -0,0 +1,133 @@
|
||||
-- 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;
|
||||
@@ -1,13 +0,0 @@
|
||||
-- Convert soaking duration to hours instead of minutes
|
||||
-- 1) Rename column
|
||||
ALTER TABLE public.soaking RENAME COLUMN soaking_duration_minutes TO soaking_duration_hours;
|
||||
|
||||
-- 2) Change type to double precision to allow fractional hours
|
||||
ALTER TABLE public.soaking ALTER COLUMN soaking_duration_hours TYPE DOUBLE PRECISION USING soaking_duration_hours::double precision;
|
||||
|
||||
-- 3) Convert existing data (currently minutes) to hours
|
||||
UPDATE public.soaking SET soaking_duration_hours = soaking_duration_hours / 60.0;
|
||||
|
||||
-- 4) Ensure CHECK constraint (> 0)
|
||||
ALTER TABLE public.soaking DROP CONSTRAINT IF EXISTS soaking_soaking_duration_minutes_check;
|
||||
ALTER TABLE public.soaking ADD CONSTRAINT soaking_soaking_duration_hours_check CHECK (soaking_duration_hours > 0);
|
||||
@@ -1,27 +0,0 @@
|
||||
-- Migration: Add cracking_machine_type_id to experiment_phases
|
||||
-- Adds optional reference to machine_types so a phase can specify the cracking machine
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 1) Add column (nullable to avoid breaking existing data)
|
||||
ALTER TABLE public.experiment_phases
|
||||
ADD COLUMN IF NOT EXISTS cracking_machine_type_id UUID NULL;
|
||||
|
||||
-- 2) Add foreign key to machine_types
|
||||
ALTER TABLE public.experiment_phases
|
||||
ADD CONSTRAINT fk_experiment_phases_cracking_machine_type
|
||||
FOREIGN KEY (cracking_machine_type_id)
|
||||
REFERENCES public.machine_types(id)
|
||||
ON DELETE SET NULL;
|
||||
|
||||
-- 3) Optional: index for lookup/filtering
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_phases_cracking_machine_type_id
|
||||
ON public.experiment_phases (cracking_machine_type_id);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
-- Migration: Require cracking_machine_type_id when has_cracking is true
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Drop existing constraint if it exists (for re-runs)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM pg_constraint c
|
||||
JOIN pg_class t ON c.conrelid = t.oid
|
||||
WHERE t.relname = 'experiment_phases'
|
||||
AND c.conname = 'ck_experiment_phases_machine_required_when_cracking'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_phases
|
||||
DROP CONSTRAINT ck_experiment_phases_machine_required_when_cracking;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Add check: if has_cracking then cracking_machine_type_id must not be null
|
||||
ALTER TABLE public.experiment_phases
|
||||
ADD CONSTRAINT ck_experiment_phases_machine_required_when_cracking
|
||||
CHECK (
|
||||
(has_cracking = false) OR (cracking_machine_type_id IS NOT NULL)
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
-- 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;
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
-- Align experiment_repetitions schema with application expectations
|
||||
-- Adds experiment_id and scheduled_date, maintains existing data, and updates constraints
|
||||
|
||||
-- 1) Add columns if missing and remove NOT NULL constraints from old columns
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'experiment_repetitions' AND column_name = 'experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD COLUMN experiment_id UUID;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'experiment_repetitions' AND column_name = 'scheduled_date'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD COLUMN scheduled_date TIMESTAMPTZ NULL;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'experiment_repetitions' AND column_name = 'completion_status'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD COLUMN completion_status BOOLEAN NOT NULL DEFAULT false;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'experiment_repetitions' AND column_name = 'is_locked'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD COLUMN is_locked BOOLEAN NOT NULL DEFAULT false,
|
||||
ADD COLUMN locked_at TIMESTAMPTZ NULL,
|
||||
ADD COLUMN locked_by UUID NULL REFERENCES public.user_profiles(id);
|
||||
END IF;
|
||||
|
||||
-- Remove NOT NULL constraints from old columns to allow new data insertion
|
||||
ALTER TABLE public.experiment_repetitions ALTER COLUMN experiment_number DROP NOT NULL;
|
||||
ALTER TABLE public.experiment_repetitions ALTER COLUMN experiment_phase_id DROP NOT NULL;
|
||||
END $$;
|
||||
|
||||
-- 2) Backfill experiment_id by joining on (experiment_number, experiment_phase_id) -> experiments(id)
|
||||
UPDATE public.experiment_repetitions er
|
||||
SET experiment_id = e.id
|
||||
FROM public.experiments e
|
||||
WHERE er.experiment_id IS NULL
|
||||
AND e.experiment_number = er.experiment_number
|
||||
AND e.phase_id = er.experiment_phase_id;
|
||||
|
||||
-- 3) Create trigger to auto-populate experiment_id for inserts
|
||||
CREATE OR REPLACE FUNCTION public.set_experiment_id_on_repetition()
|
||||
RETURNS TRIGGER AS $func$
|
||||
BEGIN
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
SELECT e.id INTO NEW.experiment_id
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number = NEW.experiment_number
|
||||
AND e.phase_id = NEW.experiment_phase_id;
|
||||
|
||||
-- If still NULL, raise an error with helpful message
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
RAISE EXCEPTION 'Could not find experiment with experiment_number=% and phase_id=%',
|
||||
NEW.experiment_number, NEW.experiment_phase_id;
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_set_experiment_id_on_repetition ON public.experiment_repetitions;
|
||||
CREATE TRIGGER trg_set_experiment_id_on_repetition
|
||||
BEFORE INSERT OR UPDATE OF experiment_number, experiment_phase_id ON public.experiment_repetitions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_experiment_id_on_repetition();
|
||||
|
||||
-- 4) Add FK and not null once backfilled and trigger is in place
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD CONSTRAINT experiment_repetitions_experiment_id_fkey
|
||||
FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ALTER COLUMN experiment_id SET NOT NULL;
|
||||
|
||||
-- 5) Create indexes to support queries used in app
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_experiment_id ON public.experiment_repetitions(experiment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_repetition_number ON public.experiment_repetitions(repetition_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_experiment_repetitions_scheduled_date ON public.experiment_repetitions(scheduled_date);
|
||||
|
||||
-- 6) Maintain uniqueness: unique repetition_number per experiment_id
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint
|
||||
WHERE conname = 'uniq_experiment_repetition_number_per_experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.experiment_repetitions
|
||||
ADD CONSTRAINT uniq_experiment_repetition_number_per_experiment_id
|
||||
UNIQUE (experiment_id, repetition_number);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 6) Optional: keep legacy uniqueness on (experiment_number, experiment_phase_id, repetition_number) if desired
|
||||
-- This keeps backward compatibility with any existing references
|
||||
|
||||
-- 7) RLS already enabled; no change to policies necessary for added columns
|
||||
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
-- Fix phase tables to use experiment_id instead of composite key
|
||||
-- This aligns the schema with application expectations
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 1) Add experiment_id column to all phase tables and remove NOT NULL constraints from old columns
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Soaking table
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'soaking' AND column_name = 'experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.soaking ADD COLUMN experiment_id UUID;
|
||||
END IF;
|
||||
|
||||
-- Remove NOT NULL constraints from old columns to allow new data insertion
|
||||
ALTER TABLE public.soaking ALTER COLUMN experiment_number DROP NOT NULL;
|
||||
ALTER TABLE public.soaking ALTER COLUMN experiment_phase_id DROP NOT NULL;
|
||||
|
||||
-- Airdrying table
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'airdrying' AND column_name = 'experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.airdrying ADD COLUMN experiment_id UUID;
|
||||
END IF;
|
||||
|
||||
ALTER TABLE public.airdrying ALTER COLUMN experiment_number DROP NOT NULL;
|
||||
ALTER TABLE public.airdrying ALTER COLUMN experiment_phase_id DROP NOT NULL;
|
||||
|
||||
-- Cracking table
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'cracking' AND column_name = 'experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.cracking ADD COLUMN experiment_id UUID;
|
||||
END IF;
|
||||
|
||||
ALTER TABLE public.cracking ALTER COLUMN experiment_number DROP NOT NULL;
|
||||
ALTER TABLE public.cracking ALTER COLUMN experiment_phase_id DROP NOT NULL;
|
||||
|
||||
-- Shelling table
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'public' AND table_name = 'shelling' AND column_name = 'experiment_id'
|
||||
) THEN
|
||||
ALTER TABLE public.shelling ADD COLUMN experiment_id UUID;
|
||||
END IF;
|
||||
|
||||
ALTER TABLE public.shelling ALTER COLUMN experiment_number DROP NOT NULL;
|
||||
ALTER TABLE public.shelling ALTER COLUMN experiment_phase_id DROP NOT NULL;
|
||||
END $$;
|
||||
|
||||
-- 2) Backfill experiment_id from composite key for all phase tables (only if old data exists)
|
||||
-- This migration is designed to work with existing data that has the old schema
|
||||
-- For fresh data, the seed files will populate experiment_id directly
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Only backfill if there are records with the old schema (experiment_number is NOT NULL)
|
||||
-- and experiment_id is NULL (meaning they haven't been migrated yet)
|
||||
IF EXISTS (SELECT 1 FROM public.soaking WHERE experiment_id IS NULL AND experiment_number IS NOT NULL) THEN
|
||||
UPDATE public.soaking s
|
||||
SET experiment_id = e.id
|
||||
FROM public.experiments e
|
||||
WHERE s.experiment_id IS NULL
|
||||
AND e.experiment_number = s.experiment_number
|
||||
AND e.phase_id = s.experiment_phase_id;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM public.airdrying WHERE experiment_id IS NULL AND experiment_number IS NOT NULL) THEN
|
||||
UPDATE public.airdrying a
|
||||
SET experiment_id = e.id
|
||||
FROM public.experiments e
|
||||
WHERE a.experiment_id IS NULL
|
||||
AND e.experiment_number = a.experiment_number
|
||||
AND e.phase_id = a.experiment_phase_id;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM public.cracking WHERE experiment_id IS NULL AND experiment_number IS NOT NULL) THEN
|
||||
UPDATE public.cracking c
|
||||
SET experiment_id = e.id
|
||||
FROM public.experiments e
|
||||
WHERE c.experiment_id IS NULL
|
||||
AND e.experiment_number = c.experiment_number
|
||||
AND e.phase_id = c.experiment_phase_id;
|
||||
END IF;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM public.shelling WHERE experiment_id IS NULL AND experiment_number IS NOT NULL) THEN
|
||||
UPDATE public.shelling s
|
||||
SET experiment_id = e.id
|
||||
FROM public.experiments e
|
||||
WHERE s.experiment_id IS NULL
|
||||
AND e.experiment_number = s.experiment_number
|
||||
AND e.phase_id = s.experiment_phase_id;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 3) Add foreign key constraints to experiments(id)
|
||||
ALTER TABLE public.soaking
|
||||
ADD CONSTRAINT soaking_experiment_id_fkey
|
||||
FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.airdrying
|
||||
ADD CONSTRAINT airdrying_experiment_id_fkey
|
||||
FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.cracking
|
||||
ADD CONSTRAINT cracking_experiment_id_fkey
|
||||
FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE public.shelling
|
||||
ADD CONSTRAINT shelling_experiment_id_fkey
|
||||
FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
|
||||
|
||||
-- 4) Create triggers to auto-populate experiment_id for phase tables
|
||||
CREATE OR REPLACE FUNCTION public.set_experiment_id_on_soaking()
|
||||
RETURNS TRIGGER AS $func$
|
||||
BEGIN
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
SELECT e.id INTO NEW.experiment_id
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number = NEW.experiment_number
|
||||
AND e.phase_id = NEW.experiment_phase_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.set_experiment_id_on_airdrying()
|
||||
RETURNS TRIGGER AS $func$
|
||||
BEGIN
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
SELECT e.id INTO NEW.experiment_id
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number = NEW.experiment_number
|
||||
AND e.phase_id = NEW.experiment_phase_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.set_experiment_id_on_cracking()
|
||||
RETURNS TRIGGER AS $func$
|
||||
BEGIN
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
SELECT e.id INTO NEW.experiment_id
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number = NEW.experiment_number
|
||||
AND e.phase_id = NEW.experiment_phase_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.set_experiment_id_on_shelling()
|
||||
RETURNS TRIGGER AS $func$
|
||||
BEGIN
|
||||
IF NEW.experiment_id IS NULL THEN
|
||||
SELECT e.id INTO NEW.experiment_id
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number = NEW.experiment_number
|
||||
AND e.phase_id = NEW.experiment_phase_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$func$ LANGUAGE plpgsql;
|
||||
|
||||
-- Create triggers
|
||||
DROP TRIGGER IF EXISTS trg_set_experiment_id_on_soaking ON public.soaking;
|
||||
CREATE TRIGGER trg_set_experiment_id_on_soaking
|
||||
BEFORE INSERT OR UPDATE OF experiment_number, experiment_phase_id ON public.soaking
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_experiment_id_on_soaking();
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_set_experiment_id_on_airdrying ON public.airdrying;
|
||||
CREATE TRIGGER trg_set_experiment_id_on_airdrying
|
||||
BEFORE INSERT OR UPDATE OF experiment_number, experiment_phase_id ON public.airdrying
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_experiment_id_on_airdrying();
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_set_experiment_id_on_cracking ON public.cracking;
|
||||
CREATE TRIGGER trg_set_experiment_id_on_cracking
|
||||
BEFORE INSERT OR UPDATE OF experiment_number, experiment_phase_id ON public.cracking
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_experiment_id_on_cracking();
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_set_experiment_id_on_shelling ON public.shelling;
|
||||
CREATE TRIGGER trg_set_experiment_id_on_shelling
|
||||
BEFORE INSERT OR UPDATE OF experiment_number, experiment_phase_id ON public.shelling
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_experiment_id_on_shelling();
|
||||
|
||||
-- 5) Make experiment_id NOT NULL after backfilling and triggers are in place
|
||||
-- Only do this if there are no NULL values
|
||||
DO $$
|
||||
BEGIN
|
||||
-- Check if all records have experiment_id populated before making it NOT NULL
|
||||
IF NOT EXISTS (SELECT 1 FROM public.soaking WHERE experiment_id IS NULL) THEN
|
||||
ALTER TABLE public.soaking ALTER COLUMN experiment_id SET NOT NULL;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM public.airdrying WHERE experiment_id IS NULL) THEN
|
||||
ALTER TABLE public.airdrying ALTER COLUMN experiment_id SET NOT NULL;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM public.cracking WHERE experiment_id IS NULL) THEN
|
||||
ALTER TABLE public.cracking ALTER COLUMN experiment_id SET NOT NULL;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM public.shelling WHERE experiment_id IS NULL) THEN
|
||||
ALTER TABLE public.shelling ALTER COLUMN experiment_id SET NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 6) Create indexes for experiment_id
|
||||
CREATE INDEX IF NOT EXISTS idx_soaking_experiment_id ON public.soaking(experiment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_airdrying_experiment_id ON public.airdrying(experiment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_cracking_experiment_id ON public.cracking(experiment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_shelling_experiment_id ON public.shelling(experiment_id);
|
||||
|
||||
-- 7) Update unique constraints to use experiment_id instead of composite key
|
||||
-- Drop old unique constraints
|
||||
ALTER TABLE public.soaking DROP CONSTRAINT IF EXISTS unique_soaking_per_experiment;
|
||||
ALTER TABLE public.airdrying DROP CONSTRAINT IF EXISTS unique_airdrying_per_experiment;
|
||||
ALTER TABLE public.cracking DROP CONSTRAINT IF EXISTS unique_cracking_per_experiment;
|
||||
ALTER TABLE public.shelling DROP CONSTRAINT IF EXISTS unique_shelling_per_experiment;
|
||||
|
||||
-- Add new unique constraints using experiment_id
|
||||
ALTER TABLE public.soaking ADD CONSTRAINT unique_soaking_per_experiment UNIQUE (experiment_id);
|
||||
ALTER TABLE public.airdrying ADD CONSTRAINT unique_airdrying_per_experiment UNIQUE (experiment_id);
|
||||
ALTER TABLE public.cracking ADD CONSTRAINT unique_cracking_per_experiment UNIQUE (experiment_id);
|
||||
ALTER TABLE public.shelling ADD CONSTRAINT unique_shelling_per_experiment UNIQUE (experiment_id);
|
||||
|
||||
COMMIT;
|
||||
@@ -258,7 +258,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'Brendan.Surio@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- Create William Mcconnell (Data Recorder)
|
||||
@@ -306,7 +307,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'William.McConnell@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- Create Camille Deguzman (Data Recorder)
|
||||
@@ -354,7 +356,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'cpd08598@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- Create Justin Hetzler (Data Recorder)
|
||||
@@ -402,7 +405,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'Justin.Hetzler@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- Create Joshua Wilson (Data Recorder)
|
||||
@@ -450,7 +454,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'jdw58940@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- Create Sydney Orlofsky (Data Recorder)
|
||||
@@ -498,7 +503,8 @@ SELECT
|
||||
FROM public.user_profiles up
|
||||
CROSS JOIN public.roles r
|
||||
WHERE up.email = 'Sydney.Orlofsky@uga.edu'
|
||||
AND r.name = 'data recorder'
|
||||
AND r.name IN ('conductor', 'data recorder')
|
||||
|
||||
;
|
||||
|
||||
-- =============================================
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
-- Phase 2 JC Experiments Seed Data
|
||||
-- This file contains all Phase 2 JC experiments from phase_2_experimental_run_sheet.csv
|
||||
-- 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 use 1-based numbering per phase and composite primary key
|
||||
-- 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)
|
||||
-- First, insert unique experiments (based on experiment_number from CSV: 0-19)
|
||||
INSERT INTO public.experiments (
|
||||
experiment_number,
|
||||
reps_required,
|
||||
@@ -16,8 +16,11 @@ INSERT INTO public.experiments (
|
||||
phase_id,
|
||||
created_by
|
||||
) VALUES
|
||||
-- Phase 2 JC Experiments 1-20 (1-based numbering)
|
||||
(1, 3, 'valid', false,
|
||||
-- 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,
|
||||
@@ -72,9 +75,6 @@ INSERT INTO public.experiments (
|
||||
(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;
|
||||
@@ -83,67 +83,65 @@ 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)
|
||||
-- Create soaking records for Phase 2 JC experiments (0-19) with data from CSV
|
||||
INSERT INTO public.soaking (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
soaking_duration_hours,
|
||||
soaking_duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
NOW() + (e.experiment_number) * INTERVAL '1 day',
|
||||
e.id,
|
||||
NOW() + (e.experiment_number + 1) * 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
|
||||
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) * INTERVAL '1 day' +
|
||||
NOW() + (e.experiment_number + 1) * 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'
|
||||
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 1 AND 20
|
||||
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;
|
||||
|
||||
@@ -151,31 +149,30 @@ ON CONFLICT DO NOTHING;
|
||||
-- CREATE AIRDRYING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create airdrying records for Phase 2 JC experiments (1-20)
|
||||
-- Create airdrying records for Phase 2 JC experiments (0-19) with data from CSV
|
||||
INSERT INTO public.airdrying (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking
|
||||
e.id,
|
||||
NOW() + (e.experiment_number + 1) * 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 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
|
||||
@@ -184,21 +181,21 @@ SELECT
|
||||
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' +
|
||||
NOW() + (e.experiment_number + 1) * 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 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
|
||||
@@ -207,11 +204,10 @@ SELECT
|
||||
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
|
||||
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;
|
||||
|
||||
@@ -219,22 +215,20 @@ ON CONFLICT DO NOTHING;
|
||||
-- CREATE CRACKING PHASE RECORDS FOR PHASE 2 JC EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create cracking records for Phase 2 JC experiments (1-20)
|
||||
-- Create cracking records for Phase 2 JC experiments (0-19)
|
||||
INSERT INTO public.cracking (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
machine_type_id,
|
||||
scheduled_start_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
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
|
||||
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 1 AND 20
|
||||
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;
|
||||
|
||||
@@ -242,7 +236,7 @@ ON CONFLICT DO NOTHING;
|
||||
-- CREATE JC CRACKER PARAMETERS FOR PHASE 2 JC EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create JC cracker parameters for Phase 2 JC experiments (1-20)
|
||||
-- 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,
|
||||
@@ -253,96 +247,96 @@ INSERT INTO public.jc_cracker_parameters (
|
||||
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 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 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
|
||||
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 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 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.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 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.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.07
|
||||
WHEN 20 THEN 0.06
|
||||
WHEN 19 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
|
||||
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.experiment_number AND c.experiment_phase_id = e.phase_id
|
||||
WHERE e.experiment_number BETWEEN 1 AND 20
|
||||
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;
|
||||
|
||||
@@ -354,19 +348,17 @@ ON CONFLICT DO NOTHING;
|
||||
-- Each experiment needs 3 repetitions
|
||||
INSERT INTO public.experiment_repetitions (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
repetition_number,
|
||||
status,
|
||||
completion_status,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
e.id,
|
||||
rep_num,
|
||||
'pending',
|
||||
false,
|
||||
e.created_by
|
||||
FROM public.experiments e
|
||||
CROSS JOIN generate_series(1, 3) AS rep_num
|
||||
WHERE e.experiment_number BETWEEN 1 AND 20
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
-- 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_number,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
soaking_duration_hours,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
machine_type_id,
|
||||
scheduled_start_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number = e.experiment_number AND c.experiment_phase_id = e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
repetition_number,
|
||||
status,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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;
|
||||
@@ -370,3 +370,4 @@ 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;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
-- Meyer Experiments Seed Data
|
||||
-- This file contains all 40 Meyer experiments from meyer experiments.csv
|
||||
-- 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 use 1-based numbering per phase and composite primary key
|
||||
-- Updated to match the actual CSV data with correct experiment numbers and parameters
|
||||
|
||||
-- =============================================
|
||||
-- INSERT MEYER EXPERIMENTS (Post Workshop)
|
||||
-- =============================================
|
||||
|
||||
-- Insert Meyer experiments (experiments 1-40)
|
||||
-- Insert Meyer experiments (experiments 1-40) with data from CSV
|
||||
INSERT INTO public.experiments (
|
||||
experiment_number,
|
||||
reps_required,
|
||||
@@ -16,7 +16,7 @@ INSERT INTO public.experiments (
|
||||
phase_id,
|
||||
created_by
|
||||
) VALUES
|
||||
-- Meyer Experiments 1-40 (1-based numbering)
|
||||
-- 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')),
|
||||
@@ -143,103 +143,101 @@ ON CONFLICT (experiment_number, phase_id) DO NOTHING;
|
||||
-- CREATE SOAKING PHASE RECORDS FOR MEYER EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create soaking records for Meyer experiments (1-40)
|
||||
-- Create soaking records for Meyer experiments (1-40) with data from CSV
|
||||
INSERT INTO public.soaking (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
soaking_duration_hours,
|
||||
soaking_duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
NOW() + (e.experiment_number) * INTERVAL '1 day',
|
||||
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
|
||||
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' +
|
||||
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'
|
||||
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
|
||||
@@ -251,19 +249,17 @@ ON CONFLICT DO NOTHING;
|
||||
-- CREATE AIRDRYING PHASE RECORDS FOR MEYER EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create airdrying records for Meyer experiments (1-40)
|
||||
-- Create airdrying records for Meyer experiments (1-40) with data from CSV
|
||||
INSERT INTO public.airdrying (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days', -- Start 2 days after soaking
|
||||
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
|
||||
@@ -306,7 +302,7 @@ SELECT
|
||||
WHEN 39 THEN 25 -- 25 minutes
|
||||
WHEN 40 THEN 13 -- 13 minutes
|
||||
END,
|
||||
NOW() + (e.experiment_number) * INTERVAL '1 day' + INTERVAL '2 days' +
|
||||
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
|
||||
@@ -362,16 +358,14 @@ ON CONFLICT DO NOTHING;
|
||||
-- Create cracking records for Meyer experiments (1-40)
|
||||
INSERT INTO public.cracking (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
machine_type_id,
|
||||
scheduled_start_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
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
|
||||
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
|
||||
@@ -382,7 +376,7 @@ ON CONFLICT DO NOTHING;
|
||||
-- CREATE MEYER CRACKER PARAMETERS FOR MEYER EXPERIMENTS
|
||||
-- =============================================
|
||||
|
||||
-- Create Meyer cracker parameters for Meyer experiments (1-40)
|
||||
-- Create Meyer cracker parameters for Meyer experiments (1-40) with data from CSV
|
||||
INSERT INTO public.meyer_cracker_parameters (
|
||||
cracking_id,
|
||||
motor_speed_hz,
|
||||
@@ -518,7 +512,7 @@ SELECT
|
||||
WHEN 40 THEN 2000.0
|
||||
END
|
||||
FROM public.experiments e
|
||||
JOIN public.cracking c ON c.experiment_id = e.experiment_number AND c.experiment_phase_id = e.phase_id
|
||||
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;
|
||||
@@ -531,16 +525,14 @@ ON CONFLICT DO NOTHING;
|
||||
-- Each experiment needs only 1 repetition
|
||||
INSERT INTO public.experiment_repetitions (
|
||||
experiment_id,
|
||||
experiment_phase_id,
|
||||
repetition_number,
|
||||
status,
|
||||
completion_status,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_id,
|
||||
e.id,
|
||||
1,
|
||||
'pending',
|
||||
false,
|
||||
e.created_by
|
||||
FROM public.experiments e
|
||||
WHERE e.experiment_number BETWEEN 1 AND 40
|
||||
|
||||
@@ -0,0 +1,548 @@
|
||||
-- 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_number,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
soaking_duration_hours,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
scheduled_start_time,
|
||||
duration_minutes,
|
||||
scheduled_end_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
machine_type_id,
|
||||
scheduled_start_time,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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_number = e.experiment_number AND c.experiment_phase_id = e.phase_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_number,
|
||||
experiment_phase_id,
|
||||
repetition_number,
|
||||
status,
|
||||
created_by
|
||||
)
|
||||
SELECT
|
||||
e.experiment_number,
|
||||
e.phase_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;
|
||||
@@ -546,3 +546,4 @@ 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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user