Add operational planning view for vehicle and guard availability
Implement GET /api/operational-planning/availability endpoint to fetch and sort vehicles and guards based on their availability and CCNL rules for a given date. 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/EEOXc3D
This commit is contained in:
parent
278419c4ff
commit
181de6a028
4
.replit
4
.replit
@ -19,6 +19,10 @@ externalPort = 80
|
|||||||
localPort = 33035
|
localPort = 33035
|
||||||
externalPort = 3001
|
externalPort = 3001
|
||||||
|
|
||||||
|
[[ports]]
|
||||||
|
localPort = 34977
|
||||||
|
externalPort = 4200
|
||||||
|
|
||||||
[[ports]]
|
[[ports]]
|
||||||
localPort = 41343
|
localPort = 41343
|
||||||
externalPort = 3000
|
externalPort = 3000
|
||||||
|
|||||||
121
server/routes.ts
121
server/routes.ts
@ -534,6 +534,127 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============= OPERATIONAL PLANNING ROUTES =============
|
||||||
|
app.get("/api/operational-planning/availability", isAuthenticated, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { getGuardAvailabilityReport } = await import("./ccnlRules");
|
||||||
|
const date = req.query.date ? new Date(req.query.date as string) : new Date();
|
||||||
|
|
||||||
|
// Imposta inizio e fine giornata
|
||||||
|
const startOfDay = new Date(date);
|
||||||
|
startOfDay.setHours(0, 0, 0, 0);
|
||||||
|
const endOfDay = new Date(date);
|
||||||
|
endOfDay.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
// Ottieni tutti i veicoli
|
||||||
|
const allVehicles = await storage.getAllVehicles();
|
||||||
|
|
||||||
|
// Ottieni turni del giorno per trovare veicoli assegnati
|
||||||
|
const dayShifts = await db
|
||||||
|
.select()
|
||||||
|
.from(shifts)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
gte(shifts.startTime, startOfDay),
|
||||||
|
lte(shifts.startTime, endOfDay)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mappa veicoli con disponibilità
|
||||||
|
const vehiclesWithAvailability = await Promise.all(
|
||||||
|
allVehicles.map(async (vehicle) => {
|
||||||
|
const assignedShift = dayShifts.find((shift: any) => shift.vehicleId === vehicle.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...vehicle,
|
||||||
|
isAvailable: !assignedShift,
|
||||||
|
assignedShift: assignedShift ? {
|
||||||
|
id: assignedShift.id,
|
||||||
|
startTime: assignedShift.startTime,
|
||||||
|
endTime: assignedShift.endTime,
|
||||||
|
siteId: assignedShift.siteId
|
||||||
|
} : null
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ottieni tutte le guardie
|
||||||
|
const allGuards = await storage.getAllGuards();
|
||||||
|
|
||||||
|
// Ottieni assegnazioni turni del giorno
|
||||||
|
const dayShiftAssignments = await db
|
||||||
|
.select()
|
||||||
|
.from(shiftAssignments)
|
||||||
|
.innerJoin(shifts, eq(shiftAssignments.shiftId, shifts.id))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
gte(shifts.startTime, startOfDay),
|
||||||
|
lte(shifts.startTime, endOfDay)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calcola disponibilità agenti con report CCNL
|
||||||
|
const guardsWithAvailability = await Promise.all(
|
||||||
|
allGuards.map(async (guard) => {
|
||||||
|
const assignedShift = dayShiftAssignments.find(
|
||||||
|
(assignment: any) => assignment.shift_assignments.guardId === guard.id
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calcola report disponibilità CCNL
|
||||||
|
const availabilityReport = await getGuardAvailabilityReport(
|
||||||
|
guard.id,
|
||||||
|
startOfDay,
|
||||||
|
endOfDay
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...guard,
|
||||||
|
isAvailable: !assignedShift,
|
||||||
|
assignedShift: assignedShift ? {
|
||||||
|
id: assignedShift.shifts.id,
|
||||||
|
startTime: assignedShift.shifts.startTime,
|
||||||
|
endTime: assignedShift.shifts.endTime,
|
||||||
|
siteId: assignedShift.shifts.siteId
|
||||||
|
} : null,
|
||||||
|
availability: {
|
||||||
|
weeklyHours: availabilityReport.weeklyHours.current,
|
||||||
|
remainingWeeklyHours: availabilityReport.remainingWeeklyHours,
|
||||||
|
remainingMonthlyHours: availabilityReport.remainingMonthlyHours,
|
||||||
|
consecutiveDaysWorked: availabilityReport.consecutiveDaysWorked
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ordina veicoli: disponibili prima, poi per targa
|
||||||
|
const sortedVehicles = vehiclesWithAvailability.sort((a, b) => {
|
||||||
|
if (a.isAvailable && !b.isAvailable) return -1;
|
||||||
|
if (!a.isAvailable && b.isAvailable) return 1;
|
||||||
|
return a.licensePlate.localeCompare(b.licensePlate);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ordina agenti: disponibili prima, poi per ore settimanali (meno ore = più disponibili)
|
||||||
|
const sortedGuards = guardsWithAvailability.sort((a, b) => {
|
||||||
|
if (a.isAvailable && !b.isAvailable) return -1;
|
||||||
|
if (!a.isAvailable && b.isAvailable) return 1;
|
||||||
|
// Se entrambi disponibili, ordina per ore settimanali (meno ore = prima)
|
||||||
|
if (a.isAvailable && b.isAvailable) {
|
||||||
|
return a.availability.weeklyHours - b.availability.weeklyHours;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
date: date.toISOString(),
|
||||||
|
vehicles: sortedVehicles,
|
||||||
|
guards: sortedGuards
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching operational planning availability:", error);
|
||||||
|
res.status(500).json({ message: "Failed to fetch availability" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ============= CERTIFICATION ROUTES =============
|
// ============= CERTIFICATION ROUTES =============
|
||||||
app.post("/api/certifications", isAuthenticated, async (req, res) => {
|
app.post("/api/certifications", isAuthenticated, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user