*/ public function nearby(float $latitude, float $longitude, float $radiusKm = 5.0, int $limit = 25): Collection { $radiusMeters = $radiusKm * 1000; $rows = DB::table('drop_off_points') ->whereNull('deleted_at') ->where('status', DropOffPoint::STATUS_ACTIVE) ->select('id') ->selectRaw( 'ST_Distance_Sphere(coordinates, ST_SRID(POINT(?, ?), 4326)) AS distance_meters', [$longitude, $latitude], ) ->whereRaw( 'ST_Distance_Sphere(coordinates, ST_SRID(POINT(?, ?), 4326)) <= ?', [$longitude, $latitude, $radiusMeters], ) ->orderBy('distance_meters') ->limit($limit) ->get(); if ($rows->isEmpty()) { return collect(); } $distancesById = $rows->pluck('distance_meters', 'id'); $points = DropOffPoint::with('barangay') ->whereIn('id', $rows->pluck('id')) ->get() ->keyBy('id'); return $rows->map(function ($r) use ($points, $distancesById) { $p = $points->get($r->id); if ($p) { $p->distance_meters = (float) $distancesById->get($r->id); } return $p; })->filter()->values(); } public function nearest(float $latitude, float $longitude, float $maxKm = 25.0): ?DropOffPoint { return $this->nearby($latitude, $longitude, $maxKm, 1)->first(); } }