Compare commits

..

No commits in common. "24a1c81d6ebc8b3000d7a5a8901630563545fa9d" and "19158357fb64f9f326b2ee47ad853baf10dfceb0" have entirely different histories.

5 changed files with 8 additions and 46 deletions

View File

@ -132,7 +132,7 @@ export default function GeneralPlanning() {
}; };
// Query per guardie disponibili (solo quando dialog è aperto) // Query per guardie disponibili (solo quando dialog è aperto)
const { data: availableGuards, isLoading: isLoadingGuards, refetch: refetchGuards } = useQuery<GuardAvailability[]>({ const { data: availableGuards, isLoading: isLoadingGuards } = useQuery<GuardAvailability[]>({
queryKey: ["/api/guards/availability", selectedCell?.siteId, selectedLocation, startTime, durationHours], queryKey: ["/api/guards/availability", selectedCell?.siteId, selectedLocation, startTime, durationHours],
queryFn: async () => { queryFn: async () => {
if (!selectedCell) return []; if (!selectedCell) return [];
@ -144,7 +144,6 @@ export default function GeneralPlanning() {
return response.json(); return response.json();
}, },
enabled: !!selectedCell, // Query attiva solo se dialog è aperto enabled: !!selectedCell, // Query attiva solo se dialog è aperto
staleTime: 0, // Dati sempre considerati stale, refetch ad ogni apertura dialog
}); });
// Mutation per eliminare assegnazione guardia // Mutation per eliminare assegnazione guardia
@ -175,21 +174,19 @@ export default function GeneralPlanning() {
mutationFn: async (data: { siteId: string; date: string; guardId: string; startTime: string; durationHours: number; consecutiveDays: number }) => { mutationFn: async (data: { siteId: string; date: string; guardId: string; startTime: string; durationHours: number; consecutiveDays: number }) => {
return apiRequest("POST", "/api/general-planning/assign-guard", data); return apiRequest("POST", "/api/general-planning/assign-guard", data);
}, },
onSuccess: async () => { onSuccess: () => {
// Invalida cache planning generale // Invalida cache planning generale
await queryClient.invalidateQueries({ queryKey: ["/api/general-planning"] }); queryClient.invalidateQueries({ queryKey: ["/api/general-planning"] });
await queryClient.invalidateQueries({ queryKey: ["/api/guards/availability"] }); queryClient.invalidateQueries({ queryKey: ["/api/guards/availability"] });
// Refetch immediatamente guardie disponibili per aggiornare lista
await refetchGuards();
toast({ toast({
title: "Guardia assegnata", title: "Guardia assegnata",
description: "La guardia è stata assegnata con successo", description: "La guardia è stata assegnata con successo",
}); });
// Reset solo guardia selezionata (NON chiudere dialog per vedere lista aggiornata) // Reset form
setSelectedGuardId(""); setSelectedGuardId("");
setSelectedCell(null);
}, },
onError: (error: any) => { onError: (error: any) => {
// Parse error message from API response // Parse error message from API response

View File

@ -1326,7 +1326,6 @@ export async function registerRoutes(app: Express): Promise<Server> {
.from(shiftAssignments) .from(shiftAssignments)
.where(eq(shiftAssignments.guardId, guard.id)); .where(eq(shiftAssignments.guardId, guard.id));
// Check for time overlaps
for (const existing of existingAssignments) { for (const existing of existingAssignments) {
const hasOverlap = const hasOverlap =
plannedStart < existing.plannedEndTime && plannedStart < existing.plannedEndTime &&
@ -1339,34 +1338,6 @@ export async function registerRoutes(app: Express): Promise<Server> {
} }
} }
// CCNL: Check daily hour limit (max 9h/day)
const maxDailyHours = 9;
let dailyHoursAlreadyAssigned = 0;
for (const existing of existingAssignments) {
// Check if assignment is on the same day
const existingDate = new Date(existing.plannedStartTime);
if (
existingDate.getUTCFullYear() === actualYear &&
existingDate.getUTCMonth() === actualMonth &&
existingDate.getUTCDate() === actualDay
) {
const assignmentHours = differenceInHours(
existing.plannedEndTime,
existing.plannedStartTime
);
dailyHoursAlreadyAssigned += assignmentHours;
}
}
// 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
const [assignment] = await tx.insert(shiftAssignments).values({ const [assignment] = await tx.insert(shiftAssignments).values({
shiftId: shift.id, shiftId: shift.id,

View File

@ -1,13 +1,7 @@
{ {
"version": "1.0.30", "version": "1.0.29",
"lastUpdate": "2025-10-22T07:13:11.868Z", "lastUpdate": "2025-10-21T17:19:38.090Z",
"changelog": [ "changelog": [
{
"version": "1.0.30",
"date": "2025-10-22",
"type": "patch",
"description": "Deployment automatico v1.0.30"
},
{ {
"version": "1.0.29", "version": "1.0.29",
"date": "2025-10-21", "date": "2025-10-21",