'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); }); }); }); } }