netgescon-master/_BACKUP_OLD_netgescon-laravel_INACTIVE/app/Models/Stabile.php

614 lines
18 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Stabile extends Model
{
use HasFactory;
protected $table = 'stabili';
protected $fillable = [
'amministratore_id',
'denominazione',
'codice_stabile',
'codice_fiscale',
'cod_fisc_amministratore',
'indirizzo',
'citta',
'cap',
'provincia',
'note',
'old_id',
'stato',
// Nuovi campi dati tecnici
'anno_costruzione',
'superficie_totale',
'numero_piani',
'numero_ascensori',
'numero_garage',
'numero_cantine',
// Nuovi campi amministratore
'nome_amministratore',
'telefono_amministratore',
'email_amministratore',
'data_nomina_amministratore',
// Campi bancari
'iban_principale',
'banca_principale',
'filiale',
'iban_secondario',
'banca_secondaria',
'filiale_secondaria',
// Amministratore semplificato
'amministratore_nome',
'amministratore_email',
'data_nomina',
'scadenza_mandato',
// Dati catastali aggiuntivi
'mappale',
'categoria',
'rendita_catastale',
'superficie_catastale',
// JSON fields
'palazzine_data',
'locali_servizio',
// Campi esistenti per compatibilità
'codice_catastale_comune',
'foglio',
'particella',
'subalterno',
'sezione',
'codice_destinatario_sdi',
'pec_amministratore',
'pec_condominio',
'numero_rate_ordinarie',
'mesi_rate_ordinarie',
'numero_rate_straordinarie',
'mesi_rate_straordinarie',
'numero_unita',
'tipo_riscaldamento',
'tipo_acqua',
'presenza_ascensore',
'presenza_giardino',
'presenza_piscina',
'presenza_garage',
'codice_interno',
'registro_anagrafe',
'documenti_path',
'attivo',
'struttura_fisica_json',
'numero_palazzine',
'numero_scale_per_palazzina',
'piano_seminterrato',
'piano_sottotetto',
'cortile_giardino',
'superficie_cortile',
'riscaldamento_centralizzato',
'acqua_centralizzata',
'gas_centralizzato',
'servizio_portineria',
'orari_portineria',
'videocitofono',
'antenna_tv_centralizzata',
'internet_condominiale',
'fondo_riserva_minimo',
'importo_rata_standard',
'frequenza_rate',
// Registro Amministratori (Legge 220/2012 Art.10 c.7)
'registro_data_nomina',
'registro_scadenza',
'registro_delibera',
'registro_note',
'giorno_scadenza_rate',
'iban_condominio',
'millesimi_generali_calcolati',
'millesimi_riscaldamento_separati',
'millesimi_acqua_separati',
'millesimi_ascensore_separati',
'configurazione_avanzata',
'ultima_generazione_unita'
];
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'anno_costruzione' => 'integer',
'numero_piani' => 'integer',
'numero_unita' => 'integer',
'superficie_totale' => 'decimal:2',
'numero_ascensori' => 'integer',
'numero_garage' => 'integer',
'numero_rate_ordinarie' => 'integer',
'numero_rate_straordinarie' => 'integer',
'presenza_ascensore' => 'boolean',
'presenza_giardino' => 'boolean',
'presenza_piscina' => 'boolean',
// Nuovi cast per campi avanzati
'struttura_fisica_json' => 'array',
'palazzine_data' => 'array',
'locali_servizio' => 'array',
'numero_palazzine' => 'integer',
'numero_scale_per_palazzina' => 'integer',
'piano_seminterrato' => 'boolean',
'piano_sottotetto' => 'boolean',
'cortile_giardino' => 'boolean',
'superficie_cortile' => 'decimal:2',
'riscaldamento_centralizzato' => 'boolean',
'acqua_centralizzata' => 'boolean',
'gas_centralizzato' => 'boolean',
'servizio_portineria' => 'boolean',
'videocitofono' => 'boolean',
'antenna_tv_centralizzata' => 'boolean',
'internet_condominiale' => 'boolean',
'fondo_riserva_minimo' => 'decimal:2',
'importo_rata_standard' => 'decimal:2',
'giorno_scadenza_rate' => 'integer',
'millesimi_generali_calcolati' => 'boolean',
'millesimi_riscaldamento_separati' => 'boolean',
'millesimi_acqua_separati' => 'boolean',
'millesimi_ascensore_separati' => 'boolean',
'configurazione_avanzata' => 'array',
'ultima_generazione_unita' => 'datetime',
'presenza_garage' => 'boolean',
'registro_anagrafe' => 'boolean',
'attivo' => 'boolean',
'mesi_rate_ordinarie' => 'array',
'mesi_rate_straordinarie' => 'array',
// Nuovi cast per campi aggiunti
'palazzine_data' => 'array',
'locali_servizio' => 'array',
'data_nomina' => 'date',
'scadenza_mandato' => 'date',
'rendita_catastale' => 'decimal:2',
'superficie_catastale' => 'decimal:2',
// Nuovi cast per i campi aggiunti
'palazzine_data' => 'array',
'locali_servizio' => 'array',
'rendita_catastale' => 'decimal:2',
'superficie_catastale' => 'decimal:2',
'data_nomina' => 'date',
'scadenza_mandato' => 'date'
];
/**
* Relazione con Amministratore
*/
public function amministratore()
{
return $this->belongsTo(Amministratore::class, 'amministratore_id', 'id');
}
/**
* Relazione con UnitaImmobiliari
*/
public function unitaImmobiliari()
{
return $this->hasMany(UnitaImmobiliare::class, 'stabile_id', 'id');
}
/**
* Relazione con Tickets
*/
public function tickets()
{
return $this->hasMany(Ticket::class, 'stabile_id', 'id');
}
/**
* Relazione con RipartizioneSpese
*/
public function ripartizioniSpese()
{
return $this->hasMany(RipartizioneSpese::class);
}
/**
* Relazione con PianoRateizzazione
*/
public function pianiRateizzazione()
{
return $this->hasMany(PianoRateizzazione::class);
}
/**
* Relazione con ChiaviStabili
*/
public function chiavi()
{
return $this->hasMany(ChiaveStabile::class, 'stabile_id');
}
/**
* Relazione con FondiCondominiali
*/
public function fondi()
{
return $this->hasMany(FondoCondominiale::class, 'stabile_id');
}
/**
* Relazione con StrutturaFisicaDettaglio
*/
public function strutturaFisica()
{
return $this->hasMany(StrutturaFisicaDettaglio::class, 'stabile_id');
}
/**
* Relazione con le tabelle millesimali dinamiche
*/
public function tabelleMillesimali()
{
return $this->hasMany(TabellaMillesimale::class, 'stabile_id', 'id');
}
/**
* Relazione con i contatori
*/
public function contatori()
{
return $this->hasMany(Contatore::class, 'stabile_id', 'id');
}
/**
* Relazione con gli algoritmi di ripartizione
*/
public function algoritmiRipartizione()
{
return $this->hasMany(AlgoritmoRipartizione::class, 'stabile_id', 'id');
}
/**
* Contatori condominiali (non legati a unità specifiche)
*/
public function contatoriCondominiali()
{
return $this->hasMany(Contatore::class, 'stabile_id', 'id')->whereNull('unita_immobiliare_id');
}
/**
* Esercizi contabili dello stabile
*/
public function eserciziContabili()
{
return $this->hasMany(EsercizioContabile::class, 'stabile_id', 'id');
}
/**
* Esercizi contabili ordinari
*/
public function eserciziOrdinari()
{
return $this->eserciziContabili()->byTipologia('ordinaria')->ordinatiSequenzialmente();
}
/**
* Esercizi riscaldamento
*/
public function eserciziRiscaldamento()
{
return $this->eserciziContabili()->byTipologia('riscaldamento')->ordinatiSequenzialmente();
}
/**
* Esercizi straordinari
*/
public function eserciziStraordinari()
{
return $this->eserciziContabili()->byTipologia('straordinaria')->ordinatiSequenzialmente();
}
/**
* Tabelle millesimali attive
*/
public function tabelleMillesimaliAttive()
{
return $this->tabelleMillesimali()->attive();
}
/**
* Tabella millesimi di proprietà (principale)
*/
public function tabellaMillesimiProprieta()
{
return $this->hasOne(TabellaMillesimale::class, 'stabile_id', 'id')
->where('tipo_tabella', 'proprieta')
->where('attiva', true);
}
/**
* Documenti dello stabile
*/
public function documenti()
{
return $this->hasMany(DocumentoStabile::class, 'stabile_id', 'id');
}
/**
* Documenti per categoria
*/
public function documentiPerCategoria($categoria = null)
{
$query = $this->documenti()->orderBy('created_at', 'desc');
if ($categoria) {
$query->where('categoria', $categoria);
}
return $query;
}
/**
* Documenti pubblici (visibili ai condomini)
*/
public function documentiPubblici()
{
return $this->documenti()->where('pubblico', true);
}
/**
* Documenti in scadenza
*/
public function documentiInScadenza($giorni = 30)
{
return $this->documenti()
->whereNotNull('data_scadenza')
->where('data_scadenza', '<=', now()->addDays($giorni))
->where('data_scadenza', '>=', now());
}
/**
* Costanti per frequenza rate
*/
public const FREQUENZE_RATE = [
'mensile' => 'Mensile',
'bimestrale' => 'Bimestrale',
'trimestrale' => 'Trimestrale',
'quadrimestrale' => 'Quadrimestrale',
'semestrale' => 'Semestrale',
'annuale' => 'Annuale'
];
/**
* Calcola il numero totale di unità immobiliari dalla struttura fisica
*/
public function calcolaTotaleUnita()
{
$totale = 0;
for ($palazzina = 1; $palazzina <= $this->numero_palazzine; $palazzina++) {
for ($scala = 1; $scala <= $this->numero_scale_per_palazzina; $scala++) {
// Calcola piani totali (incluso seminterrato e sottotetto)
$pianiTotali = $this->numero_piani;
if ($this->piano_seminterrato) $pianiTotali++;
if ($this->piano_sottotetto) $pianiTotali++;
$totale += $pianiTotali * 2; // Assumiamo 2 unità per piano di default
}
}
return $totale;
}
/**
* Genera automaticamente la struttura fisica dettagliata
*/
public function generaStrutturaFisica()
{
$struttura = [];
for ($palazzina = 1; $palazzina <= $this->numero_palazzine; $palazzina++) {
$nomePalazzina = $this->numero_palazzine > 1 ? chr(64 + $palazzina) : '1';
for ($scala = 1; $scala <= $this->numero_scale_per_palazzina; $scala++) {
$pianoMin = $this->piano_seminterrato ? -1 : 0;
$pianoMax = $this->numero_piani;
if ($this->piano_sottotetto) $pianoMax++;
for ($piano = $pianoMin; $piano <= $pianoMax; $piano++) {
$struttura[] = [
'palazzina' => $nomePalazzina,
'scala' => (string)$scala,
'piano' => $piano,
'numero_interni' => 2, // Default 2 interni per piano
'presenza_ascensore' => $this->presenza_ascensore
];
}
}
}
return $struttura;
}
/**
* Accessor per nome completo stabile
*/
public function getNomeCompletoAttribute()
{
return $this->denominazione . ' - ' . $this->indirizzo . ', ' . $this->citta;
}
/**
* Scope per stabili attivi
*/
public function scopeAttivi($query)
{
return $query->where('stato', 'attivo');
}
/**
* Verifica se lo stabile ha la struttura fisica configurata
*/
public function hasStrutturaFisicaConfigurata()
{
return !empty($this->struttura_fisica_json) || $this->strutturaFisica()->count() > 0;
}
/**
* Accessor per il nome completo dell'indirizzo
*/
public function getIndirizzoCompletoAttribute()
{
return $this->indirizzo . ', ' . $this->cap . ' ' . $this->citta .
($this->provincia ? ' (' . $this->provincia . ')' : '');
}
/**
* Accessor per i dati catastali
*/
public function getDatiCatastaliAttribute()
{
return [
'codice_comune' => $this->codice_catastale_comune,
'foglio' => $this->foglio,
'particella' => $this->particella,
'subalterno' => $this->subalterno,
'sezione' => $this->sezione
];
}
/**
* Accessor per i dati SDI
*/
public function getDatiSdiAttribute()
{
return [
'codice_destinatario' => $this->codice_destinatario_sdi,
'pec_amministratore' => $this->pec_amministratore,
'pec_condominio' => $this->pec_condominio
];
}
/**
* Accessor per la configurazione rate ordinarie
*/
public function getConfigurazioneRateOrdinarieAttribute()
{
return [
'numero_rate' => $this->numero_rate_ordinarie,
'mesi' => $this->mesi_rate_ordinarie
];
}
/**
* Accessor per la configurazione rate straordinarie
*/
public function getConfigurazioneRateStraordinarieAttribute()
{
return [
'numero_rate' => $this->numero_rate_straordinarie,
'mesi' => $this->mesi_rate_straordinarie
];
}
/**
* Accessor per le caratteristiche dello stabile
*/
public function getCaratteristicheAttribute()
{
return [
'anno_costruzione' => $this->anno_costruzione,
'numero_piani' => $this->numero_piani,
'numero_unita' => $this->numero_unita,
'superficie_totale' => $this->superficie_totale,
'tipo_riscaldamento' => $this->tipo_riscaldamento,
'tipo_acqua' => $this->tipo_acqua,
'presenza_ascensore' => $this->presenza_ascensore,
'numero_ascensori' => $this->numero_ascensori,
'presenza_giardino' => $this->presenza_giardino,
'presenza_piscina' => $this->presenza_piscina,
'presenza_garage' => $this->presenza_garage,
'numero_garage' => $this->numero_garage
];
}
/**
* Metodo per ottenere tutte le anagrafiche associate
*/
public function getAnagraficheAssociate()
{
return AnagraficaCondominiale::whereHas('dirittiReali.unitaImmobiliare', function ($query) {
$query->where('stabile_id', $this->id);
})->orWhereHas('contrattiLocazione.unitaImmobiliare', function ($query) {
$query->where('stabile_id', $this->id);
})->distinct()->get();
}
/**
* Metodo per ottenere i proprietari dello stabile
*/
public function getProprietari()
{
return AnagraficaCondominiale::whereHas('dirittiReali', function ($query) {
$query->where('tipo_diritto', 'proprieta')
->whereNull('data_fine')
->whereHas('unitaImmobiliare', function ($q) {
$q->where('stabile_id', $this->id);
});
})->distinct()->get();
}
/**
* Metodo per ottenere gli inquilini dello stabile
*/
public function getInquilini()
{
return AnagraficaCondominiale::whereHas('contrattiLocazione', function ($query) {
$query->where('stato', 'attivo')
->whereDate('data_inizio', '<=', now())
->where(function ($q) {
$q->whereNull('data_fine')
->orWhereDate('data_fine', '>=', now());
})
->whereHas('unitaImmobiliare', function ($q) {
$q->where('stabile_id', $this->id);
});
})->distinct()->get();
}
/**
* Metodo per calcolare il totale millesimi
*/
public function getTotaleMillesimi($tipo = 'proprieta')
{
$campo = 'millesimi_' . $tipo;
return $this->unitaImmobiliari()->where('attiva', true)->sum($campo);
}
/**
* Metodo per verificare la coerenza dei millesimi
*/
public function verificaMillesimi($tipo = 'proprieta')
{
$totale = $this->getTotaleMillesimi($tipo);
return abs($totale - 1000) < 0.001; // Tolleranza per errori di arrotondamento
}
/**
* Metodo per ottenere le statistiche dello stabile
*/
public function getStatistiche()
{
$unita = $this->unitaImmobiliari()->where('attiva', true);
return [
'totale_unita' => $unita->count(),
'unita_in_locazione' => $unita->whereHas('contrattiLocazione', function ($query) {
$query->where('stato', 'attivo')
->whereDate('data_inizio', '<=', now())
->where(function ($q) {
$q->whereNull('data_fine')
->orWhereDate('data_fine', '>=', now());
});
})->count(),
'superficie_totale' => $unita->sum('superficie_commerciale'),
'totale_millesimi_proprieta' => $this->getTotaleMillesimi('proprieta'),
'totale_proprietari' => $this->getProprietari()->count(),
'totale_inquilini' => $this->getInquilini()->count()
];
}
}