'decimal:2', 'attiva' => 'boolean', 'ordinamento' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; /** * Relazione con Stabile */ public function stabile() { return $this->belongsTo(Stabile::class, 'stabile_id', 'id'); } /** * Relazione con Tabella Millesimale Default */ public function tabellaMillesimaleDefault() { return $this->belongsTo(TabellaMillesimale::class, 'tabella_millesimale_default_id'); } /** * Relazione con RipartizioneSpese */ public function ripartizioniSpese() { return $this->hasMany(RipartizioneSpese::class); } /** * Scope per voci attive */ public function scopeAttive($query) { return $query->where('attiva', true); } /** * Scope per tipo gestione */ public function scopeTipoGestione($query, $tipo) { return $query->where('tipo_gestione', $tipo); } /** * Scope ordinato */ public function scopeOrdinato($query) { return $query->orderBy('ordinamento')->orderBy('descrizione'); } /** * Boot del modello per generazione automatica codice */ protected static function boot() { parent::boot(); static::creating(function ($model) { if (empty($model->codice)) { $model->codice = self::generateUniqueCode($model->stabile_id); } }); } /** * Genera un codice univoco per la voce di spesa */ private static function generateUniqueCode($stabileId) { do { $code = 'VS' . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT); } while (self::where('stabile_id', $stabileId)->where('codice', $code)->exists()); return $code; } /** * Scope per categoria specifica */ public function scopeByCategoria($query, $categoria) { return $query->where('categoria', $categoria); } /** * Ottieni tutte le categorie standard */ public static function getCategorieStandard() { return [ 'manutenzione_ordinaria' => 'Manutenzione Ordinaria', 'manutenzione_straordinaria' => 'Manutenzione Straordinaria', 'pulizia' => 'Pulizia', 'illuminazione' => 'Illuminazione', 'riscaldamento' => 'Riscaldamento', 'acqua' => 'Acqua', 'energia_elettrica' => 'Energia Elettrica', 'gas' => 'Gas', 'ascensore' => 'Ascensore', 'giardino_verde' => 'Giardino e Verde', 'sicurezza' => 'Sicurezza', 'amministrazione' => 'Amministrazione', 'assicurazioni' => 'Assicurazioni', 'tasse_tributi' => 'Tasse e Tributi', 'spese_legali' => 'Spese Legali', 'lavori_miglioramento' => 'Lavori di Miglioramento', 'altre_spese' => 'Altre Spese' ]; } /** * Ottieni i tipi di gestione */ public static function getTipiGestione() { return [ 'ordinaria' => 'Gestione Ordinaria', 'straordinaria' => 'Gestione Straordinaria', 'speciale' => 'Gestione Speciale' ]; } /** * Accessor per descrizione completa */ public function getDescrizioneCompletaAttribute() { return $this->codice . ' - ' . $this->descrizione; } /** * Accessor per categoria formattata */ public function getCategoriaFormattataAttribute() { $categorie = self::getCategorieStandard(); return $categorie[$this->categoria] ?? $this->categoria; } /** * Accessor per riassunto voce */ public function getRiassuntoAttribute() { return [ 'codice' => $this->codice, 'descrizione' => $this->descrizione, 'categoria' => $this->categoria_formattata, 'tipo_gestione' => $this->tipo_gestione, 'tabella_default' => $this->tabellaMillesimaleDefault->nome_tabella_millesimale ?? 'Nessuna', 'ritenuta_default' => $this->ritenuta_acconto_default . '%', 'attiva' => $this->attiva ? 'Sì' : 'No' ]; } /** * Metodo per duplicare voce di spesa */ public function duplica($nuovaDescrizione = null) { $nuovaVoce = $this->replicate(); $nuovaVoce->codice = null; // Verrà rigenerato automaticamente $nuovaVoce->descrizione = $nuovaDescrizione ?? ($this->descrizione . ' (Copia)'); $nuovaVoce->save(); return $nuovaVoce; } /** * Scope per ricerca testuale */ public function scopeRicerca($query, $termine) { return $query->where(function($q) use ($termine) { $q->where('codice', 'LIKE', "%{$termine}%") ->orWhere('descrizione', 'LIKE', "%{$termine}%") ->orWhere('categoria', 'LIKE', "%{$termine}%"); }); } /** * Metodo per ottenere ripartizioni spese che utilizzano questa voce */ public function getRipartizioniSpese() { return $this->ripartizioniSpese() ->with(['stabile', 'tabellaMillesimale', 'dettagli']) ->orderBy('data_ripartizione', 'desc') ->get(); } }