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

248 lines
7.0 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class RipartizioneSpese extends Model
{
protected $table = 'ripartizione_spese';
protected $table = 'ripartizioni_spese';
protected $fillable = [
'stabile_id',
'nome_ripartizione',
'descrizione',
'tipo_millesimi',
'includi_pertinenze',
'includi_locazioni',
'minimo_presenza',
'attiva',
'aggiornamento_automatico',
'data_inizio',
'data_fine',
'created_by'
];
protected $casts = [
'includi_pertinenze' => 'boolean',
'includi_locazioni' => 'boolean',
'minimo_presenza' => 'decimal:2',
'attiva' => 'boolean',
'aggiornamento_automatico' => 'boolean',
'data_inizio' => 'date',
'data_fine' => 'date'
];
// === RELAZIONI ===
public function stabile(): BelongsTo
{
return $this->belongsTo(Stabile::class);
}
public function createdBy(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
// === METODI UTILITÀ ===
public function getTipoMillesimiLabel(): string
{
return match($this->tipo_millesimi) {
'proprieta' => 'Proprietà',
'riscaldamento' => 'Riscaldamento',
'ascensore' => 'Ascensore',
'scale' => 'Scale',
'pulizie' => 'Pulizie',
'custom_1' => 'Custom 1',
'custom_2' => 'Custom 2',
'custom_3' => 'Custom 3',
default => ucfirst($this->tipo_millesimi)
};
}
public function getTipoMillesimiIcon(): string
{
return match($this->tipo_millesimi) {
'proprieta' => 'fas fa-home',
'riscaldamento' => 'fas fa-thermometer-half',
'ascensore' => 'fas fa-elevator',
'scale' => 'fas fa-stairs',
'pulizie' => 'fas fa-broom',
'custom_1', 'custom_2', 'custom_3' => 'fas fa-cog',
default => 'fas fa-chart-pie'
};
}
public function getStatoBadgeColor(): string
{
if (!$this->attiva) {
return 'secondary';
}
$now = now()->toDateString();
if ($this->data_fine && $this->data_fine < $now) {
return 'danger'; // Scaduta
}
if ($this->data_inizio > $now) {
return 'warning'; // Futura
}
return 'success'; // Attiva
}
public function isAttiva(): bool
{
if (!$this->attiva) {
return false;
}
$now = now()->toDateString();
if ($this->data_inizio > $now) {
return false; // Non ancora iniziata
}
if ($this->data_fine && $this->data_fine < $now) {
return false; // Scaduta
}
return true;
}
public function calcolaRipartizione(): array
{
$unita = $this->stabile->unita();
// Applica filtri
if (!$this->includi_pertinenze) {
// Logica per escludere pertinenze
}
if (!$this->includi_locazioni) {
// Escludi unità in locazione
}
$unitaValide = $unita->conMillesimi($this->tipo_millesimi)->get();
$ripartizione = [];
$totaleMillesimi = 0;
foreach ($unitaValide as $unita) {
$millesimi = $this->getMillesimiUnita($unita);
if ($millesimi >= $this->minimo_presenza) {
$ripartizione[] = [
'unita_id' => $unita->id,
'denominazione' => $unita->denominazione,
'millesimi' => $millesimi,
'proprietario' => $unita->proprietarioAttuale()?->denominazione
];
$totaleMillesimi += $millesimi;
}
}
// Normalizza i millesimi per raggiungere 1000
if ($totaleMillesimi > 0 && $totaleMillesimi != 1000) {
$fattoreCorrezione = 1000 / $totaleMillesimi;
foreach ($ripartizione as &$riga) {
$riga['millesimi'] = round($riga['millesimi'] * $fattoreCorrezione, 4);
}
}
return [
'ripartizione' => $ripartizione,
'totale_millesimi' => $totaleMillesimi,
'unita_incluse' => count($ripartizione),
'unita_escluse' => $unita->count() - count($ripartizione)
];
}
private function getMillesimiUnita(UnitaImmobiliare $unita): float
{
$campo = "millesimi_{$this->tipo_millesimi}";
return $unita->$campo ?? 0;
}
public function applicaRipartizione(array $spese): array
{
$ripartizione = $this->calcolaRipartizione();
$risultato = [];
foreach ($spese as $spesa) {
$importoTotale = $spesa['importo'];
$ripartizioneSpesa = [];
foreach ($ripartizione['ripartizione'] as $riga) {
$importoUnita = ($importoTotale * $riga['millesimi']) / 1000;
$ripartizioneSpesa[] = [
'unita_id' => $riga['unita_id'],
'denominazione' => $riga['denominazione'],
'proprietario' => $riga['proprietario'],
'millesimi' => $riga['millesimi'],
'importo' => round($importoUnita, 2)
];
}
$risultato[] = [
'spesa' => $spesa,
'ripartizione' => $ripartizioneSpesa,
'totale_ripartito' => array_sum(array_column($ripartizioneSpesa, 'importo'))
];
}
return $risultato;
}
// === SCOPES ===
public function scopeAttive($query)
{
$now = now()->toDateString();
return $query->where('attiva', true)
->where('data_inizio', '<=', $now)
->where(function($q) use ($now) {
$q->whereNull('data_fine')
->orWhere('data_fine', '>=', $now);
});
}
public function scopePerTipo($query, string $tipo)
{
return $query->where('tipo_millesimi', $tipo);
}
public function scopeConAggiornamentoAutomatico($query)
{
return $query->where('aggiornamento_automatico', true);
}
public function scopeDelPeriodo($query, $dataInizio, $dataFine)
{
return $query->where(function($q) use ($dataInizio, $dataFine) {
$q->whereBetween('data_inizio', [$dataInizio, $dataFine])
->orWhereBetween('data_fine', [$dataInizio, $dataFine])
->orWhere(function($q2) use ($dataInizio, $dataFine) {
$q2->where('data_inizio', '<=', $dataInizio)
->where(function($q3) use ($dataFine) {
$q3->whereNull('data_fine')
->orWhere('data_fine', '>=', $dataFine);
});
});
});
}
}