netgescon-master/app/Models/TabellaMillesimale.php

289 lines
7.7 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class TabellaMillesimale extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'tabelle_millesimali';
protected $fillable = [
'stabile_id',
'nome_tabella', // Campo effettivo nel database
'codice_tabella', // TAB.A, TAB.B, TAB.C, etc.
'nome_tabella_millesimale', // Mantengo per compatibilità
'denominazione', // Spese Generali, Spese Scale, etc.
'descrizione',
'tipo', // Mantengo per compatibilità
'tipo_tabella', // 'generali', 'scale', 'riscaldamento', 'ascensore', 'altro'
'tipo_calcolo', // 'millesimi', 'parti', 'fisso'
'totale_millesimi',
'attiva', // Mantengo per compatibilità
'stato_tabella', // 'attiva', 'sospesa', 'archiviata'
'data_approvazione',
'data_decorrenza',
'ordinamento',
'note',
'creato_da',
'modificato_da'
];
protected $casts = [
'attiva' => 'boolean',
'totale_millesimi' => 'decimal:4',
'data_approvazione' => 'date',
'data_decorrenza' => 'date',
'ordinamento' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
];
/**
* Relazione con Stabile
*/
public function stabile()
{
return $this->belongsTo(Stabile::class, 'stabile_id', 'id');
}
/**
* Relazione con Dettagli Millesimi
*/
public function dettagli()
{
return $this->hasMany(DettaglioMillesimale::class, 'tabella_id');
}
/**
* Relazione con dettagli millesimali per unità (nuovo nome)
*/
public function dettagliMillesimali()
{
return $this->hasMany(DettaglioMillesimale::class, 'tabella_id');
}
/**
* Relazione con utente che ha creato
*/
public function createBy()
{
return $this->belongsTo(User::class, 'creato_da');
}
/**
* Relazione con utente che ha modificato
*/
public function updatedBy()
{
return $this->belongsTo(User::class, 'modificato_da');
}
/**
* Relazione con RipartizioneSpese
*/
public function ripartizioniSpese()
{
return $this->hasMany(RipartizioneSpese::class);
}
/**
* Scope per tabelle attive
*/
public function scopeAttive($query)
{
return $query->where('attiva', true)
->orWhere('stato_tabella', 'attiva');
}
/**
* Scope per tipo tabella
*/
public function scopeTipo($query, $tipo)
{
return $query->where('tipo_tabella', $tipo)
->orWhere('tipo', $tipo);
}
/**
* Scope per stabile
*/
public function scopePerStabile($query, $stabileId)
{
return $query->where('stabile_id', $stabileId);
}
/**
* Scope ordinato
*/
public function scopeOrdinato($query)
{
return $query->orderBy('ordinamento')->orderBy('nome_tabella_millesimale');
}
/**
* Calcola il totale millesimi
*/
public function getTotaleMillesimiAttribute()
{
return $this->dettagli()->sum('millesimi');
}
/**
* Calcola totale millesimi dalla somma dei dettagli
*/
public function calcolaTotaleMillesimi()
{
return $this->dettagliMillesimali()->sum('millesimi');
}
/**
* Accessor per descrizione completa
*/
public function getDescrizioneCompletaAttribute()
{
$codice = $this->codice_tabella ?: $this->nome_tabella_millesimale;
$nome = $this->denominazione ?: $this->nome_tabella_millesimale;
return "{$codice} - {$nome}";
}
/**
* Verifica se la tabella è bilanciata (totale = 1000)
*/
public function getIsBilanciataAttribute()
{
$totale = $this->totale_millesimi;
return abs($totale - 1000) < 0.0001; // Tolleranza per errori di precisione
}
/**
* Verifica se la tabella è bilanciata
*/
public function isBilanciata()
{
$calcolato = $this->calcolaTotaleMillesimi();
return abs($calcolato - 1000) < 0.01; // Tolleranza di 0.01
}
/**
* Ottieni tutte le unità con i loro millesimi per questa tabella
*/
public function getUnitaConMillesimi()
{
return $this->dettagliMillesimali()
->with('unitaImmobiliare')
->orderBy('millesimi', 'desc')
->get();
}
/**
* Ottieni lo sbilanciamento della tabella
*/
public function getSbilanciamentoAttribute()
{
return $this->totale_millesimi - 1000;
}
/**
* Conta le unità immobiliari con millesimi assegnati
*/
public function getUnitaAssegnateAttribute()
{
return $this->dettagli()->count();
}
/**
* Accessor per riassunto tabella
*/
public function getRiassuntoAttribute()
{
return [
'nome' => $this->nome_tabella_millesimale,
'stabile' => $this->stabile->denominazione ?? 'N/A',
'unita_assegnate' => $this->unita_assegnate,
'totale_millesimi' => $this->totale_millesimi,
'is_bilanciata' => $this->is_bilanciata,
'sbilanciamento' => $this->sbilanciamento
];
}
/**
* Metodo per assegnare millesimi a un'unità immobiliare
*/
public function assegnaMillesimi($unitaImmobiliareId, $millesimi)
{
return DettaglioTabellaMillesimale::updateOrCreate(
[
'tabella_millesimale_id' => $this->id,
'unita_immobiliare_id' => $unitaImmobiliareId
],
[
'millesimi' => $millesimi
]
);
}
/**
* Metodo per bilanciare automaticamente la tabella
*/
public function bilancia()
{
$dettagli = $this->dettagli;
$totaleCorrente = $dettagli->sum('millesimi');
if ($totaleCorrente == 0) {
throw new \InvalidArgumentException('Impossibile bilanciare una tabella senza millesimi assegnati');
}
$fattoreCorrezione = 1000 / $totaleCorrente;
foreach ($dettagli as $dettaglio) {
$nuoviMillesimi = round($dettaglio->millesimi * $fattoreCorrezione, 4);
$dettaglio->update(['millesimi' => $nuoviMillesimi]);
}
return $this->fresh();
}
/**
* Ottieni tutte le tipologie standard di tabelle millesimali
*/
public static function getTipologieStandard()
{
return [
'proprieta_generale' => 'Proprietà Generale',
'scale' => 'Scale',
'ascensore' => 'Ascensore',
'riscaldamento' => 'Riscaldamento',
'acqua_calda' => 'Acqua Calda Sanitaria',
'condizionamento' => 'Condizionamento',
'garage' => 'Garage/Autorimesse',
'giardino' => 'Giardino',
'piscina' => 'Piscina',
'personalizzata' => 'Personalizzata'
];
}
/**
* Metodo per creare ripartizione spese automatica
*/
public function creaRipartizioneSpese($voceSpesaId, $importoTotale, $dataRipartizione = null)
{
return RipartizioneSpese::create([
'voce_spesa_id' => $voceSpesaId,
'stabile_id' => $this->id,
'tabella_millesimale_id' => $this->tabelleMillesimali()->where('tipo', 'generale')->first()?->id,
'tipo_ripartizione' => 'millesimale',
'importo_totale' => $importoTotale,
'data_ripartizione' => $dataRipartizione ?? now(),
'stato' => 'bozza',
'creato_da' => auth()->id() ?? 1
]);
}
}