881 lines
34 KiB
PHP
881 lines
34 KiB
PHP
<?php
|
|
namespace App\Filament\Pages\Gescon;
|
|
|
|
use App\Models\Fornitore;
|
|
use App\Models\FornitoreDipendente;
|
|
use App\Models\RubricaUniversale;
|
|
use App\Models\User;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Support\Str;
|
|
use UnitEnum;
|
|
|
|
class FornitoriArchivio extends Page
|
|
{
|
|
public int $fornitoriCount = 0;
|
|
public string $fornitoriSearch = '';
|
|
public string $activeTab = 'elenco';
|
|
public ?int $selectedFornitoreId = null;
|
|
|
|
/** @var Collection<int, Fornitore> */
|
|
public $fornitoreMatches;
|
|
|
|
/** @var array<string, string> */
|
|
public array $automazioni = [
|
|
'fornitore_acqua' => '0',
|
|
'abilita_ticket' => '1',
|
|
'abilita_allegati_camera' => '1',
|
|
];
|
|
|
|
public ?string $contoIban = null;
|
|
public ?string $contoIntestazioneEsatta = null;
|
|
public string $dipendentiRubricaSearch = '';
|
|
|
|
public string $searchInput = '';
|
|
|
|
public string $editRagioneSociale = '';
|
|
public string $editTitolo = '';
|
|
public string $editNome = '';
|
|
public string $editCognome = '';
|
|
public string $editEmail = '';
|
|
public string $editPec = '';
|
|
public string $editTelefono = '';
|
|
public string $editCellulare = '';
|
|
public string $editPartitaIva = '';
|
|
public string $editCodiceFiscale = '';
|
|
public string $editSitoWeb = '';
|
|
public string $editTags = '';
|
|
public string $editNote = '';
|
|
|
|
public string $newFornitoreRagioneSociale = '';
|
|
public string $newFornitoreNome = '';
|
|
public string $newFornitoreCognome = '';
|
|
public string $newFornitoreEmail = '';
|
|
public string $newFornitoreTelefono = '';
|
|
public string $newFornitorePartitaIva = '';
|
|
public string $newFornitoreCodiceFiscale = '';
|
|
|
|
public string $newDipendenteNome = '';
|
|
public string $newDipendenteCognome = '';
|
|
public string $newDipendenteEmail = '';
|
|
public string $newDipendenteTelefono = '';
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $dipendenteInline = [];
|
|
|
|
protected static ?string $navigationLabel = 'Fornitori';
|
|
|
|
protected static ?string $title = 'Fornitori';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-building-storefront';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'NetGescon';
|
|
|
|
protected static ?int $navigationSort = 12;
|
|
|
|
protected static ?string $slug = 'gescon/anagrafica/fornitori';
|
|
|
|
protected string $view = 'filament.pages.gescon.table';
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
return $user instanceof User
|
|
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
try {
|
|
$this->fornitoriCount = (int) $this->getTableQuery()->count();
|
|
} catch (\Throwable) {
|
|
$this->fornitoriCount = 0;
|
|
}
|
|
|
|
$this->fornitoreMatches = new Collection();
|
|
$this->searchInput = $this->fornitoriSearch;
|
|
$this->searchFornitoreMatches();
|
|
}
|
|
|
|
protected function getTableQuery(): Builder
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return Fornitore::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin'])) {
|
|
return Fornitore::query();
|
|
}
|
|
|
|
$amministratoreId = $user->amministratore?->id;
|
|
if (! $amministratoreId) {
|
|
$stabile = StabileContext::getActiveStabile($user);
|
|
$amministratoreId = $stabile?->amministratore_id;
|
|
}
|
|
|
|
if (! $amministratoreId) {
|
|
return Fornitore::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
return Fornitore::query()->where('amministratore_id', (int) $amministratoreId);
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, Fornitore>
|
|
*/
|
|
public function getFornitoriRowsProperty(): Collection
|
|
{
|
|
$query = $this->getTableQuery()
|
|
->withCount('dipendenti')
|
|
->orderBy('ragione_sociale')
|
|
->orderBy('cognome')
|
|
->orderBy('nome');
|
|
|
|
$this->applyFornitoreSearch($query, trim($this->fornitoriSearch));
|
|
|
|
return $query->limit(400)->get();
|
|
}
|
|
|
|
public function updatedFornitoriSearch(): void
|
|
{
|
|
$this->searchInput = $this->fornitoriSearch;
|
|
$this->searchFornitoreMatches();
|
|
}
|
|
|
|
public function updatedSearchInput(): void
|
|
{
|
|
$this->fornitoriSearch = trim($this->searchInput);
|
|
$this->searchFornitoreMatches();
|
|
}
|
|
|
|
public function getFornitoreLabel(Fornitore $fornitore): string
|
|
{
|
|
$label = trim((string) ($fornitore->ragione_sociale ?: trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? ''))));
|
|
|
|
return $label !== '' ? $label : ('Fornitore #' . $fornitore->id);
|
|
}
|
|
|
|
public function getFornitoreHubUrl(int $fornitoreId): string
|
|
{
|
|
return FornitoreScheda::getUrl(['record' => $fornitoreId], panel: 'admin-filament');
|
|
}
|
|
|
|
public function getFornitoreAnagraficaUrl(int $fornitoreId): string
|
|
{
|
|
return url('/admin-filament/anagrafica/fornitori/' . $fornitoreId);
|
|
}
|
|
|
|
public function getSelectedFornitoreProperty(): ?Fornitore
|
|
{
|
|
if ((int) ($this->selectedFornitoreId ?? 0) <= 0) {
|
|
return null;
|
|
}
|
|
|
|
return $this->getTableQuery()
|
|
->with(['rubrica', 'dipendenti.user'])
|
|
->withCount('dipendenti')
|
|
->find((int) $this->selectedFornitoreId);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
public function getActiveSearchFiltersProperty(): array
|
|
{
|
|
return $this->extractSearchTokens((string) $this->fornitoriSearch);
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, FornitoreDipendente>
|
|
*/
|
|
public function getDipendentiRowsProperty(): Collection
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
return new Collection();
|
|
}
|
|
|
|
return FornitoreDipendente::query()
|
|
->with('user')
|
|
->where('fornitore_id', (int) $fornitore->id)
|
|
->orderByDesc('attivo')
|
|
->orderBy('cognome')
|
|
->orderBy('nome')
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, RubricaUniversale>
|
|
*/
|
|
public function getRubricaDipendentiCandidatesProperty(): Collection
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
return new Collection();
|
|
}
|
|
|
|
$query = RubricaUniversale::query()
|
|
->whereNull('deleted_at')
|
|
->where(function (Builder $q): void {
|
|
$q->where('tipo_contatto', 'persona_fisica')
|
|
->orWhereNull('tipo_contatto');
|
|
})
|
|
->where(function (Builder $q): void {
|
|
$q->whereNotNull('nome')
|
|
->where('nome', '!=', '')
|
|
->orWhereNotNull('cognome')
|
|
->where('cognome', '!=', '')
|
|
->orWhereNotNull('email')
|
|
->where('email', '!=', '');
|
|
});
|
|
|
|
if (Schema::hasColumn('rubrica_universale', 'amministratore_id')) {
|
|
$adminId = (int) ($fornitore->amministratore_id ?? 0);
|
|
if ($adminId > 0) {
|
|
$query->where(function (Builder $q) use ($adminId): void {
|
|
$q->where('amministratore_id', $adminId)
|
|
->orWhereNull('amministratore_id');
|
|
});
|
|
}
|
|
}
|
|
|
|
$term = trim($this->dipendentiRubricaSearch);
|
|
if ($term !== '') {
|
|
$tokens = $this->extractSearchTokens($term);
|
|
foreach ($tokens as $token) {
|
|
$like = '%' . $token . '%';
|
|
$query->where(function (Builder $sub) use ($like): void {
|
|
$sub->where('nome', 'like', $like)
|
|
->orWhere('cognome', 'like', $like)
|
|
->orWhere('ragione_sociale', 'like', $like)
|
|
->orWhere('email', 'like', $like)
|
|
->orWhere('telefono_cellulare', 'like', $like)
|
|
->orWhere('telefono_ufficio', 'like', $like)
|
|
->orWhere('codice_fiscale', 'like', $like);
|
|
});
|
|
}
|
|
}
|
|
|
|
return $query
|
|
->orderBy('cognome')
|
|
->orderBy('nome')
|
|
->limit(80)
|
|
->get(['id', 'nome', 'cognome', 'ragione_sociale', 'email', 'telefono_cellulare', 'telefono_ufficio', 'codice_fiscale']);
|
|
}
|
|
|
|
public function apriElenco(): void
|
|
{
|
|
$this->activeTab = 'elenco';
|
|
}
|
|
|
|
public function apriNuovoFornitore(): void
|
|
{
|
|
$this->selectedFornitoreId = null;
|
|
$this->activeTab = 'scheda';
|
|
}
|
|
|
|
public function apriTabScheda(): void
|
|
{
|
|
if ((int) ($this->selectedFornitoreId ?? 0) <= 0) {
|
|
Notification::make()
|
|
->title('Seleziona prima un fornitore dalla Tab 1')
|
|
->warning()
|
|
->send();
|
|
$this->activeTab = 'elenco';
|
|
return;
|
|
}
|
|
|
|
$this->hydrateSchedaFromSelected();
|
|
$this->activeTab = 'scheda';
|
|
}
|
|
|
|
public function apriTabDipendenti(): void
|
|
{
|
|
if ((int) ($this->selectedFornitoreId ?? 0) <= 0) {
|
|
Notification::make()
|
|
->title('Seleziona prima un fornitore dalla Tab 1')
|
|
->warning()
|
|
->send();
|
|
$this->activeTab = 'elenco';
|
|
return;
|
|
}
|
|
|
|
$this->hydrateSchedaFromSelected();
|
|
$this->activeTab = 'dipendenti';
|
|
}
|
|
|
|
public function applicaRicerca(): void
|
|
{
|
|
$this->fornitoriSearch = trim($this->searchInput);
|
|
$this->searchFornitoreMatches();
|
|
$this->activeTab = 'elenco';
|
|
}
|
|
|
|
public function pulisciRicerca(): void
|
|
{
|
|
$this->fornitoriSearch = '';
|
|
$this->searchInput = '';
|
|
$this->searchFornitoreMatches();
|
|
$this->activeTab = 'elenco';
|
|
}
|
|
|
|
public function removeSearchFilter(string $token): void
|
|
{
|
|
$tokens = array_values(array_filter(
|
|
$this->extractSearchTokens((string) $this->fornitoriSearch),
|
|
static fn(string $value): bool => mb_strtolower($value) !== mb_strtolower($token)
|
|
));
|
|
|
|
$this->fornitoriSearch = implode(' e ', $tokens);
|
|
$this->searchInput = $this->fornitoriSearch;
|
|
$this->searchFornitoreMatches();
|
|
$this->activeTab = 'elenco';
|
|
}
|
|
|
|
public function apriScheda(int $fornitoreId): void
|
|
{
|
|
$fornitore = $this->getTableQuery()->find($fornitoreId);
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Fornitore non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$this->selectedFornitoreId = (int) $fornitore->id;
|
|
$this->activeTab = 'scheda';
|
|
$this->loadSchedaState($fornitore);
|
|
$this->loadDipendentiInlineState();
|
|
}
|
|
|
|
public function updatedSelectedFornitoreId(): void
|
|
{
|
|
if (in_array($this->activeTab, ['scheda', 'dipendenti'], true)) {
|
|
$this->hydrateSchedaFromSelected();
|
|
}
|
|
}
|
|
|
|
public function createFornitoreRapido(): void
|
|
{
|
|
$adminId = $this->resolveAmministratoreId();
|
|
if ($adminId <= 0) {
|
|
Notification::make()->title('Amministratore non risolto')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$data = Validator::make([
|
|
'ragione_sociale' => trim($this->newFornitoreRagioneSociale),
|
|
'nome' => trim($this->newFornitoreNome),
|
|
'cognome' => trim($this->newFornitoreCognome),
|
|
'email' => trim($this->newFornitoreEmail),
|
|
'telefono' => trim($this->newFornitoreTelefono),
|
|
'partita_iva' => trim($this->newFornitorePartitaIva),
|
|
'codice_fiscale' => trim($this->newFornitoreCodiceFiscale),
|
|
], [
|
|
'ragione_sociale' => ['nullable', 'string', 'max:255'],
|
|
'nome' => ['nullable', 'string', 'max:255'],
|
|
'cognome' => ['nullable', 'string', 'max:255'],
|
|
'email' => ['nullable', 'email', 'max:255'],
|
|
'telefono' => ['nullable', 'string', 'max:64'],
|
|
'partita_iva' => ['nullable', 'string', 'max:32'],
|
|
'codice_fiscale' => ['nullable', 'string', 'max:32'],
|
|
])->validate();
|
|
|
|
if (($data['ragione_sociale'] ?? '') === '' && (($data['nome'] ?? '') === '' && ($data['cognome'] ?? '') === '')) {
|
|
Notification::make()->title('Inserisci almeno ragione sociale o nominativo')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$fornitore = Fornitore::query()->create([
|
|
'amministratore_id' => $adminId,
|
|
'ragione_sociale' => $this->cleanNullable($data['ragione_sociale'] ?? null),
|
|
'nome' => $this->cleanNullable($data['nome'] ?? null),
|
|
'cognome' => $this->cleanNullable($data['cognome'] ?? null),
|
|
'email' => $this->cleanNullable($data['email'] ?? null),
|
|
'telefono' => $this->cleanNullable($data['telefono'] ?? null),
|
|
'partita_iva' => $this->cleanNullable($data['partita_iva'] ?? null),
|
|
'codice_fiscale' => $this->cleanNullable($data['codice_fiscale'] ?? null),
|
|
]);
|
|
|
|
$this->newFornitoreRagioneSociale = '';
|
|
$this->newFornitoreNome = '';
|
|
$this->newFornitoreCognome = '';
|
|
$this->newFornitoreEmail = '';
|
|
$this->newFornitoreTelefono = '';
|
|
$this->newFornitorePartitaIva = '';
|
|
$this->newFornitoreCodiceFiscale = '';
|
|
|
|
$this->fornitoriCount = (int) $this->getTableQuery()->count();
|
|
$this->apriScheda((int) $fornitore->id);
|
|
$this->searchInput = $this->getFornitoreLabel($fornitore);
|
|
$this->fornitoriSearch = $this->searchInput;
|
|
$this->searchFornitoreMatches();
|
|
|
|
Notification::make()->title('Fornitore creato')->success()->send();
|
|
}
|
|
|
|
public function saveSchedaAnagrafica(): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona un fornitore')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$data = Validator::make([
|
|
'ragione_sociale' => trim($this->editRagioneSociale),
|
|
'titolo' => trim($this->editTitolo),
|
|
'nome' => trim($this->editNome),
|
|
'cognome' => trim($this->editCognome),
|
|
'email' => trim($this->editEmail),
|
|
'pec' => trim($this->editPec),
|
|
'telefono' => trim($this->editTelefono),
|
|
'cellulare' => trim($this->editCellulare),
|
|
'partita_iva' => trim($this->editPartitaIva),
|
|
'codice_fiscale' => trim($this->editCodiceFiscale),
|
|
'sito_web' => trim($this->editSitoWeb),
|
|
'tags' => trim($this->editTags),
|
|
'note' => trim($this->editNote),
|
|
], [
|
|
'ragione_sociale' => ['nullable', 'string', 'max:255'],
|
|
'titolo' => ['nullable', 'string', 'max:50'],
|
|
'nome' => ['nullable', 'string', 'max:255'],
|
|
'cognome' => ['nullable', 'string', 'max:255'],
|
|
'email' => ['nullable', 'email', 'max:255'],
|
|
'pec' => ['nullable', 'email', 'max:255'],
|
|
'telefono' => ['nullable', 'string', 'max:64'],
|
|
'cellulare' => ['nullable', 'string', 'max:64'],
|
|
'partita_iva' => ['nullable', 'string', 'max:32'],
|
|
'codice_fiscale' => ['nullable', 'string', 'max:32'],
|
|
'sito_web' => ['nullable', 'string', 'max:255'],
|
|
'tags' => ['nullable', 'string', 'max:1000'],
|
|
'note' => ['nullable', 'string', 'max:5000'],
|
|
])->validate();
|
|
|
|
$fornitore->ragione_sociale = $this->cleanNullable($data['ragione_sociale'] ?? null);
|
|
if (Schema::hasColumn('fornitori', 'titolo')) {
|
|
$fornitore->titolo = $this->cleanNullable($data['titolo'] ?? null);
|
|
}
|
|
$fornitore->nome = $this->cleanNullable($data['nome'] ?? null);
|
|
$fornitore->cognome = $this->cleanNullable($data['cognome'] ?? null);
|
|
$fornitore->email = $this->cleanNullable($data['email'] ?? null);
|
|
$fornitore->pec = $this->cleanNullable($data['pec'] ?? null);
|
|
$fornitore->telefono = $this->cleanNullable($data['telefono'] ?? null);
|
|
$fornitore->cellulare = $this->cleanNullable($data['cellulare'] ?? null);
|
|
$fornitore->partita_iva = $this->cleanNullable($data['partita_iva'] ?? null);
|
|
$fornitore->codice_fiscale = $this->cleanNullable($data['codice_fiscale'] ?? null);
|
|
$fornitore->sito_web = $this->cleanNullable($data['sito_web'] ?? null);
|
|
$fornitore->tags = $this->cleanNullable($data['tags'] ?? null);
|
|
$fornitore->note = $this->cleanNullable($data['note'] ?? null);
|
|
$fornitore->save();
|
|
|
|
$this->loadSchedaState($fornitore->fresh());
|
|
$this->searchFornitoreMatches();
|
|
Notification::make()->title('Anagrafica fornitore aggiornata')->success()->send();
|
|
}
|
|
|
|
public function addDipendenteManuale(): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona un fornitore')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$nome = trim($this->newDipendenteNome);
|
|
$email = trim($this->newDipendenteEmail);
|
|
if ($nome === '') {
|
|
Notification::make()->title('Nome dipendente obbligatorio')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
if ($email !== '') {
|
|
$exists = FornitoreDipendente::query()
|
|
->where('fornitore_id', (int) $fornitore->id)
|
|
->whereRaw('LOWER(email) = ?', [mb_strtolower($email)])
|
|
->exists();
|
|
if ($exists) {
|
|
Notification::make()->title('Dipendente con stessa email gia presente')->warning()->send();
|
|
return;
|
|
}
|
|
}
|
|
|
|
FornitoreDipendente::query()->create([
|
|
'fornitore_id' => (int) $fornitore->id,
|
|
'nome' => $nome,
|
|
'cognome' => $this->cleanNullable($this->newDipendenteCognome),
|
|
'email' => $this->cleanNullable($email),
|
|
'telefono' => $this->cleanNullable($this->newDipendenteTelefono),
|
|
'attivo' => true,
|
|
'created_by_user_id' => Auth::id(),
|
|
'updated_by_user_id' => Auth::id(),
|
|
]);
|
|
|
|
$this->newDipendenteNome = '';
|
|
$this->newDipendenteCognome = '';
|
|
$this->newDipendenteEmail = '';
|
|
$this->newDipendenteTelefono = '';
|
|
$this->loadDipendentiInlineState();
|
|
|
|
Notification::make()->title('Dipendente aggiunto')->success()->send();
|
|
}
|
|
|
|
public function createDipendenteRubricaAndLink(): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona prima un fornitore')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$nome = trim($this->newDipendenteNome);
|
|
if ($nome === '') {
|
|
Notification::make()->title('Nome nominativo obbligatorio')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$rubrica = RubricaUniversale::query()->create([
|
|
'nome' => $nome,
|
|
'cognome' => $this->cleanNullable($this->newDipendenteCognome),
|
|
'email' => $this->cleanNullable($this->newDipendenteEmail),
|
|
'telefono_cellulare' => $this->cleanNullable($this->newDipendenteTelefono),
|
|
'tipo_contatto' => 'persona_fisica',
|
|
'categoria' => 'fornitore',
|
|
'stato' => 'attivo',
|
|
'note' => 'Creato da Fornitori > Dipendenti per il fornitore #' . (int) $fornitore->id,
|
|
'data_inserimento' => now()->toDateString(),
|
|
'data_ultima_modifica' => now()->toDateString(),
|
|
'creato_da' => Auth::id(),
|
|
'modificato_da' => Auth::id(),
|
|
]);
|
|
|
|
$this->addDipendenteFromRubrica((int) $rubrica->id);
|
|
}
|
|
|
|
public function addDipendenteFromRubrica(int $rubricaId): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona prima un fornitore')->warning()->send();
|
|
$this->activeTab = 'elenco';
|
|
return;
|
|
}
|
|
|
|
$rubrica = RubricaUniversale::query()->find((int) $rubricaId);
|
|
if (! $rubrica instanceof RubricaUniversale) {
|
|
Notification::make()->title('Contatto rubrica non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$email = trim((string) ($rubrica->email ?? ''));
|
|
$nome = trim((string) ($rubrica->nome ?? ''));
|
|
$cognome = trim((string) ($rubrica->cognome ?? ''));
|
|
$telefono = trim((string) ($rubrica->telefono_cellulare ?: $rubrica->telefono_ufficio ?: ''));
|
|
|
|
if ($nome === '' && $cognome === '') {
|
|
$fromRs = trim((string) ($rubrica->ragione_sociale ?? ''));
|
|
if ($fromRs !== '') {
|
|
$nome = $fromRs;
|
|
} else {
|
|
Notification::make()->title('Rubrica senza nominativo utile')->warning()->send();
|
|
return;
|
|
}
|
|
}
|
|
|
|
$exists = FornitoreDipendente::query()
|
|
->where('fornitore_id', (int) $fornitore->id)
|
|
->where(function (Builder $q) use ($email, $nome, $cognome, $telefono): void {
|
|
if ($email !== '') {
|
|
$q->orWhereRaw('LOWER(email) = ?', [mb_strtolower($email)]);
|
|
}
|
|
|
|
$full = mb_strtolower(trim($nome . ' ' . $cognome));
|
|
if ($full !== '') {
|
|
$q->orWhereRaw("LOWER(TRIM(CONCAT(COALESCE(nome, ''), ' ', COALESCE(cognome, '')))) = ?", [$full]);
|
|
}
|
|
|
|
if ($telefono !== '') {
|
|
$normalized = preg_replace('/\D+/', '', $telefono) ?? '';
|
|
if ($normalized !== '') {
|
|
$q->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono, ''), ' ', ''), '-', ''), '.', ''), '(', ''), ')', '') = ?", [$normalized]);
|
|
}
|
|
}
|
|
})
|
|
->exists();
|
|
|
|
if ($exists) {
|
|
Notification::make()->title('Dipendente gia collegato a questo fornitore')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$dipendente = new FornitoreDipendente();
|
|
$dipendente->fornitore_id = (int) $fornitore->id;
|
|
$dipendente->nome = $nome;
|
|
$dipendente->cognome = $cognome !== '' ? $cognome : null;
|
|
$dipendente->email = $email !== '' ? $email : null;
|
|
$dipendente->telefono = $telefono !== '' ? $telefono : null;
|
|
$dipendente->attivo = true;
|
|
$dipendente->created_by_user_id = Auth::id();
|
|
$dipendente->updated_by_user_id = Auth::id();
|
|
|
|
$existingNote = trim((string) ($rubrica->note ?? ''));
|
|
$linkNote = 'Agganciato da rubrica ID #' . (int) $rubrica->id;
|
|
$dipendente->note = Str::limit(trim($linkNote . ($existingNote !== '' ? (' | ' . $existingNote) : '')), 2000, '');
|
|
$dipendente->save();
|
|
|
|
$this->loadDipendentiInlineState();
|
|
|
|
Notification::make()->title('Dipendente collegato al fornitore')->success()->send();
|
|
$this->activeTab = 'dipendenti';
|
|
}
|
|
|
|
public function saveDipendenteInline(int $dipendenteId): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona prima un fornitore')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$dipendente = FornitoreDipendente::query()
|
|
->where('fornitore_id', (int) $fornitore->id)
|
|
->find($dipendenteId);
|
|
|
|
if (! $dipendente instanceof FornitoreDipendente) {
|
|
Notification::make()->title('Dipendente non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$state = $this->dipendenteInline[$dipendenteId] ?? [];
|
|
$data = Validator::make($state, [
|
|
'nome' => ['required', 'string', 'max:255'],
|
|
'cognome' => ['nullable', 'string', 'max:255'],
|
|
'email' => ['nullable', 'email', 'max:255'],
|
|
'telefono' => ['nullable', 'string', 'max:64'],
|
|
'attivo' => ['nullable', 'boolean'],
|
|
])->validate();
|
|
|
|
$dipendente->nome = trim((string) ($data['nome'] ?? ''));
|
|
$dipendente->cognome = $this->cleanNullable($data['cognome'] ?? null);
|
|
$dipendente->email = $this->cleanNullable($data['email'] ?? null);
|
|
$dipendente->telefono = $this->cleanNullable($data['telefono'] ?? null);
|
|
$dipendente->attivo = (bool) ($data['attivo'] ?? false);
|
|
$dipendente->updated_by_user_id = Auth::id();
|
|
$dipendente->save();
|
|
|
|
$this->loadDipendentiInlineState();
|
|
|
|
Notification::make()->title('Dipendente aggiornato')->success()->send();
|
|
}
|
|
|
|
public function saveSchedaAutomazioni(): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona un fornitore')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$features = is_array($fornitore->fe_features ?? null) ? $fornitore->fe_features : [];
|
|
$features['automazioni'] = [
|
|
'fornitore_acqua' => ($this->automazioni['fornitore_acqua'] ?? '0') === '1',
|
|
'abilita_ticket' => ($this->automazioni['abilita_ticket'] ?? '0') === '1',
|
|
'abilita_allegati_camera' => ($this->automazioni['abilita_allegati_camera'] ?? '0') === '1',
|
|
];
|
|
|
|
$fornitore->fe_features = $features;
|
|
$fornitore->save();
|
|
|
|
Notification::make()->title('Automazioni aggiornate')->success()->send();
|
|
}
|
|
|
|
public function saveSchedaBancaria(): void
|
|
{
|
|
$fornitore = $this->selectedFornitore;
|
|
if (! $fornitore instanceof Fornitore) {
|
|
Notification::make()->title('Seleziona un fornitore')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$fornitore->iban = $this->cleanNullable($this->contoIban);
|
|
$fornitore->intestazione_cc_esatta = $this->cleanNullable($this->contoIntestazioneEsatta);
|
|
$fornitore->save();
|
|
|
|
Notification::make()->title('Dati conto aggiornati')->success()->send();
|
|
}
|
|
|
|
private function loadSchedaState(Fornitore $fornitore): void
|
|
{
|
|
$features = is_array($fornitore->fe_features ?? null) ? $fornitore->fe_features : [];
|
|
$auto = (array) ($features['automazioni'] ?? []);
|
|
|
|
$this->automazioni = [
|
|
'fornitore_acqua' => ! empty($auto['fornitore_acqua']) ? '1' : '0',
|
|
'abilita_ticket' => ! empty($auto['abilita_ticket']) ? '1' : '0',
|
|
'abilita_allegati_camera' => ! empty($auto['abilita_allegati_camera']) ? '1' : '0',
|
|
];
|
|
|
|
$this->contoIban = is_string($fornitore->iban) ? $fornitore->iban : null;
|
|
$this->contoIntestazioneEsatta = is_string($fornitore->intestazione_cc_esatta ?? null)
|
|
? $fornitore->intestazione_cc_esatta
|
|
: null;
|
|
|
|
$this->editRagioneSociale = (string) ($fornitore->ragione_sociale ?? '');
|
|
$this->editTitolo = Schema::hasColumn('fornitori', 'titolo')
|
|
? (string) ($fornitore->titolo ?? '')
|
|
: '';
|
|
$this->editNome = (string) ($fornitore->nome ?? '');
|
|
$this->editCognome = (string) ($fornitore->cognome ?? '');
|
|
$this->editEmail = (string) ($fornitore->email ?? '');
|
|
$this->editPec = (string) ($fornitore->pec ?? '');
|
|
$this->editTelefono = (string) ($fornitore->telefono ?? '');
|
|
$this->editCellulare = (string) ($fornitore->cellulare ?? '');
|
|
$this->editPartitaIva = (string) ($fornitore->partita_iva ?? '');
|
|
$this->editCodiceFiscale = (string) ($fornitore->codice_fiscale ?? '');
|
|
$this->editSitoWeb = (string) ($fornitore->sito_web ?? '');
|
|
$this->editTags = (string) ($fornitore->tags ?? '');
|
|
$this->editNote = (string) ($fornitore->note ?? '');
|
|
}
|
|
|
|
private function loadDipendentiInlineState(): void
|
|
{
|
|
$rows = $this->getDipendentiRowsProperty();
|
|
|
|
$this->dipendenteInline = $rows->mapWithKeys(function (FornitoreDipendente $dipendente): array {
|
|
return [
|
|
(int) $dipendente->id => [
|
|
'nome' => (string) ($dipendente->nome ?? ''),
|
|
'cognome' => (string) ($dipendente->cognome ?? ''),
|
|
'email' => (string) ($dipendente->email ?? ''),
|
|
'telefono' => (string) ($dipendente->telefono ?? ''),
|
|
'attivo' => (bool) ($dipendente->attivo ?? false),
|
|
],
|
|
];
|
|
})->all();
|
|
}
|
|
|
|
private function resolveAmministratoreId(): int
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return 0;
|
|
}
|
|
|
|
$adminId = (int) ($user->amministratore?->id ?? 0);
|
|
if ($adminId > 0) {
|
|
return $adminId;
|
|
}
|
|
|
|
$stabile = StabileContext::getActiveStabile($user);
|
|
return (int) ($stabile?->amministratore_id ?? 0);
|
|
}
|
|
|
|
public function hydrateSchedaFromSelected(): void
|
|
{
|
|
if ((int) ($this->selectedFornitoreId ?? 0) <= 0) {
|
|
return;
|
|
}
|
|
|
|
$fornitore = $this->getTableQuery()->find((int) $this->selectedFornitoreId);
|
|
if (! $fornitore instanceof Fornitore) {
|
|
return;
|
|
}
|
|
|
|
$this->loadSchedaState($fornitore);
|
|
$this->loadDipendentiInlineState();
|
|
}
|
|
|
|
private function applyFornitoreSearch(Builder $query, string $raw): Builder
|
|
{
|
|
$tokens = $this->extractSearchTokens($raw);
|
|
if ($tokens === []) {
|
|
return $query;
|
|
}
|
|
$hasTags = Schema::hasColumn('fornitori', 'tags');
|
|
|
|
foreach ($tokens as $token) {
|
|
$term = trim($token);
|
|
if ($term === '') {
|
|
continue;
|
|
}
|
|
|
|
$digits = preg_replace('/\D+/', '', $term) ?: '';
|
|
$needleText = '%' . mb_strtolower($term) . '%';
|
|
$needle = '%' . $digits . '%';
|
|
|
|
$query->where(function (Builder $sub) use ($needleText, $needle, $digits, $hasTags): void {
|
|
$sub->whereRaw("LOWER(COALESCE(ragione_sociale, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(nome, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(cognome, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(email, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(partita_iva, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(codice_fiscale, '')) LIKE ?", [$needleText]);
|
|
|
|
if ($hasTags) {
|
|
$sub->orWhereRaw("LOWER(COALESCE(tags, '')) LIKE ?", [$needleText]);
|
|
}
|
|
|
|
if ($digits !== '') {
|
|
$sub->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", [$needle])
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(cellulare, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", [$needle]);
|
|
}
|
|
});
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
private function searchFornitoreMatches(): void
|
|
{
|
|
$raw = trim($this->searchInput !== '' ? $this->searchInput : $this->fornitoriSearch);
|
|
if ($raw === '') {
|
|
$this->fornitoreMatches = new Collection();
|
|
return;
|
|
}
|
|
|
|
$query = $this->getTableQuery()
|
|
->withCount('dipendenti')
|
|
->orderByRaw('CASE WHEN id = ? THEN 0 ELSE 1 END', [(int) ($this->selectedFornitoreId ?? 0)])
|
|
->orderBy('ragione_sociale')
|
|
->orderBy('cognome')
|
|
->orderBy('nome');
|
|
|
|
$this->fornitoreMatches = $this->applyFornitoreSearch($query, $raw)
|
|
->limit(12)
|
|
->get();
|
|
}
|
|
|
|
private function cleanNullable(?string $value): ?string
|
|
{
|
|
$value = trim((string) $value);
|
|
return $value !== '' ? $value : null;
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
private function extractSearchTokens(string $raw): array
|
|
{
|
|
$term = trim(preg_replace('/\s+/', ' ', $raw) ?? '');
|
|
if ($term === '') {
|
|
return [];
|
|
}
|
|
|
|
$hasLogicalSeparator = preg_match('/[,;|+]|\s(?:e|ed|and)\s/ui', $term) === 1;
|
|
if (! $hasLogicalSeparator) {
|
|
return [$term];
|
|
}
|
|
|
|
$parts = preg_split('/(?:[,;|+]|\s(?:e|ed|and)\s)+/ui', $term) ?: [];
|
|
$parts = array_values(array_filter(array_map(static fn(string $value): string => trim($value), $parts), static fn(string $value): bool => $value !== ''));
|
|
|
|
return $parts !== [] ? array_values(array_unique($parts)) : [$term];
|
|
}
|
|
}
|