netgescon-master/netgescon-laravel/app/Models/FondoCondominiale.php

217 lines
5.5 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class FondoCondominiale extends Model
{
use HasFactory;
protected $table = 'fondi_condominiali';
protected $fillable = [
'stabile_id',
'tipo_fondo',
'denominazione',
'descrizione',
'saldo_attuale',
'saldo_minimo',
'percentuale_accantonamento',
'attivo'
];
protected $casts = [
'saldo_attuale' => 'decimal:2',
'saldo_minimo' => 'decimal:2',
'percentuale_accantonamento' => 'decimal:2',
'attivo' => 'boolean',
'created_at' => 'datetime',
'updated_at' => 'datetime'
];
/**
* Tipi fondo disponibili
*/
public const TIPI_FONDO = [
'ordinario' => 'Fondo Ordinario',
'riserva' => 'Fondo di Riserva',
'ascensore' => 'Fondo Ascensore',
'riscaldamento' => 'Fondo Riscaldamento',
'facciata_tetto' => 'Fondo Facciata/Tetto',
'verde_giardini' => 'Fondo Verde/Giardini',
'sicurezza' => 'Fondo Sicurezza/Videosorveglianza',
'innovazione' => 'Fondo Innovazione Tecnologica',
'investimenti' => 'Fondo Investimenti Spazi Comuni',
'personalizzato' => 'Fondo Personalizzato'
];
/**
* Priorità fondi (per ordinamento)
*/
public const PRIORITA_FONDI = [
'ordinario' => 1,
'riserva' => 2,
'ascensore' => 3,
'riscaldamento' => 4,
'facciata_tetto' => 5,
'verde_giardini' => 6,
'sicurezza' => 7,
'innovazione' => 8,
'investimenti' => 9,
'personalizzato' => 10
];
/**
* Relazione con Stabile
*/
public function stabile()
{
return $this->belongsTo(Stabile::class, 'stabile_id');
}
/**
* Relazione con MovimentiContabili
*/
public function movimenti()
{
return $this->hasMany(MovimentoContabile::class, 'fondo_id');
}
/**
* Accessor per tipo fondo descrizione
*/
public function getTipoFondoDescrizioneAttribute()
{
return self::TIPI_FONDO[$this->tipo_fondo] ?? $this->tipo_fondo;
}
/**
* Accessor per priorità ordinamento
*/
public function getPrioritaAttribute()
{
return self::PRIORITA_FONDI[$this->tipo_fondo] ?? 999;
}
/**
* Accessor per badge class tipo fondo
*/
public function getTipoFondoBadgeClassAttribute()
{
return match($this->tipo_fondo) {
'ordinario' => 'bg-primary',
'riserva' => 'bg-success',
'ascensore', 'riscaldamento', 'facciata_tetto' => 'bg-warning',
'verde_giardini', 'sicurezza' => 'bg-info',
'innovazione', 'investimenti' => 'bg-purple',
'personalizzato' => 'bg-secondary',
default => 'bg-secondary'
};
}
/**
* Accessor per stato saldo (critico, normale, ottimale)
*/
public function getStatoSaldoAttribute()
{
if ($this->saldo_attuale < $this->saldo_minimo) {
return 'critico';
} elseif ($this->saldo_attuale < ($this->saldo_minimo * 1.5)) {
return 'normale';
} else {
return 'ottimale';
}
}
/**
* Accessor per stato saldo badge class
*/
public function getStatoSaldoBadgeClassAttribute()
{
return match($this->stato_saldo) {
'critico' => 'bg-danger',
'normale' => 'bg-warning',
'ottimale' => 'bg-success',
default => 'bg-secondary'
};
}
/**
* Scope per fondi attivi
*/
public function scopeAttivi($query)
{
return $query->where('attivo', true);
}
/**
* Scope per tipo fondo
*/
public function scopePerTipo($query, $tipo)
{
return $query->where('tipo_fondo', $tipo);
}
/**
* Scope ordinati per priorità
*/
public function scopeOrdinatiPerPriorita($query)
{
return $query->orderByRaw("FIELD(tipo_fondo, 'ordinario', 'riserva', 'ascensore', 'riscaldamento', 'facciata_tetto', 'verde_giardini', 'sicurezza', 'innovazione', 'investimenti', 'personalizzato')");
}
/**
* Calcola l'accantonamento necessario per raggiungere il saldo minimo
*/
public function calcolaAccantonamentoNecessario()
{
$differenza = $this->saldo_minimo - $this->saldo_attuale;
return max(0, $differenza);
}
/**
* Aggiorna il saldo del fondo
*/
public function aggiornaSaldo($importo, $descrizione = null)
{
$this->saldo_attuale += $importo;
$this->save();
// Registra il movimento se richiesto
if ($descrizione) {
$this->movimenti()->create([
'descrizione' => $descrizione,
'importo' => $importo,
'data_movimento' => now()
]);
}
return $this;
}
/**
* Verifica se il fondo è sotto la soglia minima
*/
public function isSaldoCritico()
{
return $this->saldo_attuale < $this->saldo_minimo;
}
/**
* Boot method per eventi model
*/
protected static function boot()
{
parent::boot();
static::creating(function ($fondo) {
// Se non specificata, genera denominazione automatica
if (empty($fondo->denominazione)) {
$fondo->denominazione = self::TIPI_FONDO[$fondo->tipo_fondo] ?? 'Fondo Personalizzato';
}
});
}
}