netgescon-day0/app/Filament/Pages/Fornitore/ProdottiCatalogo.php

147 lines
5.3 KiB
PHP

<?php
namespace App\Filament\Pages\Fornitore;
use App\Filament\Pages\Fornitore\Concerns\ResolvesOperatoreContext;
use App\Models\Fornitore;
use App\Models\Product;
use App\Models\ProductIdentifier;
use App\Models\ProductOffer;
use App\Models\User;
use BackedEnum;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
use UnitEnum;
class ProdottiCatalogo extends Page
{
use ResolvesOperatoreContext;
protected static ?string $navigationLabel = 'Prodotti';
protected static ?string $title = 'Catalogo prodotti fornitore';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-archive-box';
protected static UnitEnum|string|null $navigationGroup = 'Fornitore';
protected static ?int $navigationSort = 4;
protected static ?string $slug = 'fornitore/prodotti';
protected string $view = 'filament.pages.fornitore.prodotti-catalogo';
public ?int $fornitoreId = null;
public ?string $fornitoreLabel = null;
public bool $missingAdminContext = false;
public string $search = '';
/** @var array<int, array<string, mixed>> */
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->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 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);
}
}