386 lines
13 KiB
PHP
386 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Bilancio;
|
|
use App\Models\ScritturaBilancio;
|
|
use App\Models\Conguaglio;
|
|
use App\Models\Quadratura;
|
|
use App\Models\Stabile;
|
|
use App\Models\Gestione;
|
|
use App\Models\PianoConto;
|
|
use App\Models\MovimentoContabile;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Carbon\Carbon;
|
|
|
|
class BilancioController extends Controller
|
|
{
|
|
/**
|
|
* Dashboard bilanci
|
|
*/
|
|
public function index()
|
|
{
|
|
$amministratore_id = Auth::user()->amministratore->id_amministratore ?? null;
|
|
|
|
$bilanci = Bilancio::with(['stabile', 'gestione', 'approvatoDa'])
|
|
->whereHas('stabile', function($q) use ($amministratore_id) {
|
|
$q->where('amministratore_id', $amministratore_id);
|
|
})
|
|
->orderBy('anno_esercizio', 'desc')
|
|
->orderBy('created_at', 'desc')
|
|
->paginate(15);
|
|
|
|
// Statistiche
|
|
$stats = [
|
|
'bilanci_aperti' => Bilancio::whereHas('stabile', function($q) use ($amministratore_id) {
|
|
$q->where('amministratore_id', $amministratore_id);
|
|
})->whereIn('stato', ['bozza', 'provvisorio'])->count(),
|
|
|
|
'bilanci_approvati' => Bilancio::whereHas('stabile', function($q) use ($amministratore_id) {
|
|
$q->where('amministratore_id', $amministratore_id);
|
|
})->where('stato', 'approvato')->count(),
|
|
|
|
'conguagli_da_pagare' => Conguaglio::whereHas('bilancio.stabile', function($q) use ($amministratore_id) {
|
|
$q->where('amministratore_id', $amministratore_id);
|
|
})->where('stato', 'calcolato')->count(),
|
|
|
|
'totale_avanzi' => Bilancio::whereHas('stabile', function($q) use ($amministratore_id) {
|
|
$q->where('amministratore_id', $amministratore_id);
|
|
})->where('risultato_gestione', '>', 0)->sum('risultato_gestione'),
|
|
];
|
|
|
|
return view('admin.bilanci.index', compact('bilanci', 'stats'));
|
|
}
|
|
|
|
/**
|
|
* Form creazione bilancio
|
|
*/
|
|
public function create()
|
|
{
|
|
$amministratore_id = Auth::user()->amministratore->id_amministratore ?? null;
|
|
$stabili = Stabile::where('amministratore_id', $amministratore_id)->attivi()->get();
|
|
|
|
return view('admin.bilanci.create', compact('stabili'));
|
|
}
|
|
|
|
/**
|
|
* Store bilancio
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'stabile_id' => 'required|exists:stabili,id_stabile',
|
|
'gestione_id' => 'required|exists:gestioni,id_gestione',
|
|
'anno_esercizio' => 'required|integer|min:2020|max:2030',
|
|
'data_inizio_esercizio' => 'required|date',
|
|
'data_fine_esercizio' => 'required|date|after:data_inizio_esercizio',
|
|
'tipo_gestione' => 'required|in:ordinaria,riscaldamento,straordinaria,acqua,altro',
|
|
'descrizione' => 'required|string|max:255',
|
|
]);
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$bilancio = Bilancio::create([
|
|
'stabile_id' => $request->stabile_id,
|
|
'gestione_id' => $request->gestione_id,
|
|
'anno_esercizio' => $request->anno_esercizio,
|
|
'data_inizio_esercizio' => $request->data_inizio_esercizio,
|
|
'data_fine_esercizio' => $request->data_fine_esercizio,
|
|
'tipo_gestione' => $request->tipo_gestione,
|
|
'descrizione' => $request->descrizione,
|
|
'stato' => 'bozza',
|
|
'versione' => 1,
|
|
]);
|
|
|
|
// Importa movimenti contabili del periodo
|
|
$this->importaMovimentiContabili($bilancio);
|
|
|
|
DB::commit();
|
|
|
|
return redirect()->route('admin.bilanci.show', $bilancio)
|
|
->with('success', 'Bilancio creato con successo.');
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore durante la creazione: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Visualizza bilancio
|
|
*/
|
|
public function show(Bilancio $bilancio)
|
|
{
|
|
// Verifica accesso
|
|
if ($bilancio->stabile->amministratore_id !== Auth::user()->amministratore->id_amministratore ?? null) {
|
|
abort(403);
|
|
}
|
|
|
|
$bilancio->load([
|
|
'stabile',
|
|
'gestione',
|
|
'scritture.dettagli.conto',
|
|
'conguagli.unitaImmobiliare',
|
|
'quadrature',
|
|
'rimborsiAssicurativi'
|
|
]);
|
|
|
|
// Calcola totali aggiornati
|
|
$bilancio->calcolaTotali();
|
|
|
|
return view('admin.bilanci.show', compact('bilancio'));
|
|
}
|
|
|
|
/**
|
|
* Importa movimenti contabili nel bilancio
|
|
*/
|
|
private function importaMovimentiContabili(Bilancio $bilancio)
|
|
{
|
|
$movimenti = MovimentoContabile::where('stabile_id', $bilancio->stabile_id)
|
|
->where('gestione_id', $bilancio->gestione_id)
|
|
->whereBetween('data_registrazione', [
|
|
$bilancio->data_inizio_esercizio,
|
|
$bilancio->data_fine_esercizio
|
|
])
|
|
->with('dettagli')
|
|
->get();
|
|
|
|
foreach ($movimenti as $movimento) {
|
|
$this->creaScritturaDaMovimento($bilancio, $movimento);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crea scrittura bilancio da movimento contabile
|
|
*/
|
|
private function creaScritturaDaMovimento(Bilancio $bilancio, MovimentoContabile $movimento)
|
|
{
|
|
$scrittura = ScritturaBilancio::create([
|
|
'bilancio_id' => $bilancio->id,
|
|
'numero_scrittura' => $this->generaNumeroScrittura($bilancio),
|
|
'data_scrittura' => $movimento->data_registrazione,
|
|
'descrizione' => $movimento->descrizione,
|
|
'tipo_scrittura' => 'gestione',
|
|
'importo_totale' => $movimento->importo_totale,
|
|
'movimento_contabile_id' => $movimento->id,
|
|
'creato_da_user_id' => Auth::id(),
|
|
]);
|
|
|
|
// Crea dettagli in partita doppia
|
|
foreach ($movimento->dettagli as $dettaglio) {
|
|
$scrittura->dettagli()->create([
|
|
'conto_id' => $dettaglio->conto_id ?? $this->getContoDefault($movimento->tipo_movimento),
|
|
'importo_dare' => $dettaglio->importo_dare,
|
|
'importo_avere' => $dettaglio->importo_avere,
|
|
'descrizione_dettaglio' => $dettaglio->descrizione,
|
|
]);
|
|
}
|
|
|
|
return $scrittura;
|
|
}
|
|
|
|
/**
|
|
* Calcola conguagli
|
|
*/
|
|
public function calcolaConguagli(Bilancio $bilancio)
|
|
{
|
|
// Verifica accesso
|
|
if ($bilancio->stabile->amministratore_id !== Auth::user()->amministratore->id_amministratore ?? null) {
|
|
abort(403);
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$bilancio->calcolaConguagli();
|
|
|
|
DB::commit();
|
|
return back()->with('success', 'Conguagli calcolati con successo.');
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore nel calcolo conguagli: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Genera rate conguaglio
|
|
*/
|
|
public function generaRateConguaglio(Request $request, Bilancio $bilancio)
|
|
{
|
|
$request->validate([
|
|
'conguaglio_ids' => 'required|array',
|
|
'numero_rate' => 'required|integer|min:1|max:12',
|
|
'data_inizio' => 'required|date',
|
|
]);
|
|
|
|
// Verifica accesso
|
|
if ($bilancio->stabile->amministratore_id !== Auth::user()->amministratore->id_amministratore ?? null) {
|
|
abort(403);
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$dataInizio = Carbon::parse($request->data_inizio);
|
|
$rateGenerate = 0;
|
|
|
|
foreach ($request->conguaglio_ids as $conguaglioId) {
|
|
$conguaglio = Conguaglio::findOrFail($conguaglioId);
|
|
|
|
if ($conguaglio->bilancio_id !== $bilancio->id) {
|
|
continue;
|
|
}
|
|
|
|
$rate = $conguaglio->generaRate($request->numero_rate, $dataInizio, Auth::id());
|
|
$rateGenerate += $rate->count();
|
|
}
|
|
|
|
DB::commit();
|
|
return back()->with('success', "Generate {$rateGenerate} rate di conguaglio.");
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore nella generazione rate: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Quadratura bilancio
|
|
*/
|
|
public function quadratura(Request $request, Bilancio $bilancio)
|
|
{
|
|
$request->validate([
|
|
'data_quadratura' => 'required|date',
|
|
'saldo_banca_effettivo' => 'required|numeric',
|
|
]);
|
|
|
|
// Verifica accesso
|
|
if ($bilancio->stabile->amministratore_id !== Auth::user()->amministratore->id_amministratore ?? null) {
|
|
abort(403);
|
|
}
|
|
|
|
// Calcola saldo contabile
|
|
$saldoContabile = $this->calcolaSaldoContabile($bilancio, $request->data_quadratura);
|
|
|
|
// Calcola totali crediti/debiti
|
|
$totaleCrediti = $bilancio->conguagli()->where('tipo_conguaglio', 'a_credito')->sum('conguaglio_dovuto');
|
|
$totaleDebiti = $bilancio->conguagli()->where('tipo_conguaglio', 'a_debito')->sum('conguaglio_dovuto');
|
|
|
|
// Calcola rate
|
|
$totaleRateEmesse = $this->calcolaTotaleRateEmesse($bilancio);
|
|
$totaleRateIncassate = $this->calcolaTotaleRateIncassate($bilancio);
|
|
|
|
$differenza = $request->saldo_banca_effettivo - $saldoContabile;
|
|
|
|
$quadratura = Quadratura::create([
|
|
'bilancio_id' => $bilancio->id,
|
|
'data_quadratura' => $request->data_quadratura,
|
|
'saldo_banca_effettivo' => $request->saldo_banca_effettivo,
|
|
'saldo_contabile_calcolato' => $saldoContabile,
|
|
'differenza' => $differenza,
|
|
'totale_crediti_condomini' => $totaleCrediti,
|
|
'totale_debiti_condomini' => $totaleDebiti,
|
|
'totale_rate_emesse' => $totaleRateEmesse,
|
|
'totale_rate_incassate' => $totaleRateIncassate,
|
|
'quadratura_ok' => abs($differenza) < 0.01,
|
|
'verificato_da_user_id' => Auth::id(),
|
|
]);
|
|
|
|
return back()->with('success', 'Quadratura eseguita con successo.');
|
|
}
|
|
|
|
/**
|
|
* Chiusura esercizio
|
|
*/
|
|
public function chiusuraEsercizio(Request $request, Bilancio $bilancio)
|
|
{
|
|
$request->validate([
|
|
'motivo_chiusura' => 'required|string',
|
|
]);
|
|
|
|
// Verifica accesso e stato
|
|
if ($bilancio->stabile->amministratore_id !== Auth::user()->amministratore->id_amministratore ?? null) {
|
|
abort(403);
|
|
}
|
|
|
|
if ($bilancio->stato !== 'approvato') {
|
|
return back()->withErrors(['error' => 'Il bilancio deve essere approvato prima della chiusura.']);
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
// Genera scritture di chiusura
|
|
$bilancio->generaScritture ChiusuraEsercizio(Auth::id());
|
|
|
|
// Aggiorna stato bilancio
|
|
$bilancio->update([
|
|
'stato' => 'chiuso',
|
|
'data_chiusura' => now(),
|
|
'chiuso_da_user_id' => Auth::id(),
|
|
]);
|
|
|
|
DB::commit();
|
|
return back()->with('success', 'Esercizio chiuso con successo.');
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollback();
|
|
return back()->withErrors(['error' => 'Errore nella chiusura: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calcola saldo contabile alla data
|
|
*/
|
|
private function calcolaSaldoContabile(Bilancio $bilancio, $data)
|
|
{
|
|
// Implementazione calcolo saldo contabile
|
|
return $bilancio->totale_entrate - $bilancio->totale_uscite;
|
|
}
|
|
|
|
/**
|
|
* Calcola totale rate emesse
|
|
*/
|
|
private function calcolaTotaleRateEmesse(Bilancio $bilancio)
|
|
{
|
|
// Implementazione calcolo rate emesse
|
|
return 0; // Placeholder
|
|
}
|
|
|
|
/**
|
|
* Calcola totale rate incassate
|
|
*/
|
|
private function calcolaTotaleRateIncassate(Bilancio $bilancio)
|
|
{
|
|
// Implementazione calcolo rate incassate
|
|
return 0; // Placeholder
|
|
}
|
|
|
|
/**
|
|
* Genera numero scrittura
|
|
*/
|
|
private function generaNumeroScrittura(Bilancio $bilancio)
|
|
{
|
|
$ultimaScrittura = ScritturaBilancio::where('bilancio_id', $bilancio->id)
|
|
->orderBy('numero_scrittura', 'desc')
|
|
->first();
|
|
|
|
if ($ultimaScrittura) {
|
|
$numero = intval(substr($ultimaScrittura->numero_scrittura, -4)) + 1;
|
|
} else {
|
|
$numero = 1;
|
|
}
|
|
|
|
return 'SCR/' . $bilancio->anno_esercizio . '/' . str_pad($numero, 4, '0', STR_PAD_LEFT);
|
|
}
|
|
|
|
/**
|
|
* Get conto default per tipo movimento
|
|
*/
|
|
private function getContoDefault($tipoMovimento)
|
|
{
|
|
// Implementazione per ottenere conto default
|
|
return 1; // Placeholder
|
|
}
|
|
} |