mountInteractsWithTable(); } protected function getTableQuery(): Builder { $user = Auth::user(); if (! $user instanceof User) { return RubricaUniversale::query()->whereRaw('1 = 0'); } $activeStabile = StabileContext::getActiveStabile($user); $adminId = (int) ($activeStabile?->amministratore_id ?: 0); if ($adminId <= 0) { return RubricaUniversale::query()->whereRaw('1 = 0'); } $query = RubricaUniversale::query(); // Tenant-aware: limita ai contatti appartenenti allo stesso amministratore. // Include: rubrica_universale.amministratore_id, collegamento via fornitori/stabili, e contatti con ruoli su stabili dell'admin. $query->where(function (Builder $q) use ($adminId): void { // Seed per evitare `OR ...` come prima condizione del gruppo. $q->whereRaw('1 = 0'); if (Schema::hasColumn('rubrica_universale', 'amministratore_id')) { $q->orWhere('rubrica_universale.amministratore_id', $adminId); } if (Schema::hasTable('fornitori')) { $q->orWhereExists(function ($sub) use ($adminId) { $sub->select(DB::raw(1)) ->from('fornitori as f') ->whereColumn('f.rubrica_id', 'rubrica_universale.id') ->where('f.amministratore_id', $adminId); }); } if (Schema::hasTable('stabili') && Schema::hasColumn('stabili', 'rubrica_id')) { $q->orWhereExists(function ($sub) use ($adminId) { $sub->select(DB::raw(1)) ->from('stabili as s') ->whereColumn('s.rubrica_id', 'rubrica_universale.id') ->where('s.amministratore_id', $adminId); }); } if (Schema::hasTable('rubrica_ruoli') && Schema::hasTable('stabili')) { $q->orWhereExists(function ($sub) use ($adminId) { $sub->select(DB::raw(1)) ->from('rubrica_ruoli as rr') ->join('stabili as s2', 's2.id', '=', 'rr.stabile_id') ->whereColumn('rr.rubrica_id', 'rubrica_universale.id') ->where('s2.amministratore_id', $adminId); }); } }); // Nascondi contatti completamente vuoti (tipicamente creati da import difettosi). $query->where(function (Builder $q): void { $q->whereNotNull('ragione_sociale')->where('ragione_sociale', '!=', '') ->orWhereNotNull('cognome')->where('cognome', '!=', '') ->orWhereNotNull('nome')->where('nome', '!=', '') ->orWhereNotNull('codice_fiscale')->where('codice_fiscale', '!=', '') ->orWhereNotNull('partita_iva')->where('partita_iva', '!=', '') ->orWhereNotNull('email')->where('email', '!=', '') ->orWhereNotNull('pec')->where('pec', '!=', '') ->orWhereNotNull('telefono_ufficio')->where('telefono_ufficio', '!=', '') ->orWhereNotNull('telefono_cellulare')->where('telefono_cellulare', '!=', '') ->orWhereNotNull('telefono_casa')->where('telefono_casa', '!=', ''); }); return $query->orderBy('ragione_sociale')->orderBy('cognome')->orderBy('nome'); } public function table(Table $table): Table { return $table ->striped() ->columns([ TextColumn::make('codice_univoco')->label('Codice')->sortable()->searchable()->toggleable(), TextColumn::make('nome_completo') ->label('Nominativo') ->wrap() ->searchable(query: function (Builder $query, string $search): Builder { $search = trim($search); if ($search === '') { return $query; } $like = '%' . str_replace(['%', '_'], ['\\%', '\\_'], $search) . '%'; return $query->where(function (Builder $q) use ($like) { $q->where('ragione_sociale', 'like', $like) ->orWhere('nome', 'like', $like) ->orWhere('cognome', 'like', $like) ->orWhereRaw("TRIM(CONCAT(COALESCE(nome, ''), ' ', COALESCE(cognome, ''))) LIKE ?", [$like]); }); }), TextColumn::make('categoria')->label('Categoria')->sortable()->toggleable(), TextColumn::make('partita_iva')->label('P.IVA')->searchable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('codice_fiscale')->label('CF')->searchable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('email')->label('Email')->searchable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('pec')->label('PEC')->searchable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('telefono_ufficio')->label('Tel.')->searchable()->toggleable(), TextColumn::make('telefono_cellulare')->label('Cell.')->searchable()->toggleable(), TextColumn::make('telefono_casa')->label('Tel. casa')->searchable()->toggleable(isToggledHiddenByDefault: true), TextColumn::make('stato')->label('Stato')->sortable()->toggleable(isToggledHiddenByDefault: true), ]) ->actions([ Action::make('modifica') ->label('Modifica') ->icon('heroicon-o-pencil-square') ->modalHeading('Modifica contatto') ->fillForm(fn(RubricaUniversale $record): array => [ 'ragione_sociale' => $record->ragione_sociale, 'nome' => $record->nome, 'cognome' => $record->cognome, 'codice_fiscale' => $record->codice_fiscale, 'partita_iva' => $record->partita_iva, 'email' => $record->email, 'pec' => $record->pec, 'telefono_ufficio' => $record->telefono_ufficio, 'telefono_cellulare' => $record->telefono_cellulare, 'telefono_casa' => $record->telefono_casa, 'indirizzo' => $record->indirizzo, 'cap' => $record->cap, 'citta' => $record->citta, 'provincia' => $record->provincia, 'note' => $record->note, ]) ->form([ TextInput::make('ragione_sociale')->label('Ragione sociale')->maxLength(255), TextInput::make('nome')->maxLength(255), TextInput::make('cognome')->maxLength(255), TextInput::make('codice_fiscale')->label('Codice fiscale')->maxLength(32), TextInput::make('partita_iva')->label('Partita IVA')->maxLength(32), TextInput::make('email')->email()->maxLength(255), TextInput::make('pec')->maxLength(255), TextInput::make('telefono_ufficio')->label('Telefono')->maxLength(64), TextInput::make('telefono_cellulare')->label('Cellulare')->maxLength(64), TextInput::make('telefono_casa')->label('Telefono casa')->maxLength(64), TextInput::make('indirizzo')->maxLength(255), TextInput::make('cap')->maxLength(20), TextInput::make('citta')->maxLength(255), TextInput::make('provincia')->maxLength(10), Textarea::make('note')->rows(3), ]) ->action(function (RubricaUniversale $record, array $data): void { $record->fill($data); if ($record->isDirty()) { $record->save(); } }), Action::make('apri_scheda') ->label('Apri scheda') ->icon('heroicon-o-identification') ->url(fn(RubricaUniversale $record) => RubricaUniversaleScheda::getUrl(['record' => $record->id], panel: 'admin-filament')), ]); } public function makeFilamentTranslatableContentDriver(): ?TranslatableContentDriver { return null; } }