mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-12-01 06:55:45 +01:00
moved range to slot for shift planing
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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[];
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user