diff --git a/controllers/milerController.go b/controllers/milerController.go index 0c745d6..dcc5e49 100644 --- a/controllers/milerController.go +++ b/controllers/milerController.go @@ -963,6 +963,34 @@ func isHyperlocal(pickupPincode, deliveryPincode string) bool { return pickupPincode[:3] == deliveryPincode[:3] } +// maxHyperlocalKM bounds the straight-line pickup→delivery distance under which +// a booking with a missing/short pincode is still treated as hyperlocal. It is +// used ONLY as a fallback when the pincode-prefix rule can't decide: console- +// created kitchen→customer bookings (e.g. DailyGrubs) frequently carry accurate +// coordinates but no delivery pincode, and must not be wrongly routed through a +// hub. When both pincodes are present the prefix rule still wins. +const maxHyperlocalKM = 30.0 + +// isHyperlocalBooking decides whether a booking can skip the hub and be carried +// straight to the final mile. It prefers the pincode-prefix rule (isHyperlocal) +// when both pincodes are present, and falls back to the straight-line distance +// between the pickup and delivery coordinates when a pincode is missing — so a +// same-area booking whose address carried no pincode isn't sent to a hub. +func isHyperlocalBooking(pickupPincode, deliveryPincode string, pLat, pLng, dLat, dLng float64) bool { + // Both pincodes present: the prefix rule decides definitively (a matching + // pincode is hyperlocal, a differing one is genuinely inter-area — don't let + // distance override that). + if len(pickupPincode) >= 3 && len(deliveryPincode) >= 3 { + return isHyperlocal(pickupPincode, deliveryPincode) + } + // A pincode is missing: fall back to straight-line distance when we have both + // coordinates. + if pLat != 0 && pLng != 0 && dLat != 0 && dLng != 0 { + return haversineKM(pLat, pLng, dLat, dLng) <= maxHyperlocalKM + } + return false +} + // collectedStateEnabled gates the two-step hyperlocal delivery flow // (Collected_By_Miler → start-delivery → Out_for_Delivery) and its knock-on // changes: OTP issued at start-delivery instead of pickup, and Arrived_At_Pickup @@ -1061,7 +1089,9 @@ func BookingPickupComplete(c *fiber.Ctx) error { // delivering". With it OFF (default, and what the current app expects) it goes // straight to Out_for_Delivery exactly as before. consignmentStatus := constants.ConsignmentInwardedAtHub - if isHyperlocal(booking.Pickuppincode, booking.Deliverypincode) { + if isHyperlocalBooking(booking.Pickuppincode, booking.Deliverypincode, + booking.Pickuplatitude, booking.Pickuplongitude, + booking.Deliverylatitude, booking.Deliverylongitude) { if collectedStateEnabled() { consignmentStatus = constants.ConsignmentCollectedByMiler } else {