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

277 lines
13 KiB
PHP
Executable File

<?php
namespace App\Filament\Pages\Fornitore;
use App\Filament\Pages\Fornitore\Concerns\ResolvesOperatoreContext;
use App\Models\FatturaElettronica;
use App\Models\Fornitore;
use App\Models\ProductSerial;
use App\Models\User;
use BackedEnum;
use Filament\Pages\Page;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use UnitEnum;
class SerialiCatalogo extends Page
{
use ResolvesOperatoreContext;
protected static ?string $navigationLabel = 'Seriali';
protected static ?string $title = 'Ricerca seriali fornitore';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-qr-code';
protected static UnitEnum|string|null $navigationGroup = 'Fornitore';
protected static ?int $navigationSort = 5;
protected static ?string $slug = 'fornitore/seriali';
protected string $view = 'filament.pages.fornitore.seriali-catalogo';
public ?int $fornitoreId = null;
public ?string $fornitoreLabel = null;
public bool $missingAdminContext = false;
public string $search = '';
public ?int $selectedSerialId = null;
/** @var array<string, mixed>|null */
public ?array $detailCard = null;
/** @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', '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();
}
}