385 lines
14 KiB
PHP
Executable File
385 lines
14 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Persona;
|
|
use App\Models\PersonaUnitaRelazione;
|
|
use App\Models\TipoRelazionePersonaUnita;
|
|
use App\Models\UnitaImmobiliare;
|
|
use App\Models\PersonaAudit;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
class RubricaUnicaController extends Controller
|
|
{
|
|
/**
|
|
* Dashboard Rubrica Unica
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$query = Persona::with(['relazioniUnitaAttive.unitaImmobiliare.stabile'])
|
|
->attive();
|
|
|
|
// Filtri di ricerca
|
|
if ($request->filled('search')) {
|
|
$search = $request->search;
|
|
$query->where(function ($q) use ($search) {
|
|
$q->ricercaNome($search)
|
|
->orWhere('codice_interno', 'LIKE', "%{$search}%")
|
|
->orWhere('codice_fiscale', 'LIKE', "%{$search}%")
|
|
->orWhere('telefono_principale', 'LIKE', "%{$search}%")
|
|
->orWhere('email_principale', 'LIKE', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
if ($request->filled('tipologia')) {
|
|
$query->where('tipologia', $request->tipologia);
|
|
}
|
|
|
|
$persone = $query->orderBy('cognome')->orderBy('nome')->paginate(20);
|
|
|
|
// Statistiche
|
|
$statistiche = [
|
|
'totale_persone' => Persona::attive()->count(),
|
|
'persone_fisiche' => Persona::attive()->fisiche()->count(),
|
|
'persone_giuridiche' => Persona::attive()->giuridiche()->count(),
|
|
'con_relazioni_attive' => Persona::attive()->whereHas('relazioniUnitaAttive')->count(),
|
|
'senza_relazioni' => Persona::attive()->whereDoesntHave('relazioniUnitaAttive')->count(),
|
|
];
|
|
|
|
return view('admin.rubrica.index', compact('persone', 'statistiche'));
|
|
}
|
|
|
|
/**
|
|
* Scheda persona completa
|
|
*/
|
|
public function show(Persona $persona)
|
|
{
|
|
$persona->load([
|
|
'relazioniUnita.unitaImmobiliare.stabile',
|
|
'relazioniUnita.tipoRelazioneDettagli',
|
|
'emailMultiple' => function ($query) {
|
|
$query->attive();
|
|
},
|
|
'auditModifiche' => function ($query) {
|
|
$query->orderBy('data_modifica', 'desc')->limit(10);
|
|
}
|
|
]);
|
|
|
|
$tipiRelazione = TipoRelazionePersonaUnita::attivi()->ordinati()->get();
|
|
|
|
return view('admin.rubrica.show', compact('persona', 'tipiRelazione'));
|
|
}
|
|
|
|
/**
|
|
* Form nuova persona
|
|
*/
|
|
public function create()
|
|
{
|
|
$tipiRelazione = TipoRelazionePersonaUnita::attivi()->ordinati()->get();
|
|
$unitaDisponibili = UnitaImmobiliare::with('stabile')->get();
|
|
|
|
return view('admin.rubrica.create', compact('tipiRelazione', 'unitaDisponibili'));
|
|
}
|
|
|
|
/**
|
|
* Salva nuova persona
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
// Validazione base
|
|
$validator = Validator::make($request->all(), [
|
|
'tipologia' => 'required|in:fisica,giuridica,ditta_individuale',
|
|
'cognome' => 'required|string|max:100',
|
|
'nome' => 'required|string|max:100',
|
|
'codice_fiscale' => 'nullable|string|size:16|unique:persone,codice_fiscale',
|
|
'telefono_principale' => 'nullable|string|max:20|unique:persone,telefono_principale',
|
|
'email_principale' => 'nullable|email|max:255',
|
|
'data_nascita' => 'nullable|date',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return back()->withErrors($validator)->withInput();
|
|
}
|
|
|
|
// Controllo duplicati avanzato
|
|
$duplicati = Persona::verificaDuplicati($request->all());
|
|
|
|
if (!empty($duplicati)) {
|
|
$duplicatiCritici = collect($duplicati)->where('tipo', 'CRITICO');
|
|
|
|
if (!$request->has('force_save') && $duplicatiCritici->isNotEmpty()) {
|
|
return back()
|
|
->withInput()
|
|
->with('duplicati', $duplicati)
|
|
->withErrors(['duplicati' => 'Trovati duplicati critici. Verifica i dati o procedi con il merge.']);
|
|
}
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
// Crea persona
|
|
$persona = Persona::create($request->only([
|
|
'tipologia',
|
|
'cognome',
|
|
'nome',
|
|
'codice_fiscale',
|
|
'partita_iva',
|
|
'data_nascita',
|
|
'residenza_via',
|
|
'telefono_principale',
|
|
'telefono_secondario',
|
|
'email_principale',
|
|
'email_pec',
|
|
'whatsapp',
|
|
'modalita_comunicazione_preferita',
|
|
'consenso_privacy',
|
|
'consenso_marketing',
|
|
'ragione_sociale',
|
|
'forma_giuridica',
|
|
'note'
|
|
]));
|
|
|
|
// Aggiungi relazioni con unità (se specificate)
|
|
if ($request->filled('relazioni')) {
|
|
foreach ($request->relazioni as $relazione) {
|
|
if (!empty($relazione['unita_id']) && !empty($relazione['tipo_relazione'])) {
|
|
PersonaUnitaRelazione::create([
|
|
'persona_id' => $persona->id,
|
|
'unita_id' => $relazione['unita_id'],
|
|
'tipo_relazione' => $relazione['tipo_relazione'],
|
|
'quota_relazione' => $relazione['quota_relazione'] ?? null,
|
|
'data_inizio' => $relazione['data_inizio'] ?? now(),
|
|
'riceve_comunicazioni' => $relazione['riceve_comunicazioni'] ?? true,
|
|
'riceve_convocazioni' => $relazione['riceve_convocazioni'] ?? true,
|
|
'vota_assemblea' => $relazione['vota_assemblea'] ?? false,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Registra audit
|
|
PersonaAudit::registraModifica(
|
|
$persona->id,
|
|
'CREAZIONE',
|
|
null,
|
|
'Persona creata',
|
|
auth()->user()->name ?? 'Sistema'
|
|
);
|
|
|
|
DB::commit();
|
|
|
|
return redirect()->route('admin.rubrica.show', $persona)
|
|
->with('success', 'Persona creata con successo! Codice: ' . $persona->codice_interno);
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore durante il salvataggio: ' . $e->getMessage()])->withInput();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Form modifica persona
|
|
*/
|
|
public function edit(Persona $persona)
|
|
{
|
|
$persona->load(['relazioniUnita', 'emailMultiple']);
|
|
$tipiRelazione = TipoRelazionePersonaUnita::attivi()->ordinati()->get();
|
|
$unitaDisponibili = UnitaImmobiliare::with('stabile')->get();
|
|
|
|
return view('admin.rubrica.edit', compact('persona', 'tipiRelazione', 'unitaDisponibili'));
|
|
}
|
|
|
|
/**
|
|
* Aggiorna persona
|
|
*/
|
|
public function update(Request $request, Persona $persona)
|
|
{
|
|
// Validazione
|
|
$validator = Validator::make($request->all(), [
|
|
'tipologia' => 'required|in:fisica,giuridica,ditta_individuale',
|
|
'cognome' => 'required|string|max:100',
|
|
'nome' => 'required|string|max:100',
|
|
'codice_fiscale' => 'nullable|string|size:16|unique:persone,codice_fiscale,' . $persona->id,
|
|
'telefono_principale' => 'nullable|string|max:20|unique:persone,telefono_principale,' . $persona->id,
|
|
'email_principale' => 'nullable|email|max:255',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return back()->withErrors($validator)->withInput();
|
|
}
|
|
|
|
// Controllo duplicati (escludendo la persona corrente)
|
|
$duplicati = Persona::verificaDuplicati($request->all(), $persona->id);
|
|
|
|
if (!empty($duplicati)) {
|
|
$duplicatiCritici = collect($duplicati)->where('tipo', 'CRITICO');
|
|
|
|
if (!$request->has('force_save') && $duplicatiCritici->isNotEmpty()) {
|
|
return back()
|
|
->withInput()
|
|
->with('duplicati', $duplicati)
|
|
->withErrors(['duplicati' => 'Trovati duplicati critici. Verifica i dati.']);
|
|
}
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
// Audit delle modifiche
|
|
$datiOriginali = $persona->getOriginal();
|
|
$datiNuovi = $request->only([
|
|
'tipologia',
|
|
'cognome',
|
|
'nome',
|
|
'codice_fiscale',
|
|
'partita_iva',
|
|
'data_nascita',
|
|
'residenza_via',
|
|
'telefono_principale',
|
|
'telefono_secondario',
|
|
'email_principale',
|
|
'email_pec',
|
|
'whatsapp',
|
|
'modalita_comunicazione_preferita',
|
|
'consenso_privacy',
|
|
'consenso_marketing',
|
|
'ragione_sociale',
|
|
'forma_giuridica',
|
|
'note'
|
|
]);
|
|
|
|
// Registra modifiche significative
|
|
foreach ($datiNuovi as $campo => $nuovoValore) {
|
|
$vecchioValore = $datiOriginali[$campo] ?? null;
|
|
|
|
if ($vecchioValore != $nuovoValore) {
|
|
PersonaAudit::registraModifica(
|
|
$persona->id,
|
|
$campo,
|
|
$vecchioValore,
|
|
$nuovoValore
|
|
);
|
|
}
|
|
}
|
|
|
|
// Aggiorna persona
|
|
$persona->update($datiNuovi);
|
|
|
|
DB::commit();
|
|
|
|
return redirect()->route('admin.rubrica.show', $persona)
|
|
->with('success', 'Persona aggiornata con successo!');
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore durante l\'aggiornamento: ' . $e->getMessage()])->withInput();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ricerca avanzata
|
|
*/
|
|
public function search(Request $request)
|
|
{
|
|
$risultati = collect();
|
|
|
|
if ($request->filled('q')) {
|
|
$termine = $request->q;
|
|
|
|
$risultati = Persona::with(['relazioniUnitaAttive.unitaImmobiliare.stabile'])
|
|
->where(function ($query) use ($termine) {
|
|
$query->ricercaNome($termine)
|
|
->orRicercaCodice($termine)
|
|
->orWhere('codice_fiscale', 'LIKE', "%{$termine}%")
|
|
->orWhere('telefono_principale', 'LIKE', "%{$termine}%");
|
|
})
|
|
->attive()
|
|
->limit(10)
|
|
->get();
|
|
}
|
|
|
|
return response()->json([
|
|
'risultati' => $risultati->map(function ($persona) {
|
|
return [
|
|
'id' => $persona->id,
|
|
'codice_interno' => $persona->codice_interno,
|
|
'nome_completo' => $persona->nome_completo,
|
|
'telefono' => $persona->telefono_principale,
|
|
'email' => $persona->email_principale,
|
|
'relazioni_count' => $persona->relazioniUnitaAttive->count(),
|
|
'url' => route('admin.rubrica.show', $persona)
|
|
];
|
|
})
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* API per ricerca veloce (per select2, autocomplete, etc)
|
|
*/
|
|
public function apiSearch(Request $request)
|
|
{
|
|
$persone = Persona::attive()
|
|
->ricercaNome($request->get('q', ''))
|
|
->limit(20)
|
|
->get(['id', 'codice_interno', 'cognome', 'nome', 'ragione_sociale']);
|
|
|
|
return response()->json([
|
|
'results' => $persone->map(function ($persona) {
|
|
return [
|
|
'id' => $persona->id,
|
|
'text' => $persona->nome_display
|
|
];
|
|
})
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Merge di persone duplicate
|
|
*/
|
|
public function merge(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'persona_principale_id' => 'required|exists:persone,id',
|
|
'persona_duplicata_id' => 'required|exists:persone,id|different:persona_principale_id'
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return back()->withErrors($validator);
|
|
}
|
|
|
|
$personaPrincipale = Persona::findOrFail($request->persona_principale_id);
|
|
$personaDuplicata = Persona::findOrFail($request->persona_duplicata_id);
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
// Trasferisci relazioni
|
|
PersonaUnitaRelazione::where('persona_id', $personaDuplicata->id)
|
|
->update(['persona_id' => $personaPrincipale->id]);
|
|
|
|
// Trasferisci email multiple
|
|
DB::table('persone_email_multiple')
|
|
->where('persona_id', $personaDuplicata->id)
|
|
->update(['persona_id' => $personaPrincipale->id]);
|
|
|
|
// Audit del merge
|
|
PersonaAudit::registraModifica(
|
|
$personaPrincipale->id,
|
|
'MERGE',
|
|
"Merge con persona ID: {$personaDuplicata->id}",
|
|
"Merge completato - dati consolidati"
|
|
);
|
|
|
|
// Disattiva persona duplicata
|
|
$personaDuplicata->update(['attivo' => false]);
|
|
|
|
DB::commit();
|
|
|
|
return redirect()->route('admin.rubrica.show', $personaPrincipale)
|
|
->with('success', 'Merge completato con successo!');
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore durante il merge: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
}
|