> */ public array $amazonRows = []; /** @var array> */ public array $rows = []; public static function canAccess(): bool { $user = Auth::user(); return $user instanceof User && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'fornitore']); } public function mount(): void { [$fornitore] = $this->resolveOperatoreContext(allowAdminWithoutSupplier: true); if (! $fornitore instanceof Fornitore) { $this->missingAdminContext = true; return; } $this->fornitoreId = (int) $fornitore->id; $this->fornitoreLabel = $this->getFornitoreLabel($fornitore); $this->amazonConfigured = app(AmazonCreatorsApiService::class)->isConfigured(); $this->refreshRows(); } public function updatedSearch(): void { $this->refreshRows(); } public function refreshRows(): void { if (! $this->fornitoreId) { $this->rows = []; return; } $term = trim($this->search); $normalized = preg_replace('/[^A-Za-z0-9]+/', '', strtoupper($term)) ?? ''; $products = Product::query() ->with(['identifiers', 'offers']) ->where('is_active', true) ->where(function ($query): void { $query->whereNull('default_fornitore_id') ->orWhere('default_fornitore_id', (int) $this->fornitoreId) ->orWhereHas('offers', fn($offerQuery) => $offerQuery->where('fornitore_id', (int) $this->fornitoreId)); }) ->when($term !== '', function ($query) use ($term, $normalized): void { $query->where(function ($builder) use ($term, $normalized): void { $builder->where('name', 'like', '%' . $term . '%') ->orWhere('brand', 'like', '%' . $term . '%') ->orWhere('model', 'like', '%' . $term . '%') ->orWhere('internal_code', 'like', '%' . $term . '%'); if ($normalized !== '') { $builder->orWhereHas('identifiers', function ($identifierQuery) use ($normalized): void { $identifierQuery->where('normalized_code', $normalized) ->orWhere('code_value', 'like', '%' . $normalized . '%'); }); } }); }) ->limit(120) ->get(); $this->rows = $products->map(function (Product $product): array { $identifier = $product->identifiers ->first(fn(ProductIdentifier $item): bool => (int) ($item->fornitore_id ?? 0) === (int) $this->fornitoreId) ?? $product->identifiers->first(); $offer = $product->offers ->first(fn(ProductOffer $item): bool => (int) ($item->fornitore_id ?? 0) === (int) $this->fornitoreId) ?? $product->offers->first(); return [ 'id' => (int) $product->id, 'internal_code' => (string) ($product->internal_code ?? ''), 'label' => trim(implode(' ', array_filter([(string) $product->name, (string) ($product->brand ?? ''), (string) ($product->model ?? '')]))), 'barcode' => (string) ($identifier->code_value ?? ''), 'source' => (string) ($offer?->source_name ?: 'Catalogo interno'), 'price' => $offer?->price_amount !== null ? number_format((float) $offer->price_amount, 2, ',', '.') . ' ' . (string) ($offer->currency ?? 'EUR') : '-', 'external_url' => (string) ($offer?->referral_url ?: $offer?->external_url ?: $this->buildAmazonSearchUrl((string) $product->name)), ]; })->all(); } public function searchAmazonCatalog(): void { if (! $this->amazonConfigured) { Notification::make() ->title('Amazon Creators API non configurata') ->body('Valorizza prima le variabili AMAZON_CREATORS_* in ambiente.') ->danger() ->send(); return; } $query = trim($this->amazonQuery); if ($query === '') { Notification::make()->title('Inserisci una query Amazon')->warning()->send(); return; } try { $this->amazonRows = app(AmazonCreatorsCatalogSyncService::class) ->searchCatalog($query, 8); } catch (RuntimeException $e) { $this->amazonRows = []; Notification::make()->title('Ricerca Amazon non riuscita')->body($e->getMessage())->danger()->send(); return; } if ($this->amazonRows === []) { Notification::make()->title('Nessun risultato Amazon')->warning()->send(); } } public function saveAmazonCandidate(string $asin): void { $asin = trim($asin); $row = collect($this->amazonRows)->first(fn(array $item): bool => (string) ($item['asin'] ?? '') === $asin); if (! is_array($row) || ! is_array($row['item_payload'] ?? null)) { Notification::make()->title('Risultato Amazon non disponibile')->danger()->send(); return; } $fornitore = $this->fornitoreId ? Fornitore::query()->find((int) $this->fornitoreId) : null; if (! $fornitore instanceof Fornitore) { Notification::make()->title('Fornitore non trovato')->danger()->send(); return; } try { $result = app(AmazonCreatorsCatalogSyncService::class) ->importItemForSupplier($fornitore, $row['item_payload'], ['source' => 'amazon_catalog_search_ui']); } catch (RuntimeException $e) { Notification::make()->title('Import Amazon non riuscito')->body($e->getMessage())->danger()->send(); return; } $product = $result['product'] ?? null; Notification::make() ->title(! empty($result['created']) ? 'Prodotto Amazon memorizzato' : 'Prodotto Amazon aggiornato') ->body($product instanceof Product ? 'Articolo salvato nel catalogo come candidato da verificare: ' . ((string) ($product->internal_code ?? '') !== '' ? $product->internal_code . ' ยท ' : '') . (string) ($product->name ?? '') : 'Import completato.') ->success() ->send(); $this->refreshRows(); $this->searchAmazonCatalog(); } public function getLavorazioniUrl(): string { return LavorazioniOperative::getUrl(['fornitore' => (int) $this->fornitoreId], panel: 'admin-filament'); } public function getRubricaUrl(): string { return RubricaClienti::getUrl(['fornitore' => (int) $this->fornitoreId], panel: 'admin-filament'); } protected function buildAmazonSearchUrl(string $term): string { $query = ['k' => trim($term)]; $tag = trim((string) config('services.amazon.referral_tag', '')); if ($tag !== '') { $query['tag'] = $tag; } return 'https://www.amazon.it/s?' . http_build_query($query); } }