Allow overriding daily hour limits for guard assignments
Update the general planning API endpoint to include a 'force' option, enabling the assignment of guards even if they exceed the daily hour limit. This change adds a confirmation prompt for such cases and refactors error handling to provide more specific messages. Replit-Commit-Author: Agent Replit-Commit-Session-Id: e5565357-90e1-419f-b9a8-6ee8394636df Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e5565357-90e1-419f-b9a8-6ee8394636df/2w7P7NW
This commit is contained in:
parent
fb99b5f738
commit
9c28befcb1
@ -1241,7 +1241,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
// Assign guard to site/date with specific time slot (supports multi-day assignments)
|
// Assign guard to site/date with specific time slot (supports multi-day assignments)
|
||||||
app.post("/api/general-planning/assign-guard", isAuthenticated, async (req, res) => {
|
app.post("/api/general-planning/assign-guard", isAuthenticated, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { siteId, date, guardId, startTime, durationHours, consecutiveDays = 1, vehicleId } = req.body;
|
const { siteId, date, guardId, startTime, durationHours, consecutiveDays = 1, vehicleId, force = false } = req.body;
|
||||||
|
|
||||||
if (!siteId || !date || !guardId || !startTime || !durationHours) {
|
if (!siteId || !date || !guardId || !startTime || !durationHours) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
@ -1369,32 +1369,35 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CCNL: Check daily hour limit (max 9h/day)
|
// CCNL: Check daily hour limit (max 9h/day) - skip if force=true
|
||||||
const maxDailyHours = 9;
|
if (!force) {
|
||||||
let dailyHoursAlreadyAssigned = 0;
|
const maxDailyHours = 9;
|
||||||
|
let dailyHoursAlreadyAssigned = 0;
|
||||||
for (const existing of existingAssignments) {
|
|
||||||
// Check if assignment is on the same day
|
for (const existing of existingAssignments) {
|
||||||
const existingDate = new Date(existing.plannedStartTime);
|
// Check if assignment is on the same day
|
||||||
if (
|
const existingDate = new Date(existing.plannedStartTime);
|
||||||
existingDate.getUTCFullYear() === actualYear &&
|
if (
|
||||||
existingDate.getUTCMonth() === actualMonth &&
|
existingDate.getUTCFullYear() === actualYear &&
|
||||||
existingDate.getUTCDate() === actualDay
|
existingDate.getUTCMonth() === actualMonth &&
|
||||||
) {
|
existingDate.getUTCDate() === actualDay
|
||||||
const assignmentHours = differenceInHours(
|
) {
|
||||||
existing.plannedEndTime,
|
const assignmentHours = differenceInHours(
|
||||||
existing.plannedStartTime
|
existing.plannedEndTime,
|
||||||
);
|
existing.plannedStartTime
|
||||||
dailyHoursAlreadyAssigned += assignmentHours;
|
);
|
||||||
|
dailyHoursAlreadyAssigned += assignmentHours;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if new assignment would exceed daily limit
|
||||||
|
if (dailyHoursAlreadyAssigned + durationHours > maxDailyHours) {
|
||||||
|
const excessHours = (dailyHoursAlreadyAssigned + durationHours) - maxDailyHours;
|
||||||
|
throw new Error(
|
||||||
|
`Limite giornaliero superato: la guardia ha già ${dailyHoursAlreadyAssigned}h assegnate il ${shiftDate.toLocaleDateString('it-IT')}. ` +
|
||||||
|
`Aggiungendo ${durationHours}h si supererebbero di ${excessHours}h le ${maxDailyHours}h massime giornaliere (CCNL).`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if new assignment would exceed daily limit
|
|
||||||
if (dailyHoursAlreadyAssigned + durationHours > maxDailyHours) {
|
|
||||||
throw new Error(
|
|
||||||
`Limite giornaliero superato: la guardia ha già ${dailyHoursAlreadyAssigned}h assegnate il ${shiftDate.toLocaleDateString('it-IT')}. ` +
|
|
||||||
`Aggiungendo ${durationHours}h si supererebbero le ${maxDailyHours}h massime giornaliere (CCNL).`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create assignment for this day
|
// Create assignment for this day
|
||||||
@ -1423,8 +1426,14 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
if (errorMessage.includes('overlap') ||
|
if (errorMessage.includes('overlap') ||
|
||||||
errorMessage.includes('conflict') ||
|
errorMessage.includes('conflict') ||
|
||||||
errorMessage.includes('conflitto') ||
|
errorMessage.includes('conflitto') ||
|
||||||
errorMessage.includes('già assegnata')) {
|
errorMessage.includes('già assegnata') ||
|
||||||
return res.status(409).json({ message: error.message });
|
errorMessage.includes('limite giornaliero') ||
|
||||||
|
errorMessage.includes('limite settimanale') ||
|
||||||
|
errorMessage.includes('ccnl')) {
|
||||||
|
return res.status(409).json({
|
||||||
|
message: error.message,
|
||||||
|
type: errorMessage.includes('limite') ? 'CCNL_VIOLATION' : 'CONFLICT'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
res.status(500).json({ message: "Failed to assign guard", error: String(error) });
|
res.status(500).json({ message: "Failed to assign guard", error: String(error) });
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user