registrazione_id)) { $existing = Registrazione::query()->find((int) $incasso->registrazione_id); if ($existing) { return $existing; } } $stabileId = (int) ($incasso->condominio_id ?? 0); if ($stabileId <= 0) { throw new RuntimeException('Incasso senza condominio/stabile.'); } $gestioneId = (int) (($override['gestione_id'] ?? null) ?: ($incasso->gestione_id ?? 0)); if ($gestioneId <= 0) { throw new RuntimeException('Seleziona una gestione per questo incasso.'); } if (Schema::hasTable('contabilita_chiusure_gestione')) { $chiusa = app(ChiusuraGestioneService::class)->isGestioneChiusa($gestioneId); if ($chiusa) { throw new RuntimeException('Gestione chiusa: non è possibile generare nuove registrazioni.'); } } $importo = (float) ($incasso->importo_pagato_euro ?? $incasso->importo_pagato ?? 0); if (abs($importo) < 0.005) { throw new RuntimeException('Importo incasso non valido.'); } $amount = round(abs($importo), 2); $data = isset($override['data_registrazione']) && is_string($override['data_registrazione']) ? trim((string) $override['data_registrazione']) : null; if ($data === '') { $data = null; } if (! empty($incasso->dt_empag)) { try { $data = $data ?: $incasso->dt_empag->toDateString(); } catch (\Throwable) { $data = null; } } if (! $data && ! empty($incasso->data_pagamento)) { try { $data = $incasso->data_pagamento->toDateString(); } catch (\Throwable) { $data = null; } } $data = $data ?: now()->toDateString(); $descr = isset($override['descrizione']) && is_string($override['descrizione']) ? trim((string) $override['descrizione']) : ''; if ($descr === '' && ! empty($incasso->movimento_bancario_id)) { $mb = MovimentoBancario::query()->find((int) $incasso->movimento_bancario_id); if ($mb) { $parts = []; $c = is_string($mb->causale) ? trim((string) $mb->causale) : ''; if ($c !== '') { $parts[] = $c; } $b = is_string($mb->beneficiario) ? trim((string) $mb->beneficiario) : ''; if ($b !== '') { $parts[] = $b; } $n = is_string($mb->note) ? trim((string) $mb->note) : ''; if ($n !== '') { $parts[] = $n; } $descr = trim(implode(' - ', $parts)); } } if ($descr === '') { $descr = is_string($incasso->descrizione) ? trim((string) $incasso->descrizione) : ''; } if ($descr === '') { $nr = is_numeric($incasso->n_ricevuta ?? null) ? (' #'.(int) $incasso->n_ricevuta) : ''; $descr = 'Incasso rata' . $nr; } $contoBancarioId = (int) ($incasso->conto_bancario_id ?? 0); if ($contoBancarioId <= 0) { throw new RuntimeException('Incasso senza conto bancario/cassa.'); } $contoBancario = ContoBancario::query()->find($contoBancarioId); $modalita = isset($override['modalita_incasso']) && is_string($override['modalita_incasso']) ? trim((string) $override['modalita_incasso']) : (is_string($incasso->modalita_incasso ?? null) ? trim((string) $incasso->modalita_incasso) : ''); $chiave = $modalita !== '' ? $modalita : ( $contoBancario && is_string($contoBancario->codice) && trim($contoBancario->codice) !== '' ? trim($contoBancario->codice) : 'default' ); $regola = RegolaPrimaNota::query() ->where('stabile_id', $stabileId) ->where('origine', 'incasso') ->where('chiave', $chiave) ->where('attiva', true) ->first(); if (! $regola) { $regola = RegolaPrimaNota::query() ->where('stabile_id', $stabileId) ->where('origine', 'incasso') ->where('chiave', 'default') ->where('attiva', true) ->first(); } $contoDareId = isset($override['conto_dare_id']) && (int) $override['conto_dare_id'] > 0 ? (int) $override['conto_dare_id'] : ($regola?->conto_dare_id ? (int) $regola->conto_dare_id : null); $contoAvereId = $regola?->conto_avere_id ? (int) $regola->conto_avere_id : null; // Fallback minimo: prova a risolvere conti per codice (banca/cassa = codice conto bancario; crediti condomini = config) if (! $contoDareId) { if ($contoBancario && is_string($contoBancario->codice)) { $byCode = PianoConti::query()->where('codice', trim((string) $contoBancario->codice))->first(); if ($byCode) { $contoDareId = (int) $byCode->id; } } } $condominoId = (int) (($override['condomino_id'] ?? null) ?: ($incasso->condomino_id ?? 0)); if (! $contoAvereId && $condominoId > 0) { $condomino = Condomino::query()->find($condominoId); $conto = app(ContiSoggettiService::class)->resolveContoCreditoCondomino( $stabileId, $condominoId, $condomino?->display_name, is_string($condomino?->codice_univoco ?? null) ? trim((string) $condomino->codice_univoco) : null ); $contoAvereId = (int) $conto->id; } if (! $contoAvereId) { $cod = (string) config('contabilita.conti_speciali.crediti_condomini_codice', '1100'); $desc = (string) config('contabilita.conti_speciali.crediti_condomini_descrizione', 'Crediti verso condomini'); $tipo = (string) config('contabilita.conti_speciali.crediti_condomini_tipo', 'Attività'); $conto = app(ChiusuraGestioneService::class)->resolveOrCreateConto($cod, $desc, $tipo); $contoAvereId = (int) $conto->id; } if (! $contoDareId || ! $contoAvereId) { throw new RuntimeException('Regola prima nota incassi non configurata (origine=incasso, chiave=' . $chiave . ' o default).'); } return DB::transaction(function () use ($user, $incasso, $stabileId, $gestioneId, $data, $descr, $amount, $contoDareId, $contoAvereId, $modalita, $condominoId) { $regPayload = [ 'stabile_id' => $stabileId, 'gestione_id' => (Schema::hasColumn('contabilita_registrazioni', 'gestione_id') ? Registrazione::resolveGestioneIdOrDefault($gestioneId, $stabileId, $data) : null), 'data_registrazione' => $data, 'descrizione' => $descr, 'created_by' => (int) $user->id, 'updated_by' => (int) $user->id, ]; if (Schema::hasColumn('contabilita_registrazioni', 'user_id')) { $regPayload['user_id'] = (int) $user->id; } /** @var Registrazione $reg */ $reg = Registrazione::query()->create($regPayload); Movimento::query()->create([ 'registrazione_id' => (int) $reg->id, 'conto_id' => (int) $contoDareId, 'tipo' => 'dare', 'importo' => $amount, ]); Movimento::query()->create([ 'registrazione_id' => (int) $reg->id, 'conto_id' => (int) $contoAvereId, 'tipo' => 'avere', 'importo' => $amount, ]); $reg->assertBilanciata(); if (Schema::hasColumn('incassi', 'registrazione_id')) { $incasso->registrazione_id = (int) $reg->id; if (Schema::hasColumn('incassi', 'gestione_id') && empty($incasso->gestione_id)) { $incasso->gestione_id = $gestioneId; } if (Schema::hasColumn('incassi', 'modalita_incasso') && $modalita !== '') { $incasso->modalita_incasso = $modalita; } if (Schema::hasColumn('incassi', 'condomino_id') && $condominoId > 0) { $incasso->condomino_id = $condominoId; } $incasso->save(); } return $reg; }); } }