shift assignment works

This commit is contained in:
2025-10-14 17:45:53 +02:00
parent 9885d962f1
commit f45d0391c1
3 changed files with 380 additions and 123 deletions

View File

@@ -148,6 +148,56 @@ const ShiftPlanView: React.FC = () => {
return date.getDay() === 0 ? 7 : date.getDay(); return date.getDay() === 0 ? 7 : date.getDay();
}; };
const debugManagerAvailability = () => {
if (!shiftPlan || !employees.length || !availabilities.length) return;
const manager = employees.find(emp => emp.role === 'admin');
if (!manager) {
console.log('❌ Kein Manager (admin) gefunden');
return;
}
console.log('🔍 Manager-Analyse:', {
manager: manager.name,
managerId: manager.id,
totalAvailabilities: availabilities.length,
managerAvailabilities: availabilities.filter(a => a.employeeId === manager.id).length
});
// Prüfe speziell die leeren Manager-Schichten
const emptyManagerShifts = [
'a8ef4ce0-adfd-4ec3-8c58-efa0f7347f9f',
'a496a8d6-f7a0-4d77-96de-c165379378c4',
'ea2d73d1-8354-4833-8c87-40f318ce8be0',
'90eb5454-2ae2-4445-86b7-a6e0e2cf0b22'
];
emptyManagerShifts.forEach(shiftId => {
const scheduledShift = shiftPlan.scheduledShifts?.find(s => s.id === shiftId);
if (scheduledShift) {
const dayOfWeek = getDayOfWeek(scheduledShift.date);
const shiftKey = `${dayOfWeek}-${scheduledShift.timeSlotId}`;
const managerAvailability = availabilities.find(a =>
a.employeeId === manager.id &&
a.dayOfWeek === dayOfWeek &&
a.timeSlotId === scheduledShift.timeSlotId
);
console.log(`📊 Schicht ${shiftId}:`, {
date: scheduledShift.date,
dayOfWeek,
timeSlotId: scheduledShift.timeSlotId,
shiftKey,
managerAvailability: managerAvailability ? managerAvailability.preferenceLevel : 'NICHT GEFUNDEN',
status: managerAvailability ?
(managerAvailability.preferenceLevel === 3 ? '❌ NICHT VERFÜGBAR' : '✅ VERFÜGBAR') :
'❌ KEINE VERFÜGBARKEITSDATEN'
});
}
});
};
const handlePreviewAssignment = async () => { const handlePreviewAssignment = async () => {
if (!shiftPlan) return; if (!shiftPlan) return;
@@ -164,6 +214,26 @@ const ShiftPlanView: React.FC = () => {
} }
); );
// DEBUG: Überprüfe die tatsächlichen Violations
console.log('🔍 VIOLATIONS ANALYSIS:', {
allViolations: result.violations,
criticalViolations: result.violations.filter(v =>
v.includes('ERROR:') || v.includes('❌ KRITISCH:')
),
warningViolations: result.violations.filter(v =>
v.includes('WARNING:') || v.includes('⚠️')
),
infoViolations: result.violations.filter(v =>
v.includes('INFO:')
),
criticalCount: result.violations.filter(v =>
v.includes('ERROR:') || v.includes('❌ KRITISCH:')
).length,
canPublish: result.violations.filter(v =>
v.includes('ERROR:') || v.includes('❌ KRITISCH:')
).length === 0
});
setAssignmentResult(result); setAssignmentResult(result);
setShowAssignmentPreview(true); setShowAssignmentPreview(true);
@@ -173,48 +243,23 @@ const ShiftPlanView: React.FC = () => {
result.resolutionReport.forEach(line => console.log(line)); result.resolutionReport.forEach(line => console.log(line));
} }
// KORRIGIERT: Entscheidung basierend auf Reparatur-Bericht statt allProblemsResolved // Entscheidung basierend auf tatsächlichen kritischen Violations
const allCriticalResolved = result.resolutionReport && const criticalCount = result.violations.filter(v =>
result.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length;
);
if (allCriticalResolved) { if (criticalCount === 0) {
showNotification({ showNotification({
type: 'success', type: 'success',
title: 'Erfolg', title: 'Erfolg',
message: 'Alle kritischen Probleme wurden behoben! Der Schichtplan kann veröffentlicht werden.' message: 'Alle kritischen Probleme wurden behoben! Der Schichtplan kann veröffentlicht werden.'
}); });
} else { } else {
// Zähle nur kritische Probleme (ERROR oder ❌ KRITISCH) showNotification({
const criticalProblems = result.violations.filter(v => type: 'error',
v.includes('ERROR:') || v.includes('❌ KRITISCH:') title: 'Kritische Probleme',
); message: `${criticalCount} kritische Probleme müssen behoben werden`
});
// Zähle Warnungen separat
const warnings = result.violations.filter(v =>
v.includes('WARNING:') || v.includes('⚠️')
);
if (criticalProblems.length > 0) {
showNotification({
type: 'error',
title: 'Kritische Probleme',
message: `${criticalProblems.length} kritische Probleme müssen behoben werden`
});
} else if (warnings.length > 0) {
showNotification({
type: 'warning',
title: 'Warnungen',
message: `${warnings.length} Warnungen - Plan kann trotzdem veröffentlicht werden`
});
} else {
showNotification({
type: 'success',
title: 'Erfolg',
message: 'Keine Probleme gefunden! Der Schichtplan kann veröffentlicht werden.'
});
}
} }
} catch (error) { } catch (error) {
@@ -312,14 +357,28 @@ const ShiftPlanView: React.FC = () => {
try { try {
setReverting(true); setReverting(true);
// 1. Zuerst zurücksetzen
const updatedPlan = await shiftPlanService.revertToDraft(id); const updatedPlan = await shiftPlanService.revertToDraft(id);
setShiftPlan(updatedPlan);
// 2. Dann ALLE Daten neu laden
await loadShiftPlanData();
// 3. Assignment-Result zurücksetzen
setAssignmentResult(null); setAssignmentResult(null);
// 4. Preview schließen falls geöffnet
setShowAssignmentPreview(false);
showNotification({ showNotification({
type: 'success', type: 'success',
title: 'Erfolg', title: 'Erfolg',
message: 'Schichtplan wurde erfolgreich zurück in den Entwurfsstatus gesetzt.' message: 'Schichtplan wurde erfolgreich zurück in den Entwurfsstatus gesetzt. Alle Daten wurden neu geladen.'
});
console.log('Scheduled shifts after revert:', {
hasScheduledShifts: !!shiftPlan.scheduledShifts,
count: shiftPlan.scheduledShifts?.length || 0,
firstFew: shiftPlan.scheduledShifts?.slice(0, 3)
}); });
} catch (error) { } catch (error) {
@@ -705,28 +764,56 @@ const ShiftPlanView: React.FC = () => {
}}> }}>
<h2>Wochenmuster-Zuordnung</h2> <h2>Wochenmuster-Zuordnung</h2>
{/* Reparatur-Bericht anzeigen */} {/* Detaillierter Reparatur-Bericht anzeigen */}
{assignmentResult.resolutionReport && ( {assignmentResult.resolutionReport && (
<div style={{ <div style={{
backgroundColor: '#e8f4fd', backgroundColor: '#f8f9fa',
border: '1px solid #b8d4f0', border: '1px solid #e9ecef',
borderRadius: '4px', borderRadius: '4px',
padding: '15px', padding: '15px',
marginBottom: '20px', marginBottom: '20px',
fontSize: '14px' fontSize: '14px',
maxHeight: '400px',
overflow: 'auto'
}}> }}>
<h4 style={{ color: '#2c3e50', marginTop: 0 }}>Reparatur-Bericht</h4> <h4 style={{ color: '#2c3e50', marginTop: 0, display: 'flex', alignItems: 'center', gap: '10px' }}>
<div style={{ maxHeight: '200px', overflow: 'auto' }}> <span>📋</span> Detaillierter Reparatur-Bericht
{assignmentResult.resolutionReport.map((line, index) => ( </h4>
<div key={index} style={{ <div style={{
color: line.includes('✅') ? '#2ecc71' : line.includes('❌') ? '#e74c3c' : '#2c3e50', fontFamily: 'monospace',
fontFamily: 'monospace', fontSize: '12px',
fontSize: '12px', lineHeight: '1.4'
marginBottom: '2px' }}>
}}> {assignmentResult.resolutionReport.map((line, index) => {
{line} let color = '#2c3e50';
</div> let fontWeight = 'normal';
))}
if (line.includes('✅') || line.includes('ALLES KRITISCHEN PROBLEME BEHOBEN')) {
color = '#2ecc71';
fontWeight = 'bold';
} else if (line.includes('❌') || line.includes('KRITISCHEN PROBLEME')) {
color = '#e74c3c';
fontWeight = 'bold';
} else if (line.includes('⚠️')) {
color = '#f39c12';
} else if (line.includes('📊') || line.includes('🔧') || line.includes('📅') || line.includes('🚨') || line.includes('🛠️') || line.includes('💡') || line.includes('🎯')) {
color = '#3498db';
fontWeight = 'bold';
} else if (line.startsWith(' •') || line.startsWith(' -')) {
color = '#7f8c8d';
}
return (
<div key={index} style={{
color,
fontWeight,
marginBottom: line === '' ? '5px' : '2px',
paddingLeft: line.startsWith(' ') ? '20px' : '0px'
}}>
{line}
</div>
);
})}
</div> </div>
</div> </div>
)} )}
@@ -736,11 +823,10 @@ const ShiftPlanView: React.FC = () => {
<div style={{ marginBottom: '20px' }}> <div style={{ marginBottom: '20px' }}>
<h4>Zusammenfassung:</h4> <h4>Zusammenfassung:</h4>
{/* Entscheidung basierend auf Reparatur-Bericht */} {/* Entscheidung basierend auf tatsächlichen kritischen Problemen */}
{assignmentResult.resolutionReport && {assignmentResult.violations.filter(v =>
assignmentResult.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length === 0 ? (
) ? (
<div style={{ <div style={{
padding: '15px', padding: '15px',
backgroundColor: '#d4edda', backgroundColor: '#d4edda',
@@ -822,33 +908,28 @@ const ShiftPlanView: React.FC = () => {
<button <button
onClick={handlePublish} onClick={handlePublish}
disabled={publishing || !(assignmentResult.resolutionReport && disabled={publishing || assignmentResult.violations.filter(v =>
assignmentResult.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length > 0}
))
}
style={{ style={{
padding: '10px 20px', padding: '10px 20px',
backgroundColor: (assignmentResult.resolutionReport && backgroundColor: assignmentResult.violations.filter(v =>
assignmentResult.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length === 0 ? '#2ecc71' : '#95a5a6',
)) ? '#2ecc71' : '#95a5a6',
color: 'white', color: 'white',
border: 'none', border: 'none',
borderRadius: '4px', borderRadius: '4px',
cursor: (assignmentResult.resolutionReport && cursor: assignmentResult.violations.filter(v =>
assignmentResult.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length === 0 ? 'pointer' : 'not-allowed',
)) ? 'pointer' : 'not-allowed',
fontWeight: 'bold', fontWeight: 'bold',
fontSize: '16px' fontSize: '16px'
}} }}
> >
{publishing ? 'Veröffentliche...' : ( {publishing ? 'Veröffentliche...' : (
(assignmentResult.resolutionReport && assignmentResult.violations.filter(v =>
assignmentResult.resolutionReport.some(line => v.includes('ERROR:') || v.includes('❌ KRITISCH:')
line.includes('Alle kritischen Probleme behoben: ✅ JA') ).length === 0
))
? 'Schichtplan veröffentlichen' ? 'Schichtplan veröffentlichen'
: 'Kritische Probleme müssen behoben werden' : 'Kritische Probleme müssen behoben werden'
)} )}

View File

@@ -864,3 +864,192 @@ export function checkAllProblemsResolved(
return { resolved, remaining, allResolved }; return { resolved, remaining, allResolved };
} }
export function createDetailedResolutionReport(
assignments: Assignment,
employees: Map<string, SchedulingEmployee>,
shifts: SchedulingShift[],
managerShifts: string[],
repairContext: RepairContext
): string[] {
const report: string[] = [];
report.push('=== DETAILIERTER REPARATUR-BERICHT ===');
report.push('');
// 1. ZUSAMMENFASSUNG
report.push('📊 ZUSAMMENFASSUNG');
const totalShifts = shifts.length;
const assignedShifts = Object.values(assignments).filter(a => a.length > 0).length;
const emptyShifts = totalShifts - assignedShifts;
report.push(` • Gesamtschichten: ${totalShifts}`);
report.push(` • Zugewiesene Schichten: ${assignedShifts}`);
report.push(` • Leere Schichten: ${emptyShifts}`);
report.push(` • Pool-Mitarbeiter: ${repairContext.unassignedPool.length}`);
report.push(` • Gesperrte Schichten: ${repairContext.lockedShifts.size}`);
report.push('');
// 2. DURCHGEFÜHRTE AKTIONEN
if (repairContext.warnings.length > 0) {
report.push('🔧 DURCHGEFÜHRTE REPARATURAKTIONEN');
repairContext.warnings.forEach((action, index) => {
if (action.includes('zugewiesen') || action.includes('entfernt') || action.includes('getauscht') || action.includes('bewegt')) {
report.push(`${action}`);
}
});
report.push('');
}
// 3. DETAILLIERTE SCHICHTANALYSE
report.push('📅 DETAILLIERTE SCHICHTANALYSE');
shifts.forEach(shift => {
const assignment = assignments[shift.id] || [];
const assignedEmployees = assignment.map(empId => {
const emp = employees.get(empId);
return emp ? `${emp.name} (${emp.role})` : 'Unbekannt';
}).join(', ');
const isManagerShift = managerShifts.includes(shift.id);
const isEmpty = assignment.length === 0;
const hasOnlyNew = onlyNeuAssigned(assignment, employees);
const experiencedAloneCheck = hasExperiencedAloneNotAllowed(assignment, employees);
let status = '✅ OK';
if (isEmpty) status = '❌ LEER';
else if (isManagerShift && hasOnlyNew) status = '⚠️ MANAGER + NUR NEUE';
else if (experiencedAloneCheck.hasViolation) status = '❌ ERFAHRENER ALLEIN';
else if (hasOnlyNew) status = '⚠️ NUR NEUE';
report.push(` • Schicht ${shift.id}:`);
report.push(` - Status: ${status}`);
report.push(` - Zugewiesene: ${assignedEmployees || 'Keine'}`);
report.push(` - Benötigt: ${shift.requiredEmployees} Mitarbeiter`);
report.push(` - Aktuell: ${assignment.length} Mitarbeiter`);
if (isManagerShift) report.push(` - 💼 MANAGER-SCHICHT`);
report.push('');
});
// 4. PROBLEMANALYSE NACH TYP
report.push('🚨 PROBLEMANALYSE NACH TYP');
const emptyShiftsList = shifts.filter(shift =>
(assignments[shift.id] || []).length === 0
);
const managerWithOnlyNewList = shifts.filter(shift =>
managerShifts.includes(shift.id) &&
isManagerShiftWithOnlyNew(assignments[shift.id] || [], employees, Array.from(employees.values()).find(e => e.role === 'manager')?.id)
);
const experiencedAloneList = shifts.filter(shift => {
const check = hasExperiencedAloneNotAllowed(assignments[shift.id] || [], employees);
return check.hasViolation;
});
const onlyNewList = shifts.filter(shift =>
!managerShifts.includes(shift.id) &&
onlyNeuAssigned(assignments[shift.id] || [], employees)
);
if (emptyShiftsList.length > 0) {
report.push(` ❌ LEERE SCHICHTEN (${emptyShiftsList.length}):`);
emptyShiftsList.forEach(shift => {
report.push(` - ${shift.id}`);
});
report.push('');
}
if (managerWithOnlyNewList.length > 0) {
report.push(` ⚠️ MANAGER + NUR NEUE (${managerWithOnlyNewList.length}):`);
managerWithOnlyNewList.forEach(shift => {
const assignment = assignments[shift.id] || [];
const employeesList = assignment.map(empId => {
const emp = employees.get(empId);
return emp ? emp.name : 'Unbekannt';
}).join(', ');
report.push(` - ${shift.id}: ${employeesList}`);
});
report.push('');
}
if (experiencedAloneList.length > 0) {
report.push(` ❌ ERFAHRENER ALLEIN (${experiencedAloneList.length}):`);
experiencedAloneList.forEach(shift => {
const check = hasExperiencedAloneNotAllowed(assignments[shift.id] || [], employees);
const emp = employees.get(check.employeeId!);
report.push(` - ${shift.id}: ${emp?.name || check.employeeId}`);
});
report.push('');
}
if (onlyNewList.length > 0) {
report.push(` ⚠️ NUR NEUE IN SCHICHT (${onlyNewList.length}):`);
onlyNewList.forEach(shift => {
report.push(` - ${shift.id}`);
});
report.push('');
}
// 5. REPARATURVERSUCHE
report.push('🛠️ REPARATURVERSUCHE UND -ERGEBNISSE');
// Zähle die verschiedenen Reparaturtypen
const assignmentActions = repairContext.warnings.filter(w =>
w.includes('zugewiesen')
).length;
const removalActions = repairContext.warnings.filter(w =>
w.includes('entfernt')
).length;
const swapActions = repairContext.warnings.filter(w =>
w.includes('getauscht') || w.includes('bewegt')
).length;
report.push(` • Zuweisungen: ${assignmentActions}`);
report.push(` • Entfernungen: ${removalActions}`);
report.push(` • Tausche/Bewegungen: ${swapActions}`);
report.push(` • Gesamte Aktionen: ${repairContext.warnings.length}`);
report.push('');
// 6. EMPFEHLUNGEN
report.push('💡 EMPFEHLUNGEN ZUR PROBLEMBEHANDLUNG');
if (emptyShiftsList.length > 0) {
report.push(` • Für ${emptyShiftsList.length} leere Schichten:`);
report.push(` - Verfügbare Mitarbeiter prüfen`);
report.push(` - Vertragskapazitäten überprüfen`);
report.push(` - Ggf. Schichtanforderungen reduzieren`);
report.push('');
}
if (managerWithOnlyNewList.length > 0) {
report.push(` • Für ${managerWithOnlyNewList.length} Manager+Neue-Schichten:`);
report.push(` - Erfahrene Mitarbeiter zuweisen`);
report.push(` - Manager-Verfügbarkeit anpassen`);
report.push(` - Teamzusammensetzung optimieren`);
report.push('');
}
// 7. FINALE BEWERTUNG
report.push('🎯 FINALE BEWERTUNG');
const totalProblems = emptyShiftsList.length + experiencedAloneList.length;
const totalWarnings = managerWithOnlyNewList.length + onlyNewList.length;
if (totalProblems === 0) {
report.push(' ✅ ALLE KRITISCHEN PROBLEME BEHOBEN');
report.push(' Der Schichtplan kann veröffentlicht werden.');
} else {
report.push(`${totalProblems} KRITISCHE PROBLEME VERBLEIBEND`);
report.push(` ⚠️ ${totalWarnings} WARNUNGEN`);
report.push(' Der Schichtplan kann nicht veröffentlicht werden.');
}
report.push('');
report.push('=== ENDE DES DETAILIERTEN BERICHTES ===');
return report;
}

View File

@@ -29,7 +29,8 @@ import {
resolveOverstaffedExperienced, resolveOverstaffedExperienced,
prioritizeWarningsWithPool, prioritizeWarningsWithPool,
resolveExperiencedAloneNotAllowed, resolveExperiencedAloneNotAllowed,
checkAllProblemsResolved checkAllProblemsResolved,
createDetailedResolutionReport
} from './repairFunctions'; } from './repairFunctions';
// Phase A: Regular employee scheduling (without manager) // Phase A: Regular employee scheduling (without manager)
@@ -144,7 +145,7 @@ function phaseBInsertManager(
console.log(`🎯 Phase B: Processing ${managerShifts.length} manager shifts`); console.log(`🎯 Phase B: Processing ${managerShifts.length} manager shifts`);
for (const shiftId of managerShifts) { for (const shiftId of managerShifts) {
//const shift = nonManagerShifts.find(s => s.id === shiftId) || { id: shiftId, requiredEmployees: 2 }; let _shift = nonManagerShifts.find(s => s.id === shiftId) || { id: shiftId, requiredEmployees: 2 };
// Assign manager to his chosen shifts // Assign manager to his chosen shifts
if (!assignments[shiftId].includes(manager.id)) { if (!assignments[shiftId].includes(manager.id)) {
@@ -240,11 +241,12 @@ export function enhancedPhaseCRepairValidate(
const employeeMap = new Map(employees.map(emp => [emp.id, emp])); const employeeMap = new Map(employees.map(emp => [emp.id, emp]));
const manager = employees.find(emp => emp.role === 'manager'); const manager = employees.find(emp => emp.role === 'manager');
console.log('🔄 Starting Enhanced Phase C: Smart Repair & Validation'); console.log('🔄 Starting Enhanced Phase C: Detailed Repair & Validation');
// 1. Manager-Schutzregel // 1. Manager-Schutzregel
managerShifts.forEach(shiftId => { managerShifts.forEach(shiftId => {
repairContext.lockedShifts.add(shiftId); repairContext.lockedShifts.add(shiftId);
repairContext.warnings.push(`Schicht ${shiftId} als Manager-Schicht gesperrt`);
}); });
// 2. Überbesetzte erfahrene Mitarbeiter identifizieren und in Pool verschieben // 2. Überbesetzte erfahrene Mitarbeiter identifizieren und in Pool verschieben
@@ -276,6 +278,7 @@ export function enhancedPhaseCRepairValidate(
severity: 'error', severity: 'error',
message: `Leere Schicht: ${shift.id}` message: `Leere Schicht: ${shift.id}`
}); });
repairContext.warnings.push(`Konnte leere Schicht ${shift.id} nicht beheben`);
} }
} }
@@ -302,7 +305,7 @@ export function enhancedPhaseCRepairValidate(
shiftId: shift.id, shiftId: shift.id,
employeeId: experiencedAloneCheck.employeeId, employeeId: experiencedAloneCheck.employeeId,
severity: 'error', severity: 'error',
message: `Erfahrener Mitarbeiter ${emp?.name || experiencedAloneCheck.employeeId} arbeitet allein, darf aber nicht alleine arbeiten` message: `Erfahrener Mitarbeiter ${emp?.name || experiencedAloneCheck.employeeId} arbeitet allein in Schicht ${shift.id}`
}); });
} }
}); });
@@ -325,26 +328,26 @@ export function enhancedPhaseCRepairValidate(
managerShifts.forEach(shiftId => { managerShifts.forEach(shiftId => {
const assignment = assignments[shiftId] || []; const assignment = assignments[shiftId] || [];
// Manager allein -> KRITISCH (error) // Manager allein
if (isManagerAlone(assignment, manager?.id)) { if (isManagerAlone(assignment, manager?.id)) {
repairContext.violations.push({ repairContext.violations.push({
type: 'ManagerAlone', type: 'ManagerAlone',
shiftId: shiftId, shiftId: shiftId,
severity: 'error', // KRITISCH severity: 'error',
message: `Manager allein in Schicht ${shiftId}` message: `Manager allein in Schicht ${shiftId}`
}); });
} }
// Manager + nur Neue -> NUR WARNUNG (warning) // Manager + nur Neue
if (isManagerShiftWithOnlyNew(assignment, employeeMap, manager?.id)) { if (isManagerShiftWithOnlyNew(assignment, employeeMap, manager?.id)) {
repairContext.violations.push({ repairContext.violations.push({
type: 'ManagerWithOnlyNew', type: 'ManagerWithOnlyNew',
shiftId: shiftId, shiftId: shiftId,
severity: 'warning', // NUR WARNUNG severity: 'warning',
message: `Manager mit nur Neuen in Schicht ${shiftId}` message: `Manager mit nur Neuen in Schicht ${shiftId}`
}); });
} }
}); });
// Erstelle finale Violations-Liste // Erstelle finale Violations-Liste
const uniqueViolations = repairContext.violations.filter((v, index, self) => const uniqueViolations = repairContext.violations.filter((v, index, self) =>
@@ -360,56 +363,40 @@ export function enhancedPhaseCRepairValidate(
); );
const finalViolations = [ const finalViolations = [
// Nur ERROR-Violations als ERROR markieren
...uniqueViolations ...uniqueViolations
.filter(v => v.severity === 'error') .filter(v => v.severity === 'error')
.map(v => `ERROR: ${v.message}`), .map(v => `ERROR: ${v.message}`),
// WARNING-Violations als WARNING markieren
...uniqueViolations ...uniqueViolations
.filter(v => v.severity === 'warning') .filter(v => v.severity === 'warning')
.map(v => `WARNING: ${v.message}`), .map(v => `WARNING: ${v.message}`),
// Andere Warnungen als INFO (Aktionen)
...uniqueWarnings.map(w => `INFO: ${w}`) ...uniqueWarnings.map(w => `INFO: ${w}`)
]; ];
// 9. FINALE ÜBERPRÜFUNG: Prüfe ob alle kritischen Probleme gelöst wurden // 9. DETAILLIERTER REPARATUR-BERICHT
const resolutionCheck = checkAllProblemsResolved( const resolutionReport = createDetailedResolutionReport(
assignments, assignments,
employeeMap, employeeMap,
shifts, shifts,
managerShifts, managerShifts,
finalViolations repairContext
); );
const resolutionReport = [ // Bestimme ob alle kritischen Probleme behoben wurden
'=== REPARATUR-BERICHT ===', const criticalProblems = uniqueViolations.filter(v => v.severity === 'error');
`Aufgelöste Probleme: ${resolutionCheck.resolved.length}`, const allProblemsResolved = criticalProblems.length === 0;
`Verbleibende Probleme: ${resolutionCheck.remaining.length}`,
`Alle kritischen Probleme behoben: ${resolutionCheck.allResolved ? '✅ JA' : '❌ NEIN'}`,
'',
'--- AUFGELÖSTE PROBLEME ---',
...(resolutionCheck.resolved.length > 0 ? resolutionCheck.resolved : ['Keine']),
'',
'--- VERBLEIBENDE PROBLEME ---',
...(resolutionCheck.remaining.length > 0 ? resolutionCheck.remaining : ['Keine']),
'',
'=== ENDE BERICHT ==='
];
console.log('📊 Enhanced Phase C completed:', { console.log('📊 Enhanced Phase C completed:', {
poolSize: repairContext.unassignedPool.length, totalActions: uniqueWarnings.length,
violations: uniqueViolations.length, criticalProblems: criticalProblems.length,
warnings: uniqueWarnings.length, warnings: uniqueViolations.filter(v => v.severity === 'warning').length,
allProblemsResolved: resolutionCheck.allResolved allProblemsResolved
}); });
return { return {
assignments, assignments,
violations: finalViolations, violations: finalViolations,
resolutionReport, resolutionReport,
allProblemsResolved: resolutionCheck.allResolved allProblemsResolved
}; };
} }
@@ -421,7 +408,7 @@ export function scheduleWithManager(
): SchedulingResult & { resolutionReport?: string[]; allProblemsResolved?: boolean } { ): SchedulingResult & { resolutionReport?: string[]; allProblemsResolved?: boolean } {
const assignments: Assignment = {}; const assignments: Assignment = {};
//const allViolations: string[] = []; const allViolations: string[] = [];
// Initialisiere Zuweisungen // Initialisiere Zuweisungen
shifts.forEach(shift => { shifts.forEach(shift => {
@@ -444,14 +431,14 @@ export function scheduleWithManager(
console.log('🔄 Starting Phase B: Enhanced Manager insertion'); console.log('🔄 Starting Phase B: Enhanced Manager insertion');
// Phase B: Erweiterte Manager-Einfügung // Phase B: Erweiterte Manager-Einfügung
/*const phaseBResult = phaseBInsertManager( const phaseBResult = phaseBInsertManager(
assignments, assignments,
manager, manager,
managerShifts, managerShifts,
employees, employees,
nonManagerShifts, nonManagerShifts,
constraints constraints
);*/ );
console.log('🔄 Starting Enhanced Phase C: Smart Repair & Validation'); console.log('🔄 Starting Enhanced Phase C: Smart Repair & Validation');