moved range to slot for shift planing

This commit is contained in:
2025-10-11 00:52:10 +02:00
parent ebce18e880
commit 4875f13321
4 changed files with 69 additions and 39 deletions

View File

@@ -10,6 +10,8 @@ import { AuthRequest } from '../middleware/auth.js';
export const getTemplates = async (req: Request, res: Response): Promise<void> => { export const getTemplates = async (req: Request, res: Response): Promise<void> => {
try { try {
console.log('🔍 Lade Vorlagen...');
const templates = await db.all<any>(` const templates = await db.all<any>(`
SELECT st.*, u.name as created_by_name SELECT st.*, u.name as created_by_name
FROM shift_templates st FROM shift_templates st
@@ -17,12 +19,14 @@ export const getTemplates = async (req: Request, res: Response): Promise<void> =
ORDER BY st.created_at DESC 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 // Für jede Vorlage die Schichten und Zeit-Slots laden
const templatesWithShifts = await Promise.all( const templatesWithShifts = await Promise.all(
templates.map(async (template) => { templates.map(async (template) => {
// Lade Schicht-Slots // Lade Schicht-Slots
const shiftSlots = await db.all<any>(` const shiftSlots = await db.all<any>(`
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 FROM template_shifts ts
LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id
WHERE ts.template_id = ? WHERE ts.template_id = ?
@@ -41,11 +45,11 @@ export const getTemplates = async (req: Request, res: Response): Promise<void> =
shifts: shiftSlots.map(slot => ({ shifts: shiftSlots.map(slot => ({
id: slot.id, id: slot.id,
dayOfWeek: slot.day_of_week, dayOfWeek: slot.day_of_week,
timeRange: { timeSlot: {
id: slot.time_slot_id, id: slot.time_slot_id,
name: slot.time_range_name, name: slot.time_slot_name,
startTime: slot.time_range_start, startTime: slot.time_slot_start,
endTime: slot.time_range_end endTime: slot.time_slot_end
}, },
requiredEmployees: slot.required_employees, requiredEmployees: slot.required_employees,
color: slot.color color: slot.color
@@ -86,7 +90,7 @@ export const getTemplate = async (req: Request, res: Response): Promise<void> =>
// Lade Schicht-Slots // Lade Schicht-Slots
const shiftSlots = await db.all<any>(` const shiftSlots = await db.all<any>(`
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 FROM template_shifts ts
LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id
WHERE ts.template_id = ? WHERE ts.template_id = ?
@@ -105,11 +109,11 @@ export const getTemplate = async (req: Request, res: Response): Promise<void> =>
shifts: shiftSlots.map(slot => ({ shifts: shiftSlots.map(slot => ({
id: slot.id, id: slot.id,
dayOfWeek: slot.day_of_week, dayOfWeek: slot.day_of_week,
timeRange: { timeSlot: {
id: slot.time_slot_id, id: slot.time_slot_id,
name: slot.time_range_name, name: slot.time_slot_name,
startTime: slot.time_range_start, startTime: slot.time_slot_start,
endTime: slot.time_range_end endTime: slot.time_slot_end
}, },
requiredEmployees: slot.required_employees, requiredEmployees: slot.required_employees,
color: slot.color color: slot.color
@@ -240,7 +244,7 @@ export const createTemplate = async (req: Request, res: Response): Promise<void>
await db.run( await db.run(
`INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color)
VALUES (?, ?, ?, ?, ?, ?)`, 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<void>
await db.run( await db.run(
`INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color) `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color)
VALUES (?, ?, ?, ?, ?, ?)`, 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<any> {
// Lade Schicht-Slots // Lade Schicht-Slots
const shiftSlots = await db.all<any>(` const shiftSlots = await db.all<any>(`
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 FROM template_shifts ts
LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id LEFT JOIN template_time_slots tts ON ts.time_slot_id = tts.id
WHERE ts.template_id = ? WHERE ts.template_id = ?
@@ -414,11 +418,11 @@ async function getTemplateById(templateId: string): Promise<any> {
shifts: shiftSlots.map(slot => ({ shifts: shiftSlots.map(slot => ({
id: slot.id, id: slot.id,
dayOfWeek: slot.day_of_week, dayOfWeek: slot.day_of_week,
timeRange: { timeSlot: {
id: slot.time_slot_id, id: slot.time_slot_id,
name: slot.time_range_name, name: slot.time_slot_name,
startTime: slot.time_range_start, startTime: slot.time_slot_start,
endTime: slot.time_range_end endTime: slot.time_slot_end
}, },
requiredEmployees: slot.required_employees, requiredEmployees: slot.required_employees,
color: slot.color color: slot.color

View File

@@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS users (
is_sufficiently_independent BOOLEAN DEFAULT FALSE, is_sufficiently_independent BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE, is_active BOOLEAN DEFAULT TRUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
last_login TEXT || NULL last_login TEXT DEFAULT NULL
); );
-- Tabelle für Schichtvorlagen -- Tabelle für Schichtvorlagen
@@ -27,12 +27,12 @@ CREATE TABLE IF NOT EXISTS shift_templates (
CREATE TABLE IF NOT EXISTS template_shifts ( CREATE TABLE IF NOT EXISTS template_shifts (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
template_id TEXT NOT NULL, 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), day_of_week INTEGER NOT NULL CHECK (day_of_week >= 1 AND day_of_week <= 7),
required_employees INTEGER DEFAULT 1, required_employees INTEGER DEFAULT 1,
color TEXT DEFAULT '#3498db', color TEXT DEFAULT '#3498db',
FOREIGN KEY (template_id) REFERENCES shift_templates(id) ON DELETE CASCADE, 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 -- Tabelle für Zeitbereiche in den Vorlagen

View File

@@ -13,24 +13,30 @@ export interface TemplateShiftSlot {
id: string; id: string;
templateId: string; templateId: string;
dayOfWeek: number; dayOfWeek: number;
timeRange: TemplateShiftTimeRange; timeSlot: TemplateShiftTimeSlot;
requiredEmployees: number; requiredEmployees: number;
color?: string; color?: string;
} }
export interface TemplateShiftTimeRange { export interface TemplateShiftTimeSlot {
id: string; id: string;
name: string; // e.g., "Frühschicht", "Spätschicht" name: string; // e.g., "Frühschicht", "Spätschicht"
startTime: string; startTime: string;
endTime: 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 { export interface CreateShiftTemplateRequest {
name: string; name: string;
description?: string; description?: string;
isDefault: boolean; isDefault: boolean;
shifts: Omit<TemplateShiftSlot, 'id' | 'templateId'>[]; shifts: Omit<TemplateShiftSlot, 'id' | 'templateId'>[];
timeSlots: TemplateShiftTimeRange[]; timeSlots: TemplateShiftTimeSlot[];
} }
export interface UpdateShiftTemplateRequest { export interface UpdateShiftTemplateRequest {
@@ -38,5 +44,5 @@ export interface UpdateShiftTemplateRequest {
description?: string; description?: string;
isDefault?: boolean; isDefault?: boolean;
shifts?: Omit<TemplateShiftSlot, 'id' | 'templateId'>[]; shifts?: Omit<TemplateShiftSlot, 'id' | 'templateId'>[];
timeSlots?: TemplateShiftTimeRange[]; timeSlots?: TemplateShiftTimeSlot[];
} }

View File

@@ -1,6 +1,7 @@
// backend/src/scripts/setupDefaultTemplate.ts // backend/src/scripts/setupDefaultTemplate.ts
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { db } from '../services/databaseService.js'; import { db } from '../services/databaseService.js';
import { DEFAULT_TIME_SLOTS } from '../models/ShiftTemplate.js';
interface AdminUser { interface AdminUser {
id: string; id: string;
@@ -34,10 +35,14 @@ export async function setupDefaultTemplate(): Promise<void> {
} }
const templateId = uuidv4(); const templateId = uuidv4();
console.log('🔄 Erstelle Standard-Vorlage mit ID:', templateId);
// Transaktion starten // Transaktion starten
await db.run('BEGIN TRANSACTION'); await db.run('BEGIN TRANSACTION');
const timeSlots = DEFAULT_TIME_SLOTS;
try { try {
// Standard-Vorlage erstellen // Standard-Vorlage erstellen
await db.run( await db.run(
@@ -54,36 +59,51 @@ export async function setupDefaultTemplate(): Promise<void> {
console.log('Standard-Vorlage erstellt:', templateId); console.log('Standard-Vorlage erstellt:', templateId);
// Vormittagsschicht Mo-Do for (const slot of timeSlots) {
for (let day = 1; day <= 5; day++) {
await db.run( await db.run(
`INSERT INTO template_shifts (id, template_id, day_of_week, name, start_time, end_time, required_employees) `INSERT INTO template_time_slots (id, template_id, name, start_time, end_time)
VALUES (?, ?, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?)`,
[uuidv4(), templateId, day, 'Vormittagsschicht', '08:00', '12:00', 1] [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++) { for (let day = 1; day <= 4; day++) {
// Vormittagsschicht
await db.run( await db.run(
`INSERT INTO template_shifts (id, template_id, day_of_week, name, start_time, end_time, required_employees) `INSERT INTO template_shifts (id, template_id, day_of_week, time_slot_id, required_employees, color)
VALUES (?, ?, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?, ?)`,
[uuidv4(), templateId, day, 'Nachmittagsschicht', '11:30', '15:30', 1] [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'); await db.run('COMMIT');
console.log('Standard-Vorlage erfolgreich initialisiert'); console.log('🎉 Standard-Vorlage erfolgreich initialisiert');
} catch (error) { } catch (error) {
await db.run('ROLLBACK'); await db.run('ROLLBACK');
console.error('❌ Fehler beim Erstellen der Vorlage:', error);
throw error; throw error;
} }
} catch (error) { } catch (error) {
console.error('Fehler beim Erstellen der Standard-Vorlage:', error); console.error('Fehler in setupDefaultTemplate:', error);
throw error;
} }
} }