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