reworked scheduling

This commit is contained in:
2025-10-18 01:55:04 +02:00
parent b86040dc04
commit f705a83cd4
26 changed files with 3222 additions and 3193 deletions

View File

@@ -295,6 +295,8 @@ export const getAvailabilities = async (req: AuthRequest, res: Response): Promis
ORDER BY day_of_week, time_slot_id
`, [employeeId]);
//console.log('✅ Successfully got availabilities from employee:', availabilities);
res.json(availabilities.map(avail => ({
id: avail.id,
employeeId: avail.employee_id,
@@ -348,6 +350,9 @@ export const updateAvailabilities = async (req: AuthRequest, res: Response): Pro
await db.run('COMMIT');
console.log('✅ Successfully updated availablities employee:', );
// Return updated availabilities
const updatedAvailabilities = await db.all<any>(`
SELECT * FROM employee_availability
@@ -365,6 +370,8 @@ export const updateAvailabilities = async (req: AuthRequest, res: Response): Pro
notes: avail.notes
})));
console.log('✅ Successfully updated employee:', updateAvailabilities);
} catch (error) {
await db.run('ROLLBACK');
throw error;

View File

@@ -740,53 +740,6 @@ export const generateScheduledShiftsForPlan = async (req: Request, res: Response
}
};
export const revertToDraft = async (req: Request, res: Response): Promise<void> => {
try {
const { id } = req.params;
const userId = (req as AuthRequest).user?.userId;
if (!userId) {
res.status(401).json({ error: 'Unauthorized' });
return;
}
// Check if plan exists
const existingPlan = await getShiftPlanById(id);
//const existingPlan: ShiftPlan = await db.get('SELECT * FROM shift_plans WHERE id = ?', [id]);
if (!existingPlan) {
res.status(404).json({ error: 'Shift plan not found' });
return;
}
// Only allow reverting from published to draft
if (existingPlan.status !== 'published') {
res.status(400).json({ error: 'Can only revert published plans to draft' });
return;
}
// Update plan status to draft
await db.run(
'UPDATE shift_plans SET status = ? WHERE id = ?',
['draft', id]
);
// Clear all assigned employees from scheduled shifts
await db.run(
'UPDATE scheduled_shifts SET assigned_employees = ? WHERE plan_id = ?',
[JSON.stringify([]), id]
);
console.log(`✅ Plan ${id} reverted to draft status`);
// Return updated plan
const updatedPlan = await getShiftPlanById(id);
res.json(updatedPlan);
} catch (error) {
console.error('Error reverting plan to draft:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
export const regenerateScheduledShifts = async (req: Request, res: Response): Promise<void> => {
try {
@@ -921,4 +874,63 @@ export const updateScheduledShift = async (req: AuthRequest, res: Response): Pro
console.error('❌ Error updating scheduled shift:', error);
res.status(500).json({ error: 'Internal server error: ' + error.message });
}
};
export const clearAssignments = async (req: Request, res: Response): Promise<void> => {
try {
const { id } = req.params;
console.log('🔄 Clearing assignments for plan:', id);
// Check if plan exists
const existingPlan = await db.get('SELECT * FROM shift_plans WHERE id = ?', [id]);
if (!existingPlan) {
res.status(404).json({ error: 'Shift plan not found' });
return;
}
await db.run('BEGIN TRANSACTION');
try {
// Get all scheduled shifts for this plan
const scheduledShifts = await db.all<any>(
'SELECT id FROM scheduled_shifts WHERE plan_id = ?',
[id]
);
console.log(`📋 Found ${scheduledShifts.length} scheduled shifts to clear`);
// Clear all assignments (set assigned_employees to empty array)
for (const shift of scheduledShifts) {
await db.run(
'UPDATE scheduled_shifts SET assigned_employees = ? WHERE id = ?',
[JSON.stringify([]), shift.id]
);
console.log(`✅ Cleared assignments for shift: ${shift.id}`);
}
// Update plan status back to draft
await db.run(
'UPDATE shift_plans SET status = ? WHERE id = ?',
['draft', id]
);
await db.run('COMMIT');
console.log(`✅ Successfully cleared all assignments for plan ${id}`);
res.json({
message: 'Assignments cleared successfully',
clearedShifts: scheduledShifts.length
});
} catch (error) {
await db.run('ROLLBACK');
throw error;
}
} catch (error) {
console.error('❌ Error clearing assignments:', error);
res.status(500).json({ error: 'Internal server error' });
}
};

View File

@@ -18,7 +18,7 @@ const router = express.Router();
router.use(authMiddleware);
// Employee CRUD Routes
router.get('/', requireRole(['admin', 'instandhalter']), getEmployees);
router.get('/', authMiddleware, getEmployees);
router.get('/:id', requireRole(['admin', 'instandhalter']), getEmployee);
router.post('/', requireRole(['admin']), createEmployee);
router.put('/:id', requireRole(['admin']), updateEmployee);

View File

@@ -19,12 +19,12 @@ router.post('/:id/generate-shifts', requireRole(['admin', 'instandhalter']), gen
router.post('/:id/regenerate-shifts', requireRole(['admin', 'instandhalter']), regenerateScheduledShifts);
// GET all scheduled shifts for a plan
router.get('/plan/:planId', requireRole(['admin']), getScheduledShiftsFromPlan);
router.get('/plan/:planId', authMiddleware, getScheduledShiftsFromPlan);
// GET specific scheduled shift
router.get('/:id', requireRole(['admin']), getScheduledShift);
router.get('/:id', authMiddleware, getScheduledShift);
// UPDATE scheduled shift
router.put('/:id', requireRole(['admin']), updateScheduledShift);
router.put('/:id', authMiddleware, updateScheduledShift);
export default router;

View File

@@ -8,7 +8,7 @@ import {
updateShiftPlan,
deleteShiftPlan,
createFromPreset,
revertToDraft,
clearAssignments
} from '../controllers/shiftPlanController.js';
const router = express.Router();
@@ -18,13 +18,13 @@ router.use(authMiddleware);
// Combined routes for both shift plans and templates
// GET all shift plans (including templates)
router.get('/', getShiftPlans);
router.get('/' , authMiddleware, getShiftPlans);
// GET templates only
//router.get('/templates', getTemplates);
// GET specific shift plan or template
router.get('/:id', getShiftPlan);
router.get('/:id', authMiddleware, getShiftPlan);
// POST create new shift plan
router.post('/', requireRole(['admin', 'instandhalter']), createShiftPlan);
@@ -41,7 +41,7 @@ router.put('/:id', requireRole(['admin', 'instandhalter']), updateShiftPlan);
// DELETE shift plan or template
router.delete('/:id', requireRole(['admin', 'instandhalter']), deleteShiftPlan);
// PUT revert published plan to draft
router.put('/:id/revert-to-draft', requireRole(['admin', 'instandhalter']), revertToDraft);
// POST clear assignments and reset to draft
router.post('/:id/clear-assignments', requireRole(['admin', 'instandhalter']), clearAssignments);
export default router;