Backup: old custom PHP API code removed from fahrschultermin.de
This commit is contained in:
145
backup/old_api_20260520/database/migrations/001_initial.sql
Normal file
145
backup/old_api_20260520/database/migrations/001_initial.sql
Normal file
@@ -0,0 +1,145 @@
|
||||
CREATE TABLE IF NOT EXISTS tenants (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
timezone TEXT NOT NULL DEFAULT 'Europe/Berlin',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NULL,
|
||||
role TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS instructors (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
color TEXT NOT NULL,
|
||||
notes TEXT DEFAULT '',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS lesson_types (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
color TEXT NOT NULL,
|
||||
default_duration INTEGER NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
requirement_key TEXT DEFAULT NULL,
|
||||
is_billable INTEGER NOT NULL DEFAULT 0,
|
||||
is_counted INTEGER NOT NULL DEFAULT 0,
|
||||
is_rest_relevant INTEGER NOT NULL DEFAULT 0,
|
||||
fixed_duration INTEGER NOT NULL DEFAULT 0,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS license_class_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
code TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
is_combination INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
UNIQUE (tenant_id, code),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS license_template_requirements (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
requirement_key TEXT NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
required_units INTEGER NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (template_id) REFERENCES license_class_templates (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS students (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
phone TEXT DEFAULT '',
|
||||
notes TEXT DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (template_id) REFERENCES license_class_templates (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS student_requirement_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
student_id INTEGER NOT NULL,
|
||||
requirement_key TEXT NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
required_units INTEGER NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS appointments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
student_id INTEGER DEFAULT NULL,
|
||||
instructor_id INTEGER NOT NULL,
|
||||
lesson_type_id INTEGER NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
start_at TEXT NOT NULL,
|
||||
end_at TEXT NOT NULL,
|
||||
units INTEGER NOT NULL DEFAULT 1,
|
||||
status TEXT NOT NULL DEFAULT 'planned',
|
||||
notes TEXT DEFAULT '',
|
||||
warning_acknowledged INTEGER NOT NULL DEFAULT 0,
|
||||
created_by INTEGER NOT NULL,
|
||||
updated_by INTEGER NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (instructor_id) REFERENCES instructors (id),
|
||||
FOREIGN KEY (lesson_type_id) REFERENCES lesson_types (id),
|
||||
FOREIGN KEY (created_by) REFERENCES users (id),
|
||||
FOREIGN KEY (updated_by) REFERENCES users (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS appointment_units (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
appointment_id INTEGER NOT NULL,
|
||||
requirement_key TEXT DEFAULT NULL,
|
||||
label TEXT DEFAULT NULL,
|
||||
units_counted INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL,
|
||||
FOREIGN KEY (appointment_id) REFERENCES appointments (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
key_name TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
UNIQUE (tenant_id, key_name),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants (id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE instructors ADD COLUMN user_id INTEGER DEFAULT NULL;
|
||||
@@ -0,0 +1,11 @@
|
||||
UPDATE instructors
|
||||
SET user_id = (
|
||||
SELECT u.id
|
||||
FROM users u
|
||||
WHERE u.tenant_id = instructors.tenant_id
|
||||
AND u.role = 'instructor'
|
||||
AND u.first_name = instructors.first_name
|
||||
AND u.last_name = instructors.last_name
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE user_id IS NULL;
|
||||
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE IF NOT EXISTS lesson_type_template_visibility (
|
||||
lesson_type_id INTEGER NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (lesson_type_id, template_id),
|
||||
FOREIGN KEY (lesson_type_id) REFERENCES lesson_types (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (template_id) REFERENCES license_class_templates (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO lesson_type_template_visibility (lesson_type_id, template_id)
|
||||
SELECT lt.id, tpl.id
|
||||
FROM lesson_types lt
|
||||
JOIN license_class_templates tpl ON tpl.tenant_id = lt.tenant_id
|
||||
WHERE lt.category = 'student';
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE tenants ADD COLUMN location_label TEXT DEFAULT '';
|
||||
ALTER TABLE tenants ADD COLUMN latitude REAL DEFAULT NULL;
|
||||
ALTER TABLE tenants ADD COLUMN longitude REAL DEFAULT NULL;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE tenants ADD COLUMN federal_state TEXT DEFAULT 'BE';
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE student_requirement_snapshots ADD COLUMN prior_completed_units INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE lesson_types ADD COLUMN system_key TEXT DEFAULT NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_lesson_types_tenant_system_key ON lesson_types (tenant_id, system_key) WHERE system_key IS NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE license_template_requirements ADD COLUMN phase_label TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE student_requirement_snapshots ADD COLUMN phase_label TEXT NOT NULL DEFAULT '';
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE students ADD COLUMN email TEXT NOT NULL DEFAULT '';
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE students ADD COLUMN email TEXT DEFAULT '';
|
||||
ALTER TABLE students ADD COLUMN needs_glasses INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE students ADD COLUMN needs_glasses INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,183 @@
|
||||
DROP TABLE IF EXISTS student_requirement_snapshots_old;
|
||||
CREATE TEMP TABLE student_requirement_snapshots_old AS
|
||||
SELECT *
|
||||
FROM student_requirement_snapshots
|
||||
WHERE student_id IN (
|
||||
SELECT s.id
|
||||
FROM students s
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.code IN ('C+CE', 'C1+C1E')
|
||||
);
|
||||
|
||||
DELETE FROM license_template_requirements
|
||||
WHERE template_id IN (
|
||||
SELECT id FROM license_class_templates WHERE code IN ('C+CE', 'C1+C1E')
|
||||
);
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C::practice', 'Uebungsstunden', 8, 0, 'C'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C::rural', 'Ueberland', 5, 1, 'C'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C::highway', 'Autobahn', 4, 2, 'C'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C::night', 'Nachtfahrt', 3, 3, 'C'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'CE::practice', 'Uebungsstunden', 6, 100, 'CE'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'CE::rural', 'Ueberland', 3, 101, 'CE'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'CE::highway', 'Autobahn', 3, 102, 'CE'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'CE::night', 'Nachtfahrt', 2, 103, 'CE'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C+CE';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1::practice', 'Uebungsstunden', 6, 0, 'C1'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1::rural', 'Ueberland', 4, 1, 'C1'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1::highway', 'Autobahn', 3, 2, 'C1'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1::night', 'Nachtfahrt', 2, 3, 'C1'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1E::practice', 'Uebungsstunden', 4, 100, 'C1E'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1E::rural', 'Ueberland', 2, 101, 'C1E'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1E::highway', 'Autobahn', 2, 102, 'C1E'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
INSERT INTO license_template_requirements (template_id, requirement_key, label, required_units, sort_order, phase_label)
|
||||
SELECT id, 'C1E::night', 'Nachtfahrt', 1, 103, 'C1E'
|
||||
FROM license_class_templates
|
||||
WHERE code = 'C1+C1E';
|
||||
|
||||
UPDATE appointment_units
|
||||
SET requirement_key = 'C::' || requirement_key
|
||||
WHERE requirement_key IN ('practice', 'rural', 'highway', 'night')
|
||||
AND appointment_id IN (
|
||||
SELECT a.id
|
||||
FROM appointments a
|
||||
JOIN students s ON s.id = a.student_id
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.code = 'C+CE'
|
||||
);
|
||||
|
||||
UPDATE appointment_units
|
||||
SET requirement_key = 'C1::' || requirement_key
|
||||
WHERE requirement_key IN ('practice', 'rural', 'highway', 'night')
|
||||
AND appointment_id IN (
|
||||
SELECT a.id
|
||||
FROM appointments a
|
||||
JOIN students s ON s.id = a.student_id
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.code = 'C1+C1E'
|
||||
);
|
||||
|
||||
DELETE FROM student_requirement_snapshots
|
||||
WHERE student_id IN (
|
||||
SELECT s.id
|
||||
FROM students s
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.code IN ('C+CE', 'C1+C1E')
|
||||
);
|
||||
|
||||
INSERT INTO student_requirement_snapshots (student_id, requirement_key, label, required_units, sort_order, prior_completed_units, phase_label)
|
||||
SELECT
|
||||
s.id,
|
||||
r.requirement_key,
|
||||
r.label,
|
||||
r.required_units,
|
||||
r.sort_order,
|
||||
CASE
|
||||
WHEN r.requirement_key = 'C::practice' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'practice'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C::rural' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'rural'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C::highway' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'highway'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C::night' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'night'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C1::practice' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'practice'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C1::rural' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'rural'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C1::highway' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'highway'
|
||||
), 0)
|
||||
WHEN r.requirement_key = 'C1::night' THEN COALESCE((
|
||||
SELECT prior_completed_units
|
||||
FROM student_requirement_snapshots_old old
|
||||
WHERE old.student_id = s.id AND old.requirement_key = 'night'
|
||||
), 0)
|
||||
ELSE 0
|
||||
END,
|
||||
r.phase_label
|
||||
FROM students s
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
JOIN license_template_requirements r ON r.template_id = t.id
|
||||
WHERE t.code IN ('C+CE', 'C1+C1E');
|
||||
|
||||
DROP TABLE IF EXISTS student_requirement_snapshots_old;
|
||||
@@ -0,0 +1,42 @@
|
||||
UPDATE appointment_units
|
||||
SET requirement_key = COALESCE(
|
||||
(
|
||||
SELECT r.requirement_key
|
||||
FROM appointments a
|
||||
JOIN students s ON s.id = a.student_id
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
JOIN license_template_requirements r ON r.template_id = t.id
|
||||
WHERE a.id = appointment_units.appointment_id
|
||||
AND t.is_combination = 1
|
||||
AND COALESCE(r.phase_label, '') <> ''
|
||||
AND substr(r.requirement_key, instr(r.requirement_key, '::') + 2) = appointment_units.requirement_key
|
||||
ORDER BY r.sort_order
|
||||
LIMIT 1
|
||||
),
|
||||
requirement_key
|
||||
)
|
||||
WHERE requirement_key NOT LIKE '%::%'
|
||||
AND appointment_id IN (
|
||||
SELECT a.id
|
||||
FROM appointments a
|
||||
JOIN students s ON s.id = a.student_id
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.is_combination = 1
|
||||
);
|
||||
|
||||
DELETE FROM student_requirement_snapshots
|
||||
WHERE requirement_key NOT LIKE '%::%'
|
||||
AND student_id IN (
|
||||
SELECT s.id
|
||||
FROM students s
|
||||
JOIN license_class_templates t ON t.id = s.template_id
|
||||
WHERE t.is_combination = 1
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM students s
|
||||
JOIN license_template_requirements r ON r.template_id = s.template_id
|
||||
WHERE s.id = student_requirement_snapshots.student_id
|
||||
AND COALESCE(r.phase_label, '') <> ''
|
||||
AND substr(r.requirement_key, instr(r.requirement_key, '::') + 2) = student_requirement_snapshots.requirement_key
|
||||
);
|
||||
@@ -0,0 +1,170 @@
|
||||
UPDATE appointment_units
|
||||
SET requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM appointments a
|
||||
JOIN students s ON s.id = a.student_id
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE a.id = appointment_units.appointment_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND (
|
||||
(appointment_units.requirement_key = 'intro' AND lt.name = 'Einweisung')
|
||||
OR (appointment_units.requirement_key = 'practice' AND lt.name IN ('Uebungsstunde', 'Übungsstunde', 'Uebungsstunden', 'Übungsstunden'))
|
||||
OR (appointment_units.requirement_key = 'rural' AND lt.name IN ('Ueberlandfahrt', 'Überlandfahrt', 'Bundes- / Landstrasse'))
|
||||
OR (appointment_units.requirement_key = 'highway' AND lt.name IN ('Autobahn', 'Autobahnfahrt'))
|
||||
OR (appointment_units.requirement_key = 'night' AND lt.name IN ('Nachtfahrt', 'Nachtfahrten', 'Daemmerung / Dunkelheit'))
|
||||
)
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), requirement_key)
|
||||
WHERE requirement_key IN ('intro', 'practice', 'rural', 'highway', 'night');
|
||||
|
||||
UPDATE student_requirement_snapshots AS target
|
||||
SET prior_completed_units = prior_completed_units + COALESCE((
|
||||
SELECT SUM(src.prior_completed_units)
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'intro'
|
||||
), 0)
|
||||
WHERE target.requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = target.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND lt.name = 'Einweisung'
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), target.requirement_key)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'intro'
|
||||
);
|
||||
|
||||
UPDATE student_requirement_snapshots AS target
|
||||
SET prior_completed_units = prior_completed_units + COALESCE((
|
||||
SELECT SUM(src.prior_completed_units)
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'practice'
|
||||
), 0)
|
||||
WHERE target.requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = target.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND lt.name IN ('Uebungsstunde', 'Übungsstunde', 'Uebungsstunden', 'Übungsstunden')
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), target.requirement_key)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'practice'
|
||||
);
|
||||
|
||||
UPDATE student_requirement_snapshots AS target
|
||||
SET prior_completed_units = prior_completed_units + COALESCE((
|
||||
SELECT SUM(src.prior_completed_units)
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'rural'
|
||||
), 0)
|
||||
WHERE target.requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = target.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND lt.name IN ('Ueberlandfahrt', 'Überlandfahrt', 'Bundes- / Landstrasse')
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), target.requirement_key)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'rural'
|
||||
);
|
||||
|
||||
UPDATE student_requirement_snapshots AS target
|
||||
SET prior_completed_units = prior_completed_units + COALESCE((
|
||||
SELECT SUM(src.prior_completed_units)
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'highway'
|
||||
), 0)
|
||||
WHERE target.requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = target.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND lt.name IN ('Autobahn', 'Autobahnfahrt')
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), target.requirement_key)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'highway'
|
||||
);
|
||||
|
||||
UPDATE student_requirement_snapshots AS target
|
||||
SET prior_completed_units = prior_completed_units + COALESCE((
|
||||
SELECT SUM(src.prior_completed_units)
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'night'
|
||||
), 0)
|
||||
WHERE target.requirement_key = COALESCE((
|
||||
SELECT 'lesson_type_' || lt.id
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = target.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND lt.name IN ('Nachtfahrt', 'Nachtfahrten', 'Daemmerung / Dunkelheit')
|
||||
ORDER BY lt.sort_order, lt.id
|
||||
LIMIT 1
|
||||
), target.requirement_key)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM student_requirement_snapshots src
|
||||
WHERE src.student_id = target.student_id
|
||||
AND src.requirement_key = 'night'
|
||||
);
|
||||
|
||||
DELETE FROM student_requirement_snapshots
|
||||
WHERE requirement_key IN ('intro', 'practice', 'rural', 'highway', 'night')
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM students s
|
||||
JOIN lesson_type_template_visibility vis ON vis.template_id = s.template_id
|
||||
JOIN lesson_types lt ON lt.id = vis.lesson_type_id
|
||||
WHERE s.id = student_requirement_snapshots.student_id
|
||||
AND lt.category = 'student'
|
||||
AND lt.is_counted = 1
|
||||
AND (
|
||||
(student_requirement_snapshots.requirement_key = 'intro' AND lt.name = 'Einweisung')
|
||||
OR (student_requirement_snapshots.requirement_key = 'practice' AND lt.name IN ('Uebungsstunde', 'Übungsstunde', 'Uebungsstunden', 'Übungsstunden'))
|
||||
OR (student_requirement_snapshots.requirement_key = 'rural' AND lt.name IN ('Ueberlandfahrt', 'Überlandfahrt', 'Bundes- / Landstrasse'))
|
||||
OR (student_requirement_snapshots.requirement_key = 'highway' AND lt.name IN ('Autobahn', 'Autobahnfahrt'))
|
||||
OR (student_requirement_snapshots.requirement_key = 'night' AND lt.name IN ('Nachtfahrt', 'Nachtfahrten', 'Daemmerung / Dunkelheit'))
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE instructors ADD COLUMN pre_start_buffer_minutes INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,22 @@
|
||||
-- Migration: 015_lesson_type_allows_student_and_notes_private.sql
|
||||
-- Adds allows_student column to lesson_types and notes_private to appointments
|
||||
|
||||
-- 1. lesson_types.allows_student: which lesson types can be assigned a student
|
||||
ALTER TABLE lesson_types ADD COLUMN IF NOT EXISTS allows_student integer NOT NULL DEFAULT 0;
|
||||
COMMENT ON COLUMN lesson_types.allows_student IS '1 = lesson type can have a student_id (e.g. driving lessons), 0 = no student (theory, work, private)';
|
||||
|
||||
-- 2. appointments.notes_private: private note only visible to the instructor (not chef/office)
|
||||
ALTER TABLE appointments ADD COLUMN IF NOT EXISTS notes_private text DEFAULT '';
|
||||
|
||||
-- Default: only 'student' category allows student_id, all other categories = 0
|
||||
UPDATE lesson_types SET allows_student = 1 WHERE category = 'student';
|
||||
UPDATE lesson_types SET allows_student = 0 WHERE category != 'student';
|
||||
|
||||
-- For existing appointments, clear student_id if the lesson_type doesn't allow it
|
||||
-- (data cleanup - not normally needed but defensive)
|
||||
UPDATE appointments
|
||||
SET student_id = NULL
|
||||
WHERE student_id IS NOT NULL
|
||||
AND lesson_type_id IN (
|
||||
SELECT id FROM lesson_types WHERE allows_student = 0
|
||||
);
|
||||
@@ -0,0 +1,39 @@
|
||||
-- Migration: 016_consolidate_lesson_types.sql
|
||||
-- Reihen: tenant 1 und tenant 2 bereinigen, konsistente Einstellungen
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- TENANT 1
|
||||
-- ══════════════════════════════════════════════════════
|
||||
|
||||
-- Tenant 1: Doppelte Einweisung (id=1, id=14 → id=14 renamed to avoid conflict via rename approach)
|
||||
-- Already unique (no action needed)
|
||||
|
||||
-- Tenant 1: Doppelte Übungsstunde (id=2, id=15 → id=15 is in tenant 1 but was already unique)
|
||||
-- Actually tenant 1 has only id=2 (Uebungsstunde) - no duplicate
|
||||
|
||||
-- Tenant 1 work type fixes:
|
||||
-- Sonstige Arbeiten (id=8): is_rest_relevant=1 (zählt für Ruhezeit)
|
||||
UPDATE lesson_types SET is_rest_relevant = 1, fixed_duration = 0 WHERE id = 8 AND tenant_id = 1;
|
||||
|
||||
-- Theorieunterricht (id=7): is_rest_relevant=1, is_billable=1, fixed_duration=0
|
||||
UPDATE lesson_types SET is_rest_relevant = 1, fixed_duration = 0, is_billable = 1 WHERE id = 7 AND tenant_id = 1;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- TENANT 2
|
||||
-- ══════════════════════════════════════════════════════
|
||||
|
||||
-- Tenant 2: Doppelte Namen konsolidieren
|
||||
-- Autobahnfahrt → Autobahn (id=13 → name='Autobahn')
|
||||
UPDATE lesson_types SET name = 'Autobahn' WHERE id = 13 AND tenant_id = 2;
|
||||
-- Übungsstunde (id=15 already named correctly)
|
||||
|
||||
-- Verify tenant 2 student types
|
||||
-- Note: id=11 Nachtfahrten stays (different from tenant 1 which has no Nachtfahrten)
|
||||
-- id=16 Praktische Prüfung stays
|
||||
-- id=12 Überlandfahrt stays
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- ALL TENANTS: allows_student defaults
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- already done in migration 015
|
||||
-- student=1, all others=0
|
||||
@@ -0,0 +1,202 @@
|
||||
-- Migration: 017_student_booking_schema.sql
|
||||
-- Fahrschüler-Buchungssystem + Multi-Tenant Instructor + Break-Rules
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 1. users.role ist bereits text (kein ENUM), keine Änderung nötig
|
||||
-- ══════════════════════════════════════════════════════
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 2. instructors erweitern: UE-Limits + Booking-Settings
|
||||
-- ══════════════════════════════════════════════════════
|
||||
ALTER TABLE instructors ADD COLUMN IF NOT EXISTS max_daily_units integer DEFAULT NULL;
|
||||
ALTER TABLE instructors ADD COLUMN IF NOT EXISTS max_daily_override integer DEFAULT 0;
|
||||
ALTER TABLE instructors ADD COLUMN IF NOT EXISTS max_weekly_units integer DEFAULT NULL;
|
||||
ALTER TABLE instructors ADD COLUMN IF NOT EXISTS max_weekly_override integer DEFAULT 0;
|
||||
ALTER TABLE instructors ADD COLUMN IF NOT EXISTS booking_enabled integer DEFAULT 1;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 3. students erweitern: user_id FK
|
||||
-- ══════════════════════════════════════════════════════
|
||||
ALTER TABLE students ADD COLUMN IF NOT EXISTS user_id bigint REFERENCES users(id) NULL;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 4. tenants erweitern: free_cancellation_hours
|
||||
-- ══════════════════════════════════════════════════════
|
||||
ALTER TABLE tenants ADD COLUMN IF NOT EXISTS free_cancellation_hours integer DEFAULT 24;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 5. tenant_registration_codes
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS tenant_registration_codes (
|
||||
id bigserial PRIMARY KEY,
|
||||
tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
code text NOT NULL UNIQUE,
|
||||
is_active integer DEFAULT 1,
|
||||
used_count integer DEFAULT 0,
|
||||
created_at timestamptz DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_tenant_reg_codes_code ON tenant_registration_codes(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_tenant_reg_codes_tenant ON tenant_registration_codes(tenant_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 6. student_tenants
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS student_tenants (
|
||||
id bigserial PRIMARY KEY,
|
||||
student_user_id bigint NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'suspended')),
|
||||
registered_at timestamptz DEFAULT NOW(),
|
||||
confirmed_at timestamptz NULL,
|
||||
confirmed_by bigint NULL REFERENCES users(id),
|
||||
UNIQUE(student_user_id, tenant_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_student_tenants_user ON student_tenants(student_user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_student_tenants_tenant ON student_tenants(tenant_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 7. instructor_availability
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_availability (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
weekday integer NOT NULL CHECK (weekday BETWEEN 0 AND 6),
|
||||
time_from text NOT NULL,
|
||||
time_to text NOT NULL,
|
||||
is_active integer DEFAULT 1,
|
||||
UNIQUE(instructor_id, weekday, time_from)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_instructor_avail_instructor ON instructor_availability(instructor_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 8. appointment_requests
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS appointment_requests (
|
||||
id bigserial PRIMARY KEY,
|
||||
student_user_id bigint NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
lesson_type_id bigint NOT NULL REFERENCES lesson_types(id),
|
||||
requested_start timestamptz NOT NULL,
|
||||
requested_end timestamptz NOT NULL,
|
||||
status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'rejected', 'cancelled')),
|
||||
requested_at timestamptz DEFAULT NOW(),
|
||||
responded_at timestamptz NULL,
|
||||
response_by bigint NULL REFERENCES users(id),
|
||||
notes text DEFAULT '',
|
||||
confirmed_appointment_id bigint NULL REFERENCES appointments(id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_appt_req_student ON appointment_requests(student_user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_appt_req_instructor ON appointment_requests(instructor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_appt_req_status ON appointment_requests(status);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 9. instructor_vacations
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_vacations (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
date_from date NOT NULL,
|
||||
date_to date NOT NULL,
|
||||
notes text DEFAULT '',
|
||||
created_at timestamptz DEFAULT NOW(),
|
||||
UNIQUE(instructor_id, date_from, date_to)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_instructor_vacations_instructor ON instructor_vacations(instructor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_instructor_vacations_dates ON instructor_vacations(date_from, date_to);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 10. private_appointments
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS private_appointments (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
title text NOT NULL DEFAULT 'Privat',
|
||||
date date NOT NULL,
|
||||
time_from text NOT NULL,
|
||||
time_to text NOT NULL,
|
||||
color text DEFAULT '#9ca3af',
|
||||
created_at timestamptz DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_private_appts_instructor ON private_appointments(instructor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_private_appts_date ON private_appointments(date);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 11. instructor_tenants
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_tenants (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
is_primary integer DEFAULT 0,
|
||||
created_at timestamptz DEFAULT NOW(),
|
||||
UNIQUE(instructor_id, tenant_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_instructor_tenants_instructor ON instructor_tenants(instructor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_instructor_tenants_tenant ON instructor_tenants(tenant_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 12. instructor_travel_times
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_travel_times (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
from_tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
to_tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
minutes integer NOT NULL,
|
||||
UNIQUE(instructor_id, from_tenant_id, to_tenant_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_travel_times_instructor ON instructor_travel_times(instructor_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 13. instructor_home_to_tenant
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_home_to_tenant (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
tenant_id bigint NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
minutes integer NOT NULL,
|
||||
UNIQUE(instructor_id, tenant_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_home_to_tenant_instructor ON instructor_home_to_tenant(instructor_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 14. instructor_break_rules
|
||||
-- ══════════════════════════════════════════════════════
|
||||
CREATE TABLE IF NOT EXISTS instructor_break_rules (
|
||||
id bigserial PRIMARY KEY,
|
||||
instructor_id bigint NOT NULL REFERENCES instructors(id) ON DELETE CASCADE,
|
||||
condition_type text NOT NULL CHECK (condition_type IN ('daily_units', 'weekly_units', 'hours_daily', 'between_appointments', 'continuous_minutes')),
|
||||
operator text NOT NULL CHECK (operator IN ('greater_than', 'equals', 'at_least')),
|
||||
threshold numeric NOT NULL,
|
||||
break_minutes integer NOT NULL,
|
||||
is_active integer DEFAULT 1,
|
||||
created_at timestamptz DEFAULT NOW(),
|
||||
UNIQUE(instructor_id, condition_type, operator, threshold)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_break_rules_instructor ON instructor_break_rules(instructor_id);
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 15. Default Registration-Codes für bestehende Tenants
|
||||
-- ══════════════════════════════════════════════════════
|
||||
INSERT INTO tenant_registration_codes (tenant_id, code, is_active)
|
||||
SELECT id, LPAD(id::text, 8, '0') || '-' || UPPER(SUBSTRING(MD5(id::text || 'salt') FROM 1 FOR 4)), 1
|
||||
FROM tenants
|
||||
WHERE id NOT IN (SELECT tenant_id FROM tenant_registration_codes)
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
-- ══════════════════════════════════════════════════════
|
||||
-- 16. Default Availability für alle Instructors (Mo-So 08:00-19:00)
|
||||
-- ══════════════════════════════════════════════════════
|
||||
INSERT INTO instructor_availability (instructor_id, weekday, time_from, time_to, is_active)
|
||||
SELECT i.id, w.day, '08:00', '19:00', 1
|
||||
FROM instructors i
|
||||
CROSS JOIN (VALUES (0),(1),(2),(3),(4),(5),(6)) AS w(day)
|
||||
WHERE i.is_active = 1
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM instructor_availability ia
|
||||
WHERE ia.instructor_id = i.id AND ia.weekday = w.day
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user