1755 lines
73 KiB
PHP
1755 lines
73 KiB
PHP
<?php
|
|
namespace App\Filament\Pages\Gescon;
|
|
|
|
use App\Models\Fornitore;
|
|
use App\Models\FornitoreDipendente;
|
|
use App\Models\Persona;
|
|
use App\Models\PersonaEmailMultipla;
|
|
use App\Models\RubricaContattoCanale;
|
|
use App\Models\RubricaRuolo;
|
|
use App\Models\RubricaUniversale;
|
|
use App\Models\Stabile;
|
|
use App\Models\Titolo;
|
|
use App\Models\UnitaImmobiliare;
|
|
use App\Models\User;
|
|
use App\Support\StabileContext;
|
|
use Filament\Actions\Action;
|
|
use Filament\Forms\Components\DatePicker;
|
|
use Filament\Forms\Components\Hidden;
|
|
use Filament\Forms\Components\Repeater;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Components\Toggle;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilderContract;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Str;
|
|
|
|
class RubricaUniversaleScheda extends Page
|
|
{
|
|
protected static ?string $title = 'Scheda anagrafica (Rubrica)';
|
|
|
|
protected static ?string $slug = 'gescon/anagrafica/rubrica/{record}';
|
|
|
|
protected static bool $shouldRegisterNavigation = false;
|
|
|
|
protected string $view = 'filament.pages.gescon.rubrica-universale-scheda';
|
|
|
|
public RubricaUniversale $rubrica;
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $fornitori = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $stabili = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $contattiPrincipali = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $ruoliAttivi = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $cronistoriaRuoli = [];
|
|
|
|
public int $adminId = 0;
|
|
|
|
public ?int $prevRecordId = null;
|
|
|
|
public ?int $nextRecordId = null;
|
|
|
|
public int $navPerPage = 25;
|
|
|
|
public int $navPage = 1;
|
|
|
|
public int $navPages = 1;
|
|
|
|
/** @var array<int, int> */
|
|
public array $adminStabileIds = [];
|
|
|
|
public bool $isInlineEditing = false;
|
|
|
|
public string $sideTab = 'collegamenti';
|
|
|
|
/** @var array<int,array<string,mixed>> */
|
|
public array $fornitoriCollegati = [];
|
|
|
|
/** @var array<int,array<string,mixed>> */
|
|
public array $dipendentiFornitoreRows = [];
|
|
|
|
/** @var array<int,int|string> */
|
|
public array $dipendenteRubricaSelect = [];
|
|
|
|
/** @var array<int,array<string,string>> */
|
|
public array $dipendenteManualDraft = [];
|
|
|
|
/** @var array<int,string> */
|
|
public array $dipendentePbxExtension = [];
|
|
|
|
/** @var array<string,mixed> */
|
|
public array $inlineForm = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $emailMultiple = [];
|
|
|
|
public function mount(int | string $record): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
abort(403);
|
|
}
|
|
|
|
if (! $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore'])) {
|
|
abort(403);
|
|
}
|
|
|
|
$this->rubrica = RubricaUniversale::query()->findOrFail((int) $record);
|
|
|
|
$activeStabile = StabileContext::getActiveStabile($user);
|
|
$adminId = (int) ($activeStabile?->amministratore_id ?: 0);
|
|
$this->adminId = $adminId;
|
|
|
|
$stabiliAdminIds = [];
|
|
if (! $user->hasRole('super-admin') && $adminId > 0) {
|
|
$stabiliAdminIds = Stabile::query()
|
|
->where('amministratore_id', $adminId)
|
|
->pluck('id')
|
|
->map(fn($id) => (int) $id)
|
|
->all();
|
|
}
|
|
|
|
$this->adminStabileIds = $stabiliAdminIds;
|
|
|
|
$this->initArchivioNavigation();
|
|
|
|
$this->fornitori = Fornitore::query()
|
|
->where('amministratore_id', $adminId)
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->orderBy('ragione_sociale')
|
|
->limit(50)
|
|
->get(['id', 'codice_univoco', 'ragione_sociale', 'partita_iva', 'codice_fiscale'])
|
|
->map(fn(Fornitore $f) => [
|
|
'id' => (int) $f->id,
|
|
'codice' => (string) ($f->codice_univoco ?? ''),
|
|
'nome' => (string) ($f->ragione_sociale ?: trim((string) ($f->cognome ?? '') . ' ' . (string) ($f->nome ?? ''))),
|
|
'piva' => (string) ($f->partita_iva ?? ''),
|
|
'cf' => (string) ($f->codice_fiscale ?? ''),
|
|
])
|
|
->all();
|
|
|
|
$ruoliQuery = RubricaRuolo::query()
|
|
->with(['stabile', 'unitaImmobiliare.stabile'])
|
|
->where('rubrica_id', (int) $this->rubrica->id);
|
|
|
|
if (! $user->hasRole('super-admin') && ! empty($stabiliAdminIds)) {
|
|
$ruoliQuery->where(function ($q) use ($stabiliAdminIds) {
|
|
$q->whereNull('stabile_id')
|
|
->orWhereIn('stabile_id', $stabiliAdminIds);
|
|
});
|
|
}
|
|
|
|
$ruoli = $ruoliQuery
|
|
->orderByDesc('is_attivo')
|
|
->orderByDesc('is_preferito')
|
|
->orderByDesc('data_inizio')
|
|
->orderByDesc('id')
|
|
->limit(200)
|
|
->get();
|
|
|
|
$labels = self::getRuoliLabels();
|
|
|
|
$this->ruoliAttivi = $ruoli
|
|
->filter(fn(RubricaRuolo $r) => (bool) $r->is_attivo)
|
|
->map(function (RubricaRuolo $r) use ($labels) {
|
|
$stabile = $r->stabile ?: $r->unitaImmobiliare?->stabile;
|
|
$ruoloKey = (string) ($r->ruolo_standard ?? 'altro');
|
|
$ruoloLabel = (string) ($labels[$ruoloKey] ?? $ruoloKey);
|
|
if (! empty($r->ruolo_custom)) {
|
|
$ruoloLabel .= ' (' . (string) $r->ruolo_custom . ')';
|
|
}
|
|
|
|
return [
|
|
'ruolo' => $ruoloLabel,
|
|
'stabile_codice' => (string) ($stabile?->codice_operatore ?? $stabile?->codice_stabile ?? ''),
|
|
'stabile_nome' => (string) ($stabile?->denominazione ?? ''),
|
|
'unita_id' => (int) ($r->unitaImmobiliare?->id ?? 0),
|
|
'unita_codice' => (string) ($r->unitaImmobiliare?->codice_unita ?? ''),
|
|
'unita_nome' => (string) ($r->unitaImmobiliare?->denominazione ?? ''),
|
|
'preferito' => (bool) ($r->is_preferito ?? false),
|
|
];
|
|
})
|
|
->values()
|
|
->all();
|
|
|
|
$this->cronistoriaRuoli = $ruoli
|
|
->map(function (RubricaRuolo $r) use ($labels) {
|
|
$stabile = $r->stabile ?: $r->unitaImmobiliare?->stabile;
|
|
$unita = $r->unitaImmobiliare;
|
|
|
|
$ruoloKey = (string) ($r->ruolo_standard ?? 'altro');
|
|
$ruoloLabel = (string) ($labels[$ruoloKey] ?? $ruoloKey);
|
|
if (! empty($r->ruolo_custom)) {
|
|
$ruoloLabel .= ' (' . (string) $r->ruolo_custom . ')';
|
|
}
|
|
|
|
return [
|
|
'ruolo' => $ruoloLabel,
|
|
'data_inizio' => optional($r->data_inizio)->format('d/m/Y'),
|
|
'data_fine' => $r->data_fine ? optional($r->data_fine)->format('d/m/Y') : null,
|
|
'attivo' => (bool) ($r->is_attivo ?? true),
|
|
'preferito' => (bool) ($r->is_preferito ?? false),
|
|
'stabile_codice' => (string) ($stabile?->codice_operatore ?? $stabile?->codice_stabile ?? ''),
|
|
'stabile_nome' => (string) ($stabile?->denominazione ?? ''),
|
|
'unita_id' => (int) ($unita?->id ?? 0),
|
|
'unita_codice' => (string) ($unita?->codice_unita ?? ''),
|
|
'unita_nome' => (string) ($unita?->denominazione ?? ''),
|
|
];
|
|
})
|
|
->all();
|
|
|
|
// Collegamenti stabili: includi sia stabili con rubrica_id diretto sia stabili legati tramite ruoli.
|
|
$stabiliIds = [];
|
|
foreach ($ruoli as $r) {
|
|
$sid = (int) ($r->stabile_id ?? 0);
|
|
if ($sid <= 0) {
|
|
$sid = (int) ($r->unitaImmobiliare?->stabile_id ?? 0);
|
|
}
|
|
if ($sid > 0) {
|
|
$stabiliIds[] = $sid;
|
|
}
|
|
}
|
|
$stabiliIds = array_values(array_unique($stabiliIds));
|
|
|
|
$stabiliQuery = Stabile::query()->where('amministratore_id', $adminId);
|
|
if (! empty($stabiliIds)) {
|
|
$stabiliQuery->where(function (Builder $q) use ($stabiliIds): void {
|
|
$q->whereIn('id', $stabiliIds)
|
|
->orWhere('rubrica_id', (int) $this->rubrica->id);
|
|
});
|
|
} else {
|
|
$stabiliQuery->where('rubrica_id', (int) $this->rubrica->id);
|
|
}
|
|
|
|
$this->stabili = $stabiliQuery
|
|
->orderBy('codice_stabile')
|
|
->limit(100)
|
|
->get(['id', 'codice_stabile', 'cod_stabile', 'denominazione', 'codice_fiscale'])
|
|
->map(fn(Stabile $s) => [
|
|
'id' => (int) $s->id,
|
|
'codice' => (string) ($s->codice_operatore ?? $s->codice_stabile ?? ''),
|
|
'nome' => (string) ($s->denominazione ?? ''),
|
|
'cf' => (string) ($s->codice_fiscale ?? ''),
|
|
])
|
|
->all();
|
|
|
|
// Contatti principali (per mostrarli velocemente nella scheda): prende canali principali + fallback ai campi telefono/email.
|
|
$principali = RubricaContattoCanale::query()
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->orderByDesc('is_principale')
|
|
->orderByDesc('data_inizio')
|
|
->orderByDesc('id')
|
|
->limit(20)
|
|
->get();
|
|
|
|
$this->contattiPrincipali = $principali
|
|
->map(fn(RubricaContattoCanale $c) => [
|
|
'tipo' => (string) ($c->tipo ?? 'altro'),
|
|
'etichetta' => (string) ($c->etichetta ?? ''),
|
|
'valore' => (string) ($c->valore ?? ''),
|
|
'principale' => (bool) ($c->is_principale ?? false),
|
|
])
|
|
->all();
|
|
|
|
$this->hydrateEmailMultiple();
|
|
$this->fillInlineForm();
|
|
$this->hydrateFornitoriWorkspace();
|
|
}
|
|
|
|
public function startInlineEdit(): void
|
|
{
|
|
$this->fillInlineForm();
|
|
$this->isInlineEditing = true;
|
|
}
|
|
|
|
public function cancelInlineEdit(): void
|
|
{
|
|
$this->fillInlineForm();
|
|
$this->isInlineEditing = false;
|
|
}
|
|
|
|
public function saveInlineEdit(): void
|
|
{
|
|
$legacyIdentity = $this->extractLegacyIdentityFromNote($this->inlineForm['note'] ?? null);
|
|
$resolvedAddress = $this->parseAddressComponents($this->inlineForm['indirizzo_completo'] ?? null);
|
|
|
|
$data = validator($this->inlineForm, [
|
|
'nome' => ['nullable', 'string', 'max:255'],
|
|
'cognome' => ['nullable', 'string', 'max:255'],
|
|
'ragione_sociale' => ['nullable', 'string', 'max:255'],
|
|
'tipo_contatto' => ['nullable', 'string', 'max:120'],
|
|
'categoria' => ['nullable', 'string', 'max:120'],
|
|
'codice_fiscale' => ['nullable', 'string', 'max:32'],
|
|
'partita_iva' => ['nullable', 'string', 'max:32'],
|
|
'sesso' => ['nullable', 'string', 'max:1'],
|
|
'data_nascita' => ['nullable', 'date'],
|
|
'luogo_nascita' => ['nullable', 'string', 'max:100'],
|
|
'provincia_nascita' => ['nullable', 'string', 'max:2'],
|
|
'email' => ['nullable', 'string', 'max:255'],
|
|
'pec' => ['nullable', 'string', 'max:255'],
|
|
'telefono_ufficio' => ['nullable', 'string', 'max:64'],
|
|
'telefono_cellulare' => ['nullable', 'string', 'max:64'],
|
|
'telefono_casa' => ['nullable', 'string', 'max:64'],
|
|
'indirizzo' => ['nullable', 'string', 'max:255'],
|
|
'civico' => ['nullable', 'string', 'max:32'],
|
|
'cap' => ['nullable', 'string', 'max:5'],
|
|
'citta' => ['nullable', 'string', 'max:100'],
|
|
'provincia' => ['nullable', 'string', 'max:2'],
|
|
'nazione' => ['nullable', 'string', 'max:50'],
|
|
'indirizzo_completo' => ['nullable', 'string', 'max:255'],
|
|
'tipo_utenza_call' => ['nullable', 'string', 'max:120'],
|
|
'riferimento_stabile' => ['nullable', 'string', 'max:255'],
|
|
'riferimento_unita' => ['nullable', 'string', 'max:255'],
|
|
'note' => ['nullable', 'string', 'max:5000'],
|
|
'note_segreteria' => ['nullable', 'string', 'max:5000'],
|
|
])->validate();
|
|
|
|
$normalizedBirthDate = $this->normalizeLegacyDateValue($data['data_nascita'] ?? $legacyIdentity['data_nascita'] ?? null);
|
|
$cleanNote = $this->cleanNullable($legacyIdentity['note_clean'] ?? ($data['note'] ?? null));
|
|
$sesso = $this->normalizeSessoValue($data['sesso'] ?? $legacyIdentity['sesso'] ?? null);
|
|
$provinciaNascita = $this->normalizeProvince($data['provincia_nascita'] ?? $legacyIdentity['provincia_nascita'] ?? null);
|
|
|
|
$indirizzo = $this->cleanNullable($data['indirizzo'] ?? null) ?: ($resolvedAddress['indirizzo'] ?? null);
|
|
$civico = $this->cleanNullable($data['civico'] ?? null) ?: ($resolvedAddress['civico'] ?? null);
|
|
$cap = $this->cleanNullable($data['cap'] ?? null) ?: ($resolvedAddress['cap'] ?? null);
|
|
$citta = $this->cleanNullable($data['citta'] ?? null) ?: ($resolvedAddress['citta'] ?? null);
|
|
$provincia = $this->normalizeProvince($data['provincia'] ?? null) ?: ($resolvedAddress['provincia'] ?? null);
|
|
|
|
$this->rubrica->fill([
|
|
'nome' => $this->cleanNullable($data['nome'] ?? null),
|
|
'cognome' => $this->cleanNullable($data['cognome'] ?? null),
|
|
'ragione_sociale' => $this->cleanNullable($data['ragione_sociale'] ?? null),
|
|
'tipo_contatto' => $this->cleanNullable($data['tipo_contatto'] ?? null),
|
|
'categoria' => $this->cleanNullable($data['categoria'] ?? null),
|
|
'codice_fiscale' => $this->cleanNullable($data['codice_fiscale'] ?? null),
|
|
'partita_iva' => $this->cleanNullable($data['partita_iva'] ?? null),
|
|
'sesso' => $sesso,
|
|
'data_nascita' => $normalizedBirthDate,
|
|
'luogo_nascita' => $this->cleanNullable($data['luogo_nascita'] ?? $legacyIdentity['luogo_nascita'] ?? null),
|
|
'provincia_nascita' => $provinciaNascita,
|
|
'email' => $this->cleanNullable($data['email'] ?? null),
|
|
'pec' => $this->cleanNullable($data['pec'] ?? null),
|
|
'telefono_ufficio' => $this->cleanNullable($data['telefono_ufficio'] ?? null),
|
|
'telefono_cellulare' => $this->cleanNullable($data['telefono_cellulare'] ?? null),
|
|
'telefono_casa' => $this->cleanNullable($data['telefono_casa'] ?? null),
|
|
'indirizzo' => $indirizzo,
|
|
'civico' => $civico,
|
|
'cap' => $cap,
|
|
'citta' => $citta,
|
|
'provincia' => $provincia,
|
|
'nazione' => $this->cleanNullable($data['nazione'] ?? null) ?: $this->rubrica->nazione,
|
|
'tipo_utenza_call' => $this->cleanNullable($data['tipo_utenza_call'] ?? null),
|
|
'riferimento_stabile' => $this->cleanNullable($data['riferimento_stabile'] ?? null),
|
|
'riferimento_unita' => $this->cleanNullable($data['riferimento_unita'] ?? null),
|
|
'note' => $cleanNote,
|
|
'note_segreteria' => $this->cleanNullable($data['note_segreteria'] ?? null),
|
|
'data_ultima_modifica' => now()->toDateString(),
|
|
'modificato_da' => Auth::id(),
|
|
]);
|
|
|
|
if (! $this->rubrica->titolo_id && ! empty($legacyIdentity['titolo_id'])) {
|
|
$this->rubrica->titolo_id = (int) $legacyIdentity['titolo_id'];
|
|
}
|
|
|
|
$this->rubrica->save();
|
|
|
|
$this->mount((int) $this->rubrica->id);
|
|
$this->isInlineEditing = false;
|
|
|
|
Notification::make()
|
|
->title('Contatto aggiornato')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
private function initArchivioNavigation(): void
|
|
{
|
|
$pp = (int) request()->query('pp', 25);
|
|
if ($pp <= 0) {
|
|
$pp = 25;
|
|
}
|
|
if (! in_array($pp, [10, 25, 50, 100], true)) {
|
|
$pp = 25;
|
|
}
|
|
|
|
$this->navPerPage = $pp;
|
|
|
|
if ($this->adminId <= 0) {
|
|
$this->prevRecordId = null;
|
|
$this->nextRecordId = null;
|
|
$this->navPage = 1;
|
|
$this->navPages = 1;
|
|
return;
|
|
}
|
|
|
|
$base = RubricaUniversale::query()->where('amministratore_id', $this->adminId);
|
|
|
|
$total = (clone $base)->count();
|
|
$this->navPages = max(1, (int) ceil($total / $this->navPerPage));
|
|
|
|
$before = (clone $base)
|
|
->where($this->whereBeforeCurrent())
|
|
->count();
|
|
$position = $before + 1;
|
|
$this->navPage = max(1, (int) ceil($position / $this->navPerPage));
|
|
|
|
$this->prevRecordId = (clone $base)
|
|
->where($this->whereBeforeCurrent())
|
|
->tap(fn(Builder $q) => $this->applySort($q, 'desc'))
|
|
->value('id');
|
|
|
|
$this->nextRecordId = (clone $base)
|
|
->where($this->whereAfterCurrent())
|
|
->tap(fn(Builder $q) => $this->applySort($q, 'asc'))
|
|
->value('id');
|
|
}
|
|
|
|
private function applySort(Builder $query, string $direction): void
|
|
{
|
|
$dir = strtolower($direction) === 'desc' ? 'DESC' : 'ASC';
|
|
|
|
$query
|
|
->orderByRaw("COALESCE(ragione_sociale, '') {$dir}")
|
|
->orderByRaw("COALESCE(cognome, '') {$dir}")
|
|
->orderByRaw("COALESCE(nome, '') {$dir}")
|
|
->orderBy('id', $dir);
|
|
}
|
|
|
|
private function whereBeforeCurrent(): \Closure
|
|
{
|
|
$ragione = (string) ($this->rubrica->ragione_sociale ?? '');
|
|
$cognome = (string) ($this->rubrica->cognome ?? '');
|
|
$nome = (string) ($this->rubrica->nome ?? '');
|
|
$id = (int) $this->rubrica->id;
|
|
|
|
return function (Builder $q) use ($ragione, $cognome, $nome, $id): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') < ?", [$ragione])
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') < ?", [$cognome]);
|
|
})
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome, $nome): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') = ?", [$cognome])
|
|
->whereRaw("COALESCE(nome, '') < ?", [$nome]);
|
|
})
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome, $nome, $id): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') = ?", [$cognome])
|
|
->whereRaw("COALESCE(nome, '') = ?", [$nome])
|
|
->where('id', '<', $id);
|
|
});
|
|
};
|
|
}
|
|
|
|
private function whereAfterCurrent(): \Closure
|
|
{
|
|
$ragione = (string) ($this->rubrica->ragione_sociale ?? '');
|
|
$cognome = (string) ($this->rubrica->cognome ?? '');
|
|
$nome = (string) ($this->rubrica->nome ?? '');
|
|
$id = (int) $this->rubrica->id;
|
|
|
|
return function (Builder $q) use ($ragione, $cognome, $nome, $id): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') > ?", [$ragione])
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') > ?", [$cognome]);
|
|
})
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome, $nome): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') = ?", [$cognome])
|
|
->whereRaw("COALESCE(nome, '') > ?", [$nome]);
|
|
})
|
|
->orWhere(function (Builder $q) use ($ragione, $cognome, $nome, $id): void {
|
|
$q->whereRaw("COALESCE(ragione_sociale, '') = ?", [$ragione])
|
|
->whereRaw("COALESCE(cognome, '') = ?", [$cognome])
|
|
->whereRaw("COALESCE(nome, '') = ?", [$nome])
|
|
->where('id', '>', $id);
|
|
});
|
|
};
|
|
}
|
|
|
|
public function getPrevUrl(): ?string
|
|
{
|
|
if (! $this->prevRecordId) {
|
|
return null;
|
|
}
|
|
return self::getUrl(['record' => $this->prevRecordId], panel: 'admin-filament')
|
|
. '?pp=' . $this->navPerPage;
|
|
}
|
|
|
|
public function getNextUrl(): ?string
|
|
{
|
|
if (! $this->nextRecordId) {
|
|
return null;
|
|
}
|
|
return self::getUrl(['record' => $this->nextRecordId], panel: 'admin-filament')
|
|
. '?pp=' . $this->navPerPage;
|
|
}
|
|
|
|
public function getPrevPageUrl(): ?string
|
|
{
|
|
$target = $this->navPage - 1;
|
|
if ($target < 1) {
|
|
return null;
|
|
}
|
|
return $this->getPageUrl($target);
|
|
}
|
|
|
|
public function getNextPageUrl(): ?string
|
|
{
|
|
$target = $this->navPage + 1;
|
|
if ($target > $this->navPages) {
|
|
return null;
|
|
}
|
|
return $this->getPageUrl($target);
|
|
}
|
|
|
|
public function getPageUrl(int $page): ?string
|
|
{
|
|
if ($this->adminId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$page = max(1, min($page, $this->navPages));
|
|
$offset = ($page - 1) * $this->navPerPage;
|
|
|
|
$base = RubricaUniversale::query()
|
|
->where('amministratore_id', $this->adminId);
|
|
|
|
$this->applySort($base, 'asc');
|
|
$id = (int) ($base->skip($offset)->take(1)->value('id') ?? 0);
|
|
if ($id <= 0) {
|
|
return null;
|
|
}
|
|
|
|
return self::getUrl(['record' => $id], panel: 'admin-filament')
|
|
. '?pp=' . $this->navPerPage;
|
|
}
|
|
|
|
public function getPerPageUrl(int $perPage): string
|
|
{
|
|
if (! in_array($perPage, [10, 25, 50, 100], true)) {
|
|
$perPage = 25;
|
|
}
|
|
|
|
return self::getUrl(['record' => (int) $this->rubrica->id], panel: 'admin-filament')
|
|
. '?pp=' . $perPage;
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
Action::make('titolo')
|
|
->label('Titolo')
|
|
->icon('heroicon-o-tag')
|
|
->form([
|
|
Select::make('titolo_id')
|
|
->label('Titolo')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn() => $this->getTitoliOptions()),
|
|
])
|
|
->fillForm(fn(): array=> [
|
|
'titolo_id' => $this->rubrica->titolo_id ? (int) $this->rubrica->titolo_id : null,
|
|
])
|
|
->action(function (array $data): void {
|
|
$titoloId = isset($data['titolo_id']) && is_numeric($data['titolo_id'])
|
|
? (int) $data['titolo_id']
|
|
: null;
|
|
|
|
$this->rubrica->titolo_id = $titoloId;
|
|
$this->rubrica->data_ultima_modifica = now()->toDateString();
|
|
$this->rubrica->modificato_da = Auth::id();
|
|
$this->rubrica->save();
|
|
|
|
$this->mount((int) $this->rubrica->id);
|
|
|
|
Notification::make()
|
|
->title('Titolo aggiornato')
|
|
->success()
|
|
->send();
|
|
}),
|
|
Action::make('contatti')
|
|
->label('Contatti')
|
|
->icon('heroicon-o-phone')
|
|
->action(function (): void {
|
|
$this->startInlineEdit();
|
|
}),
|
|
|
|
Action::make('email_multiple')
|
|
->label('Email aggiuntive')
|
|
->icon('heroicon-o-envelope')
|
|
->modalWidth('4xl')
|
|
->form([
|
|
Repeater::make('emails')
|
|
->label('Email aggiuntive')
|
|
->defaultItems(0)
|
|
->reorderable(true)
|
|
->schema([
|
|
Hidden::make('id'),
|
|
TextInput::make('email')
|
|
->label('Email')
|
|
->email()
|
|
->required()
|
|
->maxLength(255)
|
|
->columnSpan(6),
|
|
Select::make('tipo_email')
|
|
->label('Tipo')
|
|
->native(false)
|
|
->options([
|
|
'secondaria' => 'Secondaria',
|
|
'lavoro' => 'Lavoro',
|
|
'personale' => 'Personale',
|
|
'pec' => 'PEC',
|
|
'altro' => 'Altro',
|
|
])
|
|
->default('secondaria')
|
|
->columnSpan(4),
|
|
Toggle::make('attiva')
|
|
->label('Attiva')
|
|
->default(true)
|
|
->columnSpan(2),
|
|
])
|
|
->columns(12),
|
|
])
|
|
->fillForm(fn(): array=> ['emails' => $this->getAdditionalEmailsFormRows()])
|
|
->action(function (array $data): void {
|
|
$this->saveAdditionalEmails($data['emails'] ?? []);
|
|
$this->mount((int) $this->rubrica->id);
|
|
|
|
Notification::make()
|
|
->title('Email aggiuntive aggiornate')
|
|
->success()
|
|
->send();
|
|
}),
|
|
|
|
Action::make('contatti_avanzati')
|
|
->label('Contatti avanzati')
|
|
->icon('heroicon-o-rectangle-stack')
|
|
->modalWidth('7xl')
|
|
->form([
|
|
Repeater::make('canali')
|
|
->label('Contatti aggiuntivi')
|
|
->defaultItems(0)
|
|
->reorderable(true)
|
|
->schema([
|
|
Hidden::make('id'),
|
|
|
|
Select::make('tipo')
|
|
->label('Tipo')
|
|
->options([
|
|
'telefono' => 'Telefono',
|
|
'cellulare' => 'Cellulare',
|
|
'email' => 'Email',
|
|
'pec' => 'PEC',
|
|
'fax' => 'Fax',
|
|
'sito_web' => 'Sito web',
|
|
'altro' => 'Altro',
|
|
])
|
|
->native(false)
|
|
->required()
|
|
->columnSpan(2),
|
|
|
|
TextInput::make('etichetta')
|
|
->label('Etichetta')
|
|
->maxLength(50)
|
|
->columnSpan(2),
|
|
|
|
TextInput::make('valore')
|
|
->label('Valore')
|
|
->required()
|
|
->maxLength(255)
|
|
->columnSpan(4),
|
|
|
|
Toggle::make('is_principale')
|
|
->label('Principale')
|
|
->default(false)
|
|
->columnSpan(2),
|
|
|
|
Select::make('stabile_id')
|
|
->label('Stabile (opzionale)')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn() => $this->getStabiliOptions())
|
|
->reactive()
|
|
->afterStateUpdated(fn($set) => $set('unita_immobiliare_id', null))
|
|
->columnSpan(3),
|
|
|
|
Select::make('unita_immobiliare_id')
|
|
->label('Unità (opzionale)')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn($get) => $this->getUnitaOptions($get('stabile_id')))
|
|
->columnSpan(3),
|
|
|
|
DatePicker::make('data_inizio')
|
|
->label('Data inizio')
|
|
->columnSpan(2),
|
|
|
|
DatePicker::make('data_fine')
|
|
->label('Data fine')
|
|
->columnSpan(2),
|
|
|
|
TextInput::make('note')
|
|
->label('Note')
|
|
->maxLength(255)
|
|
->columnSpan(12),
|
|
])
|
|
->columns(12),
|
|
])
|
|
->fillForm(function (): array {
|
|
$canali = RubricaContattoCanale::query()
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->orderByDesc('is_principale')
|
|
->orderByDesc('data_inizio')
|
|
->orderByDesc('id')
|
|
->limit(200)
|
|
->get();
|
|
|
|
return [
|
|
'canali' => $canali->map(fn(RubricaContattoCanale $c) => [
|
|
'id' => (int) $c->id,
|
|
'tipo' => (string) ($c->tipo ?? 'altro'),
|
|
'etichetta' => (string) ($c->etichetta ?? ''),
|
|
'valore' => (string) ($c->valore ?? ''),
|
|
'is_principale' => (bool) ($c->is_principale ?? false),
|
|
'stabile_id' => $c->stabile_id ? (int) $c->stabile_id : null,
|
|
'unita_immobiliare_id' => $c->unita_immobiliare_id ? (int) $c->unita_immobiliare_id : null,
|
|
'data_inizio' => $c->data_inizio?->format('Y-m-d'),
|
|
'data_fine' => $c->data_fine?->format('Y-m-d'),
|
|
'note' => (string) (($c->meta['note'] ?? null) ?: ''),
|
|
])->all(),
|
|
];
|
|
})
|
|
->action(function (array $data): void {
|
|
/** @var array<int, array<string, mixed>> $rows */
|
|
$rows = $data['canali'] ?? [];
|
|
$rows = is_array($rows) ? array_values($rows) : [];
|
|
|
|
DB::transaction(function () use ($rows): void {
|
|
$keepIds = [];
|
|
|
|
foreach ($rows as $row) {
|
|
$id = (int) ($row['id'] ?? 0);
|
|
$tipo = (string) ($row['tipo'] ?? 'altro');
|
|
if ($tipo === '') {
|
|
$tipo = 'altro';
|
|
}
|
|
|
|
$attrs = [
|
|
'rubrica_id' => (int) $this->rubrica->id,
|
|
'tipo' => $tipo,
|
|
'etichetta' => ! empty($row['etichetta']) ? (string) $row['etichetta'] : null,
|
|
'valore' => ! empty($row['valore']) ? (string) $row['valore'] : null,
|
|
'is_principale' => (bool) ($row['is_principale'] ?? false),
|
|
'stabile_id' => ! empty($row['stabile_id']) ? (int) $row['stabile_id'] : null,
|
|
'unita_immobiliare_id' => ! empty($row['unita_immobiliare_id']) ? (int) $row['unita_immobiliare_id'] : null,
|
|
'data_inizio' => $row['data_inizio'] ?? null,
|
|
'data_fine' => $row['data_fine'] ?? null,
|
|
'meta' => [
|
|
'note' => ! empty($row['note']) ? (string) $row['note'] : null,
|
|
],
|
|
];
|
|
|
|
if ($id > 0) {
|
|
$existing = RubricaContattoCanale::query()
|
|
->where('id', $id)
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->first();
|
|
|
|
if ($existing) {
|
|
$existing->fill($attrs);
|
|
$existing->save();
|
|
$keepIds[] = (int) $existing->id;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$created = RubricaContattoCanale::query()->create($attrs);
|
|
$keepIds[] = (int) $created->id;
|
|
}
|
|
|
|
$deleteQuery = RubricaContattoCanale::query()->where('rubrica_id', (int) $this->rubrica->id);
|
|
if (! empty($keepIds)) {
|
|
$deleteQuery->whereNotIn('id', $keepIds);
|
|
}
|
|
$deleteQuery->delete();
|
|
});
|
|
|
|
$this->mount((int) $this->rubrica->id);
|
|
|
|
Notification::make()
|
|
->title('Contatti aggiornati')
|
|
->success()
|
|
->send();
|
|
}),
|
|
|
|
Action::make('riferimenti_chiamata')
|
|
->label('Riferimenti chiamata')
|
|
->icon('heroicon-o-phone-arrow-up-right')
|
|
->form([
|
|
Select::make('tipo_utenza_call')
|
|
->label('Profilo chiamante')
|
|
->native(false)
|
|
->options([
|
|
'condomino' => 'Condomino',
|
|
'inquilino' => 'Inquilino',
|
|
'fornitore' => 'Fornitore',
|
|
'amministratore' => 'Amministratore',
|
|
'altro' => 'Altro',
|
|
]),
|
|
TextInput::make('riferimento_stabile')
|
|
->label('Riferimento stabile')
|
|
->maxLength(255),
|
|
TextInput::make('riferimento_unita')
|
|
->label('Riferimento unità')
|
|
->maxLength(255),
|
|
TextInput::make('note_segreteria')
|
|
->label('Note segreteria')
|
|
->maxLength(2000),
|
|
])
|
|
->fillForm(fn(): array=> [
|
|
'tipo_utenza_call' => $this->rubrica->tipo_utenza_call,
|
|
'riferimento_stabile' => $this->rubrica->riferimento_stabile,
|
|
'riferimento_unita' => $this->rubrica->riferimento_unita,
|
|
'note_segreteria' => $this->rubrica->note_segreteria,
|
|
])
|
|
->action(function (array $data): void {
|
|
$this->rubrica->tipo_utenza_call = ! empty($data['tipo_utenza_call']) ? (string) $data['tipo_utenza_call'] : null;
|
|
$this->rubrica->riferimento_stabile = ! empty($data['riferimento_stabile']) ? (string) $data['riferimento_stabile'] : null;
|
|
$this->rubrica->riferimento_unita = ! empty($data['riferimento_unita']) ? (string) $data['riferimento_unita'] : null;
|
|
$this->rubrica->note_segreteria = ! empty($data['note_segreteria']) ? (string) $data['note_segreteria'] : null;
|
|
$this->rubrica->data_ultima_modifica = now()->toDateString();
|
|
$this->rubrica->modificato_da = Auth::id();
|
|
$this->rubrica->save();
|
|
|
|
$this->mount((int) $this->rubrica->id);
|
|
|
|
Notification::make()
|
|
->title('Riferimenti chiamata aggiornati')
|
|
->success()
|
|
->send();
|
|
}),
|
|
|
|
Action::make('ruoli_legami')
|
|
->label('Ruoli / legami')
|
|
->icon('heroicon-o-link')
|
|
->modalWidth('7xl')
|
|
->form([
|
|
Repeater::make('ruoli')
|
|
->label('Ruoli e legami')
|
|
->defaultItems(0)
|
|
->reorderable(true)
|
|
->schema([
|
|
Hidden::make('id'),
|
|
|
|
Select::make('ruolo_standard')
|
|
->label('Ruolo')
|
|
->options(self::getRuoliLabels())
|
|
->required()
|
|
->native(false)
|
|
->default('altro')
|
|
->columnSpan(2),
|
|
|
|
TextInput::make('ruolo_custom')
|
|
->label('Ruolo custom')
|
|
->maxLength(255)
|
|
->columnSpan(2),
|
|
|
|
Select::make('stabile_id')
|
|
->label('Stabile')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn() => $this->getStabiliOptions())
|
|
->reactive()
|
|
->afterStateUpdated(fn($set) => $set('unita_immobiliare_id', null))
|
|
->columnSpan(3),
|
|
|
|
Select::make('unita_immobiliare_id')
|
|
->label('Unità')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn($get) => $this->getUnitaOptions($get('stabile_id')))
|
|
->columnSpan(3),
|
|
|
|
DatePicker::make('data_inizio')
|
|
->label('Data inizio')
|
|
->columnSpan(2),
|
|
|
|
DatePicker::make('data_fine')
|
|
->label('Data fine')
|
|
->columnSpan(2),
|
|
|
|
Toggle::make('is_preferito')
|
|
->label('Preferito')
|
|
->default(false)
|
|
->columnSpan(2),
|
|
|
|
Toggle::make('is_attivo')
|
|
->label('Attivo')
|
|
->default(true)
|
|
->columnSpan(2),
|
|
])
|
|
->columns(12),
|
|
])
|
|
->fillForm(function (): array {
|
|
$ruoli = RubricaRuolo::query()
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->orderByDesc('is_attivo')
|
|
->orderByDesc('is_preferito')
|
|
->orderByDesc('data_inizio')
|
|
->orderByDesc('id')
|
|
->limit(200)
|
|
->get();
|
|
|
|
return [
|
|
'ruoli' => $ruoli->map(fn(RubricaRuolo $r) => [
|
|
'id' => (int) $r->id,
|
|
'ruolo_standard' => (string) ($r->ruolo_standard ?? 'altro'),
|
|
'ruolo_custom' => (string) ($r->ruolo_custom ?? ''),
|
|
'stabile_id' => $r->stabile_id ? (int) $r->stabile_id : null,
|
|
'unita_immobiliare_id' => $r->unita_immobiliare_id ? (int) $r->unita_immobiliare_id : null,
|
|
'data_inizio' => $r->data_inizio?->format('Y-m-d'),
|
|
'data_fine' => $r->data_fine?->format('Y-m-d'),
|
|
'is_preferito' => (bool) ($r->is_preferito ?? false),
|
|
'is_attivo' => (bool) ($r->is_attivo ?? true),
|
|
])->all(),
|
|
];
|
|
})
|
|
->action(function (array $data): void {
|
|
/** @var array<int, array<string, mixed>> $rows */
|
|
$rows = $data['ruoli'] ?? [];
|
|
$rows = is_array($rows) ? array_values($rows) : [];
|
|
|
|
DB::transaction(function () use ($rows): void {
|
|
$keepIds = [];
|
|
|
|
foreach ($rows as $row) {
|
|
$id = (int) ($row['id'] ?? 0);
|
|
$ruoloStandard = (string) ($row['ruolo_standard'] ?? 'altro');
|
|
|
|
$attrs = [
|
|
'rubrica_id' => (int) $this->rubrica->id,
|
|
'ruolo_standard' => $ruoloStandard ?: 'altro',
|
|
'ruolo_custom' => ! empty($row['ruolo_custom']) ? (string) $row['ruolo_custom'] : null,
|
|
'stabile_id' => ! empty($row['stabile_id']) ? (int) $row['stabile_id'] : null,
|
|
'unita_immobiliare_id' => ! empty($row['unita_immobiliare_id']) ? (int) $row['unita_immobiliare_id'] : null,
|
|
'data_inizio' => $row['data_inizio'] ?? null,
|
|
'data_fine' => $row['data_fine'] ?? null,
|
|
'is_preferito' => (bool) ($row['is_preferito'] ?? false),
|
|
'is_attivo' => (bool) ($row['is_attivo'] ?? true),
|
|
];
|
|
|
|
if ($id > 0) {
|
|
$existing = RubricaRuolo::query()
|
|
->where('id', $id)
|
|
->where('rubrica_id', (int) $this->rubrica->id)
|
|
->first();
|
|
|
|
if ($existing) {
|
|
$existing->fill($attrs);
|
|
$existing->save();
|
|
$keepIds[] = (int) $existing->id;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$created = RubricaRuolo::query()->create($attrs);
|
|
$keepIds[] = (int) $created->id;
|
|
}
|
|
|
|
$deleteQuery = RubricaRuolo::query()->where('rubrica_id', (int) $this->rubrica->id);
|
|
if (! empty($keepIds)) {
|
|
$deleteQuery->whereNotIn('id', $keepIds);
|
|
}
|
|
$deleteQuery->delete();
|
|
});
|
|
|
|
$this->mount((int) $this->rubrica->id);
|
|
|
|
Notification::make()
|
|
->title('Ruoli / legami aggiornati')
|
|
->success()
|
|
->send();
|
|
}),
|
|
|
|
Action::make('torna')
|
|
->label('Torna')
|
|
->icon('heroicon-o-arrow-left')
|
|
->url(fn() => AnagraficaUnica::getUrl(panel: 'admin-filament')),
|
|
];
|
|
}
|
|
|
|
private function fillInlineForm(): void
|
|
{
|
|
$legacyIdentity = $this->extractLegacyIdentityFromNote($this->rubrica->note ?? null);
|
|
$resolvedAddress = $this->parseAddressComponents($this->rubrica->indirizzo_completo ?? null);
|
|
|
|
$this->inlineForm = [
|
|
'nome' => (string) ($this->rubrica->nome ?? ''),
|
|
'cognome' => (string) ($this->rubrica->cognome ?? ''),
|
|
'ragione_sociale' => (string) ($this->rubrica->ragione_sociale ?? ''),
|
|
'tipo_contatto' => (string) ($this->rubrica->tipo_contatto ?? ''),
|
|
'categoria' => (string) ($this->rubrica->categoria ?? ''),
|
|
'codice_fiscale' => (string) ($this->rubrica->codice_fiscale ?? ''),
|
|
'partita_iva' => (string) ($this->rubrica->partita_iva ?? ''),
|
|
'sesso' => (string) ($this->rubrica->sesso ?? $legacyIdentity['sesso'] ?? ''),
|
|
'data_nascita' => (string) (($this->rubrica->data_nascita?->format('Y-m-d')) ?? $legacyIdentity['data_nascita'] ?? ''),
|
|
'luogo_nascita' => (string) ($this->rubrica->luogo_nascita ?? $legacyIdentity['luogo_nascita'] ?? ''),
|
|
'provincia_nascita' => (string) ($this->rubrica->provincia_nascita ?? $legacyIdentity['provincia_nascita'] ?? ''),
|
|
'email' => (string) ($this->rubrica->email ?? ''),
|
|
'pec' => (string) ($this->rubrica->pec ?? ''),
|
|
'telefono_ufficio' => (string) ($this->rubrica->telefono_ufficio ?? ''),
|
|
'telefono_cellulare' => (string) ($this->rubrica->telefono_cellulare ?? ''),
|
|
'telefono_casa' => (string) ($this->rubrica->telefono_casa ?? ''),
|
|
'indirizzo' => (string) ($this->rubrica->indirizzo ?? $resolvedAddress['indirizzo'] ?? ''),
|
|
'civico' => (string) ($this->rubrica->civico ?? $resolvedAddress['civico'] ?? ''),
|
|
'cap' => (string) ($this->rubrica->cap ?? $resolvedAddress['cap'] ?? ''),
|
|
'citta' => (string) ($this->rubrica->citta ?? $resolvedAddress['citta'] ?? ''),
|
|
'provincia' => (string) ($this->rubrica->provincia ?? $resolvedAddress['provincia'] ?? ''),
|
|
'nazione' => (string) ($this->rubrica->nazione ?? 'Italia'),
|
|
'indirizzo_completo' => (string) ($this->rubrica->indirizzo_completo ?? ''),
|
|
'tipo_utenza_call' => (string) ($this->rubrica->tipo_utenza_call ?? ''),
|
|
'riferimento_stabile' => (string) ($this->rubrica->riferimento_stabile ?? ''),
|
|
'riferimento_unita' => (string) ($this->rubrica->riferimento_unita ?? ''),
|
|
'note' => (string) ($legacyIdentity['note_clean'] ?? $this->rubrica->note ?? ''),
|
|
'note_segreteria' => (string) ($this->rubrica->note_segreteria ?? ''),
|
|
];
|
|
}
|
|
|
|
private function cleanNullable(mixed $value): mixed
|
|
{
|
|
if (! is_string($value)) {
|
|
return $value;
|
|
}
|
|
|
|
$trim = trim($value);
|
|
|
|
return $trim === '' ? null : $trim;
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private function extractLegacyIdentityFromNote(mixed $note): array
|
|
{
|
|
$raw = trim((string) ($note ?? ''));
|
|
if ($raw === '') {
|
|
return [
|
|
'note_clean' => null,
|
|
'titolo_id' => null,
|
|
'sesso' => null,
|
|
'data_nascita' => null,
|
|
'luogo_nascita' => null,
|
|
'provincia_nascita' => null,
|
|
];
|
|
}
|
|
|
|
$parsed = [
|
|
'titolo_id' => null,
|
|
'sesso' => null,
|
|
'data_nascita' => null,
|
|
'luogo_nascita' => null,
|
|
'provincia_nascita' => null,
|
|
];
|
|
|
|
$cleanLines = [];
|
|
foreach (preg_split('/\r\n|\r|\n/', $raw) ?: [] as $line) {
|
|
$trimmed = trim($line);
|
|
if (! str_starts_with($trimmed, 'Dati anagrafici legacy:')) {
|
|
$cleanLines[] = $line;
|
|
continue;
|
|
}
|
|
|
|
$payload = trim(substr($trimmed, strlen('Dati anagrafici legacy:')));
|
|
$bits = preg_split('/\s*\|\s*/', $payload) ?: [];
|
|
foreach ($bits as $bit) {
|
|
[$key, $value] = array_pad(explode(':', $bit, 2), 2, null);
|
|
$key = mb_strtolower(trim((string) $key));
|
|
$value = trim((string) $value);
|
|
if ($value === '') {
|
|
continue;
|
|
}
|
|
|
|
if ($key === 'titolo') {
|
|
$parsed['titolo_id'] = $this->resolveTitoloId($value);
|
|
continue;
|
|
}
|
|
if ($key === 'sesso') {
|
|
$parsed['sesso'] = $this->normalizeSessoValue($value);
|
|
continue;
|
|
}
|
|
if ($key === 'data nascita') {
|
|
$parsed['data_nascita'] = $this->normalizeLegacyDateValue($value);
|
|
continue;
|
|
}
|
|
if ($key === 'luogo nascita') {
|
|
$parsed['luogo_nascita'] = $value;
|
|
continue;
|
|
}
|
|
if ($key === 'provincia nascita') {
|
|
$parsed['provincia_nascita'] = $this->normalizeProvince($value);
|
|
}
|
|
}
|
|
}
|
|
|
|
$cleanLines = array_values(array_filter($cleanLines, fn($line) => trim((string) $line) !== ''));
|
|
|
|
return $parsed + [
|
|
'note_clean' => $cleanLines === [] ? null : implode("\n", $cleanLines),
|
|
];
|
|
}
|
|
|
|
/** @return array<string, ?string> */
|
|
private function parseAddressComponents(mixed $value): array
|
|
{
|
|
$full = trim((string) ($value ?? ''));
|
|
if ($full === '') {
|
|
return [
|
|
'indirizzo' => null,
|
|
'civico' => null,
|
|
'cap' => null,
|
|
'citta' => null,
|
|
'provincia' => null,
|
|
];
|
|
}
|
|
|
|
$parts = [
|
|
'indirizzo' => $full,
|
|
'civico' => null,
|
|
'cap' => null,
|
|
'citta' => null,
|
|
'provincia' => null,
|
|
];
|
|
|
|
if (preg_match('/\((?<provincia>[A-Za-z]{2})\)\s*$/', $full, $provinceMatch) === 1) {
|
|
$parts['provincia'] = strtoupper($provinceMatch['provincia']);
|
|
$full = trim(substr($full, 0, -strlen($provinceMatch[0])));
|
|
}
|
|
|
|
if (preg_match('/\b(?<cap>\d{5})\b/', $full, $capMatch, PREG_OFFSET_CAPTURE) === 1) {
|
|
$parts['cap'] = $capMatch['cap'][0];
|
|
$capPos = $capMatch['cap'][1];
|
|
$beforeCap = trim(substr($full, 0, $capPos));
|
|
$afterCap = trim(substr($full, $capPos + 5));
|
|
if ($afterCap !== '') {
|
|
$parts['citta'] = $afterCap;
|
|
}
|
|
$full = $beforeCap;
|
|
}
|
|
|
|
if (preg_match('/^(?<indirizzo>.*?)(?:,\s*|\s+)(?<civico>\d+[A-Za-z\/-]*)$/', $full, $streetMatch) === 1) {
|
|
$parts['indirizzo'] = trim($streetMatch['indirizzo']) ?: null;
|
|
$parts['civico'] = trim($streetMatch['civico']) ?: null;
|
|
} else {
|
|
$parts['indirizzo'] = $full;
|
|
}
|
|
|
|
return $parts;
|
|
}
|
|
|
|
private function normalizeLegacyDateValue(mixed $value): ?string
|
|
{
|
|
if ($value instanceof \DateTimeInterface) {
|
|
return $value->format('Y-m-d');
|
|
}
|
|
|
|
$raw = trim((string) ($value ?? ''));
|
|
if ($raw === '') {
|
|
return null;
|
|
}
|
|
|
|
foreach (['Y-m-d', 'd/m/Y', 'd-m-Y', 'd.m.Y', 'd/m/y', 'd-m-y', 'd.m.y', 'm/d/Y', 'm/d/y'] as $format) {
|
|
$dt = \DateTime::createFromFormat($format, $raw);
|
|
if ($dt instanceof \DateTime) {
|
|
return $this->normalizeCenturyDrift($dt)->format('Y-m-d');
|
|
}
|
|
}
|
|
|
|
$ts = strtotime($raw);
|
|
if ($ts === false) {
|
|
return null;
|
|
}
|
|
|
|
return $this->normalizeCenturyDrift((new \DateTime())->setTimestamp($ts))->format('Y-m-d');
|
|
}
|
|
|
|
private function normalizeCenturyDrift(\DateTime $date): \DateTime
|
|
{
|
|
$thresholdYear = (int) date('Y') + 1;
|
|
if ((int) $date->format('Y') > $thresholdYear) {
|
|
$date->modify('-100 years');
|
|
}
|
|
|
|
return $date;
|
|
}
|
|
|
|
private function normalizeSessoValue(mixed $value): ?string
|
|
{
|
|
$raw = strtoupper(trim((string) ($value ?? '')));
|
|
if ($raw === '') {
|
|
return null;
|
|
}
|
|
if ($raw === 'M' || str_starts_with($raw, 'MAS')) {
|
|
return 'M';
|
|
}
|
|
if ($raw === 'F' || str_starts_with($raw, 'FEM')) {
|
|
return 'F';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function normalizeProvince(mixed $value): ?string
|
|
{
|
|
$raw = strtoupper(trim((string) ($value ?? '')));
|
|
if ($raw === '') {
|
|
return null;
|
|
}
|
|
|
|
return substr($raw, 0, 2);
|
|
}
|
|
|
|
private function resolveTitoloId(?string $raw): ?int
|
|
{
|
|
$raw = trim((string) ($raw ?? ''));
|
|
if ($raw === '' || ! Schema::hasTable('titoli')) {
|
|
return null;
|
|
}
|
|
|
|
$key = mb_strtolower($raw);
|
|
$title = Titolo::query()
|
|
->whereRaw('LOWER(sigla) = ?', [$key])
|
|
->orWhereRaw('LOWER(nome) = ?', [$key])
|
|
->first();
|
|
|
|
return $title?->id ? (int) $title->id : null;
|
|
}
|
|
|
|
private function hydrateEmailMultiple(): void
|
|
{
|
|
$persona = $this->resolvePersonaForRubrica(false);
|
|
if (! $persona instanceof Persona) {
|
|
$this->emailMultiple = [];
|
|
return;
|
|
}
|
|
|
|
$this->emailMultiple = $persona->emailMultiple()
|
|
->orderByDesc('attiva')
|
|
->orderBy('tipo_email')
|
|
->orderBy('email')
|
|
->get()
|
|
->map(fn(PersonaEmailMultipla $row): array=> [
|
|
'id' => (int) $row->id,
|
|
'email' => (string) $row->email,
|
|
'tipo_email' => (string) ($row->tipo_email ?? 'secondaria'),
|
|
'attiva' => (bool) $row->attiva,
|
|
])
|
|
->all();
|
|
}
|
|
|
|
/** @return array<int, array<string, mixed>> */
|
|
private function getAdditionalEmailsFormRows(): array
|
|
{
|
|
return $this->emailMultiple;
|
|
}
|
|
|
|
/** @param array<int, array<string, mixed>> $rows */
|
|
private function saveAdditionalEmails(array $rows): void
|
|
{
|
|
$persona = $this->resolvePersonaForRubrica(true);
|
|
if (! $persona instanceof Persona) {
|
|
throw new \RuntimeException('Impossibile associare la rubrica a una persona.');
|
|
}
|
|
|
|
$this->syncPersonaFromRubrica($persona);
|
|
|
|
DB::transaction(function () use ($rows, $persona): void {
|
|
$keepIds = [];
|
|
|
|
foreach (array_values($rows) as $row) {
|
|
$email = mb_strtolower(trim((string) ($row['email'] ?? '')));
|
|
if ($email === '') {
|
|
continue;
|
|
}
|
|
|
|
$attrs = [
|
|
'email' => $email,
|
|
'tipo_email' => trim((string) ($row['tipo_email'] ?? 'secondaria')) ?: 'secondaria',
|
|
'attiva' => (bool) ($row['attiva'] ?? true),
|
|
];
|
|
|
|
$id = (int) ($row['id'] ?? 0);
|
|
if ($id > 0) {
|
|
$existing = PersonaEmailMultipla::query()
|
|
->where('persona_id', (int) $persona->id)
|
|
->where('id', $id)
|
|
->first();
|
|
|
|
if ($existing instanceof PersonaEmailMultipla) {
|
|
$existing->fill($attrs);
|
|
$existing->save();
|
|
$keepIds[] = (int) $existing->id;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$created = PersonaEmailMultipla::query()->create([
|
|
'persona_id' => (int) $persona->id,
|
|
...$attrs,
|
|
]);
|
|
$keepIds[] = (int) $created->id;
|
|
}
|
|
|
|
$deleteQuery = PersonaEmailMultipla::query()->where('persona_id', (int) $persona->id);
|
|
if ($keepIds !== []) {
|
|
$deleteQuery->whereNotIn('id', $keepIds);
|
|
}
|
|
$deleteQuery->delete();
|
|
});
|
|
|
|
$this->hydrateEmailMultiple();
|
|
}
|
|
|
|
private function resolvePersonaForRubrica(bool $createIfMissing): ?Persona
|
|
{
|
|
if (! Schema::hasTable('persone')) {
|
|
return null;
|
|
}
|
|
|
|
$cf = trim((string) ($this->rubrica->codice_fiscale ?? ''));
|
|
if ($cf !== '') {
|
|
$found = Persona::query()->where('codice_fiscale', $cf)->first();
|
|
if ($found instanceof Persona) {
|
|
return $found;
|
|
}
|
|
}
|
|
|
|
$email = mb_strtolower(trim((string) ($this->rubrica->email ?? '')));
|
|
if ($email !== '') {
|
|
$found = Persona::query()->whereRaw('LOWER(email_principale) = ?', [$email])->first();
|
|
if ($found instanceof Persona) {
|
|
return $found;
|
|
}
|
|
|
|
if (Schema::hasTable('persone_email_multiple')) {
|
|
$match = Persona::query()
|
|
->whereHas('emailMultiple', fn(EloquentBuilderContract $query) => $query->where('email', $email))
|
|
->first();
|
|
if ($match instanceof Persona) {
|
|
return $match;
|
|
}
|
|
}
|
|
}
|
|
|
|
$phone = trim((string) ($this->rubrica->telefono_cellulare ?: $this->rubrica->telefono_ufficio ?: ''));
|
|
if ($phone !== '') {
|
|
$found = Persona::query()->where('telefono_principale', $phone)->first();
|
|
if ($found instanceof Persona) {
|
|
return $found;
|
|
}
|
|
}
|
|
|
|
$nome = trim((string) ($this->rubrica->nome ?? ''));
|
|
$cognome = trim((string) ($this->rubrica->cognome ?? ''));
|
|
if ($nome !== '' && $cognome !== '') {
|
|
$found = Persona::query()->where('nome', $nome)->where('cognome', $cognome)->first();
|
|
if ($found instanceof Persona) {
|
|
return $found;
|
|
}
|
|
}
|
|
|
|
if (! $createIfMissing) {
|
|
return null;
|
|
}
|
|
|
|
if ($nome === '' && $cognome === '' && trim((string) ($this->rubrica->ragione_sociale ?? '')) === '') {
|
|
return null;
|
|
}
|
|
|
|
$persona = Persona::query()->create([
|
|
'tipologia' => $this->rubrica->tipo_contatto === 'persona_giuridica' ? 'giuridica' : 'fisica',
|
|
'nome' => $nome !== '' ? $nome : (trim((string) ($this->rubrica->ragione_sociale ?? '')) !== '' ? 'Impresa' : 'N/D'),
|
|
'cognome' => $cognome !== '' ? $cognome : (trim((string) ($this->rubrica->ragione_sociale ?? '')) !== '' ? trim((string) $this->rubrica->ragione_sociale) : 'N/D'),
|
|
'ragione_sociale' => $this->rubrica->ragione_sociale,
|
|
'codice_fiscale' => $cf !== '' ? $cf : null,
|
|
'partita_iva' => $this->rubrica->partita_iva,
|
|
'data_nascita' => $this->rubrica->data_nascita,
|
|
'residenza_via' => $this->rubrica->indirizzo_completo,
|
|
'telefono_principale' => $phone !== '' ? $phone : null,
|
|
'telefono_secondario' => $this->rubrica->telefono_casa,
|
|
'email_principale' => $email !== '' ? $email : null,
|
|
'email_pec' => $this->rubrica->pec,
|
|
'note' => $this->rubrica->note,
|
|
'attivo' => $this->rubrica->stato !== 'inattivo',
|
|
]);
|
|
|
|
return $persona;
|
|
}
|
|
|
|
private function syncPersonaFromRubrica(Persona $persona): void
|
|
{
|
|
$updates = [];
|
|
|
|
if (! $persona->email_principale && $this->rubrica->email) {
|
|
$updates['email_principale'] = mb_strtolower(trim((string) $this->rubrica->email));
|
|
}
|
|
if (! $persona->email_pec && $this->rubrica->pec) {
|
|
$updates['email_pec'] = $this->rubrica->pec;
|
|
}
|
|
if (! $persona->telefono_principale && ($this->rubrica->telefono_cellulare || $this->rubrica->telefono_ufficio)) {
|
|
$updates['telefono_principale'] = $this->rubrica->telefono_cellulare ?: $this->rubrica->telefono_ufficio;
|
|
}
|
|
if (! $persona->residenza_via && $this->rubrica->indirizzo_completo) {
|
|
$updates['residenza_via'] = $this->rubrica->indirizzo_completo;
|
|
}
|
|
if (! $persona->data_nascita && $this->rubrica->data_nascita) {
|
|
$updates['data_nascita'] = $this->rubrica->data_nascita;
|
|
}
|
|
if (! $persona->codice_fiscale && $this->rubrica->codice_fiscale) {
|
|
$updates['codice_fiscale'] = $this->rubrica->codice_fiscale;
|
|
}
|
|
if (! $persona->partita_iva && $this->rubrica->partita_iva) {
|
|
$updates['partita_iva'] = $this->rubrica->partita_iva;
|
|
}
|
|
|
|
if ($updates !== []) {
|
|
$persona->fill($updates);
|
|
$persona->save();
|
|
}
|
|
}
|
|
|
|
public function getUrlUnita(?int $unitaId): ?string
|
|
{
|
|
if (! $unitaId) {
|
|
return null;
|
|
}
|
|
|
|
if (! class_exists(\App\Filament\Pages\UnitaImmobiliarePage::class)) {
|
|
return null;
|
|
}
|
|
|
|
return \App\Filament\Pages\UnitaImmobiliarePage::getUrl(panel: 'admin-filament')
|
|
. '?unita_id=' . (int) $unitaId
|
|
. '&back=' . urlencode((string) request()->getRequestUri());
|
|
}
|
|
|
|
/** @return array<string, string> */
|
|
protected static function getRuoliLabels(): array
|
|
{
|
|
return [
|
|
'super_admin' => 'Super admin',
|
|
'amministratore' => 'Amministratore',
|
|
'condomino' => 'Condomino',
|
|
'inquilino' => 'Inquilino',
|
|
'fornitore' => 'Fornitore',
|
|
'manutentore' => 'Manutentore',
|
|
'banca' => 'Banca',
|
|
'assicurazione' => 'Assicurazione',
|
|
'collaboratore' => 'Collaboratore',
|
|
'tester' => 'Tester',
|
|
'ospite' => 'Ospite',
|
|
'altro' => 'Altro',
|
|
];
|
|
}
|
|
|
|
/** @return array<int, string> */
|
|
protected function getStabiliOptions(): array
|
|
{
|
|
$query = Stabile::query();
|
|
|
|
$user = Auth::user();
|
|
$isSuperAdmin = $user instanceof User && method_exists($user, 'hasRole')
|
|
? (bool) $user->hasRole('super-admin')
|
|
: false;
|
|
|
|
if (! $isSuperAdmin && $this->adminId > 0) {
|
|
$query->where('amministratore_id', $this->adminId);
|
|
}
|
|
|
|
return $query
|
|
->orderBy('codice_stabile')
|
|
->limit(200)
|
|
->get(['id', 'codice_stabile', 'denominazione'])
|
|
->mapWithKeys(fn(Stabile $s) => [
|
|
(int) $s->id => trim((string) ($s->codice_operatore ?? $s->codice_stabile ?? '') . ' - ' . (string) ($s->denominazione ?? 'Stabile')),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
/** @return array<int, string> */
|
|
protected function getTitoliOptions(): array
|
|
{
|
|
if (! Schema::hasTable('titoli')) {
|
|
return [];
|
|
}
|
|
|
|
return Titolo::query()
|
|
->orderBy('ordine')
|
|
->orderBy('nome')
|
|
->get(['id', 'nome', 'sigla'])
|
|
->mapWithKeys(fn(Titolo $t) => [
|
|
(int) $t->id => trim((string) ($t->sigla ?: $t->nome)),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
/** @return array<int, string> */
|
|
protected function getUnitaOptions($stabileId): array
|
|
{
|
|
$stabileId = (int) ($stabileId ?? 0);
|
|
if ($stabileId <= 0) {
|
|
return [];
|
|
}
|
|
|
|
$query = UnitaImmobiliare::query()->where('stabile_id', $stabileId);
|
|
|
|
return $query
|
|
->orderBy('palazzina_id')
|
|
->orderBy('scala')
|
|
->orderBy('piano')
|
|
->orderBy('interno')
|
|
->orderBy('id')
|
|
->limit(1000)
|
|
->get(['id', 'codice_unita', 'denominazione', 'scala', 'piano', 'interno'])
|
|
->mapWithKeys(function (UnitaImmobiliare $u) {
|
|
$codice = $u->codice_unita ?: ('ID ' . $u->id);
|
|
$nome = $u->denominazione ?: 'Unità';
|
|
$pos = trim('Scala ' . ($u->scala ?? '-') . ' · Piano ' . ($u->piano ?? '-') . ' · Int. ' . ($u->interno ?? '-'));
|
|
|
|
return [(int) $u->id => trim($codice . ' — ' . $nome . ' (' . $pos . ')')];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function hydrateFornitoriWorkspace(): void
|
|
{
|
|
$rubricaId = (int) $this->rubrica->id;
|
|
$cf = trim((string) ($this->rubrica->codice_fiscale ?? ''));
|
|
$piva = trim((string) ($this->rubrica->partita_iva ?? ''));
|
|
$email = mb_strtolower(trim((string) ($this->rubrica->email ?? '')));
|
|
|
|
$query = Fornitore::query();
|
|
if ($this->adminId > 0) {
|
|
$query->where('amministratore_id', $this->adminId);
|
|
}
|
|
|
|
$query->where(function (Builder $q) use ($rubricaId, $cf, $piva, $email): void {
|
|
$q->where('rubrica_id', $rubricaId);
|
|
if ($cf !== '') {
|
|
$q->orWhere('codice_fiscale', $cf);
|
|
}
|
|
if ($piva !== '') {
|
|
$q->orWhere('partita_iva', $piva);
|
|
}
|
|
if ($email !== '') {
|
|
$q->orWhereRaw('LOWER(email) = ?', [$email]);
|
|
}
|
|
});
|
|
|
|
$fornitori = $query
|
|
->orderByRaw("COALESCE(ragione_sociale, '')")
|
|
->orderBy('id')
|
|
->limit(80)
|
|
->get(['id', 'rubrica_id', 'ragione_sociale', 'nome', 'cognome', 'email', 'telefono', 'cellulare', 'codice_fiscale', 'partita_iva']);
|
|
|
|
$this->fornitoriCollegati = $fornitori->map(fn(Fornitore $f) => [
|
|
'id' => (int) $f->id,
|
|
'nome' => (string) ($f->ragione_sociale ?: trim((string) ($f->nome ?? '') . ' ' . (string) ($f->cognome ?? '')) ?: ('Fornitore #' . $f->id)),
|
|
'rubrica_id' => (int) ($f->rubrica_id ?? 0),
|
|
'email' => (string) ($f->email ?? ''),
|
|
'telefono' => (string) ($f->telefono ?: $f->cellulare ?: ''),
|
|
'cf' => (string) ($f->codice_fiscale ?? ''),
|
|
'piva' => (string) ($f->partita_iva ?? ''),
|
|
])->all();
|
|
|
|
$fornitoreIds = $fornitori->pluck('id')->map(fn($v) => (int) $v)->all();
|
|
if ($fornitoreIds === []) {
|
|
$this->dipendentiFornitoreRows = [];
|
|
return;
|
|
}
|
|
|
|
$dipendenti = FornitoreDipendente::query()
|
|
->with(['user.roles', 'fornitore'])
|
|
->whereIn('fornitore_id', $fornitoreIds)
|
|
->orderByDesc('attivo')
|
|
->orderBy('cognome')
|
|
->orderBy('nome')
|
|
->limit(300)
|
|
->get();
|
|
|
|
$this->dipendentiFornitoreRows = $dipendenti->map(function (FornitoreDipendente $d): array {
|
|
$user = $d->user;
|
|
$this->dipendentePbxExtension[(int) $d->id] = (string) ($user?->pbx_extension ?? '');
|
|
|
|
return [
|
|
'id' => (int) $d->id,
|
|
'fornitore_id' => (int) $d->fornitore_id,
|
|
'fornitore_nome' => (string) ($d->fornitore?->ragione_sociale ?: ('Fornitore #' . $d->fornitore_id)),
|
|
'nome' => (string) $d->nome_completo,
|
|
'email' => (string) ($d->email ?? ''),
|
|
'telefono' => (string) ($d->telefono ?? ''),
|
|
'attivo' => (bool) $d->attivo,
|
|
'user_id' => $user ? (int) $user->id : null,
|
|
'ruoli' => $user ? $user->roles->pluck('name')->values()->all() : [],
|
|
'pbx_extension' => (string) ($user?->pbx_extension ?? ''),
|
|
];
|
|
})->all();
|
|
}
|
|
|
|
public function collegaRubricaDipendente(int $fornitoreId): void
|
|
{
|
|
$rubricaId = (int) ($this->dipendenteRubricaSelect[$fornitoreId] ?? 0);
|
|
if ($rubricaId <= 0) {
|
|
Notification::make()->title('Inserisci ID rubrica da collegare')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$fornitore = Fornitore::query()->find($fornitoreId);
|
|
if (! $fornitore || ($this->adminId > 0 && (int) ($fornitore->amministratore_id ?? 0) !== $this->adminId)) {
|
|
Notification::make()->title('Fornitore non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$rubricaDip = RubricaUniversale::query()->find($rubricaId);
|
|
if (! $rubricaDip) {
|
|
Notification::make()->title('Rubrica dipendente non trovata')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$email = mb_strtolower(trim((string) ($rubricaDip->email ?? '')));
|
|
$query = FornitoreDipendente::query()->where('fornitore_id', (int) $fornitore->id);
|
|
if ($email !== '') {
|
|
$query->whereRaw('LOWER(email) = ?', [$email]);
|
|
} else {
|
|
$query->where('nome', (string) ($rubricaDip->nome ?? ''))
|
|
->where('cognome', (string) ($rubricaDip->cognome ?? ''));
|
|
}
|
|
|
|
$dip = $query->first();
|
|
if (! $dip) {
|
|
$dip = new FornitoreDipendente();
|
|
$dip->fornitore_id = (int) $fornitore->id;
|
|
$dip->created_by_user_id = Auth::id();
|
|
}
|
|
|
|
$dip->nome = (string) ($rubricaDip->nome ?: $rubricaDip->ragione_sociale ?: 'Dipendente');
|
|
$dip->cognome = (string) ($rubricaDip->cognome ?? '');
|
|
$dip->email = $email !== '' ? $email : null;
|
|
$dip->telefono = (string) ($rubricaDip->telefono_cellulare ?: $rubricaDip->telefono_ufficio ?: '');
|
|
$dip->attivo = true;
|
|
$dip->updated_by_user_id = Auth::id();
|
|
$dip->save();
|
|
|
|
unset($this->dipendenteRubricaSelect[$fornitoreId]);
|
|
$this->hydrateFornitoriWorkspace();
|
|
|
|
Notification::make()->title('Dipendente collegato da rubrica')->success()->send();
|
|
}
|
|
|
|
public function creaDipendenteManuale(int $fornitoreId): void
|
|
{
|
|
$draft = (array) ($this->dipendenteManualDraft[$fornitoreId] ?? []);
|
|
$nome = trim((string) ($draft['nome'] ?? ''));
|
|
$cognome = trim((string) ($draft['cognome'] ?? ''));
|
|
$email = mb_strtolower(trim((string) ($draft['email'] ?? '')));
|
|
$telefono = trim((string) ($draft['telefono'] ?? ''));
|
|
|
|
if ($nome === '') {
|
|
Notification::make()->title('Nome dipendente obbligatorio')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$fornitore = Fornitore::query()->find($fornitoreId);
|
|
if (! $fornitore || ($this->adminId > 0 && (int) ($fornitore->amministratore_id ?? 0) !== $this->adminId)) {
|
|
Notification::make()->title('Fornitore non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$dip = new FornitoreDipendente();
|
|
$dip->fornitore_id = (int) $fornitore->id;
|
|
$dip->nome = $nome;
|
|
$dip->cognome = $cognome !== '' ? $cognome : null;
|
|
$dip->email = $email !== '' ? $email : null;
|
|
$dip->telefono = $telefono !== '' ? $telefono : null;
|
|
$dip->attivo = true;
|
|
$dip->created_by_user_id = Auth::id();
|
|
$dip->updated_by_user_id = Auth::id();
|
|
$dip->save();
|
|
|
|
unset($this->dipendenteManualDraft[$fornitoreId]);
|
|
$this->hydrateFornitoriWorkspace();
|
|
|
|
Notification::make()->title('Nuovo dipendente creato')->success()->send();
|
|
}
|
|
|
|
public function abilitaAccessoDipendente(int $dipendenteId): void
|
|
{
|
|
$dip = FornitoreDipendente::query()->with('fornitore')->find($dipendenteId);
|
|
if (! $dip || ($this->adminId > 0 && (int) ($dip->fornitore?->amministratore_id ?? 0) !== $this->adminId)) {
|
|
Notification::make()->title('Dipendente non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$email = mb_strtolower(trim((string) ($dip->email ?? '')));
|
|
if ($email === '') {
|
|
Notification::make()->title('Email dipendente mancante')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$user = User::query()->whereRaw('LOWER(email) = ?', [$email])->first();
|
|
if (! $user) {
|
|
$tmpPwd = Str::random(12);
|
|
$user = User::query()->create([
|
|
'name' => trim((string) ($dip->nome_completo ?: 'Utente fornitore')),
|
|
'email' => $email,
|
|
'password' => Hash::make($tmpPwd),
|
|
'email_verified_at' => now(),
|
|
'is_active' => true,
|
|
]);
|
|
}
|
|
|
|
$user->assignRole('fornitore');
|
|
$dip->user_id = (int) $user->id;
|
|
$dip->updated_by_user_id = Auth::id();
|
|
$dip->save();
|
|
|
|
$this->hydrateFornitoriWorkspace();
|
|
Notification::make()->title('Accesso dipendente abilitato')->success()->send();
|
|
}
|
|
|
|
public function salvaInternoDipendente(int $dipendenteId): void
|
|
{
|
|
$dip = FornitoreDipendente::query()->with('user', 'fornitore')->find($dipendenteId);
|
|
if (! $dip || ! $dip->user || ($this->adminId > 0 && (int) ($dip->fornitore?->amministratore_id ?? 0) !== $this->adminId)) {
|
|
Notification::make()->title('Dipendente/utente non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
if (! Schema::hasColumn('users', 'pbx_extension')) {
|
|
Notification::make()->title('Campo interno PBX non disponibile')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$ext = trim((string) ($this->dipendentePbxExtension[$dipendenteId] ?? ''));
|
|
$dip->user->pbx_extension = $ext !== '' ? $ext : null;
|
|
$dip->user->save();
|
|
|
|
$this->hydrateFornitoriWorkspace();
|
|
Notification::make()->title('Interno PBX aggiornato')->success()->send();
|
|
}
|
|
}
|