fixed settings

This commit is contained in:
2025-10-20 02:30:40 +02:00
parent e80bb81b5d
commit ec28c061a0
11 changed files with 280 additions and 102 deletions

View File

@@ -14,39 +14,39 @@ export const EMPLOYEE_DEFAULTS = {
export const MANAGER_DEFAULTS = {
role: 'admin' as const,
employeeType: 'manager' as const,
contractType: 'large' as const, // Not really used but required by DB
contractType: 'large' as const,
canWorkAlone: true,
isActive: true
};
export const EMPLOYEE_TYPE_CONFIG = [
{
export const EMPLOYEE_TYPE_CONFIG = {
manager: {
value: 'manager' as const,
label: 'Chef/Administrator',
color: '#e74c3c',
independent: true,
description: 'Vollzugriff auf alle Funktionen und Mitarbeiterverwaltung'
},
{
experienced: {
value: 'experienced' as const,
label: 'Erfahren',
color: '#3498db',
independent: true,
description: 'Langjährige Erfahrung, kann komplexe Aufgaben übernehmen'
},
{
trainee: {
value: 'trainee' as const,
label: 'Neuling',
color: '#27ae60',
independent: false,
description: 'Benötigt Einarbeitung und Unterstützung'
}
] as const;
} as const;
export const ROLE_CONFIG = [
{ value: 'user', label: 'Mitarbeiter', description: 'Kann eigene Schichten einsehen', color: '#27ae60' },
{ value: 'maintenance', label: 'Instandhalter', description: 'Kann Schichtpläne erstellen und Mitarbeiter verwalten', color: '#3498db' },
{ value: 'admin', label: 'Administrator', description: 'Voller Zugriff auf alle Funktionen', color: '#e74c3c' }
{ value: 'user' as const, label: 'Mitarbeiter', description: 'Kann eigene Schichten einsehen', color: '#27ae60' },
{ value: 'maintenance' as const, label: 'Instandhalter', description: 'Kann Schichtpläne erstellen und Mitarbeiter verwalten', color: '#3498db' },
{ value: 'admin' as const, label: 'Administrator', description: 'Voller Zugriff auf alle Funktionen', color: '#e74c3c' }
] as const;
// Contract type descriptions
@@ -64,26 +64,25 @@ export const AVAILABILITY_PREFERENCES = {
} as const;
// Default availability for new employees (all shifts unavailable as level 3)
export function createDefaultAvailabilities(employeeId: string, planId: string, timeSlotIds: string[]): Omit<EmployeeAvailability, 'id'>[] {
// UPDATED: Now uses shiftId instead of timeSlotId + dayOfWeek
export function createDefaultAvailabilities(employeeId: string, planId: string, shiftIds: string[]): Omit<EmployeeAvailability, 'id'>[] {
const availabilities: Omit<EmployeeAvailability, 'id'>[] = [];
// Monday to Friday (1-5)
for (let day = 1; day <= 5; day++) {
for (const timeSlotId of timeSlotIds) {
availabilities.push({
employeeId,
planId,
dayOfWeek: day,
timeSlotId,
preferenceLevel: 3 // Default to "unavailable" - employees must explicitly set availability
});
}
// Create one availability entry per shift
for (const shiftId of shiftIds) {
availabilities.push({
employeeId,
planId,
shiftId,
preferenceLevel: 3 // Default to "unavailable" - employees must explicitly set availability
});
}
return availabilities;
}
// Create complete manager availability for all days (default: only Mon-Tue available)
// NOTE: This function might need revision based on new schema requirements
export function createManagerDefaultSchedule(managerId: string, planId: string, timeSlotIds: string[]): Omit<ManagerAvailability, 'id'>[] {
const assignments: Omit<ManagerAvailability, 'id'>[] = [];

View File

@@ -1,25 +1,51 @@
// backend/src/models/helpers/employeeHelpers.ts
import { Employee, CreateEmployeeRequest, EmployeeAvailability } from '../Employee.js';
// Simplified validation - use schema validation instead
// Email generation function (same as in controllers)
function generateEmail(firstname: string, lastname: string): string {
// Convert German umlauts to their expanded forms
const convertUmlauts = (str: string): string => {
return str
.toLowerCase()
.replace(/ü/g, 'ue')
.replace(/ö/g, 'oe')
.replace(/ä/g, 'ae')
.replace(/ß/g, 'ss');
};
// Remove any remaining special characters and convert to lowercase
const cleanFirstname = convertUmlauts(firstname).replace(/[^a-z0-9]/g, '');
const cleanLastname = convertUmlauts(lastname).replace(/[^a-z0-9]/g, '');
return `${cleanFirstname}.${cleanLastname}@sp.de`;
}
// UPDATED: Validation for new employee model
export function validateEmployeeData(employee: CreateEmployeeRequest): string[] {
const errors: string[] = [];
if (!employee.email?.includes('@')) {
errors.push('Valid email is required');
}
// Email is now auto-generated, so no email validation needed
if (employee.password?.length < 6) {
errors.push('Password must be at least 6 characters long');
}
if (!employee.name?.trim() || employee.name.trim().length < 2) {
errors.push('Name is required and must be at least 2 characters long');
if (!employee.firstname?.trim() || employee.firstname.trim().length < 2) {
errors.push('First name is required and must be at least 2 characters long');
}
if (!employee.lastname?.trim() || employee.lastname.trim().length < 2) {
errors.push('Last name is required and must be at least 2 characters long');
}
return errors;
}
// Generate email for employee (new helper function)
export function generateEmployeeEmail(firstname: string, lastname: string): string {
return generateEmail(firstname, lastname);
}
// Simplified business logic helpers
export const isManager = (employee: Employee): boolean =>
employee.employeeType === 'manager';
@@ -38,3 +64,26 @@ export const canEmployeeWorkAlone = (employee: Employee): boolean =>
export const getEmployeeWorkHours = (employee: Employee): number =>
isManager(employee) ? 999 : (employee.contractType === 'small' ? 1 : 2);
// New helper for full name display
export const getFullName = (employee: { firstname: string; lastname: string }): string =>
`${employee.firstname} ${employee.lastname}`;
// Helper for availability validation
export function validateAvailabilityData(availability: Omit<EmployeeAvailability, 'id' | 'employeeId'>): string[] {
const errors: string[] = [];
if (!availability.planId) {
errors.push('Plan ID is required');
}
if (!availability.shiftId) {
errors.push('Shift ID is required');
}
if (![1, 2, 3].includes(availability.preferenceLevel)) {
errors.push('Preference level must be 1, 2, or 3');
}
return errors;
}

View File

@@ -1,5 +1,4 @@
// backend/src/models/helpers/shiftPlanHelpers.ts
import { shiftAssignmentService } from '../../services/shiftAssignmentService.js';
import { ShiftPlan, Shift, ScheduledShift, TimeSlot } from '../ShiftPlan.js';
// Validation helpers
@@ -79,16 +78,16 @@ export function calculateTotalRequiredEmployees(plan: ShiftPlan): number {
return plan.shifts.reduce((total, shift) => total + shift.requiredEmployees, 0);
}
/*export async function getScheduledShiftByDateAndTime(
// UPDATED: Get scheduled shift by date and time slot
export function getScheduledShiftByDateAndTime(
plan: ShiftPlan,
date: string,
timeSlotId: string
): Promise<ScheduledShift | undefined> {
const scheduledShifts = await shiftAssignmentService.getScheduledShiftsForPlan(plan.id);
return scheduledShifts.find(
shift => shift.date === date && shift.timeSlotId === timeSlotId
): ScheduledShift | undefined {
return plan.scheduledShifts?.find(shift =>
shift.date === date && shift.timeSlotId === timeSlotId
);
}*/
}
export function canPublishPlan(plan: ShiftPlan): { canPublish: boolean; errors: string[] } {
const errors: string[] = [];
@@ -117,4 +116,14 @@ export function canPublishPlan(plan: ShiftPlan): { canPublish: boolean; errors:
canPublish: errors.length === 0,
errors
};
}
// NEW: Helper for shift generation
export function generateShiftId(): string {
return `shift_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
// NEW: Helper for time slot generation
export function generateTimeSlotId(): string {
return `timeslot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}