year; $config = config('services.szunetnapok'); $apiKey = $config['key'] ?? null; $apiUrl = rtrim($config['url'] ?? 'https://szunetnapok.hu/api/', '/'); $verify = $config['verify'] ?? true; Log::channel('work_calendar')->info('WorkCalendar sync started.', [ 'year' => $year, 'api_url' => $apiUrl, 'has_api_key' => !empty($apiKey), 'ssl_verify' => $verify, ]); if (empty($apiKey)) { $this->error->add('api', 'Hiányzó szunetnapok.hu API kulcs.'); Log::channel('work_calendar')->error('WorkCalendar sync failed: Missing API key.'); return false; } try { $response = Http::withOptions(['verify' => $verify]) ->get("{$apiUrl}/{$apiKey}/{$year}/json"); Log::channel('work_calendar')->info('WorkCalendar API response.', [ 'status' => $response->status(), 'body' => $response->body(), ]); if ($response->failed()) { $this->error->add('api', 'Nem sikerült elérni a szunetnapok.hu API-t.'); return false; } } catch (\Exception $e) { $this->error->add('api', 'Hálózati hiba az API hívás közben: ' . $e->getMessage()); Log::channel('work_calendar')->error('WorkCalendar sync API error (cURL/SSL):', [ 'message' => $e->getMessage(), 'exception' => get_class($e), ]); return false; } $data = $response->json(); if (($data['response'] ?? '') !== 'OK') { $this->error->add('api', $data['message'] ?? 'Hibás válasz az API-tól.'); return false; } if (!isset($data['days']) || !is_array($data['days'])) { Log::channel('work_calendar')->info('WorkCalendar sync: No days to process.'); return true; } $savedRecords = []; foreach ($data['days'] as $day) { $type = ($day['type'] == 1) ? WorkDayType::Holiday : WorkDayType::WorkingDay; $record = WorkCalendar::updateOrCreate( ['date' => $day['date']], [ 'type' => $type, 'description' => $day['name'] ?? '', 'data_source' => DataSource::Api, ] ); $savedRecords[] = $record->toArray(); } Log::channel('work_calendar')->info('WorkCalendar sync completed.', [ 'count' => count($savedRecords), 'records' => $savedRecords, ]); return true; } /** * Megállapítja, hogy az adott nap munkanap-e. */ public function isWorkDay(Carbon $date): bool { $record = WorkCalendar::where('date', $date->toDateString())->first(); if ($record) { return $record->type === WorkDayType::WorkingDay; } // Ha nincs az adatbázisban, a hétvégék alapján döntünk return !$date->isWeekend(); } /** * Kiszámítja a következő érvényes munkanapot. */ public function getNextWorkDay(Carbon $date): Carbon { $nextDay = $date->copy()->addDay(); while (!$this->isWorkDay($nextDay)) { $nextDay->addDay(); } return $nextDay; } /** * Visszaadja a megadott időszak munkaszüneti napjait és plusz munkanapjait. */ public function getCalendarEntries(Carbon $start, Carbon $end): Collection { return WorkCalendar::whereBetween('date', [$start->toDateString(), $end->toDateString()]) ->orderBy('date') ->get(); } }