diff --git a/server/routes.ts b/server/routes.ts index bd20f37..2353990 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -4256,6 +4256,98 @@ export async function registerRoutes(app: Express): Promise { } }); + // POST - Duplica o modifica patrol route + app.post("/api/patrol-routes/duplicate", isAuthenticated, async (req: any, res) => { + try { + const { sourceRouteId, targetDate, guardId } = req.body; + + if (!sourceRouteId || !targetDate) { + return res.status(400).json({ + message: "sourceRouteId e targetDate sono obbligatori" + }); + } + + // Carica patrol route sorgente con tutti gli stops + const sourceRoute = await db.query.patrolRoutes.findFirst({ + where: eq(patrolRoutes.id, sourceRouteId), + with: { + stops: { + orderBy: (stops, { asc }) => [asc(stops.sequenceOrder)], + }, + }, + }); + + if (!sourceRoute) { + return res.status(404).json({ message: "Sequenza pattuglia sorgente non trovata" }); + } + + // Controlla se targetDate รจ uguale a sourceRoute.scheduledDate + const sourceDate = new Date(sourceRoute.scheduledDate).toISOString().split('T')[0]; + const targetDateNormalized = new Date(targetDate).toISOString().split('T')[0]; + + if (sourceDate === targetDateNormalized) { + // UPDATE: stessa data, modifica solo guardia se fornita + if (guardId && guardId !== sourceRoute.guardId) { + const updated = await db + .update(patrolRoutes) + .set({ guardId }) + .where(eq(patrolRoutes.id, sourceRouteId)) + .returning(); + + return res.json({ + action: "updated", + route: updated[0], + message: "Guardia assegnata alla sequenza esistente", + }); + } else { + return res.status(400).json({ + message: "Nessuna modifica da applicare (stessa data e stessa guardia)" + }); + } + } else { + // CREATE: data diversa, duplica sequenza con stops + + // Crea nuova patrol route + const newRoute = await db + .insert(patrolRoutes) + .values({ + guardId: guardId || sourceRoute.guardId, // Usa nuova guardia o mantieni originale + scheduledDate: new Date(targetDate), + startTime: sourceRoute.startTime, + endTime: sourceRoute.endTime, + status: "scheduled", // Nuova sequenza sempre in stato scheduled + location: sourceRoute.location, + notes: sourceRoute.notes, + }) + .returning(); + + const newRouteId = newRoute[0].id; + + // Duplica tutti gli stops + if (sourceRoute.stops && sourceRoute.stops.length > 0) { + const stopsData = sourceRoute.stops.map((stop) => ({ + patrolRouteId: newRouteId, + siteId: stop.siteId, + sequenceOrder: stop.sequenceOrder, + estimatedArrivalTime: stop.estimatedArrivalTime, + })); + + await db.insert(patrolRouteStops).values(stopsData); + } + + return res.json({ + action: "created", + route: newRoute[0], + copiedStops: sourceRoute.stops?.length || 0, + message: "Sequenza pattuglia duplicata con successo", + }); + } + } catch (error) { + console.error("Error duplicating patrol route:", error); + res.status(500).json({ message: "Errore durante duplicazione sequenza pattuglia" }); + } + }); + // ============= GEOCODING API (Nominatim/OSM) ============= // Rate limiter semplice per rispettare 1 req/sec di Nominatim