248 lines
7.0 KiB
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);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|