diff --git a/backend/src/controllers/shiftTemplateController.ts b/backend/src/controllers/shiftTemplateController.ts index 6a56fca..270658d 100644 --- a/backend/src/controllers/shiftTemplateController.ts +++ b/backend/src/controllers/shiftTemplateController.ts @@ -10,6 +10,8 @@ import { AuthRequest } from '../middleware/auth.js'; export const getTemplates = async (req: Request, res: Response): Promise => { try { + console.log('🔍 Lade Vorlagen...'); + const templates = await db.all(` SELECT st.*, u.name as created_by_name FROM shift_templates st @@ -17,12 +19,14 @@ export const getTemplates = async (req: Request, res: Response): Promise = ORDER BY st.created_at DESC `); + console.log(`✅ ${templates.length} Vorlagen gefunden:`, templates.map(t => t.name)); + // Für jede Vorlage die Schichten und Zeit-Slots laden const templatesWithShifts = await Promise.all( templates.map(async (template) => { // Lade Schicht-Slots const shiftSlots = await db.all(` - SELECT ts.*, tts.name as time_range_name, tts.start_time as time_range_start, tts.end_time as time_range_end + SELECT ts.*, tts.name as time_slot_name, tts.start_time as time_slot_start, tts.end_time as time_slot_end FROM template_shifts ts LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id WHERE ts.template_id = ? @@ -34,18 +38,18 @@ export const getTemplates = async (req: Request, res: Response): Promise = SELECT * FROM template_time_slots WHERE template_id = ? ORDER BY start_time - `, [template.id]); + `, [template.id]); return { ...template, shifts: shiftSlots.map(slot => ({ id: slot.id, dayOfWeek: slot.day_of_week, - timeRange: { + timeSlot: { id: slot.time_slot_id, - name: slot.time_range_name, - startTime: slot.time_range_start, - endTime: slot.time_range_end + name: slot.time_slot_name, + startTime: slot.time_slot_start, + endTime: slot.time_slot_end }, requiredEmployees: slot.required_employees, color: slot.color @@ -86,7 +90,7 @@ export const getTemplate = async (req: Request, res: Response): Promise => // Lade Schicht-Slots const shiftSlots = await db.all(` - SELECT ts.*, tts.name as time_range_name, tts.start_time as time_range_start, tts.end_time as time_range_end + SELECT ts.*, tts.name as time_slot_name, tts.start_time as time_slot_start, tts.end_time as time_slot_end FROM template_shifts ts LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id WHERE ts.template_id = ? @@ -105,11 +109,11 @@ export const getTemplate = async (req: Request, res: Response): Promise => shifts: shiftSlots.map(slot => ({ id: slot.id, dayOfWeek: slot.day_of_week, - timeRange: { + timeSlot: { id: slot.time_slot_id, - name: slot.time_range_name, - startTime: slot.time_range_start, - endTime: slot.time_range_end + name: slot.time_slot_name, + startTime: slot.time_slot_start, + endTime: slot.time_slot_end }, requiredEmployees: slot.required_employees, color: slot.color @@ -240,7 +244,7 @@ export const createTemplate = async (req: Request, res: Response): Promise await db.run( `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) VALUES (?, ?, ?, ?, ?, ?)`, - [shiftId, templateId, shift.dayOfWeek, shift.timeRange.id, shift.requiredEmployees, shift.color || '#3498db'] + [shiftId, templateId, shift.dayOfWeek, shift.timeSlot.id, shift.requiredEmployees, shift.color || '#3498db'] ); } @@ -329,7 +333,7 @@ export const updateTemplate = async (req: Request, res: Response): Promise await db.run( `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) VALUES (?, ?, ?, ?, ?, ?)`, - [shiftId, id, shift.dayOfWeek, shift.timeRange.id, shift.requiredEmployees, shift.color || '#3498db'] + [shiftId, id, shift.dayOfWeek, shift.timeSlot.id, shift.requiredEmployees, shift.color || '#3498db'] ); } } @@ -395,7 +399,7 @@ async function getTemplateById(templateId: string): Promise { // Lade Schicht-Slots const shiftSlots = await db.all(` - SELECT ts.*, tts.name as time_range_name, tts.start_time as time_range_start, tts.end_time as time_range_end + SELECT ts.*, tts.name as time_slot_name, tts.start_time as time_slot_start, tts.end_time as time_slot_end FROM template_shifts ts LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id WHERE ts.template_id = ? @@ -414,11 +418,11 @@ async function getTemplateById(templateId: string): Promise { shifts: shiftSlots.map(slot => ({ id: slot.id, dayOfWeek: slot.day_of_week, - timeRange: { + timeSlot: { id: slot.time_slot_id, - name: slot.time_range_name, - startTime: slot.time_range_start, - endTime: slot.time_range_end + name: slot.time_slot_name, + startTime: slot.time_slot_start, + endTime: slot.time_slot_end }, requiredEmployees: slot.required_employees, color: slot.color diff --git a/backend/src/database/schema.sql b/backend/src/database/schema.sql index c570892..f5a19b0 100644 --- a/backend/src/database/schema.sql +++ b/backend/src/database/schema.sql @@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS users ( is_sufficiently_independent BOOLEAN DEFAULT FALSE, is_active BOOLEAN DEFAULT TRUE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - last_login TEXT || NULL + last_login TEXT DEFAULT NULL ); -- Tabelle für Schichtvorlagen @@ -27,12 +27,12 @@ CREATE TABLE IF NOT EXISTS shift_templates ( CREATE TABLE IF NOT EXISTS template_shifts ( id TEXT PRIMARY KEY, template_id TEXT NOT NULL, - time_range_id TEXT NOT NULL, + time_slot_id TEXT NOT NULL, day_of_week INTEGER NOT NULL CHECK (day_of_week >= 1 AND day_of_week <= 7), required_employees INTEGER DEFAULT 1, color TEXT DEFAULT '#3498db', FOREIGN KEY (template_id) REFERENCES shift_templates(id) ON DELETE CASCADE, - FOREIGN KEY (time_range_id) REFERENCES template_time_slots(id) ON DELETE CASCADE + FOREIGN KEY (time_slot_id) REFERENCES template_time_slots(id) ON DELETE CASCADE ); -- Tabelle für Zeitbereiche in den Vorlagen diff --git a/backend/src/models/ShiftTemplate.ts b/backend/src/models/ShiftTemplate.ts index 52582a8..4ba74ca 100644 --- a/backend/src/models/ShiftTemplate.ts +++ b/backend/src/models/ShiftTemplate.ts @@ -13,24 +13,30 @@ export interface TemplateShiftSlot { id: string; templateId: string; dayOfWeek: number; - timeRange: TemplateShiftTimeRange; + timeSlot: TemplateShiftTimeSlot; requiredEmployees: number; color?: string; } -export interface TemplateShiftTimeRange { +export interface TemplateShiftTimeSlot { id: string; name: string; // e.g., "Frühschicht", "Spätschicht" startTime: string; endTime: string; } +export const DEFAULT_TIME_SLOTS: TemplateShiftTimeSlot[] = [ + { id: 'morning', name: 'Vormittag', startTime: '08:00', endTime: '12:00' }, + { id: 'afternoon', name: 'Nachmittag', startTime: '11:30', endTime: '15:30' }, +]; + + export interface CreateShiftTemplateRequest { name: string; description?: string; isDefault: boolean; shifts: Omit[]; - timeSlots: TemplateShiftTimeRange[]; + timeSlots: TemplateShiftTimeSlot[]; } export interface UpdateShiftTemplateRequest { @@ -38,5 +44,5 @@ export interface UpdateShiftTemplateRequest { description?: string; isDefault?: boolean; shifts?: Omit[]; - timeSlots?: TemplateShiftTimeRange[]; + timeSlots?: TemplateShiftTimeSlot[]; } \ No newline at end of file diff --git a/backend/src/scripts/setupDefaultTemplate.ts b/backend/src/scripts/setupDefaultTemplate.ts index 9f79ba1..24c15e0 100644 --- a/backend/src/scripts/setupDefaultTemplate.ts +++ b/backend/src/scripts/setupDefaultTemplate.ts @@ -1,6 +1,7 @@ // backend/src/scripts/setupDefaultTemplate.ts import { v4 as uuidv4 } from 'uuid'; import { db } from '../services/databaseService.js'; +import { DEFAULT_TIME_SLOTS } from '../models/ShiftTemplate.js'; interface AdminUser { id: string; @@ -34,10 +35,14 @@ export async function setupDefaultTemplate(): Promise { } const templateId = uuidv4(); + console.log('🔄 Erstelle Standard-Vorlage mit ID:', templateId); // Transaktion starten await db.run('BEGIN TRANSACTION'); + const timeSlots = DEFAULT_TIME_SLOTS; + + try { // Standard-Vorlage erstellen await db.run( @@ -54,36 +59,51 @@ export async function setupDefaultTemplate(): Promise { console.log('Standard-Vorlage erstellt:', templateId); - // Vormittagsschicht Mo-Do - for (let day = 1; day <= 5; day++) { + for (const slot of timeSlots) { await db.run( - `INSERT INTO template_shifts (id, template_id, day_of_week, name, start_time, end_time, required_employees) - VALUES (?, ?, ?, ?, ?, ?, ?)`, - [uuidv4(), templateId, day, 'Vormittagsschicht', '08:00', '12:00', 1] + `INSERT INTO template_time_slots (id, template_id, name, start_time, end_time) + VALUES (?, ?, ?, ?, ?)`, + [slot.id, templateId, slot.name, slot.startTime, slot.endTime] ); } - console.log('Vormittagsschichten Mo-Fr erstellt'); + console.log('✅ Zeit-Slots erstellt'); - // Nachmittagsschicht Mo-Do + // Schichten für Mo-Do for (let day = 1; day <= 4; day++) { + // Vormittagsschicht await db.run( - `INSERT INTO template_shifts (id, template_id, day_of_week, name, start_time, end_time, required_employees) - VALUES (?, ?, ?, ?, ?, ?, ?)`, - [uuidv4(), templateId, day, 'Nachmittagsschicht', '11:30', '15:30', 1] + `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) + VALUES (?, ?, ?, ?, ?, ?)`, + [uuidv4(), templateId, day, timeSlots[0].id, 1, '#3498db'] + ); + + // Nachmittagsschicht + await db.run( + `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) + VALUES (?, ?, ?, ?, ?, ?)`, + [uuidv4(), templateId, day, timeSlots[1].id, 1, '#e74c3c'] ); } - console.log('Nachmittagsschichten Mo-Do erstellt'); + // Freitag nur Vormittagsschicht + await db.run( + `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) + VALUES (?, ?, ?, ?, ?, ?)`, + [uuidv4(), templateId, 5, timeSlots[0].id, 1, '#3498db'] + ); + + console.log('✅ Schichten erstellt'); await db.run('COMMIT'); - console.log('Standard-Vorlage erfolgreich initialisiert'); + console.log('🎉 Standard-Vorlage erfolgreich initialisiert'); + } catch (error) { await db.run('ROLLBACK'); + console.error('❌ Fehler beim Erstellen der Vorlage:', error); throw error; } } catch (error) { - console.error('Fehler beim Erstellen der Standard-Vorlage:', error); - throw error; + console.error('❌ Fehler in setupDefaultTemplate:', error); } } \ No newline at end of file