$payload * @param array $job * @return array */ public function __invoke(array $payload = [], array $job = []): array { $forcedIntegrationId = max(0, (int) ($payload['integration_id'] ?? 0)); $activeIntegrations = array_values(array_filter( $this->integrations->listByType('shoppro'), static function (array $integration) use ($forcedIntegrationId): bool { $id = (int) ($integration['id'] ?? 0); if ($forcedIntegrationId > 0 && $id !== $forcedIntegrationId) { return false; } return $id > 0 && ($integration['is_active'] ?? false) === true && ($integration['has_api_key'] ?? false) === true; } )); if ($activeIntegrations === []) { return [ 'ok' => true, 'message' => 'Brak aktywnych integracji z kluczem API do weryfikacji powiazan.', 'checked_links' => 0, 'missing_links' => 0, 'integrations' => 0, 'integration_failures' => 0, ]; } $checkedLinks = 0; $missingLinks = 0; $resolvedAlerts = 0; $integrationFailures = 0; $errors = []; $checkedAt = date('Y-m-d H:i:s'); foreach ($activeIntegrations as $integration) { $integrationId = (int) ($integration['id'] ?? 0); if ($integrationId <= 0) { continue; } try { $credentials = $this->integrations->findApiCredentials($integrationId); } catch (Throwable $exception) { $integrationFailures++; if (count($errors) < 5) { $errors[] = 'Integracja #' . $integrationId . ': ' . $exception->getMessage(); } continue; } if ($credentials === null || trim((string) ($credentials['api_key'] ?? '')) === '') { $integrationFailures++; if (count($errors) < 5) { $errors[] = 'Integracja #' . $integrationId . ': brak poprawnych danych API.'; } continue; } $import = $this->offerImportService->importShopProOffers($credentials); if (($import['ok'] ?? false) !== true) { $integrationFailures++; if (count($errors) < 5) { $errors[] = 'Integracja #' . $integrationId . ': ' . trim((string) ($import['message'] ?? 'Blad importu ofert.')); } continue; } $links = $this->links->listActiveLinksForMissingCheck($integrationId); foreach ($links as $link) { $mapId = (int) ($link['id'] ?? 0); $externalProductId = trim((string) ($link['external_product_id'] ?? '')); $externalVariantId = $this->nullableText($link['external_variant_id'] ?? null); if ($mapId <= 0 || $externalProductId === '') { continue; } $checkedLinks++; $offer = $this->offers->findByExternalIdentity($integrationId, $externalProductId, $externalVariantId); if ($offer === null) { $missingLinks++; $this->links->upsertActiveAlert($mapId, self::ALERT_TYPE, self::ALERT_MESSAGE, $checkedAt); continue; } $this->links->resolveActiveAlert($mapId, self::ALERT_TYPE, $checkedAt); $resolvedAlerts++; } } return [ 'ok' => $integrationFailures === 0, 'message' => $integrationFailures === 0 ? 'Weryfikacja powiazan zakonczona.' : 'Weryfikacja zakonczona z bledami integracji.', 'checked_links' => $checkedLinks, 'missing_links' => $missingLinks, 'resolved_alerts' => $resolvedAlerts, 'integrations' => count($activeIntegrations), 'integration_failures' => $integrationFailures, 'errors' => $errors, ]; } private function nullableText(mixed $value): ?string { $text = trim((string) $value); return $text === '' ? null : $text; } }