614 lines
18 KiB
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()
|
|
];
|
|
}
|
|
} |