Compare commits
4 Commits
19158357fb
...
24a1c81d6e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24a1c81d6e | ||
|
|
82442a5dd9 | ||
|
|
b1b320ab69 | ||
|
|
1c34d3f79e |
@ -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 } = useQuery<GuardAvailability[]>({
|
const { data: availableGuards, isLoading: isLoadingGuards, refetch: refetchGuards } = 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,6 +144,7 @@ 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
|
||||||
@ -174,19 +175,21 @@ 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: () => {
|
onSuccess: async () => {
|
||||||
// Invalida cache planning generale
|
// Invalida cache planning generale
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/general-planning"] });
|
await queryClient.invalidateQueries({ queryKey: ["/api/general-planning"] });
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/guards/availability"] });
|
await 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 form
|
// Reset solo guardia selezionata (NON chiudere dialog per vedere lista aggiornata)
|
||||||
setSelectedGuardId("");
|
setSelectedGuardId("");
|
||||||
setSelectedCell(null);
|
|
||||||
},
|
},
|
||||||
onError: (error: any) => {
|
onError: (error: any) => {
|
||||||
// Parse error message from API response
|
// Parse error message from API response
|
||||||
|
|||||||
Binary file not shown.
BIN
database-backups/vigilanzaturni_v1.0.30_20251022_071255.sql.gz
Normal file
BIN
database-backups/vigilanzaturni_v1.0.30_20251022_071255.sql.gz
Normal file
Binary file not shown.
@ -1326,6 +1326,7 @@ 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 &&
|
||||||
@ -1338,6 +1339,34 @@ 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,
|
||||||
|
|||||||
10
version.json
10
version.json
@ -1,7 +1,13 @@
|
|||||||
{
|
{
|
||||||
"version": "1.0.29",
|
"version": "1.0.30",
|
||||||
"lastUpdate": "2025-10-21T17:19:38.090Z",
|
"lastUpdate": "2025-10-22T07:13:11.868Z",
|
||||||
"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",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user