netgescon-day0/app/Http/Controllers/Admin/RubricaUnicaController.php

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()]);
}
}
}