> */ public array $rows = []; public ?array $detailModal = null; /** @var array */ public array $totals = [ 'tutte' => 0, 'aperte' => 0, 'chiuse' => 0, 'ticket_amministratore' => 0, 'interne' => 0, ]; public static function canAccess(): bool { $user = Auth::user(); return $user instanceof User && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore', 'fornitore']); } public function mount(): void { $this->scope = (string) request()->query('scope', 'tutte'); [$fornitore] = $this->resolveOperatoreContext(allowAdminWithoutSupplier: true); if (! $fornitore instanceof Fornitore) { $this->missingAdminContext = true; return; } $this->fornitoreId = (int) $fornitore->id; $this->fornitoreLabel = $this->getFornitoreLabel($fornitore); $this->refreshData(); } public function updatedScope(): void { $this->refreshData(); } public function setScope(string $scope): void { $this->scope = $scope; $this->refreshData(); } public function refreshData(): void { if (! $this->fornitoreId) { $this->rows = []; return; } [$fornitore, $dipendente] = $this->resolveOperatoreContext($this->fornitoreId); $baseQuery = $this->buildBaseQuery($fornitore, $dipendente); $ticketCount = (clone $baseQuery)->count(); $tecnorepairCount = $this->buildTecnorepairQuery($fornitore)->count(); $this->totals = [ 'tutte' => $ticketCount + $tecnorepairCount, 'aperte' => 0, 'chiuse' => 0, 'ticket_amministratore' => $ticketCount, 'interne' => 0, ]; if ($this->scope === 'interne') { $this->rows = []; return; } $ticketRows = $baseQuery ->limit(120) ->get() ->map(function (TicketIntervento $intervento): array { $base = $this->buildInterventoRow($intervento); return array_merge($base, [ 'row_type' => 'ticket', 'row_class' => $this->resolveTicketRowClass((string) $intervento->stato), 'badge_class' => $this->resolveTicketBadgeClass((string) $intervento->stato), 'is_closed' => $this->isClosedStatus((string) $intervento->stato), 'numero' => (string) $intervento->ticket_id, 'cliente' => $base['contatto'], 'difetto' => $base['problema'], 'brand' => $this->extractDeviceBrand($base['apparato']), 'modello' => $base['apparato'], 'seriale' => '-', 'cod_prodotto' => '-', 'id' => (int) $intervento->id, 'ticket_id' => (int) $intervento->ticket_id, 'titolo' => (string) ($intervento->ticket->titolo ?? '-'), 'stato' => (string) $intervento->stato, 'stabile' => (string) ($intervento->ticket->stabile->denominazione ?? '-'), 'operatore' => (string) $intervento->operatore_assegnato_label, 'tempo_minuti' => (int) ($intervento->tempo_minuti ?? 0), 'updated_at' => optional($intervento->updated_at)->format('d/m/Y H:i') ?: '-', 'sort_at' => optional($intervento->created_at)->format('Y-m-d H:i:s') ?: '1970-01-01 00:00:00', 'origine' => 'Ticket amministratore', 'url' => TicketInterventoScheda::getUrl(['record' => (int) $intervento->id], panel: 'admin-filament'), ]); }) ->all(); $rows = array_merge($ticketRows, $this->buildTecnorepairRows($fornitore)); usort($rows, function (array $left, array $right): int { return strcmp((string) ($right['sort_at'] ?? ''), (string) ($left['sort_at'] ?? '')); }); $this->totals['aperte'] = count(array_filter($rows, fn(array $row): bool => ! (bool) ($row['is_closed'] ?? false))); $this->totals['chiuse'] = count(array_filter($rows, fn(array $row): bool => (bool) ($row['is_closed'] ?? false))); if ($this->scope === 'aperte') { $rows = array_values(array_filter($rows, fn(array $row): bool => ! (bool) ($row['is_closed'] ?? false))); } elseif ($this->scope === 'chiuse') { $rows = array_values(array_filter($rows, fn(array $row): bool => (bool) ($row['is_closed'] ?? false))); } $this->rows = array_slice($rows, 0, 150); } public function openRowDetail(string $rowType, int $rowId): void { if (! $this->fornitoreId) { return; } if ($rowType === 'tecnorepair') { $scheda = AssistenzaTecnorepairScheda::query() ->where('fornitore_id', (int) $this->fornitoreId) ->find($rowId); if (! $scheda instanceof AssistenzaTecnorepairScheda) { return; } $metadata = is_array($scheda->metadata ?? null) ? $scheda->metadata : []; $apparecchio = array_filter([ 'Numero scheda' => (string) ($scheda->legacy_numero_scheda ?: $scheda->legacy_id ?: '-'), 'Codice prodotto' => (string) ($scheda->product_code ?: '-'), 'Modello' => (string) ($scheda->product_model ?: '-'), 'Seriale 1' => (string) ($scheda->serial_number ?: '-'), 'Seriale 2' => (string) ($scheda->serial_number_2 ?: '-'), 'Numero ordine' => (string) ($scheda->order_number ?: '-'), 'RMA' => (string) ($scheda->rma_code ?: '-'), 'PIN' => (string) ($scheda->pin_code ?: '-'), 'Unlock' => (string) ($scheda->unlock_code ?: '-'), ], static fn(string $value): bool => trim($value) !== ''); $this->detailModal = [ 'type' => 'tecnorepair', 'title' => (string) $scheda->display_title, 'status' => (string) ($scheda->status_label ?: $scheda->status_bucket ?: '-'), 'customer' => (string) ($scheda->customer_name ?: 'Cliente TecnoRepair'), 'phone' => (string) ($scheda->customer_phone ?: $scheda->customer_phone_alt ?: ''), 'email' => (string) ($scheda->customer_email ?: ''), 'difetto_segnalato' => (string) ($scheda->defect_reported ?: '-'), 'note_interne' => trim((string) (($metadata['NoteInterne'] ?? $metadata['note_interne'] ?? $scheda->communications) ?: '')), 'note_stampa' => trim((string) (($metadata['NoteStampa'] ?? $metadata['note_stampa'] ?? $scheda->repair_description) ?: '')), 'communications' => (string) ($scheda->communications ?: ''), 'repair_description' => (string) ($scheda->repair_description ?: ''), 'operator' => (string) ($scheda->technician_name ?: $scheda->operator_name ?: '-'), 'updated_at' => optional($scheda->updated_at)->format('d/m/Y H:i') ?: '-', 'apparecchio_fields' => $apparecchio, 'metadata' => $metadata, ]; return; } [$fornitore, $dipendente] = $this->resolveOperatoreContext((int) $this->fornitoreId); $intervento = $this->buildBaseQuery($fornitore, $dipendente)->find($rowId); if (! $intervento instanceof TicketIntervento) { return; } $base = $this->buildInterventoRow($intervento); $this->detailModal = [ 'type' => 'ticket', 'title' => 'Ticket #' . (int) $intervento->ticket_id . ' ยท ' . (string) ($intervento->ticket->titolo ?? '-'), 'status' => (string) $intervento->stato, 'customer' => $base['contatto'], 'phone' => $base['telefono'], 'email' => '', 'difetto_segnalato' => $base['problema'], 'note_interne' => (string) ($intervento->rapporto_fornitore ?? ''), 'note_stampa' => (string) ($intervento->ticket->descrizione ?? ''), 'communications' => '', 'repair_description' => '', 'operator' => (string) $intervento->operatore_assegnato_label, 'updated_at' => optional($intervento->updated_at)->format('d/m/Y H:i') ?: '-', 'url' => TicketInterventoScheda::getUrl(['record' => (int) $intervento->id], panel: 'admin-filament'), 'apparecchio_fields' => [ 'Apparato' => $base['apparato'], 'Stabile' => (string) ($intervento->ticket->stabile->denominazione ?? '-'), ], 'metadata' => [], ]; } public function closeDetailModal(): void { $this->detailModal = null; } public function getTicketsUrl(): string { if ($this->fornitoreId) { return TicketOperativi::getUrl(['fornitore' => $this->fornitoreId], panel: 'admin-filament'); } return TicketOperativi::getUrl(panel: 'admin-filament'); } public function getCollaboratoriUrl(): string { if ($this->fornitoreId) { return Collaboratori::getUrl(['fornitore' => $this->fornitoreId], panel: 'admin-filament'); } return Collaboratori::getUrl(panel: 'admin-filament'); } public function getRubricaUrl(): string { if ($this->fornitoreId) { return RubricaClienti::getUrl(['fornitore' => $this->fornitoreId], panel: 'admin-filament'); } return RubricaClienti::getUrl(panel: 'admin-filament'); } public function getProdottiUrl(): string { if ($this->fornitoreId) { return ProdottiCatalogo::getUrl(['fornitore' => $this->fornitoreId], panel: 'admin-filament'); } return ProdottiCatalogo::getUrl(panel: 'admin-filament'); } public function getImpostazioniUrl(): string { if ($this->fornitoreId) { return ImpostazioniArchivio::getUrl(['fornitore' => $this->fornitoreId], panel: 'admin-filament'); } return ImpostazioniArchivio::getUrl(panel: 'admin-filament'); } protected function buildBaseQuery(Fornitore $fornitore, ?FornitoreDipendente $dipendente): Builder { $query = TicketIntervento::query() ->with(['ticket.stabile', 'ticket.unitaImmobiliare', 'ticket.soggettoRichiedente', 'eseguitoDaDipendente']) ->where('fornitore_id', (int) $fornitore->id) ->orderByDesc('created_at'); if ($dipendente instanceof FornitoreDipendente) { $query->where(function (Builder $builder) use ($dipendente): void { $builder->whereNull('eseguito_da_dipendente_id') ->orWhere('eseguito_da_dipendente_id', (int) $dipendente->id); }); } return $query; } protected function buildTecnorepairQuery(Fornitore $fornitore): Builder { return AssistenzaTecnorepairScheda::query() ->where('fornitore_id', (int) $fornitore->id) ->orderByDesc('date_received') ->orderByDesc('updated_at'); } /** * @return array> */ protected function buildTecnorepairRows(Fornitore $fornitore): array { return $this->buildTecnorepairQuery($fornitore) ->limit(120) ->get() ->map(function (AssistenzaTecnorepairScheda $scheda): array { return [ 'row_type' => 'tecnorepair', 'row_class' => (string) $scheda->row_classes, 'badge_class' => (string) $scheda->status_badge_classes, 'is_closed' => (bool) ($scheda->is_closed ?? false), 'numero' => (string) ($scheda->legacy_numero_scheda ?: $scheda->legacy_id), 'ingresso' => optional($scheda->date_received)->format('d/m/Y') ?: '-', 'cliente' => (string) ($scheda->customer_name ?: 'Cliente TecnoRepair'), 'contatto' => (string) ($scheda->customer_name ?: 'Cliente TecnoRepair'), 'telefono' => (string) ($scheda->customer_phone ?: $scheda->customer_phone_alt ?: ''), 'difetto' => (string) ($scheda->defect_reported ?: '-'), 'problema' => (string) ($scheda->defect_reported ?: '-'), 'brand' => $this->extractDeviceBrand((string) ($scheda->product_model ?: '')), 'apparato' => (string) ($scheda->product_model ?: '-'), 'modello' => (string) ($scheda->product_model ?: '-'), 'seriale' => (string) $scheda->serial_label, 'cod_prodotto' => (string) ($scheda->product_code ?: '-'), 'id' => (int) $scheda->id, 'ticket_id' => null, 'titolo' => (string) $scheda->display_title, 'stato' => (string) ($scheda->status_label ?: $scheda->status_bucket ?: '-'), 'stabile' => 'Archivio TecnoRepair', 'operatore' => (string) ($scheda->technician_name ?: $scheda->operator_name ?: '-'), 'tempo_minuti' => 0, 'updated_at' => optional($scheda->updated_at)->format('d/m/Y H:i') ?: '-', 'sort_at' => optional($scheda->date_received ?? $scheda->updated_at)->format('Y-m-d H:i:s') ?: '1970-01-01 00:00:00', 'origine' => 'TecnoRepair MDB', 'url' => null, ]; }) ->all(); } protected function resolveTicketRowClass(string $status): string { $status = strtolower(trim($status)); return match (true) { in_array($status, ['chiuso', 'fatturato'], true) => 'bg-emerald-50/70 hover:bg-emerald-50', in_array($status, ['fatturabile', 'verifica'], true) => 'bg-amber-50/70 hover:bg-amber-50', default => 'bg-sky-50/60 hover:bg-sky-50', }; } protected function resolveTicketBadgeClass(string $status): string { $status = strtolower(trim($status)); return match (true) { in_array($status, ['chiuso', 'fatturato'], true) => 'border-emerald-200 bg-emerald-50 text-emerald-800', in_array($status, ['fatturabile', 'verifica'], true) => 'border-amber-200 bg-amber-50 text-amber-800', default => 'border-sky-200 bg-sky-50 text-sky-800', }; } protected function isClosedStatus(string $status): bool { $status = strtolower(trim($status)); return str_contains($status, 'chius') || str_contains($status, 'fatturat') || str_contains($status, 'riconsegn') || str_contains($status, 'riparato') || str_contains($status, 'acquisto'); } protected function extractDeviceBrand(string $label): string { $label = trim($label); if ($label === '' || $label === '-') { return '-'; } $parts = preg_split('/\s+/', $label) ?: []; $first = trim((string) ($parts[0] ?? '')); return $first !== '' ? strtoupper($first) : '-'; } }