feat(GRO-2155): route CRUD + optimization endpoint (Phase 2.1) #175
Reference in New Issue
Block a user
Delete Branch "feat/gro-2155-route-optimize-endpoints-dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
GRO-2155 — Route Optimization: Route CRUD + optimization endpoint (Phase 2.1)
Phase 2.1 of GRO-1164 Mobile Groomer Route Optimization. Builds on the Phase 1 geocoding work (GRO-2152 schema, GRO-2153 service, GRO-2154 endpoints).
What's included
GET /api/routes/daily?staffId=&date=— fetches (creating adraftif absent) the groomer's daily route plus all persisted stops, enriched with appointment + client detail.POST /api/routes/optimize{ staffId, date }— pulls the day's non-cancelled, geocoded appointments, optimizes the visiting order, and persistsstopOrder,travelMinsFromPrev,travelDistanceKmFromPrev, and routetotalTravelMins/totalDistanceKm/optimizedAtin a single transaction (stops fully replaced on re-optimize).src/services/routeOptimization.ts): Google Maps Directions API withoptimizeWaypoints: truewhen a key is configured (businessSettings.googleMapsApiKeydecrypted, orGOOGLE_MAPS_API_KEY); otherwise an offline nearest-neighbor TSP heuristic over great-circle distance. Degrades to the heuristic if Google errors mid-run.requireRole("manager","groomer")on/routes/*; groomers are restricted in-handler to their own route; receptionists denied. Un-geocoded appointments are skipped and surfaced underskipped[]/warnings[].Tests
src/__tests__/routeOptimization.test.ts— haversine, leg estimation, nearest-neighbor ordering, Google path (mocked fetch, drops return leg), >25 chunking, and Google→heuristic fallback. Full suite green locally (623 tests), typecheck + lint clean.UAT Playbook
Targets
dev(Phase 1, CI-gated self-merge).Adds the core route engine for Mobile Groomer Route Optimization: - src/services/routeOptimization.ts — order a day's geocoded stops via Google Directions (optimizeWaypoints:true) when a Maps API key is configured, else an offline nearest-neighbor TSP heuristic over great-circle distance. Handles the >25-stop edge case by chunking into sub-routes (Directions waypoint cap) with a user warning, degrades to the heuristic if Google errors mid-run, and resolves the API key from businessSettings.googleMapsApiKey (decrypted) / GOOGLE_MAPS_API_KEY. - src/routes/routes.ts — GET /api/routes/daily (fetch/create draft route + enriched stops) and POST /api/routes/optimize (generate/re-optimize, persist stopOrder + travelMinsFromPrev + travelDistanceKmFromPrev and route totals/optimizedAt in one transaction). Auth: manager (any) or groomer (own route only); receptionists denied. Un-geocoded appointments are skipped and surfaced. - src/index.ts — mount /api/routes under requireRole("manager","groomer"). - Unit tests for haversine, leg estimation, nearest-neighbor ordering, the Google path (mocked fetch), chunking, and fallback. - UAT_PLAYBOOK.md §4.16 — new Route Optimization test cases. Co-Authored-By: Paperclip <noreply@paperclip.ing>