|null */ public ?array $detailCard = null; /** @var array> */ public array $rows = []; public static function canAccess(): bool { $user = Auth::user(); return $user instanceof User && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore', '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 = trim((string) ($fornitore->ragione_sociale ?: trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? '')))); $this->search = trim((string) request()->query('q', '')); $requestedSerialId = (int) request()->query('seriale', 0); $this->selectedSerialId = $requestedSerialId > 0 ? $requestedSerialId : null; $this->refreshRows(); if ($this->selectedSerialId) { $this->openSerialDetail($this->selectedSerialId); } } public function updatedSearch(): void { $this->refreshRows(); if ($this->selectedSerialId && ! collect($this->rows)->contains(fn(array $row): bool => (int) ($row['id'] ?? 0) === (int) $this->selectedSerialId)) { $this->selectedSerialId = null; $this->detailCard = null; } } public function getProdottiUrl(): string { return ProdottiCatalogo::getUrl(['fornitore' => (int) ($this->fornitoreId ?? 0), 'tab' => 'seriali', 'q' => trim($this->search)], panel: 'admin-filament'); } public function getFornitoreSchedaUrl(): ?string { if (! $this->fornitoreId) { return null; } return \App\Filament\Pages\Gescon\FornitoreScheda::getUrl(['record' => (int) $this->fornitoreId], panel: 'admin-filament'); } public function openSerialDetail(int $serialId): void { if (! $this->fornitoreId) { return; } $fornitore = Fornitore::query()->find((int) $this->fornitoreId); $supplierIds = $fornitore instanceof Fornitore ? $fornitore->catalogScopeSupplierIds() : [(int) $this->fornitoreId]; $serial = ProductSerial::query() ->with([ 'product.identifiers', 'product.offers.fornitore', 'fornitore:id,ragione_sociale,nome,cognome,email,telefono,cellulare', 'legacyScheda', ]) ->whereIn('fornitore_id', $supplierIds) ->find($serialId); if (! $serial instanceof ProductSerial) { $this->selectedSerialId = null; $this->detailCard = null; return; } $invoiceId = null; if (preg_match('/^fe:(\d+)$/', (string) ($serial->source_reference ?? ''), $match)) { $invoiceId = (int) $match[1]; } $fattura = $invoiceId ? FatturaElettronica::query()->find($invoiceId) : null; $legacyScheda = $serial->legacyScheda; $product = $serial->product; $this->selectedSerialId = (int) $serial->id; $this->detailCard = [ 'id' => (int) $serial->id, 'serial_number' => (string) ($serial->serial_number ?? ''), 'serial_number_2' => (string) ($serial->serial_number_2 ?? ''), 'supplier_label' => trim((string) ($serial->fornitore?->ragione_sociale ?: trim(($serial->fornitore?->nome ?? '') . ' ' . ($serial->fornitore?->cognome ?? '')))), 'product_internal_code' => (string) ($product?->internal_code ?? $serial->product_code ?? ''), 'product_name' => (string) ($product?->name ?? $serial->product_model ?? ''), 'product_brand' => (string) ($product?->brand ?? ''), 'product_model' => (string) ($product?->model ?? $serial->product_model ?? ''), 'product_code' => (string) ($serial->product_code ?? ''), 'customer_name' => (string) ($serial->customer_name ?? ''), 'purchase_invoice_ref' => (string) ($serial->purchase_invoice_ref ?? ''), 'purchase_invoice_line' => (int) ($serial->purchase_invoice_line ?? 0), 'purchase_date' => $serial->purchase_date?->format('d/m/Y H:i') ?: '', 'purchase_price' => $serial->purchase_price !== null ? (float) $serial->purchase_price : null, 'purchase_currency' => (string) ($serial->purchase_currency ?? 'EUR'), 'purchase_tax_rate' => $serial->purchase_tax_rate !== null ? (float) $serial->purchase_tax_rate : null, 'date_received' => $serial->date_received?->format('d/m/Y H:i') ?: '', 'date_resold' => $serial->date_resold?->format('d/m/Y H:i') ?: '', 'internal_notes' => (string) ($serial->internal_notes ?? ''), 'source' => (string) ($serial->source ?? ''), 'source_reference' => (string) ($serial->source_reference ?? ''), 'invoice' => $fattura ? [ 'numero' => (string) ($fattura->numero_fattura ?? ''), 'data' => $fattura->data_fattura?->format('d/m/Y') ?: '', 'nome_file' => (string) ($fattura->nome_file_xml ?? ''), 'fornitore_denominazione' => (string) ($fattura->fornitore_denominazione ?? ''), 'totale' => $fattura->totale !== null ? (float) $fattura->totale : null, ] : null, 'legacy' => $legacyScheda ? [ 'numero_scheda' => (string) ($legacyScheda->legacy_numero_scheda ?: $legacyScheda->legacy_id ?: ''), 'status' => (string) ($legacyScheda->status_label ?: $legacyScheda->status_bucket ?: ''), 'customer' => (string) ($legacyScheda->customer_name ?? ''), 'defect' => (string) ($legacyScheda->defect_reported ?? ''), 'repair_description' => (string) ($legacyScheda->repair_description ?? ''), 'communications' => (string) ($legacyScheda->communications ?? ''), ]: null, 'identifiers' => $product ? $product->identifiers ->sortBy(fn($identifier) => sprintf('%s-%s', (string) $identifier->code_type, (string) $identifier->code_value)) ->map(fn($identifier) : array=> [ 'type' => (string) ($identifier->code_type ?? ''), 'role' => (string) ($identifier->code_role ?? ''), 'value' => (string) ($identifier->code_value ?? ''), 'source' => (string) ($identifier->source ?? ''), ]) ->values() ->all() : [], 'offers' => $product ? $product->offers ->sortByDesc(fn($offer) => (string) ($offer->updated_at ?? '')) ->map(fn($offer) : array=> [ 'supplier' => trim((string) ($offer->fornitore?->ragione_sociale ?: trim(($offer->fornitore?->nome ?? '') . ' ' . ($offer->fornitore?->cognome ?? '')))), 'price' => $offer->price_amount !== null ? (float) $offer->price_amount : null, 'currency' => (string) ($offer->currency ?? 'EUR'), 'availability' => (string) ($offer->availability ?? ''), 'external_sku' => (string) ($offer->external_sku ?? ''), ]) ->values() ->all() : [], ]; } private function refreshRows(): void { if (! $this->fornitoreId) { $this->rows = []; return; } $fornitore = Fornitore::query()->find((int) $this->fornitoreId); $supplierIds = $fornitore instanceof Fornitore ? $fornitore->catalogScopeSupplierIds() : [(int) $this->fornitoreId]; $term = trim($this->search); $normalized = preg_replace('/[^A-Za-z0-9]+/', '', strtoupper($term)) ?? ''; $serials = ProductSerial::query() ->with(['product:id,internal_code,name,brand,model', 'fornitore:id,ragione_sociale,nome,cognome']) ->whereIn('fornitore_id', $supplierIds) ->when($term !== '', function (Builder $query) use ($term, $normalized): void { $query->where(function (Builder $builder) use ($term, $normalized): void { $builder->where('serial_number', 'like', '%' . $term . '%') ->orWhere('serial_number_2', 'like', '%' . $term . '%') ->orWhere('product_model', 'like', '%' . $term . '%') ->orWhere('product_code', 'like', '%' . $term . '%') ->orWhere('purchase_invoice_ref', 'like', '%' . $term . '%') ->orWhere('source_reference', 'like', '%' . $term . '%'); if ($normalized !== '') { $builder->orWhereHas('product', function (Builder $productQuery) use ($term, $normalized): void { $productQuery->where('internal_code', 'like', '%' . $term . '%') ->orWhere('name', 'like', '%' . $term . '%') ->orWhereHas('identifiers', function (Builder $identifierQuery) use ($normalized): void { $identifierQuery->where('normalized_code', $normalized) ->orWhere('code_value', 'like', '%' . $normalized . '%'); }); }); } }); }) ->orderByDesc('purchase_date') ->orderByDesc('date_received') ->orderByDesc('id') ->limit(120) ->get(); $this->rows = $serials->map(function (ProductSerial $serial): array { $fornitoreLabel = trim((string) ($serial->fornitore?->ragione_sociale ?: trim(($serial->fornitore?->nome ?? '') . ' ' . ($serial->fornitore?->cognome ?? '')))); return [ 'id' => (int) $serial->id, 'detail_url' => self::getUrl([ 'fornitore' => (int) ($this->fornitoreId ?? 0), 'q' => trim($this->search), 'seriale' => (int) $serial->id, ], panel: 'admin-filament'), 'serial_number' => (string) ($serial->serial_number ?? ''), 'serial_number_2' => (string) ($serial->serial_number_2 ?? ''), 'product_internal_code' => (string) ($serial->product?->internal_code ?? ''), 'product_name' => (string) ($serial->product?->name ?? ''), 'product_model' => (string) ($serial->product_model ?? ''), 'product_code' => (string) ($serial->product_code ?? ''), 'purchase_invoice_ref' => (string) ($serial->purchase_invoice_ref ?? ''), 'purchase_invoice_line' => (int) ($serial->purchase_invoice_line ?? 0), 'purchase_date' => $serial->purchase_date?->format('d/m/Y') ?: '', 'purchase_price' => $serial->purchase_price !== null ? (float) $serial->purchase_price : null, 'purchase_currency' => (string) ($serial->purchase_currency ?? 'EUR'), 'purchase_tax_rate' => $serial->purchase_tax_rate !== null ? (float) $serial->purchase_tax_rate : null, 'date_received' => $serial->date_received?->format('d/m/Y') ?: '', 'date_resold' => $serial->date_resold?->format('d/m/Y') ?: '', 'customer_name' => (string) ($serial->customer_name ?? ''), 'source' => (string) ($serial->source ?? ''), 'source_reference' => (string) ($serial->source_reference ?? ''), 'fornitore_label' => $fornitoreLabel !== '' ? $fornitoreLabel : ('Fornitore #' . (int) $serial->fornitore_id), ]; })->all(); } }