'decimal:4', 'saldo_corrente' => 'decimal:4', 'ultima_riconciliazione' => 'date', 'attivo' => 'boolean', 'configurazione_import' => 'array', 'metadati_gescon' => 'array' ]; /** * Incassi associati a questo conto */ public function incassi(): HasMany { return $this->hasMany(Incasso::class, 'conto_bancario_id'); } /** * Movimenti bancari di questo conto */ public function movimentiBancari(): HasMany { return $this->hasMany(MovimentoBancario::class, 'conto_bancario_id'); } /** * Operazioni contabili associate */ public function operazioni(): HasMany { return $this->hasMany(OperazioneContabile::class, 'conto_bancario_id'); } /** * Scope per tenant */ public function scopeForTenant($query, string $tenantId) { return $query->where('tenant_id', $tenantId); } /** * Scope per conti attivi */ public function scopeAttivi($query) { return $query->where('attivo', true); } /** * Scope per tipo conto */ public function scopeTipo($query, string $tipo) { return $query->where('tipo_conto', $tipo); } /** * Calcola saldo corrente dai movimenti */ public function calcolaSaldoCorrente(): float { $entrate = $this->movimentiBancari() ->where('tipo_movimento', 'entrata') ->sum('importo'); $uscite = $this->movimentiBancari() ->where('tipo_movimento', 'uscita') ->sum('importo'); return $this->saldo_iniziale + $entrate - $uscite; } /** * Verifica se supporta import automatico */ public function supportaImportAutomatico(): bool { return !empty($this->formato_file) && !empty($this->configurazione_import); } /** * Statistiche riconciliazione */ public function statisticheRiconciliazione(): array { $movimenti = $this->movimentiBancari(); return [ 'totale_movimenti' => $movimenti->count(), 'riconciliati_automatici' => $movimenti->where('stato_riconciliazione', 'automatica')->count(), 'riconciliati_manuali' => $movimenti->where('stato_riconciliazione', 'manuale')->count(), 'sospesi' => $movimenti->where('stato_riconciliazione', 'sospesa')->count(), 'anomali' => $movimenti->where('stato_riconciliazione', 'anomala')->count(), 'percentuale_riconciliazione' => $movimenti->count() > 0 ? round(($movimenti->whereIn('stato_riconciliazione', ['automatica', 'manuale'])->count() / $movimenti->count()) * 100, 2) : 0 ]; } /** * Estrae configurazione per import file */ public function getConfigurazioneImport(): array { $default = [ 'formato' => $this->formato_file, 'encoding' => 'UTF-8', 'separatore' => ';', 'pattern_data' => 'd/m/Y', 'skip_lines' => 0 ]; return array_merge($default, $this->configurazione_import ?? []); } /** * Aggiorna ultima riconciliazione */ public function aggiornaUltimaRiconciliazione(): void { $this->update(['ultima_riconciliazione' => today()]); } /** * Formatta saldo per display */ public function getSaldoFormattato(): string { return '€ ' . number_format($this->saldo_corrente, 2, ',', '.'); } /** * Info conto per dashboard */ public function getInfoConto(): array { return [ 'codice' => $this->codice, 'descrizione' => $this->descrizione, 'banca' => $this->banca, 'numero_conto' => $this->numero_conto, 'saldo_corrente' => $this->saldo_corrente, 'saldo_formattato' => $this->getSaldoFormattato(), 'tipo_conto' => $this->tipo_conto, 'attivo' => $this->attivo, 'ultima_riconciliazione' => $this->ultima_riconciliazione?->format('d/m/Y'), 'statistiche' => $this->statisticheRiconciliazione() ]; } }