forceRefresh) { $lastAttraction = $this->city->attractions() ->orderBy('cached_at', 'desc') ->first(); if ($lastAttraction && $lastAttraction->cached_at) { $cacheAge = now()->diffInDays($lastAttraction->cached_at); $cacheTtl = config('services.opentripmap.cache_ttl', 7); if ($cacheAge < $cacheTtl) { Log::info("Attractions data is still fresh, skipping fetch", [ 'city_id' => $this->city->id, 'cache_age' => $cacheAge, ]); return; } } } if (!$this->city->latitude || !$this->city->longitude) { Log::warning("City coordinates not set, cannot fetch attractions", [ 'city_id' => $this->city->id, ]); return; } $attractionsCreated = 0; // Fetch from OpenTripMap $openTripMapData = $openTripMapService->getAttractions( $this->city->latitude, $this->city->longitude ); foreach ($openTripMapData as $data) { $this->createOrUpdateAttraction($data, 'opentripmap'); $attractionsCreated++; } // Fetch from Overpass $overpassData = $overpassService->getPointsOfInterest( $this->city->latitude, $this->city->longitude ); foreach ($overpassData as $data) { $this->createOrUpdateAttraction($data, 'overpass'); $attractionsCreated++; } Log::info("Attractions fetched successfully", [ 'city_id' => $this->city->id, 'city_name' => $this->city->name, 'attractions_created' => $attractionsCreated, ]); } catch (\Exception $e) { Log::error("Error in FetchAttractionsJob", [ 'city_id' => $this->city->id, 'error' => $e->getMessage(), ]); throw $e; } } /** * Create or update an attraction */ private function createOrUpdateAttraction(array $data, string $source): void { Attraction::updateOrCreate( [ 'city_id' => $this->city->id, 'source' => $source, 'source_id' => $data['source_id'], ], [ 'name' => $data['name'], 'description' => $data['description'] ?? null, 'latitude' => $data['latitude'], 'longitude' => $data['longitude'], 'category' => $data['category'] ?? 'other', 'rating' => $data['rating'] ?? null, 'image_url' => $data['image_url'] ?? null, 'cached_at' => now(), ] ); } }