netgescon-master/netgescon-laravel/app/Models/GestioneContabile.php
Michele Windows e68ee85a18 🚀 CHECKPOINT STABILE - Sistema Contabile Avanzato
📋 AGGIUNTE PRINCIPALI:
- Sistema contabile partita doppia con gestioni multiple
- Documentazione implementazione completa
- Models Laravel: GestioneContabile, MovimentoPartitaDoppia
- Controller ContabilitaAvanzataController
- Migration sistema contabile completo
- Scripts automazione e trasferimento
- Manuali utente e checklist implementazione

📊 FILES PRINCIPALI:
- docs/10-IMPLEMENTAZIONE-CONTABILITA-PARTITA-DOPPIA-GESTIONI.md
- SPECIFICHE-SISTEMA-CONTABILE-COMPLETO.md
- netgescon-laravel/database/migrations/2025_07_20_100000_create_complete_accounting_system.php
- netgescon-laravel/app/Models/GestioneContabile.php

 CHECKPOINT SICURO PER ROLLBACK
2025-07-26 15:11:19 +02:00

189 lines
4.7 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Gestione Contabile
* Rappresenta una gestione specifica all'interno di un esercizio contabile
*/
class GestioneContabile extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'gestioni_contabili';
protected $fillable = [
'codice_gestione',
'stabile_id',
'esercizio_contabile_id',
'denominazione',
'descrizione',
'tipologia',
'stato',
'data_apertura',
'data_chiusura',
'budget_previsto',
'fondo_cassa_iniziale',
'regole_ripartizione',
'tabella_millesimale_id',
];
protected $casts = [
'data_apertura' => 'date',
'data_chiusura' => 'date',
'budget_previsto' => 'decimal:2',
'fondo_cassa_iniziale' => 'decimal:2',
'regole_ripartizione' => 'json',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (!$model->codice_gestione) {
$model->codice_gestione = static::generateCodiceGestione();
}
});
}
/**
* Genera un codice univoco per la gestione
*/
public static function generateCodiceGestione(): string
{
do {
$codice = 'GES' . sprintf('%05d', rand(10000, 99999));
} while (static::where('codice_gestione', $codice)->exists());
return $codice;
}
/**
* Relazioni
*/
public function stabile(): BelongsTo
{
return $this->belongsTo(Stabile::class);
}
public function esercizioContabile(): BelongsTo
{
return $this->belongsTo(EsercizioContabile::class, 'esercizio_contabile_id');
}
public function tabellaMillesimale(): BelongsTo
{
return $this->belongsTo(TabellaMillesimale::class, 'tabella_millesimale_id');
}
public function movimenti(): HasMany
{
return $this->hasMany(MovimentoPartitaDoppia::class, 'gestione_contabile_id');
}
public function rate(): HasMany
{
return $this->hasMany(RataCondominiale::class, 'gestione_contabile_id');
}
/**
* Scopes
*/
public function scopeAttive($query)
{
return $query->where('stato', 'attiva');
}
public function scopeByTipologia($query, $tipologia)
{
return $query->where('tipologia', $tipologia);
}
/**
* Metodi di business logic
*/
public function calcolaTotaleMovimenti($tipo = null): float
{
$query = $this->movimenti()->where('stato_movimento', '!=', 'bozza');
if ($tipo) {
// Implementare logica per tipo entrata/uscita basata su dare/avere
}
return $query->sum('importo_netto');
}
public function calcolaSaldoContabile(): float
{
// Implementare calcolo saldo basato su partita doppia
$entrate = $this->movimenti()
->whereHas('righeContabili', function($q) {
$q->where('dare_avere', 'avere');
})
->sum('importo_netto');
$uscite = $this->movimenti()
->whereHas('righeContabili', function($q) {
$q->where('dare_avere', 'dare');
})
->sum('importo_netto');
return $entrate - $uscite;
}
public function getTotaleRateAttribute(): float
{
return $this->rate()->sum('importo_dovuto');
}
public function getTotaleIncassatoAttribute(): float
{
return $this->rate()->sum('importo_pagato');
}
public function getPercentualeIncassoAttribute(): float
{
$totale = $this->getTotaleRateAttribute();
if ($totale == 0) return 0;
return ($this->getTotaleIncassatoAttribute() / $totale) * 100;
}
/**
* Verifica se la gestione è chiudibile
*/
public function isChiudibile(): bool
{
// Verifica che tutti i movimenti siano confermati
$movimentiNonConfermati = $this->movimenti()
->whereIn('stato_movimento', ['bozza', 'da_verificare'])
->count();
return $movimentiNonConfermati === 0;
}
/**
* Chiude la gestione
*/
public function chiudiGestione(): bool
{
if (!$this->isChiudibile()) {
return false;
}
$this->update([
'stato' => 'chiusa',
'data_chiusura' => now(),
]);
return true;
}
}