2810 lines
106 KiB
PHP
2810 lines
106 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Pages\Contabilita;
|
|
|
|
use App\Models\DatiBancari;
|
|
use App\Models\DocumentoStabile;
|
|
use App\Models\FatturaElettronica;
|
|
use App\Models\GestioneContabile;
|
|
use App\Models\PersonaUnitaRelazione;
|
|
use App\Models\RegistroRitenuteAcconto;
|
|
use App\Models\Stabile;
|
|
use App\Models\UnitaImmobiliare;
|
|
use App\Models\UnitaImmobiliareNominativo;
|
|
use App\Models\User;
|
|
use App\Modules\Contabilita\Models\MovimentoBanca;
|
|
use App\Modules\Contabilita\Models\SaldoConto;
|
|
use App\Support\StabileContext;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
|
use Livewire\WithFileUploads;
|
|
use UnitEnum;
|
|
use BackedEnum;
|
|
|
|
class SituazioneIniziale extends Page
|
|
{
|
|
use WithFileUploads;
|
|
|
|
protected static ?string $navigationLabel = 'Situazione iniziale';
|
|
|
|
protected static ?string $title = 'Situazione iniziale';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-scale';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Contabilità';
|
|
|
|
protected static ?int $navigationSort = 12;
|
|
|
|
protected static ?string $slug = 'contabilita/situazione-iniziale';
|
|
|
|
protected string $view = 'filament.pages.contabilita.situazione-iniziale';
|
|
|
|
#[Url(as: 'legacy_year')]
|
|
public ?string $legacyYear = null;
|
|
|
|
#[Url(as: 'data')]
|
|
public ?string $dataBilancio = null;
|
|
|
|
#[Url(as: 'saldo_manuale')]
|
|
public ?string $saldoBancaManuale = null;
|
|
|
|
#[Url(as: 'tab')]
|
|
public string $tab = 'bilancio';
|
|
|
|
#[Url(as: 'dett')]
|
|
public ?string $dett = null;
|
|
|
|
public array $legacyYears = [];
|
|
|
|
/** @var array<string, string> Map cartella legacy (0001) -> label utente (es. 2024-25) */
|
|
public array $legacyYearLabels = [];
|
|
|
|
public array $conti = [];
|
|
|
|
public array $risorseFinanziarie = [];
|
|
|
|
public array $bilancio = [];
|
|
|
|
public array $conguagliExcel = [];
|
|
|
|
public array $conguagliExcelCols = [];
|
|
|
|
// CRUD stile "Excel" (dati legacy su gescon_import)
|
|
public array $creDebRows = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $creDebEdit = [];
|
|
|
|
public array $formCreDebAdd = [
|
|
'cod_voc' => null,
|
|
'des_voce' => null,
|
|
'descrizione' => null,
|
|
'importo_euro' => null,
|
|
'n_stra' => null,
|
|
'incluso' => 1,
|
|
];
|
|
|
|
public array $dettTabRows = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $dettTabEdit = [];
|
|
|
|
public array $formDettTabAdd = [
|
|
'cod_tab' => 'CONG.O',
|
|
'id_cond' => null,
|
|
'cond_inquil' => null,
|
|
'mm' => null,
|
|
'cons_euro' => null,
|
|
'n_stra' => null,
|
|
'unico' => 0,
|
|
];
|
|
|
|
public array $formVoce = [
|
|
'gestione' => 'ordinaria',
|
|
'categoria' => 'crediti',
|
|
'n_stra' => null,
|
|
'codice' => null,
|
|
'descrizione' => null,
|
|
'importo_euro' => null,
|
|
];
|
|
|
|
public array $formConguaglio = [
|
|
'cod_tab' => 'CONG.O',
|
|
'n_stra' => null,
|
|
'id_cond' => null,
|
|
'cons_euro' => null,
|
|
];
|
|
|
|
public array $detailMeta = [];
|
|
|
|
public array $detailRows = [];
|
|
|
|
public ?string $saldoContoId = null;
|
|
|
|
public ?string $saldoSnapshotData = null;
|
|
|
|
public ?string $saldoSnapshotPeriodoDa = null;
|
|
|
|
public ?string $saldoSnapshotPeriodoA = null;
|
|
|
|
public ?string $saldoSnapshotSaldo = null;
|
|
|
|
public string $saldoSnapshotTipo = 'estratto_conto';
|
|
|
|
public ?string $saldoSnapshotNote = null;
|
|
|
|
public TemporaryUploadedFile|string|null $saldoSnapshotPdf = null;
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $saldoSnapshots = [];
|
|
|
|
/** @var array<string, string> */
|
|
public array $vocSpeOptions = [];
|
|
// Editing "a riga" (riduce la pagina: si modifica una riga alla volta)
|
|
public ?int $editingCreDebId = null;
|
|
|
|
public ?int $editingDettTabId = null;
|
|
|
|
// Selezione riga (per mostrare dettaglio voce spesa sotto Crediti/Debiti)
|
|
public ?int $selectedCreDebId = null;
|
|
|
|
// Sub-tab documenti (sotto Crediti/Debiti): voce / FE / RA
|
|
public string $detailTab = 'voce';
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $feRows = [];
|
|
|
|
/** @var array<int, int> */
|
|
public array $linkedFeIds = [];
|
|
|
|
/** @var array<int, array<string, mixed>> */
|
|
public array $raRows = [];
|
|
|
|
/** @var array<int, int> */
|
|
public array $linkedRaIds = [];
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return false;
|
|
}
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin'])) {
|
|
return true;
|
|
}
|
|
|
|
return $user->can('contabilita.prima-nota');
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->legacyYear = is_string($this->legacyYear) ? trim((string) $this->legacyYear) : null;
|
|
$this->legacyYear = $this->legacyYear !== '' ? $this->legacyYear : null;
|
|
|
|
$this->dataBilancio = is_string($this->dataBilancio) ? trim((string) $this->dataBilancio) : null;
|
|
$this->dataBilancio = $this->dataBilancio !== '' ? $this->dataBilancio : null;
|
|
|
|
$this->saldoBancaManuale = is_string($this->saldoBancaManuale) ? trim((string) $this->saldoBancaManuale) : null;
|
|
$this->saldoBancaManuale = $this->saldoBancaManuale !== '' ? $this->saldoBancaManuale : null;
|
|
|
|
$this->tab = is_string($this->tab) ? trim((string) $this->tab) : 'bilancio';
|
|
$this->tab = in_array($this->tab, ['bilancio', 'crediti', 'debiti', 'conguagli', 'dettaglio'], true) ? $this->tab : 'bilancio';
|
|
|
|
$this->dett = is_string($this->dett) ? trim((string) $this->dett) : null;
|
|
$this->dett = $this->dett !== '' ? $this->dett : null;
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function updatedTab(): void
|
|
{
|
|
$this->tab = is_string($this->tab) ? trim((string) $this->tab) : 'bilancio';
|
|
$this->tab = in_array($this->tab, ['bilancio', 'crediti', 'debiti', 'conguagli', 'dettaglio'], true) ? $this->tab : 'bilancio';
|
|
|
|
if ($this->tab !== 'dettaglio') {
|
|
$this->dett = null;
|
|
}
|
|
|
|
// Reset stati per evitare UI "incastrata" cambiando tab
|
|
$this->editingCreDebId = null;
|
|
$this->editingDettTabId = null;
|
|
$this->selectedCreDebId = null;
|
|
$this->detailTab = 'voce';
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function editCreDebRow(int $id): void
|
|
{
|
|
if ($id <= 0) {
|
|
return;
|
|
}
|
|
$this->editingCreDebId = $id;
|
|
$this->selectedCreDebId = $id;
|
|
}
|
|
|
|
public function cancelEditCreDebRow(): void
|
|
{
|
|
$this->editingCreDebId = null;
|
|
}
|
|
|
|
public function selectCreDebRow(int $id): void
|
|
{
|
|
if ($id <= 0) {
|
|
$this->selectedCreDebId = null;
|
|
return;
|
|
}
|
|
$this->selectedCreDebId = $id;
|
|
|
|
// Aggiorna subito i collegamenti documentali per la riga selezionata
|
|
$this->reloadDocumenti();
|
|
}
|
|
|
|
public function setDetailTab(string $tab): void
|
|
{
|
|
$tab = strtolower(trim($tab));
|
|
$this->detailTab = in_array($tab, ['voce', 'fe', 'ra'], true) ? $tab : 'voce';
|
|
}
|
|
|
|
public function editDettTabRow(int $id): void
|
|
{
|
|
if ($id <= 0) {
|
|
return;
|
|
}
|
|
$this->editingDettTabId = $id;
|
|
}
|
|
|
|
public function cancelEditDettTabRow(): void
|
|
{
|
|
$this->editingDettTabId = null;
|
|
}
|
|
|
|
private function loadCondominiLabels(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
$out = $this->loadLocalCondominiLabels();
|
|
|
|
// Tabella "condomini" (più snella) se presente
|
|
if (Schema::connection('gescon_import')->hasTable('condomini')) {
|
|
$q = DB::connection('gescon_import')->table('condomini')
|
|
->where('cod_stabile', $codStabileLegacy);
|
|
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('condomini', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$rows = $q->get(['id_cond', 'cognome', 'nome', 'cod_cond']);
|
|
foreach ($rows as $r) {
|
|
$id = trim((string) ($r->id_cond ?? ''));
|
|
if ($id === '') {
|
|
continue;
|
|
}
|
|
$label = trim(trim((string) ($r->cognome ?? '')) . ' ' . trim((string) ($r->nome ?? '')));
|
|
if ($label === '') {
|
|
$label = trim((string) ($r->cod_cond ?? ''));
|
|
}
|
|
if (! isset($out[$id]) || trim((string) $out[$id]) === '') {
|
|
$out[$id] = $label !== '' ? $label : $id;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback su "condomin" (più completa)
|
|
if (Schema::connection('gescon_import')->hasTable('condomin')) {
|
|
$q = DB::connection('gescon_import')->table('condomin')
|
|
->where('cod_stabile', $codStabileLegacy);
|
|
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('condomin', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$rows = $q->get(['id_cond', 'denominazione', 'nom_cond', 'cognome', 'nome', 'cod_cond']);
|
|
foreach ($rows as $r) {
|
|
$id = trim((string) ($r->id_cond ?? ''));
|
|
if ($id === '') {
|
|
continue;
|
|
}
|
|
$label = trim((string) ($r->denominazione ?? ''));
|
|
if ($label === '') {
|
|
$label = trim((string) ($r->nom_cond ?? ''));
|
|
}
|
|
if ($label === '') {
|
|
$label = trim(trim((string) ($r->cognome ?? '')) . ' ' . trim((string) ($r->nome ?? '')));
|
|
}
|
|
if ($label === '') {
|
|
$label = trim((string) ($r->cod_cond ?? ''));
|
|
}
|
|
if (! isset($out[$id]) || trim((string) $out[$id]) === '') {
|
|
$out[$id] = $label !== '' ? $label : $id;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
private function loadLocalCondominiLabels(): array
|
|
{
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if (! $stabileId || ! Schema::hasTable('unita_immobiliari') || ! Schema::hasColumn('unita_immobiliari', 'legacy_cond_id')) {
|
|
return [];
|
|
}
|
|
|
|
$referenceDate = $this->resolveReferenceDate();
|
|
$units = UnitaImmobiliare::query()
|
|
->where('stabile_id', (int) $stabileId)
|
|
->whereNotNull('legacy_cond_id')
|
|
->get(['id', 'legacy_cond_id', 'scala', 'interno', 'denominazione']);
|
|
|
|
if ($units->isEmpty()) {
|
|
return [];
|
|
}
|
|
|
|
$unitIds = $units->pluck('id')->map(fn ($id) => (int) $id)->all();
|
|
$namesByUnit = [];
|
|
|
|
if (Schema::hasTable('persone_unita_relazioni')) {
|
|
$relations = PersonaUnitaRelazione::query()
|
|
->with('persona')
|
|
->whereIn('unita_id', $unitIds)
|
|
->where('attivo', true)
|
|
->where(function ($query) use ($referenceDate): void {
|
|
$query->whereNull('data_inizio')->orWhere('data_inizio', '<=', $referenceDate->toDateString());
|
|
})
|
|
->where(function ($query) use ($referenceDate): void {
|
|
$query->whereNull('data_fine')->orWhere('data_fine', '>=', $referenceDate->toDateString());
|
|
})
|
|
->get();
|
|
|
|
foreach ($relations as $relation) {
|
|
$unitId = (int) $relation->unita_id;
|
|
$role = strtoupper((string) ($relation->ruolo_rate ?: PersonaUnitaRelazione::deriveRuoloRate($relation->tipo_relazione)));
|
|
if (! in_array($role, ['C', 'I'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$name = trim((string) ($relation->persona?->nome_display ?? $relation->persona?->nome_completo ?? ''));
|
|
if ($name === '') {
|
|
continue;
|
|
}
|
|
|
|
$namesByUnit[$unitId][$role][$name] = $name;
|
|
}
|
|
}
|
|
|
|
if (Schema::hasTable('unita_immobiliare_nominativi')) {
|
|
$legacyNames = UnitaImmobiliareNominativo::query()
|
|
->where('stabile_id', (int) $stabileId)
|
|
->whereIn('unita_immobiliare_id', $unitIds)
|
|
->where(function ($query) use ($referenceDate): void {
|
|
$query->whereNull('data_inizio')->orWhere('data_inizio', '<=', $referenceDate->toDateString());
|
|
})
|
|
->where(function ($query) use ($referenceDate): void {
|
|
$query->whereNull('data_fine')->orWhere('data_fine', '>=', $referenceDate->toDateString());
|
|
})
|
|
->get(['unita_immobiliare_id', 'ruolo', 'nominativo']);
|
|
|
|
foreach ($legacyNames as $row) {
|
|
$unitId = (int) ($row->unita_immobiliare_id ?? 0);
|
|
$role = strtoupper((string) ($row->ruolo ?? ''));
|
|
if (! in_array($role, ['C', 'I'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$name = trim((string) ($row->nominativo ?? ''));
|
|
if ($name === '') {
|
|
continue;
|
|
}
|
|
|
|
$namesByUnit[$unitId][$role][$name] = $name;
|
|
}
|
|
}
|
|
|
|
$labels = [];
|
|
foreach ($units as $unit) {
|
|
$legacyCondId = trim((string) ($unit->legacy_cond_id ?? ''));
|
|
if ($legacyCondId === '') {
|
|
continue;
|
|
}
|
|
|
|
$pieces = [];
|
|
$scala = trim((string) ($unit->scala ?? ''));
|
|
$interno = trim((string) ($unit->interno ?? ''));
|
|
$denominazione = trim((string) ($unit->denominazione ?? ''));
|
|
|
|
if ($scala !== '' || $interno !== '') {
|
|
$unitLabel = trim(($scala !== '' ? ('Scala ' . $scala) : '') . ($interno !== '' ? (' Int. ' . $interno) : ''));
|
|
if ($unitLabel !== '') {
|
|
$pieces[] = $unitLabel;
|
|
}
|
|
} elseif ($denominazione !== '') {
|
|
$pieces[] = $denominazione;
|
|
}
|
|
|
|
$owners = array_values($namesByUnit[(int) $unit->id]['C'] ?? []);
|
|
$tenants = array_values($namesByUnit[(int) $unit->id]['I'] ?? []);
|
|
|
|
if ($owners !== []) {
|
|
$pieces[] = 'Prop: ' . implode(', ', $owners);
|
|
}
|
|
if ($tenants !== []) {
|
|
$pieces[] = 'Inq: ' . implode(', ', $tenants);
|
|
}
|
|
if ($pieces === [] && $denominazione !== '') {
|
|
$pieces[] = $denominazione;
|
|
}
|
|
|
|
$labels[$legacyCondId] = $pieces !== [] ? implode(' · ', $pieces) : $legacyCondId;
|
|
}
|
|
|
|
return $labels;
|
|
}
|
|
|
|
private function resolveReferenceDate(): Carbon
|
|
{
|
|
try {
|
|
return $this->dataBilancio ? Carbon::parse($this->dataBilancio)->startOfDay() : now()->startOfDay();
|
|
} catch (\Throwable) {
|
|
return now()->startOfDay();
|
|
}
|
|
}
|
|
|
|
public function updatedLegacyYear(): void
|
|
{
|
|
$this->legacyYear = is_string($this->legacyYear) ? trim((string) $this->legacyYear) : null;
|
|
$this->legacyYear = $this->legacyYear !== '' ? $this->legacyYear : null;
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function updatedDataBilancio(): void
|
|
{
|
|
$this->dataBilancio = is_string($this->dataBilancio) ? trim((string) $this->dataBilancio) : null;
|
|
$this->dataBilancio = $this->dataBilancio !== '' ? $this->dataBilancio : null;
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function updatedSaldoBancaManuale(): void
|
|
{
|
|
$this->saldoBancaManuale = is_string($this->saldoBancaManuale) ? trim((string) $this->saldoBancaManuale) : null;
|
|
$this->saldoBancaManuale = $this->saldoBancaManuale !== '' ? $this->saldoBancaManuale : null;
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function updatedSaldoContoId(): void
|
|
{
|
|
$this->saldoContoId = is_string($this->saldoContoId) ? trim((string) $this->saldoContoId) : null;
|
|
$this->saldoContoId = $this->saldoContoId !== '' ? $this->saldoContoId : null;
|
|
$this->loadSaldoSnapshots();
|
|
}
|
|
|
|
public function updatedDett(): void
|
|
{
|
|
$this->dett = is_string($this->dett) ? trim((string) $this->dett) : null;
|
|
$this->dett = $this->dett !== '' ? $this->dett : null;
|
|
$this->reloadData();
|
|
}
|
|
|
|
private function getActiveStabile(): ?Stabile
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
return StabileContext::getActiveStabile($user);
|
|
}
|
|
|
|
private function reloadData(): void
|
|
{
|
|
$stabile = $this->getActiveStabile();
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
|
|
$this->legacyYears = $this->loadLegacyYears($codStabileLegacy);
|
|
$this->legacyYearLabels = $codStabileLegacy ? $this->loadLegacyYearLabels($codStabileLegacy) : [];
|
|
|
|
// Default/fallback legacyYear:
|
|
// - Se l'utente NON ha passato legacy_year in query, default al primo esercizio (tipicamente 0001).
|
|
// - Se legacy_year è passato (anche vuoto => "Tutti"), rispettalo.
|
|
// - Se legacy_year è valorizzato ma non esiste più tra quelli disponibili, fai fallback al primo disponibile.
|
|
$hasLegacyYearParam = request()->query->has('legacy_year');
|
|
if (! $hasLegacyYearParam) {
|
|
if (! empty($this->legacyYears) && ($this->legacyYear === null || $this->legacyYear === '')) {
|
|
$this->legacyYear = $this->legacyYears[0];
|
|
}
|
|
}
|
|
if ($this->legacyYear !== null && $this->legacyYear !== '' && ! in_array($this->legacyYear, $this->legacyYears, true)) {
|
|
$this->legacyYear = ! empty($this->legacyYears) ? $this->legacyYears[0] : null;
|
|
}
|
|
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
$this->conti = $stabileId ? $this->loadContiOptions($stabileId) : [];
|
|
|
|
if (($this->saldoContoId === null || $this->saldoContoId === '') && $this->conti !== []) {
|
|
$this->saldoContoId = (string) array_key_first($this->conti);
|
|
}
|
|
if ($this->saldoContoId !== null && $this->saldoContoId !== '' && ! array_key_exists($this->saldoContoId, $this->conti)) {
|
|
$this->saldoContoId = $this->conti !== [] ? (string) array_key_first($this->conti) : null;
|
|
}
|
|
|
|
if (! $this->dataBilancio) {
|
|
$this->dataBilancio = $this->defaultDataBilancio();
|
|
}
|
|
|
|
if (! $codStabileLegacy || ! $stabileId) {
|
|
$this->bilancio = $this->emptyBilancio();
|
|
$this->risorseFinanziarie = [];
|
|
$this->conguagliExcel = [];
|
|
$this->conguagliExcelCols = [];
|
|
$this->detailMeta = [];
|
|
$this->detailRows = [];
|
|
$this->saldoSnapshots = [];
|
|
return;
|
|
}
|
|
|
|
$this->risorseFinanziarie = $this->computeRisorseFinanziarie($stabileId, $this->dataBilancio);
|
|
$this->bilancio = $this->computeBilancio($stabileId, $codStabileLegacy, $this->legacyYear, $this->dataBilancio, $this->saldoBancaManuale, $this->risorseFinanziarie);
|
|
|
|
$this->vocSpeOptions = $this->loadVocSpeOptions($codStabileLegacy, $this->legacyYear);
|
|
|
|
if ($this->tab === 'conguagli') {
|
|
$this->conguagliExcel = [];
|
|
$this->conguagliExcelCols = [];
|
|
[$this->dettTabRows, $this->dettTabEdit] = $this->loadDettTabCrudRows($codStabileLegacy, $this->legacyYear);
|
|
} else {
|
|
$this->conguagliExcel = [];
|
|
$this->conguagliExcelCols = [];
|
|
$this->dettTabRows = [];
|
|
$this->dettTabEdit = [];
|
|
}
|
|
|
|
if (in_array($this->tab, ['crediti', 'debiti'], true)) {
|
|
$cd = $this->tab === 'crediti' ? 'C' : 'D';
|
|
[$this->creDebRows, $this->creDebEdit] = $this->loadCreDebPrecedCrudRows($codStabileLegacy, $this->legacyYear, $cd);
|
|
|
|
// Liste documentali per sub-tab (FE/RA)
|
|
$this->reloadDocumenti();
|
|
} else {
|
|
$this->creDebRows = [];
|
|
$this->creDebEdit = [];
|
|
|
|
$this->feRows = [];
|
|
$this->linkedFeIds = [];
|
|
$this->raRows = [];
|
|
$this->linkedRaIds = [];
|
|
}
|
|
|
|
$this->reloadDettaglio($codStabileLegacy, $this->legacyYear);
|
|
$this->loadSaldoSnapshots();
|
|
}
|
|
|
|
public function saveSaldoSnapshot(): void
|
|
{
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
if (! $stabileId) {
|
|
$this->addError('saldoContoId', 'Seleziona prima uno stabile attivo.');
|
|
return;
|
|
}
|
|
|
|
$validated = $this->validate([
|
|
'saldoContoId' => ['required', 'string'],
|
|
'saldoSnapshotData' => ['required', 'date'],
|
|
'saldoSnapshotPeriodoDa' => ['nullable', 'date'],
|
|
'saldoSnapshotPeriodoA' => ['nullable', 'date'],
|
|
'saldoSnapshotSaldo' => ['required', 'string'],
|
|
'saldoSnapshotTipo' => ['required', 'string', 'in:estratto_conto,saldo_banca,riconciliazione,altro'],
|
|
'saldoSnapshotNote' => ['nullable', 'string', 'max:255'],
|
|
'saldoSnapshotPdf' => ['nullable', 'file', 'mimes:pdf', 'max:20480'],
|
|
]);
|
|
|
|
$contoId = (int) ($validated['saldoContoId'] ?? 0);
|
|
$conto = DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('id', $contoId)
|
|
->first(['id', 'denominazione_banca', 'iban', 'numero_conto', 'legacy_cod_cassa']);
|
|
|
|
if (! $conto) {
|
|
$this->addError('saldoContoId', 'Conto non valido per lo stabile attivo.');
|
|
return;
|
|
}
|
|
|
|
$saldo = $this->parseMoney((string) ($validated['saldoSnapshotSaldo'] ?? ''));
|
|
if ($saldo === null) {
|
|
$this->addError('saldoSnapshotSaldo', 'Saldo non valido.');
|
|
return;
|
|
}
|
|
|
|
$user = Auth::user();
|
|
$documento = $this->storeSaldoSnapshotDocumento($stabileId, $conto, $this->saldoSnapshotPdf, $validated);
|
|
|
|
SaldoConto::query()->updateOrCreate(
|
|
[
|
|
'stabile_id' => $stabileId,
|
|
'conto_id' => $contoId,
|
|
'data_saldo' => $validated['saldoSnapshotData'],
|
|
],
|
|
[
|
|
'iban' => $this->normalizeIbanValue($conto->iban),
|
|
'periodo_da' => $validated['saldoSnapshotPeriodoDa'] ?? null,
|
|
'periodo_a' => $validated['saldoSnapshotPeriodoA'] ?? null,
|
|
'saldo' => $saldo,
|
|
'tipo_estratto' => $validated['saldoSnapshotTipo'],
|
|
'note' => isset($validated['saldoSnapshotNote']) ? trim((string) $validated['saldoSnapshotNote']) : null,
|
|
'documento_stabile_id' => $documento?->id,
|
|
'created_by' => (int) ($user?->id ?? 0) ?: null,
|
|
'updated_by' => (int) ($user?->id ?? 0) ?: null,
|
|
]
|
|
);
|
|
|
|
$this->resetSaldoSnapshotForm(false);
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function deleteSaldoSnapshot(int $snapshotId): void
|
|
{
|
|
if ($snapshotId <= 0) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
if (! $stabileId) {
|
|
return;
|
|
}
|
|
|
|
$snapshot = SaldoConto::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('id', $snapshotId)
|
|
->first();
|
|
|
|
if (! $snapshot) {
|
|
return;
|
|
}
|
|
|
|
$documentoId = (int) ($snapshot->documento_stabile_id ?? 0);
|
|
$snapshot->delete();
|
|
|
|
if ($documentoId > 0) {
|
|
DocumentoStabile::query()->where('id', $documentoId)->delete();
|
|
}
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
private function loadSaldoSnapshots(): void
|
|
{
|
|
$this->saldoSnapshots = [];
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
$contoId = is_numeric($this->saldoContoId) ? (int) $this->saldoContoId : 0;
|
|
if (! $stabileId || $contoId <= 0 || ! DB::getSchemaBuilder()->hasTable('contabilita_saldi_conti')) {
|
|
return;
|
|
}
|
|
|
|
$this->saldoSnapshots = SaldoConto::query()
|
|
->with('documento')
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId)
|
|
->orderByDesc('data_saldo')
|
|
->orderByDesc('id')
|
|
->get()
|
|
->map(function (SaldoConto $row): array {
|
|
return [
|
|
'id' => (int) $row->id,
|
|
'data_saldo' => $row->data_saldo?->format('d/m/Y'),
|
|
'periodo' => $this->formatPeriodoEstrattoLabel($row->periodo_da, $row->periodo_a),
|
|
'tipo' => $this->formatTipoEstrattoLabel($row->tipo_estratto),
|
|
'saldo' => (float) $row->saldo,
|
|
'note' => (string) ($row->note ?? ''),
|
|
'documento_nome' => $row->documento?->nome_originale,
|
|
'documento_url' => $row->documento?->url_view,
|
|
];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function resetSaldoSnapshotForm(bool $resetConto = true): void
|
|
{
|
|
if ($resetConto) {
|
|
$this->saldoContoId = $this->conti !== [] ? (string) array_key_first($this->conti) : null;
|
|
}
|
|
|
|
$this->saldoSnapshotData = $this->dataBilancio;
|
|
$this->saldoSnapshotPeriodoDa = null;
|
|
$this->saldoSnapshotPeriodoA = null;
|
|
$this->saldoSnapshotSaldo = null;
|
|
$this->saldoSnapshotTipo = 'estratto_conto';
|
|
$this->saldoSnapshotNote = null;
|
|
$this->saldoSnapshotPdf = null;
|
|
$this->resetValidation([
|
|
'saldoContoId',
|
|
'saldoSnapshotData',
|
|
'saldoSnapshotPeriodoDa',
|
|
'saldoSnapshotPeriodoA',
|
|
'saldoSnapshotSaldo',
|
|
'saldoSnapshotTipo',
|
|
'saldoSnapshotNote',
|
|
'saldoSnapshotPdf',
|
|
]);
|
|
}
|
|
|
|
private function formatTipoEstrattoLabel(?string $value): string
|
|
{
|
|
return match (trim((string) $value)) {
|
|
'estratto_conto' => 'Estratto conto',
|
|
'saldo_banca' => 'Saldo banca',
|
|
'riconciliazione' => 'Riconciliazione',
|
|
'altro' => 'Altro',
|
|
default => 'Saldo registrato',
|
|
};
|
|
}
|
|
|
|
private function formatPeriodoEstrattoLabel(mixed $from, mixed $to): string
|
|
{
|
|
$fromDate = $from instanceof Carbon ? $from : ($from ? Carbon::parse((string) $from) : null);
|
|
$toDate = $to instanceof Carbon ? $to : ($to ? Carbon::parse((string) $to) : null);
|
|
|
|
if ($fromDate && $toDate) {
|
|
return $fromDate->format('d/m/Y') . ' - ' . $toDate->format('d/m/Y');
|
|
}
|
|
if ($toDate) {
|
|
return 'Fino al ' . $toDate->format('d/m/Y');
|
|
}
|
|
if ($fromDate) {
|
|
return 'Dal ' . $fromDate->format('d/m/Y');
|
|
}
|
|
|
|
return 'Periodo non indicato';
|
|
}
|
|
|
|
private function normalizeIbanValue(mixed $value): ?string
|
|
{
|
|
$iban = is_string($value) ? trim((string) $value) : '';
|
|
return $iban !== '' ? $iban : null;
|
|
}
|
|
|
|
private function storeSaldoSnapshotDocumento(int $stabileId, DatiBancari $conto, TemporaryUploadedFile|string|null $file, array $validated): ?DocumentoStabile
|
|
{
|
|
if (! $file instanceof TemporaryUploadedFile) {
|
|
return null;
|
|
}
|
|
|
|
$originalName = trim((string) $file->getClientOriginalName());
|
|
$extension = strtolower((string) $file->getClientOriginalExtension());
|
|
$extension = $extension !== '' ? $extension : 'pdf';
|
|
$storedName = 'estratto-conto-' . $stabileId . '-' . (int) $conto->id . '-' . now()->format('YmdHis') . '.' . $extension;
|
|
$storedPath = $file->storeAs('documenti/stabili/' . $stabileId . '/bancari', $storedName, 'public');
|
|
|
|
return DocumentoStabile::query()->create([
|
|
'stabile_id' => $stabileId,
|
|
'nome_file' => $storedName,
|
|
'nome_originale' => $originalName !== '' ? $originalName : $storedName,
|
|
'percorso_file' => $storedPath,
|
|
'categoria' => 'bancari',
|
|
'tipo_mime' => Storage::disk('public')->mimeType($storedPath),
|
|
'dimensione' => Storage::disk('public')->size($storedPath),
|
|
'descrizione' => 'Saldo/estratto ' . ($this->conti[(string) $conto->id] ?? ('Conto #' . $conto->id)) . ' · ' . $this->formatPeriodoEstrattoLabel($validated['saldoSnapshotPeriodoDa'] ?? null, $validated['saldoSnapshotPeriodoA'] ?? null),
|
|
'caricato_da' => Auth::id(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Carica etichette user-friendly per le gestioni legacy (tabella "anni" in generale_stabile.mdb).
|
|
* Ritorna una mappa: cartella (0001) => label (2024-25 o 2024).
|
|
*/
|
|
private function loadLegacyYearLabels(string $codStabileLegacy): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('gestioni_annuali')) {
|
|
return [];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('gestioni_annuali')
|
|
->where('cod_stabile', $codStabileLegacy);
|
|
|
|
$rows = $q->get(['cartella', 'anno_ordinario', 'anno_riscaldamento']);
|
|
$out = [];
|
|
foreach ($rows as $r) {
|
|
$cartella = trim((string) ($r->cartella ?? ''));
|
|
if ($cartella === '') {
|
|
continue;
|
|
}
|
|
$ord = trim((string) ($r->anno_ordinario ?? ''));
|
|
$risc = trim((string) ($r->anno_riscaldamento ?? ''));
|
|
|
|
$parts = [];
|
|
if ($ord !== '') {
|
|
$parts[] = 'Ord. ' . $ord;
|
|
}
|
|
if ($risc !== '' && $risc !== $ord) {
|
|
$parts[] = 'Risc. ' . $risc;
|
|
}
|
|
$parts[] = 'Dir. ' . $cartella;
|
|
$out[$cartella] = implode(' · ', $parts);
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
private function reloadDocumenti(): void
|
|
{
|
|
$this->feRows = [];
|
|
$this->linkedFeIds = [];
|
|
$this->raRows = [];
|
|
$this->linkedRaIds = [];
|
|
|
|
// Documenti FE/RA: normalmente solo sui DEBITI (fatture passive + ritenute da versare)
|
|
if ($this->tab !== 'debiti') {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $stabileId) {
|
|
return;
|
|
}
|
|
|
|
$cd = 'D';
|
|
$this->feRows = $this->loadFeRows($stabileId, $cd);
|
|
$this->raRows = $this->loadRaRows($stabileId);
|
|
|
|
if (! $this->selectedCreDebId || ! $codStabileLegacy || ! $this->legacyYear) {
|
|
return;
|
|
}
|
|
|
|
$this->linkedFeIds = $this->loadLinkedFeIds($codStabileLegacy, $this->legacyYear, (int) $this->selectedCreDebId, $cd);
|
|
$this->linkedRaIds = $this->loadLinkedRaIds($codStabileLegacy, $this->legacyYear, (int) $this->selectedCreDebId, $cd);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
private function loadFeRows(int $stabileId, string $cd): array
|
|
{
|
|
$cd = strtoupper(trim($cd));
|
|
$q = FatturaElettronica::query()->where('stabile_id', $stabileId);
|
|
|
|
// Per i debiti ha senso mostrare prima le fatture da pagare.
|
|
if ($cd === 'D') {
|
|
$q->where('stato', '!=', 'pagata');
|
|
}
|
|
|
|
// Situazione iniziale: mostriamo solo documenti antecedenti alla data bilancio (cut-off).
|
|
// Esempio: bilancio al 01/01/2024 => fatture 2023.
|
|
if (is_string($this->dataBilancio) && $this->dataBilancio !== '') {
|
|
try {
|
|
$cutoff = Carbon::parse($this->dataBilancio)->startOfDay();
|
|
$q->whereDate('data_fattura', '<', $cutoff->toDateString());
|
|
} catch (\Throwable) {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
$rows = $q
|
|
->orderBy('data_fattura', 'asc')
|
|
->orderBy('id', 'asc')
|
|
->limit(100)
|
|
->get();
|
|
|
|
return $rows->map(function (FatturaElettronica $f) {
|
|
return [
|
|
'id' => (int) $f->id,
|
|
'data_fattura' => $f->data_fattura?->format('Y-m-d'),
|
|
'data_scadenza' => $f->data_scadenza?->format('Y-m-d'),
|
|
'numero_fattura' => (string) ($f->numero_fattura ?? ''),
|
|
'fornitore_denominazione' => (string) ($f->fornitore_denominazione ?? ''),
|
|
'totale' => is_numeric($f->totale) ? (float) $f->totale : null,
|
|
'stato' => (string) ($f->stato ?? ''),
|
|
];
|
|
})->all();
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
private function loadRaRows(int $stabileId): array
|
|
{
|
|
$rows = RegistroRitenuteAcconto::query()
|
|
->with(['fornitore', 'gestione'])
|
|
->whereHas('gestione', function ($q) use ($stabileId) {
|
|
$q->where('stabile_id', $stabileId);
|
|
})
|
|
->whereIn('stato_versamento', ['da_versare', 'compensata'])
|
|
->orderBy('data_competenza', 'desc')
|
|
->orderBy('id', 'desc')
|
|
->limit(100)
|
|
->get();
|
|
|
|
return $rows->map(function (RegistroRitenuteAcconto $r) {
|
|
$fornitoreLabel = '';
|
|
try {
|
|
$fornitoreLabel = (string) ($r->fornitore?->ragione_sociale ?? '');
|
|
} catch (\Throwable) {
|
|
$fornitoreLabel = '';
|
|
}
|
|
|
|
return [
|
|
'id' => (int) $r->id,
|
|
'data_competenza' => $r->data_competenza?->format('Y-m-d'),
|
|
'numero_progressivo' => (int) ($r->numero_progressivo ?? 0),
|
|
'fornitore' => $fornitoreLabel,
|
|
'importo_ritenuta' => is_numeric($r->importo_ritenuta) ? (float) $r->importo_ritenuta : null,
|
|
'stato_versamento' => (string) ($r->stato_versamento ?? ''),
|
|
];
|
|
})->all();
|
|
}
|
|
|
|
/**
|
|
* @return array<int, int>
|
|
*/
|
|
private function loadLinkedFeIds(string $codStabileLegacy, string $legacyYear, int $creDebPrecedId, string $cd): array
|
|
{
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_fe_links')) {
|
|
return [];
|
|
}
|
|
|
|
return DB::table('contabilita_situazione_iniziale_fe_links')
|
|
->where('cod_stabile_legacy', $codStabileLegacy)
|
|
->where('legacy_year', $legacyYear)
|
|
->where('cre_deb_preced_id', $creDebPrecedId)
|
|
->where('c_d', strtoupper(trim($cd)))
|
|
->pluck('fattura_elettronica_id')
|
|
->map(fn ($v) => (int) $v)
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
/**
|
|
* @return array<int, int>
|
|
*/
|
|
private function loadLinkedRaIds(string $codStabileLegacy, string $legacyYear, int $creDebPrecedId, string $cd): array
|
|
{
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_ra_links')) {
|
|
return [];
|
|
}
|
|
|
|
return DB::table('contabilita_situazione_iniziale_ra_links')
|
|
->where('cod_stabile_legacy', $codStabileLegacy)
|
|
->where('legacy_year', $legacyYear)
|
|
->where('cre_deb_preced_id', $creDebPrecedId)
|
|
->where('c_d', strtoupper(trim($cd)))
|
|
->pluck('registro_ritenuta_acconto_id')
|
|
->map(fn ($v) => (int) $v)
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
public function linkFatturaElettronica(int $fatturaId): void
|
|
{
|
|
$fatturaId = (int) $fatturaId;
|
|
if ($fatturaId <= 0 || ! $this->selectedCreDebId || ! $this->legacyYear) {
|
|
return;
|
|
}
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_fe_links')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
if ($this->tab !== 'debiti') {
|
|
return;
|
|
}
|
|
$cd = 'D';
|
|
|
|
DB::table('contabilita_situazione_iniziale_fe_links')->updateOrInsert(
|
|
[
|
|
'cod_stabile_legacy' => $codStabileLegacy,
|
|
'legacy_year' => $this->legacyYear,
|
|
'cre_deb_preced_id' => (int) $this->selectedCreDebId,
|
|
'c_d' => $cd,
|
|
'fattura_elettronica_id' => $fatturaId,
|
|
],
|
|
[
|
|
'stabile_id' => $stabileId,
|
|
'updated_at' => now(),
|
|
'created_at' => now(),
|
|
]
|
|
);
|
|
|
|
$this->reloadDocumenti();
|
|
}
|
|
|
|
public function unlinkFatturaElettronica(int $fatturaId): void
|
|
{
|
|
$fatturaId = (int) $fatturaId;
|
|
if ($fatturaId <= 0 || ! $this->selectedCreDebId || ! $this->legacyYear) {
|
|
return;
|
|
}
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_fe_links')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
if ($this->tab !== 'debiti') {
|
|
return;
|
|
}
|
|
$cd = 'D';
|
|
DB::table('contabilita_situazione_iniziale_fe_links')
|
|
->where('cod_stabile_legacy', $codStabileLegacy)
|
|
->where('legacy_year', $this->legacyYear)
|
|
->where('cre_deb_preced_id', (int) $this->selectedCreDebId)
|
|
->where('c_d', $cd)
|
|
->where('fattura_elettronica_id', $fatturaId)
|
|
->delete();
|
|
|
|
$this->reloadDocumenti();
|
|
}
|
|
|
|
public function linkRegistroRa(int $registroId): void
|
|
{
|
|
$registroId = (int) $registroId;
|
|
if ($registroId <= 0 || ! $this->selectedCreDebId || ! $this->legacyYear) {
|
|
return;
|
|
}
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_ra_links')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$stabileId = $stabile?->id ? (int) $stabile->id : null;
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
if ($this->tab !== 'debiti') {
|
|
return;
|
|
}
|
|
$cd = 'D';
|
|
|
|
DB::table('contabilita_situazione_iniziale_ra_links')->updateOrInsert(
|
|
[
|
|
'cod_stabile_legacy' => $codStabileLegacy,
|
|
'legacy_year' => $this->legacyYear,
|
|
'cre_deb_preced_id' => (int) $this->selectedCreDebId,
|
|
'c_d' => $cd,
|
|
'registro_ritenuta_acconto_id' => $registroId,
|
|
],
|
|
[
|
|
'stabile_id' => $stabileId,
|
|
'updated_at' => now(),
|
|
'created_at' => now(),
|
|
]
|
|
);
|
|
|
|
$this->reloadDocumenti();
|
|
}
|
|
|
|
public function unlinkRegistroRa(int $registroId): void
|
|
{
|
|
$registroId = (int) $registroId;
|
|
if ($registroId <= 0 || ! $this->selectedCreDebId || ! $this->legacyYear) {
|
|
return;
|
|
}
|
|
if (! Schema::hasTable('contabilita_situazione_iniziale_ra_links')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
if ($this->tab !== 'debiti') {
|
|
return;
|
|
}
|
|
$cd = 'D';
|
|
DB::table('contabilita_situazione_iniziale_ra_links')
|
|
->where('cod_stabile_legacy', $codStabileLegacy)
|
|
->where('legacy_year', $this->legacyYear)
|
|
->where('cre_deb_preced_id', (int) $this->selectedCreDebId)
|
|
->where('c_d', $cd)
|
|
->where('registro_ritenuta_acconto_id', $registroId)
|
|
->delete();
|
|
|
|
$this->reloadDocumenti();
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
private function loadVocSpeOptions(?string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
if (! $codStabileLegacy) {
|
|
return [];
|
|
}
|
|
if (! Schema::connection('gescon_import')->hasTable('voc_spe')) {
|
|
return [];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('voc_spe')->where('cod_stabile', $codStabileLegacy);
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('voc_spe', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$rows = $q
|
|
->orderBy('cod')
|
|
->limit(300)
|
|
->get(['cod', 'descriz']);
|
|
|
|
$out = [];
|
|
foreach ($rows as $r) {
|
|
$cod = trim((string) ($r->cod ?? ''));
|
|
if ($cod === '') {
|
|
continue;
|
|
}
|
|
$label = trim((string) ($r->descriz ?? ''));
|
|
$out[$cod] = $label !== '' ? ($cod . ' — ' . $label) : $cod;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
private function loadCreDebPrecedCrudRows(string $codStabileLegacy, ?string $legacyYear, string $cd): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return [[], []];
|
|
}
|
|
|
|
$cd = strtoupper(trim($cd));
|
|
if (! in_array($cd, ['C', 'D'], true)) {
|
|
$cd = 'D';
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->whereRaw('UPPER(c_d) = ?', [$cd]);
|
|
|
|
$hasForStabile = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$rows = $q->orderBy('cod_voc')->orderBy('id')->limit(5000)
|
|
->get(['id', 'c_d', 'cod_voc', 'des_voce', 'descrizione', 'importo_euro', 'n_stra', 'incluso'])
|
|
->map(fn ($r) => [
|
|
'id' => (int) $r->id,
|
|
'c_d' => (string) ($r->c_d ?? ''),
|
|
'cod_voc' => (string) ($r->cod_voc ?? ''),
|
|
'des_voce' => (string) ($r->des_voce ?? ''),
|
|
'descrizione' => (string) ($r->descrizione ?? ''),
|
|
'importo_euro' => (float) ($r->importo_euro ?? 0.0),
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
'incluso' => $r->incluso !== null ? (int) $r->incluso : 1,
|
|
])->all();
|
|
|
|
// Lookup descrizione voce di spesa da voc_spe (stesso MDB): cod_voc -> voc_spe.cod
|
|
$vocMap = [];
|
|
if (! empty($rows) && Schema::connection('gescon_import')->hasTable('voc_spe')) {
|
|
$cods = array_values(array_unique(array_filter(array_map(fn ($r) => trim((string) ($r['cod_voc'] ?? '')), $rows), fn ($v) => $v !== '')));
|
|
if (! empty($cods)) {
|
|
$vq = DB::connection('gescon_import')->table('voc_spe')->where('cod_stabile', $codStabileLegacy);
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('voc_spe', 'legacy_year')) {
|
|
$vq->where('legacy_year', $legacyYear);
|
|
}
|
|
if (Schema::connection('gescon_import')->hasColumn('voc_spe', 'cod')) {
|
|
$vq->whereIn('cod', $cods);
|
|
}
|
|
|
|
foreach ($vq->get(['cod', 'descriz', 'consuntivo_euro', 'preventivo_euro']) as $vr) {
|
|
$k = trim((string) ($vr->cod ?? ''));
|
|
if ($k === '') {
|
|
continue;
|
|
}
|
|
$vocMap[$k] = [
|
|
'descriz' => trim((string) ($vr->descriz ?? '')),
|
|
'consuntivo_euro' => $vr->consuntivo_euro !== null ? (float) $vr->consuntivo_euro : null,
|
|
'preventivo_euro' => $vr->preventivo_euro !== null ? (float) $vr->preventivo_euro : null,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! empty($vocMap)) {
|
|
foreach ($rows as &$row) {
|
|
$cod = trim((string) ($row['cod_voc'] ?? ''));
|
|
if ($cod !== '' && isset($vocMap[$cod])) {
|
|
$row['voc_spe_descriz'] = (string) ($vocMap[$cod]['descriz'] ?? '');
|
|
$row['voc_spe_consuntivo_euro'] = $vocMap[$cod]['consuntivo_euro'] ?? null;
|
|
$row['voc_spe_preventivo_euro'] = $vocMap[$cod]['preventivo_euro'] ?? null;
|
|
} else {
|
|
$row['voc_spe_descriz'] = '';
|
|
$row['voc_spe_consuntivo_euro'] = null;
|
|
$row['voc_spe_preventivo_euro'] = null;
|
|
}
|
|
}
|
|
unset($row);
|
|
} else {
|
|
foreach ($rows as &$row) {
|
|
$row['voc_spe_descriz'] = '';
|
|
$row['voc_spe_consuntivo_euro'] = null;
|
|
$row['voc_spe_preventivo_euro'] = null;
|
|
}
|
|
unset($row);
|
|
}
|
|
|
|
$edit = [];
|
|
foreach ($rows as $row) {
|
|
$id = (int) ($row['id'] ?? 0);
|
|
if ($id <= 0) {
|
|
continue;
|
|
}
|
|
$edit[$id] = [
|
|
'cod_voc' => $row['cod_voc'],
|
|
'des_voce' => $row['des_voce'],
|
|
'descrizione' => $row['descrizione'],
|
|
'importo_euro' => $row['importo_euro'],
|
|
'n_stra' => $row['n_stra'],
|
|
'incluso' => $row['incluso'],
|
|
];
|
|
}
|
|
|
|
return [$rows, $edit];
|
|
}
|
|
|
|
private function loadDettTabCrudRows(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return [[], []];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_tab', 'CONG.O')
|
|
->where(function ($query) {
|
|
$query->whereNull('n_stra')->orWhere('n_stra', '<=', 0);
|
|
});
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$labels = $this->loadCondominiLabels($codStabileLegacy, $legacyYear);
|
|
|
|
$rows = $q->orderBy('cod_tab')
|
|
->orderBy('n_stra')
|
|
->orderByRaw('CAST(id_cond AS UNSIGNED)')
|
|
->orderBy('id')
|
|
->limit(5000)
|
|
->get(['id', 'cod_tab', 'id_cond', 'cond_inquil', 'mm', 'cons_euro', 'n_stra', 'unico'])
|
|
->map(fn ($r) => [
|
|
'id' => (int) $r->id,
|
|
'cod_tab' => (string) ($r->cod_tab ?? ''),
|
|
'id_cond' => (string) ($r->id_cond ?? ''),
|
|
'cond_label' => (string) ($labels[trim((string) ($r->id_cond ?? ''))] ?? ''),
|
|
'cond_inquil' => (string) ($r->cond_inquil ?? ''),
|
|
'mm' => $r->mm !== null ? (float) $r->mm : null,
|
|
'cons_euro' => $r->cons_euro !== null ? (float) $r->cons_euro : 0.0,
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
'unico' => $r->unico !== null ? (int) $r->unico : 0,
|
|
])->all();
|
|
|
|
$edit = [];
|
|
foreach ($rows as $row) {
|
|
$id = (int) ($row['id'] ?? 0);
|
|
if ($id <= 0) {
|
|
continue;
|
|
}
|
|
$edit[$id] = [
|
|
'cod_tab' => $row['cod_tab'],
|
|
'id_cond' => $row['id_cond'],
|
|
'cond_inquil' => $row['cond_inquil'],
|
|
'mm' => $row['mm'],
|
|
'cons_euro' => $row['cons_euro'],
|
|
'n_stra' => $row['n_stra'],
|
|
'unico' => $row['unico'],
|
|
];
|
|
}
|
|
|
|
return [$rows, $edit];
|
|
}
|
|
|
|
public function saveCreDebRow(int $id): void
|
|
{
|
|
if ($id <= 0 || ! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return;
|
|
}
|
|
$edit = $this->creDebEdit[$id] ?? null;
|
|
if (! is_array($edit)) {
|
|
return;
|
|
}
|
|
|
|
$importo = $this->parseMoney(is_string($edit['importo_euro'] ?? null) ? (string) $edit['importo_euro'] : null);
|
|
if ($importo === null && is_numeric($edit['importo_euro'] ?? null)) {
|
|
$importo = (float) $edit['importo_euro'];
|
|
}
|
|
if ($importo === null) {
|
|
$importo = 0.0;
|
|
}
|
|
|
|
DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('id', $id)
|
|
->update([
|
|
'cod_voc' => is_string($edit['cod_voc'] ?? null) ? trim((string) $edit['cod_voc']) : null,
|
|
'des_voce' => is_string($edit['des_voce'] ?? null) ? trim((string) $edit['des_voce']) : null,
|
|
'descrizione' => is_string($edit['descrizione'] ?? null) ? trim((string) $edit['descrizione']) : null,
|
|
'importo_euro' => round((float) $importo, 2),
|
|
'n_stra' => is_numeric($edit['n_stra'] ?? null) ? (int) $edit['n_stra'] : null,
|
|
'incluso' => ! empty($edit['incluso']) ? 1 : 0,
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function deleteCreDebRow(int $id): void
|
|
{
|
|
if ($id <= 0 || ! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return;
|
|
}
|
|
|
|
DB::connection('gescon_import')->table('cre_deb_preced')->where('id', $id)->delete();
|
|
unset($this->creDebEdit[$id]);
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function addCreDebRow(string $cd): void
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
$cd = strtoupper(trim($cd));
|
|
if (! in_array($cd, ['C', 'D'], true)) {
|
|
$cd = 'D';
|
|
}
|
|
|
|
$importo = $this->parseMoney(is_string($this->formCreDebAdd['importo_euro'] ?? null) ? (string) $this->formCreDebAdd['importo_euro'] : null);
|
|
if ($importo === null) {
|
|
return;
|
|
}
|
|
|
|
$row = [
|
|
'cod_stabile' => $codStabileLegacy,
|
|
'legacy_year' => $this->legacyYear,
|
|
'c_d' => $cd,
|
|
'cod_voc' => is_string($this->formCreDebAdd['cod_voc'] ?? null) ? trim((string) $this->formCreDebAdd['cod_voc']) : null,
|
|
'des_voce' => is_string($this->formCreDebAdd['des_voce'] ?? null) ? trim((string) $this->formCreDebAdd['des_voce']) : null,
|
|
'descrizione' => is_string($this->formCreDebAdd['descrizione'] ?? null) ? trim((string) $this->formCreDebAdd['descrizione']) : null,
|
|
'importo_euro' => round((float) $importo, 2),
|
|
'n_stra' => is_numeric($this->formCreDebAdd['n_stra'] ?? null) ? (int) $this->formCreDebAdd['n_stra'] : null,
|
|
'incluso' => ! empty($this->formCreDebAdd['incluso']) ? 1 : 0,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
];
|
|
|
|
$this->editingCreDebId = null;
|
|
|
|
DB::connection('gescon_import')->table('cre_deb_preced')->insert($row);
|
|
|
|
$this->formCreDebAdd['cod_voc'] = null;
|
|
|
|
$this->selectedCreDebId = null;
|
|
$this->formCreDebAdd['des_voce'] = null;
|
|
$this->formCreDebAdd['descrizione'] = null;
|
|
$this->formCreDebAdd['importo_euro'] = null;
|
|
$this->formCreDebAdd['n_stra'] = null;
|
|
$this->formCreDebAdd['incluso'] = 1;
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function saveDettTabRow(int $id): void
|
|
{
|
|
if ($id <= 0 || ! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return;
|
|
}
|
|
$edit = $this->dettTabEdit[$id] ?? null;
|
|
if (! is_array($edit)) {
|
|
return;
|
|
}
|
|
|
|
$cons = $this->parseMoney(is_string($edit['cons_euro'] ?? null) ? (string) $edit['cons_euro'] : null);
|
|
if ($cons === null && is_numeric($edit['cons_euro'] ?? null)) {
|
|
$cons = (float) $edit['cons_euro'];
|
|
}
|
|
if ($cons === null) {
|
|
$cons = 0.0;
|
|
}
|
|
|
|
DB::connection('gescon_import')->table('dett_tab')
|
|
->where('id', $id)
|
|
->update([
|
|
'cod_tab' => 'CONG.O',
|
|
'id_cond' => is_string($edit['id_cond'] ?? null) ? trim((string) $edit['id_cond']) : null,
|
|
'cond_inquil' => is_string($edit['cond_inquil'] ?? null) ? trim((string) $edit['cond_inquil']) : null,
|
|
'mm' => is_numeric($edit['mm'] ?? null) ? (float) $edit['mm'] : null,
|
|
'cons_euro' => round((float) $cons, 2),
|
|
'n_stra' => null,
|
|
'unico' => ! empty($edit['unico']) ? 1 : 0,
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function deleteDettTabRow(int $id): void
|
|
{
|
|
if ($id <= 0 || ! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return;
|
|
}
|
|
|
|
DB::connection('gescon_import')->table('dett_tab')->where('id', $id)->delete();
|
|
unset($this->dettTabEdit[$id]);
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function addDettTabRow(): void
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return;
|
|
}
|
|
|
|
$stabile = $this->getActiveStabile();
|
|
$codStabileLegacy = $stabile?->codice_stabile ? (string) $stabile->codice_stabile : null;
|
|
if (! $codStabileLegacy) {
|
|
return;
|
|
}
|
|
|
|
$codTab = 'CONG.O';
|
|
$idCond = is_string($this->formDettTabAdd['id_cond'] ?? null) ? trim((string) $this->formDettTabAdd['id_cond']) : '';
|
|
if ($codTab === '' || $idCond === '') {
|
|
return;
|
|
}
|
|
|
|
$cons = $this->parseMoney(is_string($this->formDettTabAdd['cons_euro'] ?? null) ? (string) $this->formDettTabAdd['cons_euro'] : null);
|
|
if ($cons === null) {
|
|
return;
|
|
}
|
|
|
|
$row = [
|
|
'cod_tab' => $codTab,
|
|
'id_cond' => $idCond,
|
|
'cond_inquil' => is_string($this->formDettTabAdd['cond_inquil'] ?? null) ? trim((string) $this->formDettTabAdd['cond_inquil']) : null,
|
|
'mm' => is_numeric($this->formDettTabAdd['mm'] ?? null) ? (float) $this->formDettTabAdd['mm'] : null,
|
|
'cons_euro' => round((float) $cons, 2),
|
|
'n_stra' => null,
|
|
'unico' => ! empty($this->formDettTabAdd['unico']) ? 1 : 0,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
];
|
|
|
|
$this->editingDettTabId = null;
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$row['cod_stabile'] = $codStabileLegacy;
|
|
}
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$row['legacy_year'] = $this->legacyYear;
|
|
}
|
|
|
|
DB::connection('gescon_import')->table('dett_tab')->insert($row);
|
|
|
|
$this->formDettTabAdd['id_cond'] = null;
|
|
$this->formDettTabAdd['cond_inquil'] = null;
|
|
$this->formDettTabAdd['mm'] = null;
|
|
$this->formDettTabAdd['cons_euro'] = null;
|
|
$this->formDettTabAdd['n_stra'] = null;
|
|
$this->formDettTabAdd['unico'] = 0;
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
private function loadLegacyYears(?string $codStabileLegacy): array
|
|
{
|
|
$years = [];
|
|
|
|
// Preferisci la mappa "anni" (generale_stabile.mdb) per ottenere l'elenco cartelle in ordine naturale.
|
|
if ($codStabileLegacy && Schema::connection('gescon_import')->hasTable('gestioni_annuali')) {
|
|
$rows = DB::connection('gescon_import')->table('gestioni_annuali')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->get(['cartella', 'anno_ordinario', 'anno_riscaldamento']);
|
|
|
|
$mapped = [];
|
|
foreach ($rows as $r) {
|
|
$cartella = trim((string) ($r->cartella ?? ''));
|
|
if ($cartella === '') {
|
|
continue;
|
|
}
|
|
$ordYear = null;
|
|
$ao = trim((string) ($r->anno_ordinario ?? ''));
|
|
if ($ao !== '' && preg_match('/^(\d{4})$/', $ao, $m)) {
|
|
$ordYear = (int) $m[1];
|
|
}
|
|
$mapped[] = ['cartella' => $cartella, 'ord' => $ordYear ?? 0];
|
|
}
|
|
|
|
usort($mapped, function (array $a, array $b): int {
|
|
if ($a['ord'] !== $b['ord']) {
|
|
return $a['ord'] <=> $b['ord'];
|
|
}
|
|
return strcmp((string) $a['cartella'], (string) $b['cartella']);
|
|
});
|
|
|
|
foreach ($mapped as $m) {
|
|
$years[] = (string) $m['cartella'];
|
|
}
|
|
}
|
|
|
|
if ($codStabileLegacy && Schema::connection('gescon_import')->hasTable('cre_deb_preced') && Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'legacy_year')) {
|
|
$years = array_merge($years, DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->whereNotNull('legacy_year')
|
|
->distinct()
|
|
->orderBy('legacy_year')
|
|
->pluck('legacy_year')
|
|
->map(fn ($v) => (string) $v)
|
|
->all());
|
|
}
|
|
|
|
if ($codStabileLegacy && Schema::connection('gescon_import')->hasTable('dett_tab') && Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$q = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_tab', 'like', 'CONG.%')
|
|
->whereNotNull('legacy_year');
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
}
|
|
$years = array_merge($years, $q->distinct()->orderBy('legacy_year')->pluck('legacy_year')->map(fn ($v) => (string) $v)->all());
|
|
}
|
|
|
|
// Include anni presenti nelle straordinarie anche se non ci sono righe in cre_deb_preced/dett_tab.
|
|
if (Schema::connection('gescon_import')->hasTable('straordinarie') && Schema::connection('gescon_import')->hasColumn('straordinarie', 'legacy_year')) {
|
|
$q = DB::connection('gescon_import')->table('straordinarie')
|
|
->whereNotNull('legacy_year');
|
|
|
|
if ($codStabileLegacy && Schema::connection('gescon_import')->hasColumn('straordinarie', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('straordinarie')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where(function ($q) use ($codStabileLegacy) {
|
|
$q->where('cod_stabile', $codStabileLegacy)
|
|
->orWhereNull('cod_stabile')
|
|
->orWhere('cod_stabile', '');
|
|
});
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
|
|
$years = array_merge($years, $q->distinct()->orderBy('legacy_year')->pluck('legacy_year')->map(fn ($v) => (string) $v)->all());
|
|
}
|
|
|
|
$years = array_values(array_unique(array_filter($years, fn ($v) => $v !== '')));
|
|
|
|
// Se non abbiamo una mappa "anni", ordina in modo consistente.
|
|
if (! ($codStabileLegacy && Schema::connection('gescon_import')->hasTable('gestioni_annuali'))) {
|
|
sort($years);
|
|
}
|
|
|
|
return $years;
|
|
}
|
|
|
|
|
|
private function emptyBilancio(): array
|
|
{
|
|
return [
|
|
'ordinaria' => ['cong_pos' => 0.0, 'cong_neg' => 0.0, 'crediti' => 0.0, 'debiti' => 0.0, 'attivita' => 0.0, 'passivita' => 0.0],
|
|
'riscaldamento' => ['cong_pos' => 0.0, 'cong_neg' => 0.0, 'crediti' => 0.0, 'debiti' => 0.0, 'attivita' => 0.0, 'passivita' => 0.0],
|
|
'straordinarie' => [],
|
|
'tot_attivita' => 0.0,
|
|
'tot_passivita' => 0.0,
|
|
'finanziario' => 0.0,
|
|
'banca' => [
|
|
'saldo_manuale' => null,
|
|
'saldo_letto' => null,
|
|
'delta_manuale' => null,
|
|
'delta_letto' => null,
|
|
],
|
|
];
|
|
}
|
|
|
|
private function defaultDataBilancio(): string
|
|
{
|
|
$legacyYear = $this->legacyYear;
|
|
if ($legacyYear && preg_match('/^\d{4}$/', $legacyYear)) {
|
|
$n = (int) $legacyYear;
|
|
|
|
// Se è già un anno reale (es. 2024), usalo direttamente.
|
|
if ($n >= 1900 && $n <= 2100) {
|
|
return sprintf('%04d-12-31', $n - 1);
|
|
}
|
|
|
|
// Altrimenti tratta 0001/0002/... come indice esercizio (0001 = 2024).
|
|
if ($n >= 1 && $n <= 99) {
|
|
$year = 2022 + $n;
|
|
return sprintf('%04d-12-31', $year);
|
|
}
|
|
}
|
|
|
|
return now()->toDateString();
|
|
}
|
|
|
|
private function loadContiOptions(int $stabileId): array
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('dati_bancari')) {
|
|
return [];
|
|
}
|
|
|
|
return DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->orderBy('id')
|
|
->get(['id', 'denominazione_banca', 'iban', 'numero_conto', 'legacy_cod_cassa'])
|
|
->mapWithKeys(function (DatiBancari $c): array {
|
|
$iban = is_string($c->iban) ? trim((string) $c->iban) : '';
|
|
$numeroConto = is_string($c->numero_conto) ? trim((string) ($c->numero_conto ?? '')) : '';
|
|
$legacyCodCassa = is_string($c->legacy_cod_cassa) ? strtoupper(trim((string) ($c->legacy_cod_cassa ?? ''))) : '';
|
|
$label = trim((string) ($c->denominazione_banca ?? ''));
|
|
$identifier = $iban !== '' ? $iban : ($numeroConto !== '' ? $numeroConto : ($legacyCodCassa !== '' ? ('Cassa ' . $legacyCodCassa) : ('Conto #' . $c->id)));
|
|
$label = $label !== '' ? ($label . ' · ' . $identifier) : $identifier;
|
|
return [(string) $c->id => $label];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function computeBilancio(
|
|
int $stabileId,
|
|
string $codStabileLegacy,
|
|
?string $legacyYear,
|
|
string $dataBilancio,
|
|
?string $saldoBancaManuale,
|
|
array $risorseFinanziarie,
|
|
): array {
|
|
$ordinaria = $this->computeBucketOrdinaria($codStabileLegacy, $legacyYear);
|
|
$riscaldamento = $this->computeBucketRiscaldamento($codStabileLegacy, $legacyYear);
|
|
|
|
// Straordinarie: cross-year. Identità = (legacy_year, id_stra).
|
|
$straEntries = $this->loadStraEntries($codStabileLegacy, $legacyYear);
|
|
$stra = [];
|
|
foreach ($straEntries as $e) {
|
|
$eYear = $e['legacy_year'] ?? null;
|
|
$eStra = (int) ($e['n_stra'] ?? 0);
|
|
$eKey = (string) ($e['key'] ?? (string) $eStra);
|
|
if ($eStra <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$bucket = $this->computeBucketStraordinaria($codStabileLegacy, $eYear ?? $legacyYear, $eStra);
|
|
$bucket['legacy_year'] = $eYear;
|
|
$bucket['key'] = $eKey;
|
|
$bucket['label'] = $this->formatStraLabel($eYear, $eStra, (string) ($bucket['titolo'] ?? ''));
|
|
$stra[$eKey] = $bucket;
|
|
}
|
|
|
|
// Totali generali (stabile): CREDITI/DEBITI conteggiati UNA SOLA VOLTA,
|
|
// mentre i conguagli si sommano per gestione (ORD/RISC/STRA).
|
|
$totCreditiUnici = (float) ($ordinaria['crediti'] ?? 0.0);
|
|
$totDebitiUnici = (float) ($ordinaria['debiti'] ?? 0.0);
|
|
|
|
$totCongPos = (float) ($ordinaria['cong_pos'] ?? 0.0) + (float) ($riscaldamento['cong_pos'] ?? 0.0);
|
|
$totCongNeg = (float) ($ordinaria['cong_neg'] ?? 0.0) + (float) ($riscaldamento['cong_neg'] ?? 0.0);
|
|
|
|
$totAtt = $totCreditiUnici + $totCongPos;
|
|
$totPas = $totDebitiUnici + $totCongNeg;
|
|
foreach ($stra as $row) {
|
|
$totAtt += (float) ($row['cong_pos'] ?? 0.0) + (float) ($row['crediti'] ?? 0.0);
|
|
$totPas += (float) ($row['cong_neg'] ?? 0.0) + (float) ($row['debiti'] ?? 0.0);
|
|
}
|
|
|
|
$totAtt = round($totAtt, 2);
|
|
$totPas = round($totPas, 2);
|
|
$fin = round($totAtt - $totPas, 2);
|
|
|
|
$saldoLetto = $this->computeSaldoBancaTotaleLetto($risorseFinanziarie);
|
|
$saldoManualeVal = $this->parseMoney($saldoBancaManuale);
|
|
|
|
return [
|
|
'ordinaria' => $ordinaria,
|
|
'riscaldamento' => $riscaldamento,
|
|
'straordinarie' => $stra,
|
|
'tot_attivita' => $totAtt,
|
|
'tot_passivita' => $totPas,
|
|
'finanziario' => $fin,
|
|
'banca' => [
|
|
'saldo_manuale' => $saldoManualeVal,
|
|
'saldo_letto' => $saldoLetto,
|
|
'delta_manuale' => $saldoManualeVal !== null ? round($saldoManualeVal - $fin, 2) : null,
|
|
'delta_letto' => $saldoLetto !== null ? round($saldoLetto - $fin, 2) : null,
|
|
],
|
|
];
|
|
}
|
|
|
|
private function computeBucketOrdinaria(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
$crediti = $this->sumCreDebPreced($codStabileLegacy, $legacyYear, 'C', 'non_stra')
|
|
+ $this->sumManualVoci('ordinaria', 'crediti', null, $legacyYear);
|
|
$debiti = $this->sumCreDebPreced($codStabileLegacy, $legacyYear, 'D', 'non_stra')
|
|
+ $this->sumManualVoci('ordinaria', 'debiti', null, $legacyYear);
|
|
[$congPos, $congNeg] = $this->sumConguagli($codStabileLegacy, $legacyYear, 'CONG.O', 'non_stra');
|
|
|
|
$att = round($crediti + $congPos, 2);
|
|
$pas = round($debiti + $congNeg, 2);
|
|
|
|
return [
|
|
'cong_pos' => $congPos,
|
|
'cong_neg' => $congNeg,
|
|
'crediti' => $crediti,
|
|
'debiti' => $debiti,
|
|
'attivita' => $att,
|
|
'passivita' => $pas,
|
|
];
|
|
}
|
|
|
|
private function computeBucketRiscaldamento(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
// IMPORTANTE:
|
|
// `cre_deb_preced` (crediti/debiti pregressi) non distingue la gestione (ordinaria vs riscaldamento).
|
|
// Per evitare duplicazioni percepite in UI, i Crediti/Debiti "pregressi" vengono mostrati SOLO in Ordinaria.
|
|
// Qui teniamo esclusivamente i conguagli CONG.R (e gli eventuali manuali riscaldamento, se presenti).
|
|
$crediti = 0.0;
|
|
$debiti = 0.0;
|
|
[$congPos, $congNeg] = $this->sumConguagli($codStabileLegacy, $legacyYear, 'CONG.R', 'non_stra');
|
|
|
|
$att = round($crediti + $congPos, 2);
|
|
$pas = round($debiti + $congNeg, 2);
|
|
|
|
return [
|
|
'cong_pos' => $congPos,
|
|
'cong_neg' => $congNeg,
|
|
'crediti' => $crediti,
|
|
'debiti' => $debiti,
|
|
'attivita' => $att,
|
|
'passivita' => $pas,
|
|
];
|
|
}
|
|
|
|
private function computeBucketStraordinaria(string $codStabileLegacy, ?string $legacyYear, int $nStra): array
|
|
{
|
|
$crediti = $this->sumCreDebPreced($codStabileLegacy, $legacyYear, 'C', $nStra)
|
|
+ $this->sumManualVoci('straordinaria', 'crediti', $nStra, $legacyYear);
|
|
$debiti = $this->sumCreDebPreced($codStabileLegacy, $legacyYear, 'D', $nStra)
|
|
+ $this->sumManualVoci('straordinaria', 'debiti', $nStra, $legacyYear);
|
|
[$congPos, $congNeg] = $this->sumConguagli($codStabileLegacy, $legacyYear, null, $nStra);
|
|
|
|
$titolo = $this->resolveStraordinariaTitolo($codStabileLegacy, $legacyYear, $nStra);
|
|
|
|
$att = round($crediti + $congPos, 2);
|
|
$pas = round($debiti + $congNeg, 2);
|
|
|
|
return [
|
|
'n_stra' => $nStra,
|
|
'titolo' => $titolo,
|
|
'cong_pos' => $congPos,
|
|
'cong_neg' => $congNeg,
|
|
'crediti' => $crediti,
|
|
'debiti' => $debiti,
|
|
'attivita' => $att,
|
|
'passivita' => $pas,
|
|
];
|
|
}
|
|
|
|
private function formatStraLabel(?string $legacyYear, int $nStra, string $titolo): string
|
|
{
|
|
$titolo = trim($titolo);
|
|
$prefix = '';
|
|
if ($legacyYear) {
|
|
$label = $this->legacyYearLabels[$legacyYear] ?? null;
|
|
if (is_string($label) && trim($label) !== '') {
|
|
$prefix = trim($label) . ' · ';
|
|
}
|
|
}
|
|
$base = 'Straordinaria #' . $nStra;
|
|
if ($titolo === '') {
|
|
return $prefix . $base;
|
|
}
|
|
return $prefix . $base . ' · ' . $titolo;
|
|
}
|
|
|
|
private function legacyYearToRealYear(?string $legacyYear): ?int
|
|
{
|
|
if (! $legacyYear || ! preg_match('/^\d{4}$/', $legacyYear)) {
|
|
return null;
|
|
}
|
|
$n = (int) $legacyYear;
|
|
if ($n >= 1900 && $n <= 2100) {
|
|
return $n;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private function sumManualVoci(string $gestione, string $categoria, ?int $nStra, ?string $legacyYear): float
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_situazione_iniziale_voci')) {
|
|
return 0.0;
|
|
}
|
|
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if (! $stabileId) {
|
|
return 0.0;
|
|
}
|
|
|
|
$q = DB::table('contabilita_situazione_iniziale_voci')
|
|
->where('stabile_id', (int) $stabileId)
|
|
->where('gestione', $gestione)
|
|
->where('categoria', $categoria)
|
|
->where('incluso', 1);
|
|
|
|
if ($legacyYear !== null && $legacyYear !== '') {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
if ($gestione === 'straordinaria') {
|
|
$q->where('n_stra', $nStra);
|
|
} else {
|
|
$q->whereNull('n_stra');
|
|
}
|
|
|
|
return round((float) ($q->sum('importo_euro') ?? 0.0), 2);
|
|
}
|
|
|
|
private function sumManualConguagli(?string $legacyYear, ?string $codTab, int|string $straFilter): array
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_situazione_iniziale_conguagli')) {
|
|
return [0.0, 0.0];
|
|
}
|
|
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if (! $stabileId) {
|
|
return [0.0, 0.0];
|
|
}
|
|
|
|
$q = DB::table('contabilita_situazione_iniziale_conguagli')
|
|
->where('stabile_id', (int) $stabileId)
|
|
->where('incluso', 1);
|
|
|
|
if ($legacyYear !== null && $legacyYear !== '') {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
if ($codTab) {
|
|
$q->where('cod_tab', $codTab);
|
|
}
|
|
|
|
if ($straFilter === 'non_stra') {
|
|
$q->whereNull('n_stra');
|
|
} elseif (is_int($straFilter) && $straFilter > 0) {
|
|
$q->where('n_stra', $straFilter);
|
|
}
|
|
|
|
$pos = (float) (clone $q)->where('cons_euro', '>', 0)->sum('cons_euro');
|
|
$neg = (float) (clone $q)->where('cons_euro', '<', 0)->sum('cons_euro');
|
|
|
|
return [round($pos, 2), round(abs($neg), 2)];
|
|
}
|
|
|
|
private function resolveStraordinariaTitolo(string $codStabileLegacy, ?string $legacyYear, int $nStra): string
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('straordinarie')) {
|
|
return 'Straordinaria #' . $nStra;
|
|
}
|
|
|
|
$row = null;
|
|
|
|
$applyCodStabileFallback = function ($q) use ($codStabileLegacy) {
|
|
if (! Schema::connection('gescon_import')->hasColumn('straordinarie', 'cod_stabile')) {
|
|
return $q;
|
|
}
|
|
|
|
$hasForStabile = DB::connection('gescon_import')->table('straordinarie')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
|
|
if ($hasForStabile) {
|
|
// Include anche righe con cod_stabile vuoto: alcuni import parziali le lasciano NULL/''.
|
|
return $q->where(function ($q) use ($codStabileLegacy) {
|
|
$q->where('cod_stabile', $codStabileLegacy)
|
|
->orWhereNull('cod_stabile')
|
|
->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
|
|
return $q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
};
|
|
|
|
// Preferisci l'anno selezionato se presente (per compatibilità con import per-cartella),
|
|
// ma fai fallback cross-year così la UI può mostrare SEMPRE tutte le straordinarie.
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('straordinarie', 'legacy_year')) {
|
|
$q = DB::connection('gescon_import')->table('straordinarie');
|
|
$q = $applyCodStabileFallback($q);
|
|
$row = $q
|
|
->where('id_stra', $nStra)
|
|
->where('legacy_year', $legacyYear)
|
|
->first(['codice', 'descriz_prev_cons', 'descriz_ricev']);
|
|
}
|
|
|
|
if (! $row) {
|
|
$q = DB::connection('gescon_import')->table('straordinarie');
|
|
$q = $applyCodStabileFallback($q);
|
|
$row = $q
|
|
->where('id_stra', $nStra)
|
|
->orderByDesc(Schema::connection('gescon_import')->hasColumn('straordinarie', 'legacy_year') ? 'legacy_year' : 'id_stra')
|
|
->first(['codice', 'descriz_prev_cons', 'descriz_ricev']);
|
|
}
|
|
|
|
$title = '';
|
|
if ($row) {
|
|
$title = trim((string) ($row->descriz_prev_cons ?? ''));
|
|
if ($title === '') {
|
|
$title = trim((string) ($row->descriz_ricev ?? ''));
|
|
}
|
|
if ($title === '') {
|
|
$title = trim((string) ($row->codice ?? ''));
|
|
}
|
|
}
|
|
return $title !== '' ? $title : ('Straordinaria #' . $nStra);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array{key: string, legacy_year: string|null, n_stra: int}>
|
|
*/
|
|
private function loadStraEntries(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
$entries = [];
|
|
|
|
$add = function (?string $y, int $n) use (&$entries) {
|
|
if ($n <= 0) {
|
|
return;
|
|
}
|
|
$yy = $y !== null && $y !== '' ? (string) $y : null;
|
|
$key = $yy ? ($yy . ':' . $n) : (string) $n;
|
|
$entries[$key] = ['key' => $key, 'legacy_year' => $yy, 'n_stra' => $n];
|
|
};
|
|
|
|
if (Schema::connection('gescon_import')->hasTable('cre_deb_preced') && Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'n_stra')) {
|
|
$q = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->whereNotNull('n_stra')
|
|
->where('n_stra', '>', 0);
|
|
|
|
// Include anche righe con cod_stabile vuoto quando esistono righe per lo stabile.
|
|
$hasForStabile = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where(function ($q) use ($codStabileLegacy) {
|
|
$q->where('cod_stabile', $codStabileLegacy)
|
|
->orWhereNull('cod_stabile')
|
|
->orWhere('cod_stabile', '');
|
|
});
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'incluso')) {
|
|
$q->where('incluso', 1);
|
|
}
|
|
|
|
// IMPORTANTE: NON filtrare per legacy_year: vogliamo vedere tutte le straordinarie cross-year.
|
|
if (Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'legacy_year')) {
|
|
foreach ($q->distinct()->get(['legacy_year', 'n_stra']) as $r) {
|
|
$add(is_string($r->legacy_year ?? null) ? (string) $r->legacy_year : null, (int) ($r->n_stra ?? 0));
|
|
}
|
|
} else {
|
|
foreach ($q->distinct()->orderBy('n_stra')->pluck('n_stra') as $v) {
|
|
$add($legacyYear, (int) $v);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Schema::connection('gescon_import')->hasTable('dett_tab') && Schema::connection('gescon_import')->hasColumn('dett_tab', 'n_stra')) {
|
|
$q = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_tab', 'like', 'CONG.%')
|
|
->whereNotNull('n_stra')
|
|
->where('n_stra', '>', 0);
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where(function ($q) use ($codStabileLegacy) {
|
|
$q->where('cod_stabile', $codStabileLegacy)
|
|
->orWhereNull('cod_stabile')
|
|
->orWhere('cod_stabile', '');
|
|
});
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
// IMPORTANTE: NON filtrare per legacy_year: vogliamo vedere tutte le straordinarie cross-year.
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
foreach ($q->distinct()->get(['legacy_year', 'n_stra']) as $r) {
|
|
$add(is_string($r->legacy_year ?? null) ? (string) $r->legacy_year : null, (int) ($r->n_stra ?? 0));
|
|
}
|
|
} else {
|
|
foreach ($q->distinct()->orderBy('n_stra')->pluck('n_stra') as $v) {
|
|
$add($legacyYear, (int) $v);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Include tutte le straordinarie dichiarate nel MDB (tabella gescon_import.straordinarie), anche se importi = 0.
|
|
if (Schema::connection('gescon_import')->hasTable('straordinarie') && Schema::connection('gescon_import')->hasColumn('straordinarie', 'id_stra')) {
|
|
$q = DB::connection('gescon_import')->table('straordinarie')
|
|
->whereNotNull('id_stra')
|
|
->where('id_stra', '>', 0);
|
|
|
|
// Fallback: alcuni import da singolo_anno.mdb non popolano cod_stabile.
|
|
if (Schema::connection('gescon_import')->hasColumn('straordinarie', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('straordinarie')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where(function ($q) use ($codStabileLegacy) {
|
|
$q->where('cod_stabile', $codStabileLegacy)
|
|
->orWhereNull('cod_stabile')
|
|
->orWhere('cod_stabile', '');
|
|
});
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
|
|
// IMPORTANTE: NON filtrare per legacy_year.
|
|
// Le straordinarie sono "tabelle" trasversali: vogliamo vederle tutte (es. 4 in 0001 + 5 in 0003 = 9).
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('straordinarie', 'legacy_year')) {
|
|
foreach ($q->distinct()->get(['legacy_year', 'id_stra']) as $r) {
|
|
$add(is_string($r->legacy_year ?? null) ? (string) $r->legacy_year : null, (int) ($r->id_stra ?? 0));
|
|
}
|
|
} else {
|
|
foreach ($q->distinct()->orderBy('id_stra')->pluck('id_stra') as $v) {
|
|
$add($legacyYear, (int) $v);
|
|
}
|
|
}
|
|
}
|
|
|
|
$list = array_values($entries);
|
|
usort($list, function (array $a, array $b): int {
|
|
$ya = (string) ($a['legacy_year'] ?? '');
|
|
$yb = (string) ($b['legacy_year'] ?? '');
|
|
if ($ya !== $yb) {
|
|
return $ya <=> $yb;
|
|
}
|
|
return ((int) $a['n_stra']) <=> ((int) $b['n_stra']);
|
|
});
|
|
return $list;
|
|
}
|
|
|
|
private function sumCreDebPreced(string $codStabileLegacy, ?string $legacyYear, string $cd, int|string $straFilter): float
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return 0.0;
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->whereRaw('UPPER(c_d) = ?', [strtoupper($cd)]);
|
|
|
|
// Fallback: alcuni import da singolo_anno.mdb non popolano cod_stabile.
|
|
// In quel caso, se non esistono righe per lo stabile attivo, usa le righe con cod_stabile NULL/vuoto.
|
|
$hasForStabile = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'incluso')) {
|
|
$q->where('incluso', 1);
|
|
}
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
if ($straFilter === 'non_stra') {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('n_stra')->orWhere('n_stra', '<=', 0);
|
|
});
|
|
} elseif (is_int($straFilter) && $straFilter > 0) {
|
|
$q->where('n_stra', $straFilter);
|
|
}
|
|
|
|
return round((float) ($q->sum('importo_euro') ?? 0.0), 2);
|
|
}
|
|
|
|
private function sumConguagli(string $codStabileLegacy, ?string $legacyYear, ?string $codTab, int|string $straFilter): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return [0.0, 0.0];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('dett_tab');
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
if ($codTab) {
|
|
$q->where('cod_tab', $codTab);
|
|
}
|
|
|
|
if ($straFilter === 'non_stra') {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('n_stra')->orWhere('n_stra', '<=', 0);
|
|
});
|
|
} elseif (is_int($straFilter) && $straFilter > 0) {
|
|
$q->where('n_stra', $straFilter);
|
|
}
|
|
|
|
$pos = (float) (clone $q)->where('cons_euro', '>', 0)->sum('cons_euro');
|
|
$neg = (float) (clone $q)->where('cons_euro', '<', 0)->sum('cons_euro');
|
|
|
|
return [round($pos, 2), round(abs($neg), 2)];
|
|
}
|
|
|
|
private function computeRisorseFinanziarie(int $stabileId, string $date): array
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_movimenti_banca')) {
|
|
return [];
|
|
}
|
|
if (! DB::getSchemaBuilder()->hasTable('dati_bancari')) {
|
|
return [];
|
|
}
|
|
|
|
$conti = DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->when(Schema::hasColumn('dati_bancari', 'stato_conto'), function ($query) {
|
|
$query->where(function ($query) {
|
|
$query->whereNull('stato_conto')->orWhere('stato_conto', '!=', 'chiuso');
|
|
});
|
|
})
|
|
->orderBy('id')
|
|
->get(['id', 'denominazione_banca', 'iban', 'numero_conto', 'legacy_cod_cassa', 'saldo_iniziale', 'data_saldo_iniziale']);
|
|
|
|
if ($conti->isEmpty()) {
|
|
return [];
|
|
}
|
|
|
|
$dateC = Carbon::parse($date);
|
|
$out = [];
|
|
foreach ($conti as $conto) {
|
|
$iban = is_string($conto->iban) ? trim((string) $conto->iban) : '';
|
|
$numeroConto = is_string($conto->numero_conto) ? trim((string) ($conto->numero_conto ?? '')) : '';
|
|
$legacyCodCassa = is_string($conto->legacy_cod_cassa) ? strtoupper(trim((string) ($conto->legacy_cod_cassa ?? ''))) : '';
|
|
$saldo = $this->resolveContoSaldoAllaData($stabileId, $conto, $dateC);
|
|
|
|
$label = trim((string) ($conto->denominazione_banca ?? ''));
|
|
$identifier = $iban !== '' ? $iban : ($numeroConto !== '' ? $numeroConto : ($legacyCodCassa !== '' ? ('Cassa ' . $legacyCodCassa) : ('Conto #' . $conto->id)));
|
|
$label = $label !== '' ? ($label . ' · ' . $identifier) : $identifier;
|
|
|
|
$out[] = [
|
|
'conto_id' => (int) $conto->id,
|
|
'iban' => $iban,
|
|
'label' => $label,
|
|
'saldo' => $saldo,
|
|
];
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
private function resolveContoSaldoAllaData(int $stabileId, DatiBancari $conto, Carbon $date): float
|
|
{
|
|
$contoId = (int) $conto->id;
|
|
|
|
$snapshot = SaldoConto::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId)
|
|
->whereDate('data_saldo', '<=', $date->toDateString())
|
|
->orderByDesc('data_saldo')
|
|
->orderByDesc('id')
|
|
->first(['data_saldo', 'saldo']);
|
|
|
|
if ($snapshot) {
|
|
$baseDate = $snapshot->data_saldo instanceof Carbon
|
|
? $snapshot->data_saldo->copy()->startOfDay()
|
|
: Carbon::parse((string) $snapshot->data_saldo)->startOfDay();
|
|
$delta = (float) (MovimentoBanca::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId)
|
|
->whereDate('data', '>', $baseDate->toDateString())
|
|
->whereDate('data', '<=', $date->toDateString())
|
|
->sum('importo') ?? 0.0);
|
|
|
|
return round((float) ($snapshot->saldo ?? 0.0) + $delta, 2);
|
|
}
|
|
|
|
$saldoBase = is_numeric($conto->saldo_iniziale) ? (float) $conto->saldo_iniziale : 0.0;
|
|
$dataSaldoIniziale = $conto->data_saldo_iniziale instanceof Carbon
|
|
? $conto->data_saldo_iniziale->copy()->startOfDay()
|
|
: ($conto->data_saldo_iniziale ? Carbon::parse((string) $conto->data_saldo_iniziale)->startOfDay() : null);
|
|
|
|
$movimenti = MovimentoBanca::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId);
|
|
|
|
if ($dataSaldoIniziale instanceof Carbon) {
|
|
if ($dataSaldoIniziale->lte($date)) {
|
|
$delta = (float) (clone $movimenti)
|
|
->whereDate('data', '>', $dataSaldoIniziale->toDateString())
|
|
->whereDate('data', '<=', $date->toDateString())
|
|
->sum('importo');
|
|
|
|
return round($saldoBase + $delta, 2);
|
|
}
|
|
|
|
$delta = (float) (clone $movimenti)
|
|
->whereDate('data', '>', $date->toDateString())
|
|
->whereDate('data', '<=', $dataSaldoIniziale->toDateString())
|
|
->sum('importo');
|
|
|
|
return round($saldoBase - $delta, 2);
|
|
}
|
|
|
|
$delta = (float) (clone $movimenti)
|
|
->whereDate('data', '<=', $date->toDateString())
|
|
->sum('importo');
|
|
|
|
return round($saldoBase + $delta, 2);
|
|
}
|
|
|
|
private function computeSaldoBancaTotaleLetto(array $risorseFinanziarie): ?float
|
|
{
|
|
if ($risorseFinanziarie === []) {
|
|
return null;
|
|
}
|
|
|
|
$tot = 0.0;
|
|
foreach ($risorseFinanziarie as $r) {
|
|
$tot += (float) ($r['saldo'] ?? 0.0);
|
|
}
|
|
return round($tot, 2);
|
|
}
|
|
|
|
private function resolveSaldoOffsetDaSaldi(int $stabileId, int $contoId, string $iban, Carbon $date): float
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_saldi_conti')) {
|
|
return 0.0;
|
|
}
|
|
|
|
$match = SaldoConto::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId)
|
|
->where('iban', $iban)
|
|
->whereDate('data_saldo', '<=', $date->toDateString())
|
|
->orderByDesc('data_saldo')
|
|
->orderByDesc('id')
|
|
->first(['id', 'data_saldo', 'saldo']);
|
|
|
|
if (! $match) {
|
|
return 0.0;
|
|
}
|
|
|
|
$saldoIniziale = $this->resolveSaldoInizialeDaDatiBancari($stabileId, $contoId, $iban);
|
|
|
|
$sumToDateSaldo = (float) (MovimentoBanca::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', $contoId)
|
|
->where('iban', $iban)
|
|
->whereDate('data', '<=', $match->data_saldo->toDateString())
|
|
->sum('importo') ?? 0.0);
|
|
|
|
$saldoAttesoAllaDataSaldo = is_numeric($match->saldo) ? (float) $match->saldo : 0.0;
|
|
$saldoCalcolatoAllaDataSaldo = $saldoIniziale + $sumToDateSaldo;
|
|
|
|
return (float) ($saldoAttesoAllaDataSaldo - $saldoCalcolatoAllaDataSaldo);
|
|
}
|
|
|
|
private function resolveSaldoInizialeDaDatiBancari(int $stabileId, int $contoId, string $iban): float
|
|
{
|
|
$row = DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('id', $contoId)
|
|
->where('iban', $iban)
|
|
->first(['saldo_iniziale']);
|
|
|
|
return $row && is_numeric($row->saldo_iniziale) ? (float) $row->saldo_iniziale : 0.0;
|
|
}
|
|
|
|
private function parseMoney(?string $value): ?float
|
|
{
|
|
if (! is_string($value)) {
|
|
return null;
|
|
}
|
|
$v = trim($value);
|
|
if ($v === '') {
|
|
return null;
|
|
}
|
|
|
|
$v = str_replace(['€', ' '], '', $v);
|
|
// Convert Italian format "1.234,56" to "1234.56".
|
|
$v = str_replace('.', '', $v);
|
|
$v = str_replace(',', '.', $v);
|
|
|
|
if (! is_numeric($v)) {
|
|
return null;
|
|
}
|
|
|
|
return round((float) $v, 2);
|
|
}
|
|
|
|
private function reloadDettaglio(string $codStabileLegacy, ?string $legacyYear): void
|
|
{
|
|
$this->detailMeta = [];
|
|
$this->detailRows = [];
|
|
|
|
if ($this->tab !== 'dettaglio' || ! $this->dett) {
|
|
return;
|
|
}
|
|
|
|
$d = $this->dett;
|
|
|
|
if (preg_match('/^(crediti|debiti)_(ordinaria|riscaldamento)$/', $d, $m)) {
|
|
$cd = $m[1] === 'crediti' ? 'C' : 'D';
|
|
$bucket = $m[2];
|
|
|
|
$straFilter = $bucket === 'ordinaria' ? 'non_stra' : 'none';
|
|
|
|
$this->detailMeta = [
|
|
'tipo' => 'cre_deb_preced',
|
|
'titolo' => strtoupper($m[1]) . ' · ' . strtoupper($bucket),
|
|
];
|
|
$this->detailRows = $this->loadCreDebPrecedRows($codStabileLegacy, $legacyYear, $cd, $straFilter);
|
|
return;
|
|
}
|
|
|
|
if (preg_match('/^(crediti|debiti)_stra_(.+)$/', $d, $m)) {
|
|
$cd = $m[1] === 'crediti' ? 'C' : 'D';
|
|
[$detailYear, $nStra] = $this->parseStraKey($m[2]);
|
|
$effectiveYear = $detailYear ?? $legacyYear;
|
|
$this->detailMeta = [
|
|
'tipo' => 'cre_deb_preced',
|
|
'titolo' => strtoupper($m[1]) . ' · ' . $this->formatStraLabel($detailYear, (int) $nStra, ''),
|
|
];
|
|
$this->detailRows = $this->loadCreDebPrecedRows($codStabileLegacy, $effectiveYear, $cd, (int) $nStra);
|
|
return;
|
|
}
|
|
|
|
if (preg_match('/^cong_(pos|neg)_(ordinaria|riscaldamento)$/', $d, $m)) {
|
|
$sign = $m[1];
|
|
$bucket = $m[2];
|
|
$codTab = $bucket === 'ordinaria' ? 'CONG.O' : 'CONG.R';
|
|
|
|
$this->detailMeta = [
|
|
'tipo' => 'dett_tab',
|
|
'titolo' => 'CONGUAGLI ' . ($sign === 'pos' ? '(+)' : '(-)') . ' · ' . strtoupper($bucket) . ' · ' . $codTab,
|
|
];
|
|
$this->detailRows = $this->loadDettTabRows($codStabileLegacy, $legacyYear, $codTab, 'non_stra', $sign);
|
|
return;
|
|
}
|
|
|
|
if (preg_match('/^cong_(pos|neg)_stra_(.+)$/', $d, $m)) {
|
|
$sign = $m[1];
|
|
[$detailYear, $nStra] = $this->parseStraKey($m[2]);
|
|
$effectiveYear = $detailYear ?? $legacyYear;
|
|
$this->detailMeta = [
|
|
'tipo' => 'dett_tab',
|
|
'titolo' => 'CONGUAGLI ' . ($sign === 'pos' ? '(+)' : '(-)') . ' · ' . $this->formatStraLabel($detailYear, (int) $nStra, ''),
|
|
];
|
|
$this->detailRows = $this->loadDettTabRows($codStabileLegacy, $effectiveYear, null, (int) $nStra, $sign);
|
|
return;
|
|
}
|
|
|
|
$this->detailMeta = [
|
|
'tipo' => 'unknown',
|
|
'titolo' => 'Dettaglio non riconosciuto',
|
|
];
|
|
}
|
|
|
|
private function loadCreDebPrecedRows(string $codStabileLegacy, ?string $legacyYear, string $cd, int|string $straFilter): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('cre_deb_preced')) {
|
|
return [];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->whereRaw('UPPER(c_d) = ?', [strtoupper($cd)]);
|
|
|
|
$hasForStabile = DB::connection('gescon_import')->table('cre_deb_preced')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'incluso')) {
|
|
$q->where('incluso', 1);
|
|
}
|
|
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('cre_deb_preced', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
if ($straFilter === 'non_stra') {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('n_stra')->orWhere('n_stra', '<=', 0);
|
|
});
|
|
} elseif (is_int($straFilter) && $straFilter > 0) {
|
|
$q->where('n_stra', $straFilter);
|
|
} elseif ($straFilter === 'none') {
|
|
// Nessun filtro: restituisce vuoto per bucket senza criterio.
|
|
return [];
|
|
}
|
|
|
|
return $q
|
|
->orderBy('cod_voc')
|
|
->limit(5000)
|
|
->get(['c_d', 'cod_voc', 'des_voce', 'descrizione', 'importo_euro', 'n_stra'])
|
|
->map(fn ($r) => [
|
|
'c_d' => (string) ($r->c_d ?? ''),
|
|
'cod_voc' => (string) ($r->cod_voc ?? ''),
|
|
'des_voce' => (string) ($r->des_voce ?? ''),
|
|
'descrizione' => (string) ($r->descrizione ?? ''),
|
|
'importo_euro' => (float) ($r->importo_euro ?? 0),
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
])
|
|
->all();
|
|
}
|
|
|
|
private function loadDettTabRows(string $codStabileLegacy, ?string $legacyYear, ?string $codTab, int|string $straFilter, string $sign): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return [];
|
|
}
|
|
|
|
$labels = $this->loadCondominiLabels($codStabileLegacy, $legacyYear);
|
|
|
|
$q = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_tab', 'like', 'CONG.%');
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$hasForStabile = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_stabile', $codStabileLegacy)
|
|
->limit(1)
|
|
->exists();
|
|
if ($hasForStabile) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
} else {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('cod_stabile')->orWhere('cod_stabile', '');
|
|
});
|
|
}
|
|
}
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
if ($codTab) {
|
|
$q->where('cod_tab', $codTab);
|
|
}
|
|
|
|
if ($straFilter === 'non_stra') {
|
|
$q->where(function ($q) {
|
|
$q->whereNull('n_stra')->orWhere('n_stra', '<=', 0);
|
|
});
|
|
} elseif (is_int($straFilter) && $straFilter > 0) {
|
|
$q->where('n_stra', $straFilter);
|
|
}
|
|
|
|
if ($sign === 'pos') {
|
|
$q->where('cons_euro', '>', 0);
|
|
} else {
|
|
$q->where('cons_euro', '<', 0);
|
|
}
|
|
|
|
return $q
|
|
->orderBy('cod_tab')
|
|
->orderBy('id_cond')
|
|
->limit(5000)
|
|
->get(['cod_tab', 'id_cond', 'cond_inquil', 'mm', 'cons_euro', 'n_stra', 'unico', 'proviene_ors', 'proviene_n_stra', 'proviene_eserc'])
|
|
->map(fn ($r) => [
|
|
'cod_tab' => (string) ($r->cod_tab ?? ''),
|
|
'id_cond' => (string) ($r->id_cond ?? ''),
|
|
'cond_label' => (string) ($labels[trim((string) ($r->id_cond ?? ''))] ?? ''),
|
|
'cond_inquil' => (string) ($r->cond_inquil ?? ''),
|
|
'mm' => $r->mm !== null ? (float) $r->mm : null,
|
|
'cons_euro' => (float) ($r->cons_euro ?? 0),
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
'unico' => (bool) ($r->unico ?? false),
|
|
'proviene_ors' => (string) ($r->proviene_ors ?? ''),
|
|
'proviene_n_stra' => $r->proviene_n_stra !== null ? (int) $r->proviene_n_stra : null,
|
|
'proviene_eserc' => (string) ($r->proviene_eserc ?? ''),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
/**
|
|
* @return array{0: string|null, 1: int} [legacy_year, n_stra]
|
|
*/
|
|
private function parseStraKey(string $raw): array
|
|
{
|
|
$raw = trim($raw);
|
|
if ($raw === '') {
|
|
return [null, 0];
|
|
}
|
|
if (preg_match('/^(\d{4})\:(\d+)$/', $raw, $m)) {
|
|
return [$m[1], (int) $m[2]];
|
|
}
|
|
if (ctype_digit($raw)) {
|
|
return [null, (int) $raw];
|
|
}
|
|
return [null, 0];
|
|
}
|
|
|
|
private function computeConguagliExcel(string $codStabileLegacy, ?string $legacyYear): array
|
|
{
|
|
if (! Schema::connection('gescon_import')->hasTable('dett_tab')) {
|
|
return [[], []];
|
|
}
|
|
|
|
$q = DB::connection('gescon_import')->table('dett_tab')
|
|
->where('cod_tab', 'like', 'CONG.%');
|
|
|
|
if (Schema::connection('gescon_import')->hasColumn('dett_tab', 'cod_stabile')) {
|
|
$q->where('cod_stabile', $codStabileLegacy);
|
|
}
|
|
if ($legacyYear && Schema::connection('gescon_import')->hasColumn('dett_tab', 'legacy_year')) {
|
|
$q->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$labels = $this->loadCondominiLabels($codStabileLegacy, $legacyYear);
|
|
|
|
$rows = $q
|
|
->select([
|
|
'id_cond',
|
|
'cod_tab',
|
|
'n_stra',
|
|
DB::raw('SUM(cons_euro) as totale'),
|
|
])
|
|
->groupBy('id_cond', 'cod_tab', 'n_stra')
|
|
->orderByRaw('CAST(id_cond AS UNSIGNED)')
|
|
->get()
|
|
->map(fn ($r) => [
|
|
'id_cond' => (string) ($r->id_cond ?? ''),
|
|
'cond_label' => (string) ($labels[trim((string) ($r->id_cond ?? ''))] ?? ''),
|
|
'cod_tab' => (string) ($r->cod_tab ?? ''),
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
'totale' => (float) ($r->totale ?? 0.0),
|
|
])
|
|
->all();
|
|
|
|
// Merge manual conguagli
|
|
if (DB::getSchemaBuilder()->hasTable('contabilita_situazione_iniziale_conguagli')) {
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if ($stabileId) {
|
|
$mq = DB::table('contabilita_situazione_iniziale_conguagli')
|
|
->where('stabile_id', (int) $stabileId)
|
|
->where('incluso', 1);
|
|
if ($legacyYear) {
|
|
$mq->where('legacy_year', $legacyYear);
|
|
}
|
|
|
|
$manual = $mq
|
|
->select([
|
|
'id_cond',
|
|
'cod_tab',
|
|
'n_stra',
|
|
DB::raw('SUM(cons_euro) as totale'),
|
|
])
|
|
->groupBy('id_cond', 'cod_tab', 'n_stra')
|
|
->get()
|
|
->map(fn ($r) => [
|
|
'id_cond' => (string) ($r->id_cond ?? ''),
|
|
'cod_tab' => (string) ($r->cod_tab ?? ''),
|
|
'n_stra' => $r->n_stra !== null ? (int) $r->n_stra : null,
|
|
'totale' => (float) ($r->totale ?? 0.0),
|
|
])
|
|
->all();
|
|
|
|
// Sum into existing keys
|
|
$acc = [];
|
|
foreach ($rows as $r) {
|
|
$k = $r['id_cond'] . '|' . $r['cod_tab'] . '|' . (string) ($r['n_stra'] ?? '');
|
|
$acc[$k] = $r;
|
|
}
|
|
foreach ($manual as $r) {
|
|
$k = $r['id_cond'] . '|' . $r['cod_tab'] . '|' . (string) ($r['n_stra'] ?? '');
|
|
if (isset($acc[$k])) {
|
|
$acc[$k]['totale'] = (float) ($acc[$k]['totale'] ?? 0.0) + (float) ($r['totale'] ?? 0.0);
|
|
} else {
|
|
$acc[$k] = $r;
|
|
}
|
|
}
|
|
$rows = array_values($acc);
|
|
}
|
|
}
|
|
|
|
$cols = [];
|
|
foreach ($rows as $r) {
|
|
$key = $r['cod_tab'] . '|' . (string) ($r['n_stra'] ?? '');
|
|
$cols[$key] = [
|
|
'key' => $key,
|
|
'label' => $r['cod_tab'] . (($r['n_stra'] ?? null) ? (' #' . $r['n_stra']) : ''),
|
|
'cod_tab' => $r['cod_tab'],
|
|
'n_stra' => $r['n_stra'],
|
|
];
|
|
}
|
|
$cols = array_values($cols);
|
|
usort($cols, fn ($a, $b) => strcmp((string) $a['label'], (string) $b['label']));
|
|
|
|
$matrix = [];
|
|
foreach ($rows as $r) {
|
|
$idCond = $r['id_cond'] ?: '—';
|
|
if (! isset($matrix[$idCond])) {
|
|
$matrix[$idCond] = ['id_cond' => $idCond, 'cells' => []];
|
|
}
|
|
$key = $r['cod_tab'] . '|' . (string) ($r['n_stra'] ?? '');
|
|
$matrix[$idCond]['cells'][$key] = (float) ($r['totale'] ?? 0.0);
|
|
}
|
|
|
|
|
|
$out = array_values($matrix);
|
|
usort($out, fn ($a, $b) => (int) ($a['id_cond'] ?? 0) <=> (int) ($b['id_cond'] ?? 0));
|
|
|
|
return [$cols, $out];
|
|
}
|
|
|
|
public function addVoceManuale(): void
|
|
{
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if (! $stabileId) {
|
|
return;
|
|
}
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_situazione_iniziale_voci')) {
|
|
return;
|
|
}
|
|
|
|
$gestione = is_string($this->formVoce['gestione'] ?? null) ? trim((string) $this->formVoce['gestione']) : '';
|
|
$categoria = is_string($this->formVoce['categoria'] ?? null) ? trim((string) $this->formVoce['categoria']) : '';
|
|
$gestione = in_array($gestione, ['ordinaria', 'riscaldamento', 'straordinaria'], true) ? $gestione : 'ordinaria';
|
|
$categoria = in_array($categoria, ['crediti', 'debiti'], true) ? $categoria : 'crediti';
|
|
|
|
$nStra = $gestione === 'straordinaria' && is_numeric($this->formVoce['n_stra'] ?? null) ? (int) $this->formVoce['n_stra'] : null;
|
|
if ($gestione === 'straordinaria' && (! $nStra || $nStra <= 0)) {
|
|
return;
|
|
}
|
|
|
|
$importo = $this->parseMoney(is_string($this->formVoce['importo_euro'] ?? null) ? (string) $this->formVoce['importo_euro'] : null);
|
|
if ($importo === null) {
|
|
return;
|
|
}
|
|
|
|
DB::table('contabilita_situazione_iniziale_voci')->insert([
|
|
'stabile_id' => (int) $stabileId,
|
|
'legacy_year' => $this->legacyYear,
|
|
'gestione' => $gestione,
|
|
'n_stra' => $gestione === 'straordinaria' ? $nStra : null,
|
|
'categoria' => $categoria,
|
|
'codice' => is_string($this->formVoce['codice'] ?? null) ? trim((string) $this->formVoce['codice']) : null,
|
|
'descrizione' => is_string($this->formVoce['descrizione'] ?? null) ? trim((string) $this->formVoce['descrizione']) : null,
|
|
'importo_euro' => $importo,
|
|
'incluso' => 1,
|
|
'origine' => 'manuale',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->formVoce['codice'] = null;
|
|
$this->formVoce['descrizione'] = null;
|
|
$this->formVoce['importo_euro'] = null;
|
|
|
|
$this->reloadData();
|
|
}
|
|
|
|
public function addConguaglioManuale(): void
|
|
{
|
|
$stabileId = $this->getActiveStabile()?->id;
|
|
if (! $stabileId) {
|
|
return;
|
|
}
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_situazione_iniziale_conguagli')) {
|
|
return;
|
|
}
|
|
|
|
$codTab = is_string($this->formConguaglio['cod_tab'] ?? null) ? trim((string) $this->formConguaglio['cod_tab']) : '';
|
|
if ($codTab === '') {
|
|
return;
|
|
}
|
|
|
|
$idCond = is_string($this->formConguaglio['id_cond'] ?? null) ? trim((string) $this->formConguaglio['id_cond']) : '';
|
|
if ($idCond === '') {
|
|
return;
|
|
}
|
|
|
|
$nStra = is_numeric($this->formConguaglio['n_stra'] ?? null) ? (int) $this->formConguaglio['n_stra'] : null;
|
|
$cons = $this->parseMoney(is_string($this->formConguaglio['cons_euro'] ?? null) ? (string) $this->formConguaglio['cons_euro'] : null);
|
|
if ($cons === null) {
|
|
return;
|
|
}
|
|
|
|
DB::table('contabilita_situazione_iniziale_conguagli')->insert([
|
|
'stabile_id' => (int) $stabileId,
|
|
'legacy_year' => $this->legacyYear,
|
|
'cod_tab' => $codTab,
|
|
'n_stra' => $nStra && $nStra > 0 ? $nStra : null,
|
|
'id_cond' => $idCond,
|
|
'cons_euro' => $cons,
|
|
'incluso' => 1,
|
|
'origine' => 'manuale',
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
$this->formConguaglio['id_cond'] = null;
|
|
$this->formConguaglio['cons_euro'] = null;
|
|
$this->reloadData();
|
|
}
|
|
}
|