From 7c74942d0f402465a6d90c794196327c094f2ac8 Mon Sep 17 00:00:00 2001 From: michele Date: Sat, 11 Apr 2026 10:09:42 +0000 Subject: [PATCH] Reorganize supplier scheda and harden legacy support flows --- CHANGELOG.md | 1 + .../ImportLegacyFornitoriTagsCommand.php | 59 ++++++--- app/Console/Commands/SmdrListenCommand.php | 45 ++++++- .../Pages/Fornitore/RubricaClienti.php | 9 ++ app/Filament/Pages/Gescon/FornitoreScheda.php | 19 +++ .../Pages/Strumenti/PostItGestione.php | 120 ++++++++++++++++-- .../pages/fornitore/rubrica-clienti.blade.php | 12 +- .../ticket-intervento-scheda.blade.php | 1 + .../pages/gescon/fornitore-scheda.blade.php | 83 +++++++++--- ...ministratore-operativita-accessi.blade.php | 12 +- .../strumenti/post-it-gestione.blade.php | 6 +- 11 files changed, 314 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 713e692..8247027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ # Changelog ## [Unreleased] - Initial open-source release prep. +- Reorganized the supplier scheda into operational tabs, linked supplier rubrica-clienti back to anagrafica unica, fixed the supplier ticket-intervento Blade parse error, and hardened legacy supplier matching plus SMDR/Post-it labeling for Git-first rollout. - Reworked Supporto > Aggiornamento Nodo to show local/remote commit dates, explicit pending commit counts, and a clear note that Git updates do not move storage archives or private uploaded data. - Reorganized the Importazione Archivi operational tab so the action buttons come first, followed by the explanatory blocks and command fields. - Removed active-stabile filtering from topbar avvisi/urgenze counters and from the Google ticket-operativi box so cross-stabile operational tickets stay visible. diff --git a/app/Console/Commands/ImportLegacyFornitoriTagsCommand.php b/app/Console/Commands/ImportLegacyFornitoriTagsCommand.php index 695e1f1..65c1b13 100644 --- a/app/Console/Commands/ImportLegacyFornitoriTagsCommand.php +++ b/app/Console/Commands/ImportLegacyFornitoriTagsCommand.php @@ -250,20 +250,6 @@ private function resolveLocalFornitore(object $legacy): ?Fornitore $cf = trim((string) ($legacy->codice_fiscale ?? '')); $ragione = trim((string) ($legacy->ragione_sociale ?? '')); - if ($legacyId > 0) { - $found = Fornitore::query()->where('old_id', $legacyId)->first(); - if ($found instanceof Fornitore) { - return $found; - } - } - - if ($legacyCod !== '' && ctype_digit($legacyCod)) { - $found = Fornitore::query()->where('old_id', (int) $legacyCod)->first(); - if ($found instanceof Fornitore) { - return $found; - } - } - if ($piva !== '') { $found = Fornitore::query()->where('partita_iva', $piva)->first(); if ($found instanceof Fornitore) { @@ -284,11 +270,54 @@ private function resolveLocalFornitore(object $legacy): ?Fornitore $normalizedRagione = $this->normalizeComparableString($ragione); if ($normalizedRagione !== '') { - return Fornitore::query() + $found = Fornitore::query() ->get(['id', 'ragione_sociale']) ->first(function (Fornitore $fornitore) use ($normalizedRagione): bool { return $this->normalizeComparableString((string) ($fornitore->ragione_sociale ?? '')) === $normalizedRagione; }); + if ($found instanceof Fornitore) { + return $found; + } + } + + return $this->resolveLocalFornitoreByLegacyIds($legacyId, $legacyCod, $piva, $cf, $normalizedRagione); + } + + private function resolveLocalFornitoreByLegacyIds(int $legacyId, string $legacyCod, string $piva, string $cf, string $normalizedRagione): ?Fornitore + { + $candidateIds = collect([ + $legacyId > 0 ? $legacyId : null, + ($legacyCod !== '' && ctype_digit($legacyCod)) ? (int) $legacyCod : null, + ]) + ->filter(fn($value): bool => is_int($value) && $value > 0) + ->unique() + ->values(); + + foreach ($candidateIds as $candidateId) { + $matches = Fornitore::query() + ->where('old_id', (int) $candidateId) + ->get(['id', 'partita_iva', 'codice_fiscale', 'ragione_sociale']); + + if ($matches->count() === 1) { + return $matches->first(); + } + + $filtered = $matches->filter(function (Fornitore $fornitore) use ($piva, $cf, $normalizedRagione): bool { + if ($piva !== '' && trim((string) ($fornitore->partita_iva ?? '')) === $piva) { + return true; + } + + if ($cf !== '' && trim((string) ($fornitore->codice_fiscale ?? '')) === $cf) { + return true; + } + + return $normalizedRagione !== '' + && $this->normalizeComparableString((string) ($fornitore->ragione_sociale ?? '')) === $normalizedRagione; + })->values(); + + if ($filtered->count() === 1) { + return $filtered->first(); + } } return null; diff --git a/app/Console/Commands/SmdrListenCommand.php b/app/Console/Commands/SmdrListenCommand.php index 9f0d91f..9f16f93 100644 --- a/app/Console/Commands/SmdrListenCommand.php +++ b/app/Console/Commands/SmdrListenCommand.php @@ -3,6 +3,7 @@ use App\Models\ChiamataPostIt; use App\Models\CommunicationMessage; +use App\Services\Anagrafiche\RubricaPhoneLookupService; use App\Services\Cti\PbxRoutingService; use Carbon\Carbon; use Illuminate\Console\Command; @@ -243,15 +244,17 @@ public function handle(): int if ($writePostIt && Schema::hasTable('chiamate_post_it') && $this->shouldCreateOperationalPostIt($parsed)) { try { - $lineSuffix = ! empty($parsed['co']) ? ' - linea ' . (string) $parsed['co'] : ''; + $lineLabel = $this->resolveDisplayLineLabel($parsed, $routing); + $lineSuffix = $lineLabel !== '' ? ' - linea ' . $lineLabel : ''; $isMissedResponseGroup = $this->isMissedResponseGroupCall($parsed, $routing); + $caller = $this->resolveCallerDisplay($phone, $amministratoreId); ChiamataPostIt::query()->create([ 'telefono' => $phone, - 'stabile_id' => $stabileId, + 'stabile_id' => $caller['has_rubrica'] ? $stabileId : null, 'creato_da_user_id' => $assignedUserId, - 'nome_chiamante' => 'SMDR INBOUND', + 'nome_chiamante' => $caller['label'], 'oggetto' => 'Chiamata in entrata da SMDR' . $lineSuffix, 'nota' => $line, 'direzione' => 'in_arrivo', @@ -292,6 +295,42 @@ public function handle(): int } while (true); } + /** + * @return array{label:string,has_rubrica:bool} + */ + private function resolveCallerDisplay(?string $phone, ?int $amministratoreId): array + { + $digits = preg_replace('/\D+/', '', (string) $phone) ?: ''; + if ($digits === '') { + return ['label' => 'Contatto non in Rubrica', 'has_rubrica' => false]; + } + + $rubrica = app(RubricaPhoneLookupService::class)->findByPhone($digits, (int) ($amministratoreId ?? 0)); + if ($rubrica) { + $label = trim((string) ($rubrica->ragione_sociale ?: (($rubrica->nome ?? '') . ' ' . ($rubrica->cognome ?? '')))); + if ($label !== '') { + return ['label' => $label, 'has_rubrica' => true]; + } + } + + return ['label' => 'Contatto non in Rubrica', 'has_rubrica' => false]; + } + + private function resolveDisplayLineLabel(array $parsed, array $routing): string + { + $lineLabel = trim((string) ($routing['line_label'] ?? '')); + if ($lineLabel !== '') { + return $lineLabel; + } + + $rawLine = preg_replace('/\D+/', '', (string) ($parsed['co'] ?? '')) ?: ''; + if ($rawLine === '') { + return ''; + } + + return self::CO_PUBLIC_LINES[$rawLine] ?? (string) ($parsed['co'] ?? ''); + } + private function parseSmdrLine(string $line): ?array { $normalized = trim((string) preg_replace('/^\[\d+\]\s*/', '', $line)); diff --git a/app/Filament/Pages/Fornitore/RubricaClienti.php b/app/Filament/Pages/Fornitore/RubricaClienti.php index 531d061..80a82ea 100644 --- a/app/Filament/Pages/Fornitore/RubricaClienti.php +++ b/app/Filament/Pages/Fornitore/RubricaClienti.php @@ -2,6 +2,7 @@ namespace App\Filament\Pages\Fornitore; use App\Filament\Pages\Fornitore\Concerns\ResolvesOperatoreContext; +use App\Filament\Pages\Gescon\RubricaUniversaleScheda; use App\Models\Fornitore; use App\Models\TicketIntervento; use App\Models\User; @@ -118,6 +119,8 @@ public function refreshRows(): void 'email' => $contact['email'], 'stabile' => $contact['stabile'], 'origine' => $contact['origine'], + 'rubrica_url' => $contact['rubrica_url'], + 'rubrica_label' => $contact['rubrica_label'], 'ultimo_ticket_id' => (int) $intervento->ticket_id, 'ultima_scheda_url' => TicketInterventoScheda::getUrl(['record' => (int) $intervento->id], panel: 'admin-filament'), 'updated_at' => optional($intervento->updated_at)->format('d/m/Y H:i') ?: '-', @@ -164,6 +167,8 @@ protected function resolveCallerDataForRubrica(TicketIntervento $intervento): ar $telefono = $parsed['telefono']; $email = ''; $origine = 'Descrizione ticket'; + $rubricaUrl = null; + $rubricaLabel = ''; if ($ticket?->soggettoRichiedente) { $soggetto = $ticket->soggettoRichiedente; @@ -171,6 +176,8 @@ protected function resolveCallerDataForRubrica(TicketIntervento $intervento): ar $telefono = trim((string) ($soggetto->telefono ?? '')) ?: $telefono; $email = trim((string) ($soggetto->email ?? '')); $origine = 'Richiedente ticket'; + $rubricaUrl = RubricaUniversaleScheda::getUrl(['record' => (int) $soggetto->id], panel: 'admin-filament'); + $rubricaLabel = trim((string) ($soggetto->categoria ?? '')); } elseif ($ticket?->apertoDaUser) { $contatto = trim((string) ($ticket->apertoDaUser->name ?? '')) ?: $contatto; $email = trim((string) ($ticket->apertoDaUser->email ?? '')); @@ -192,6 +199,8 @@ protected function resolveCallerDataForRubrica(TicketIntervento $intervento): ar 'email' => $email, 'origine' => $origine, 'stabile' => (string) ($ticket?->stabile?->denominazione ?? '-'), + 'rubrica_url' => $rubricaUrl, + 'rubrica_label'=> $rubricaLabel, 'identity_key' => $identityKey, ]; } diff --git a/app/Filament/Pages/Gescon/FornitoreScheda.php b/app/Filament/Pages/Gescon/FornitoreScheda.php index 647814b..e91f185 100644 --- a/app/Filament/Pages/Gescon/FornitoreScheda.php +++ b/app/Filament/Pages/Gescon/FornitoreScheda.php @@ -100,6 +100,8 @@ class FornitoreScheda extends Page public ?int $dipendenteRubricaId = null; + public string $sectionTab = 'profilo'; + /** @var array> */ public array $dipendenteRubricaMatches = []; @@ -194,6 +196,23 @@ public function mount(int | string $record): void $this->loadTagSuggestions(); $this->refreshDipendentiRows(); $this->refreshCatalogRows(); + + $requestedTab = (string) request()->query('tab', 'profilo'); + if ($this->isValidSectionTab($requestedTab)) { + $this->sectionTab = $requestedTab; + } + } + + public function setSectionTab(string $tab): void + { + if ($this->isValidSectionTab($tab)) { + $this->sectionTab = $tab; + } + } + + private function isValidSectionTab(string $tab): bool + { + return in_array($tab, ['profilo', 'accessi', 'assistenza', 'catalogo', 'contabilita'], true); } public function creaDipendenteFornitore(): void diff --git a/app/Filament/Pages/Strumenti/PostItGestione.php b/app/Filament/Pages/Strumenti/PostItGestione.php index cf12b00..e9224f6 100644 --- a/app/Filament/Pages/Strumenti/PostItGestione.php +++ b/app/Filament/Pages/Strumenti/PostItGestione.php @@ -9,6 +9,7 @@ use App\Models\Ticket; use App\Models\User; use App\Services\Anagrafiche\RubricaPhoneLookupService; +use App\Services\Cti\PbxRoutingService; use BackedEnum; use Filament\Notifications\Notification; use Filament\Pages\Page; @@ -20,6 +21,16 @@ class PostItGestione extends Page { + /** @var array */ + private const SMDR_PUBLIC_LINE_FALLBACKS = [ + '1' => '0639731100', + '01' => '0639731100', + '0001' => '0639731100', + '3' => '0688812703', + '03' => '0688812703', + '0003' => '0688812703', + ]; + protected static ?string $title = 'Post-it Gestione'; protected static ?string $navigationLabel = 'Post-it Gestione'; @@ -508,6 +519,7 @@ public function creaPostItDaMessaggio(int $messageId): void $phone = (string) ($message->phone_number ?: ($smdr['dial_number'] ?? '')); $nominativo = $this->getTecnicoNominativo($message); $lineLabel = $this->getTecnicoLineaLabel($message); + $callerLabel = $this->resolveTecnicoCallerLabel($message, $phone, $nominativo); $direction = match (strtolower(trim((string) $message->direction))) { 'inbound' => 'Chiamata ricevuta', 'outbound' => 'Chiamata effettuata', @@ -534,10 +546,10 @@ public function creaPostItDaMessaggio(int $messageId): void } $postIt = ChiamataPostIt::query()->create([ - 'stabile_id' => $message->stabile_id, + 'stabile_id' => $this->resolveOperationalPostItStabileId($message, $phone), 'creato_da_user_id' => Auth::id(), - 'telefono' => $message->phone_number, - 'nome_chiamante' => $nominativo ?: ($phone !== '' ? $phone : ($sourceLabel . ' ' . strtoupper((string) $message->direction))), + 'telefono' => $phone !== '' ? $phone : $message->phone_number, + 'nome_chiamante' => $callerLabel !== '' ? $callerLabel : ($sourceLabel . ' ' . strtoupper((string) $message->direction)), 'direzione' => $this->normalizePostItDirection((string) $message->direction), 'origine' => $sourceKey . '_table', 'origine_id' => (string) $message->id, @@ -634,8 +646,7 @@ public function getTecnicoProviderLabel(CommunicationMessage $message): string public function getTecnicoLineaLabel(CommunicationMessage $message): string { if ((string) $message->channel === 'smdr') { - $line = trim((string) data_get($message->metadata, 'smdr.co', '')); - return $line !== '' ? $line : '-'; + return $this->resolveSmdrLineLabel($message); } $eventType = trim((string) data_get($message->metadata, 'event_type', '')); @@ -645,6 +656,24 @@ public function getTecnicoLineaLabel(CommunicationMessage $message): string return $parts !== [] ? implode(' / ', $parts) : '-'; } + public function shouldShowPostItStabile(ChiamataPostIt $postIt): bool + { + if (! $postIt->stabile) { + return false; + } + + if ($this->resolveGroupedRubricaId($postIt)) { + return true; + } + + $message = $this->resolveMessageFromPostIt($postIt); + if ($message instanceof CommunicationMessage && ! $this->isInternalSmdrMessage($message)) { + return false; + } + + return ! $this->isGenericCallerLabel((string) ($postIt->nome_chiamante ?? ''), (string) ($postIt->telefono ?? '')); + } + private function matchesTecnicoLineFilter(CommunicationMessage $message, string $filter): bool { $needle = mb_strtolower(trim($filter)); @@ -817,12 +846,12 @@ private function resolveGroupedCallerLabel(array $items): string } $label = trim((string) ($item->nome_chiamante ?? '')); - if ($label !== '') { + if ($label !== '' && ! $this->isGenericCallerLabel($label, (string) ($item->telefono ?? ''))) { return $label; } } - return 'Chiamante non identificato'; + return 'Contatto non in Rubrica'; } private function resolveGroupedPhoneLabel(array $items): string @@ -895,6 +924,79 @@ private function buildGroupedCollection($items) ->values(); } + private function resolveOperationalPostItStabileId(CommunicationMessage $message, string $phone): ?int + { + if ($this->isInternalSmdrMessage($message)) { + return (int) ($message->stabile_id ?? 0) ?: null; + } + + if ($this->resolveRubricaIdByPhone($phone)) { + return (int) ($message->stabile_id ?? 0) ?: null; + } + + return null; + } + + private function resolveTecnicoCallerLabel(CommunicationMessage $message, string $phone, ?string $nominativo): string + { + $label = trim((string) $nominativo); + if ($label !== '') { + return $label; + } + + if ($this->isInternalSmdrMessage($message)) { + $extension = $this->extractExtensionFromMessage($message); + + return $extension ? 'Interno ' . $extension : 'Interno PBX'; + } + + return 'Contatto non in Rubrica'; + } + + private function resolveSmdrLineLabel(CommunicationMessage $message): string + { + $stored = trim((string) data_get($message->metadata, 'smdr.line_label', '')); + if ($stored !== '') { + return $stored; + } + + $rawLine = trim((string) data_get($message->metadata, 'smdr.co', '')); + if ($rawLine === '') { + return '-'; + } + + $routing = app(PbxRoutingService::class)->resolveByIncomingLine($rawLine); + $lineLabel = trim((string) ($routing['line_label'] ?? '')); + if ($lineLabel !== '') { + return $lineLabel; + } + + $normalized = app(PbxRoutingService::class)->normalizeLineNumber($rawLine); + + return self::SMDR_PUBLIC_LINE_FALLBACKS[$normalized] ?? $rawLine; + } + + private function isGenericCallerLabel(string $label, string $phone = ''): bool + { + $normalizedLabel = mb_strtolower(trim($label)); + if ($normalizedLabel === '') { + return true; + } + + if (in_array($normalizedLabel, ['chiamante non identificato', 'contatto non in rubrica'], true)) { + return true; + } + + if (str_starts_with($normalizedLabel, 'smdr ') || str_starts_with($normalizedLabel, 'panasonic cti ')) { + return true; + } + + $labelDigits = preg_replace('/\D+/', '', $label) ?: ''; + $phoneDigits = preg_replace('/\D+/', '', $phone) ?: ''; + + return $labelDigits !== '' && $phoneDigits !== '' && $labelDigits === $phoneDigits; + } + public function richiediClickToCallDaMessaggio(int $messageId): void { $user = Auth::user(); @@ -1044,8 +1146,8 @@ private function resolveRubricaIdByPhone(?string $phone): ?int return $this->rubricaPhoneCache[$digits]; } - $adminId = (int) (Auth::user()?->amministratore?->id ?? 0); - $result = app(RubricaPhoneLookupService::class)->findByPhone($digits, $adminId)?->id; + $adminId = (int) (Auth::user()?->amministratore?->id ?? 0); + $result = app(RubricaPhoneLookupService::class)->findByPhone($digits, $adminId)?->id; $result = is_numeric($result) ? (int) $result : null; $this->rubricaPhoneCache[$digits] = $result; diff --git a/resources/views/filament/pages/fornitore/rubrica-clienti.blade.php b/resources/views/filament/pages/fornitore/rubrica-clienti.blade.php index 8ff935f..0089b89 100644 --- a/resources/views/filament/pages/fornitore/rubrica-clienti.blade.php +++ b/resources/views/filament/pages/fornitore/rubrica-clienti.blade.php @@ -6,7 +6,7 @@
Rubrica clienti fornitore
@if($this->fornitoreLabel) - Contatti emersi dai ticket e dalle lavorazioni di {{ $this->fornitoreLabel }}. + Contatti emersi dai ticket e dalle lavorazioni di {{ $this->fornitoreLabel }}, agganciati quando possibile all'anagrafica unica. @else Seleziona un fornitore per aprire la rubrica clienti. @endif @@ -19,6 +19,10 @@
+
+ Questa vista resta stretta sui contatti del singolo fornitore, ma il punto di verità anagrafico rimane la scheda dell'anagrafica unica. Da qui puoi filtrare i contatti operativi e saltare direttamente sulla scheda condivisa quando il legame esiste gia. +
+ @if($this->missingAdminContext)
Questa vista richiede un fornitore selezionato. @@ -38,10 +42,16 @@
{{ $row['contatto'] }}
Origine: {{ $row['origine'] }} · Interventi: {{ $row['totale_interventi'] }}
+ @if($row['rubrica_url']) +
Anagrafica unica collegata{{ $row['rubrica_label'] !== '' ? ' · ' . $row['rubrica_label'] : '' }}
+ @endif
Stabile: {{ $row['stabile'] }}
Ultimo aggiornamento: {{ $row['updated_at'] }}
+ @if($row['rubrica_url']) + Scheda anagrafica + @endif @if($row['telefono'] !== '') Chiama @endif diff --git a/resources/views/filament/pages/fornitore/ticket-intervento-scheda.blade.php b/resources/views/filament/pages/fornitore/ticket-intervento-scheda.blade.php index d645e09..c44b872 100644 --- a/resources/views/filament/pages/fornitore/ticket-intervento-scheda.blade.php +++ b/resources/views/filament/pages/fornitore/ticket-intervento-scheda.blade.php @@ -151,6 +151,7 @@ @endif
+ @endif
{{ $ticket->descrizione }}
diff --git a/resources/views/filament/pages/gescon/fornitore-scheda.blade.php b/resources/views/filament/pages/gescon/fornitore-scheda.blade.php index 4217577..9fce986 100644 --- a/resources/views/filament/pages/gescon/fornitore-scheda.blade.php +++ b/resources/views/filament/pages/gescon/fornitore-scheda.blade.php @@ -1,7 +1,57 @@ + @php + $tabs = [ + 'profilo' => 'Dati condivisi', + 'accessi' => 'Dipendenti e accessi', + 'assistenza' => 'Assistenza interna', + 'catalogo' => 'Catalogo e prodotti', + 'contabilita' => 'Contabilita', + ]; + @endphp + +
+
+
+
+
Scheda fornitore
+
La scheda e divisa in tab operative per separare dati condivisi, accessi, assistenza, catalogo e contabilita senza perdere il contesto del fornitore.
+
+
+
Fornitore
+
{{ $fornitore->ragione_sociale ?? trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? '')) ?: ('Fornitore #' . $fornitore->id) }}
+
+
+ +
+ @foreach($tabs as $tabKey => $tabLabel) + + @endforeach +
+
+ +
+ Qui restano visibili modulo fornitore e catalogo operativo. Il magazzino e la gestione completa del prodotto possono essere spostati in menu dedicati mantenendo qui il quadro sintetico e i collegamenti rapidi. +
+ +
+ Questa tab concentra TecnoRepair, seriali e automazioni collegate al fornitore. I ticket operativi e il protocollo comunicazioni possono poi evolvere come viste dedicate, senza ricadere in una scheda unica confusa. +
+ +
+ Qui si prepara il perimetro economico del fornitore: pagamenti, fatture, anteprime contabili e ritenute. Preventivi, ordini e fatturazione completa possono innestarsi in questa area senza mischiarsi con catalogo o assistenza. +
+
-
+
Fornitore
Codice: {{ $fornitore->codice_univoco ?? '-' }}
@@ -15,7 +65,7 @@
-
+
Contatti
@@ -43,7 +93,7 @@
-
+
Dipendenti e accessi fornitore
La gestione accessi dei dipendenti fornitore e centralizzata qui.
@@ -168,7 +218,7 @@
-
+
Modulo fornitore separato
@@ -220,7 +270,7 @@
-
+
Catalogo operativo interno
@@ -352,7 +402,7 @@
-
+
Pagamenti
IBAN: {{ $fornitore->iban ?? '-' }}
@@ -361,7 +411,7 @@
-
+
Anagrafica unica (Rubrica)
@if($fornitore->rubrica)
@@ -375,7 +425,7 @@ @endif
-
+
TAG Fornitore
Digita tag separati da virgola. Premi TAB per accettare il suggerimento corrente e aggiungere automaticamente una virgola.
@@ -415,7 +465,7 @@ class="w-full rounded-lg border-gray-300 text-sm" $acquaScan = (bool) ($acqua['scan_enabled'] ?? false); @endphp -
+
TecnoRepair / seriali
@@ -468,7 +518,7 @@ class="w-full rounded-lg border-gray-300 text-sm"
-
+
Automazioni / Consumi
Configura acquisizione dati (PDF) e scansione massiva sulle FE già importate.
@@ -500,7 +550,7 @@ class="w-full rounded-lg border-gray-300 text-sm"
-
+
Fatture (stabile attivo)
@@ -562,7 +612,7 @@ class="text-sm font-medium text-primary-600 hover:underline"
-
+
Anteprima AdE
@if(!empty($anteprimaAde))
@@ -581,7 +631,7 @@ class="text-sm font-medium text-primary-600 hover:underline" @endif
-
+
Anteprima FE
@if(!empty($anteprimaFe))
@@ -605,7 +655,7 @@ class="block rounded-md px-2 py-1 hover:bg-gray-50" @endif
-
+
Anteprima contabilità
@if(!empty($anteprimaContabilita))
@@ -629,7 +679,7 @@ class="block rounded-md px-2 py-1 hover:bg-gray-50" @endif
-
+
Fatture associate (fornitore)
@if(!empty($fattureAssociate))
@@ -656,7 +706,7 @@ class="block rounded-md px-2 py-1 hover:bg-gray-50" @endif
-
+
RA versate/compensate
@if(!empty($raVersateRows))
@@ -678,6 +728,7 @@ class="block rounded-md px-2 py-1 hover:bg-gray-50"
+