fix(ui): resolve ru.nome_completo column bug on TabelleMillesimali, group addebiti by tipo & add voci_spesa accordion (task-d095b0e23b)

This commit is contained in:
michele 2026-08-28 22:13:53 +02:00
parent 70b42033bb
commit ce701c9510
3 changed files with 120 additions and 15 deletions

View File

@ -1097,7 +1097,6 @@ protected function loadDettaglioTabella(): void
->select([ ->select([
'rr.unita_immobiliare_id', 'rr.unita_immobiliare_id',
'rr.ruolo_standard', 'rr.ruolo_standard',
'ru.nome_completo',
'ru.ragione_sociale', 'ru.ragione_sociale',
'ru.cognome', 'ru.cognome',
'ru.nome', 'ru.nome',
@ -1138,7 +1137,7 @@ protected function loadDettaglioTabella(): void
$proprietarioList = $rOcc->filter(fn($p) => in_array(strtolower(trim((string)$p->ruolo_standard)), ['condomino', 'proprietario', 'comproprietario', 'nudo_proprietario', 'usufruttuario'], true)); $proprietarioList = $rOcc->filter(fn($p) => in_array(strtolower(trim((string)$p->ruolo_standard)), ['condomino', 'proprietario', 'comproprietario', 'nudo_proprietario', 'usufruttuario'], true));
$propNames = []; $propNames = [];
foreach ($proprietarioList as $p) { foreach ($proprietarioList as $p) {
$n = trim((string) ($p->nome_completo ?: ($p->ragione_sociale ?: ($p->cognome . ' ' . $p->nome)))); $n = trim((string) ($p->ragione_sociale ?: (trim(($p->cognome ?? '') . ' ' . ($p->nome ?? '')))));
if ($n !== '' && ! in_array($n, $propNames, true)) { if ($n !== '' && ! in_array($n, $propNames, true)) {
$propNames[] = $n; $propNames[] = $n;
} }

View File

@ -814,14 +814,60 @@ public function getEstrattoContoNominativoDettaglioProperty(): array
if ($prev > 0 || $cons > 0) { if ($prev > 0 || $cons > 0) {
$yearRaw = (string) ($dt->legacy_year ?? ''); $yearRaw = (string) ($dt->legacy_year ?? '');
$humanYear = $this->resolveHumanYearLabel($yearRaw, $codStabile); $humanYear = $this->resolveHumanYearLabel($yearRaw, $codStabile);
$codTab = (string) ($dt->cod_tab ?? '—');
$tabMeta = DbSchema::connection('gescon_import')->hasTable('tabelle_millesimali')
? DB::connection('gescon_import')->table('tabelle_millesimali')
->where('cod_stabile', $codStabile)
->where('cod_tabella', $codTab)
->first()
: null;
$descrizioneTab = $tabMeta->denominazione ?? ($tabMeta->descrizione ?? $codTab);
$rawTipo = strtoupper((string) ($tabMeta->tipologia ?? 'O'));
$tipoLabel = match($rawTipo) {
'R' => 'Riscaldamento',
'S' => 'Straordinaria',
default => 'Ordinaria',
};
$sortOrder = match($rawTipo) {
'O' => 1,
'R' => 2,
'S' => 3,
default => 4,
};
$vociSpesa = [];
if (DbSchema::connection('gescon_import')->hasTable('voc_spe')) {
$vocRows = DB::connection('gescon_import')->table('voc_spe')
->where('cod_stabile', $codStabile)
->where('tabella', $codTab)
->orderBy('cod')
->get();
foreach ($vocRows as $v) {
$vociSpesa[] = [
'cod_voce' => (string) ($v->cod ?? '—'),
'descrizione' => (string) ($v->descriz ?? '—'),
'perc_proprietario' => (float) ($v->perc_proprietario ?? 100),
'perc_inquilino' => (float) ($v->perc_inquilino ?? 0),
'preventivo_euro' => (float) ($v->preventivo_euro ?? $v->importo_euro ?? 0),
'consuntivo_euro' => (float) ($v->consuntivo_euro ?? 0),
];
}
}
$dettaglioAddebiti[] = [ $dettaglioAddebiti[] = [
'anno_gestione' => $humanYear, 'anno_gestione' => $humanYear,
'cod_tabella' => (string) ($dt->cod_tab ?? '—'), 'cod_tabella' => $codTab,
'descrizione_tab' => $descrizioneTab,
'tipo_label' => $tipoLabel,
'sort_order' => $sortOrder,
'millesimi' => (float) ($dt->mm ?? 0), 'millesimi' => (float) ($dt->mm ?? 0),
'preventivo_euro' => $prev, 'preventivo_euro' => $prev,
'consuntivo_euro' => $cons, 'consuntivo_euro' => $cons,
'conguaglio_euro' => $cong, 'conguaglio_euro' => $cong,
'voci_spesa' => $vociSpesa,
]; ];
$totalePreventivo += $prev; $totalePreventivo += $prev;
@ -829,6 +875,8 @@ public function getEstrattoContoNominativoDettaglioProperty(): array
$totaleConguaglio += $cong; $totaleConguaglio += $cong;
} }
} }
usort($dettaglioAddebiti, fn($a, $b) => $a['sort_order'] <=> $b['sort_order']);
} }
$dettaglioIncassi = []; $dettaglioIncassi = [];

View File

@ -587,8 +587,13 @@ class="inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-semi
{{-- Tabella Addebiti e Ripartizioni --}} {{-- Tabella Addebiti e Ripartizioni --}}
<div class="rounded-xl border border-slate-200 bg-white overflow-hidden shadow-xs"> <div class="rounded-xl border border-slate-200 bg-white overflow-hidden shadow-xs">
<div class="border-b border-slate-200 bg-slate-50 px-4 py-3 font-semibold text-slate-800 text-sm flex items-center justify-between"> <div class="border-b border-slate-200 bg-slate-50 px-4 py-3 font-semibold text-slate-800 text-sm flex items-center justify-between">
<span>📊 Spese e Millesimi Addebitati per Gestione</span> <div class="flex items-center gap-2">
<span class="text-xs text-slate-500 font-normal">Estratti da dett_tab / singolo_anno.mdb</span> <span>📊 Spese e Millesimi Addebitati a <strong>{{ $soggetto['nominativo'] }}</strong></span>
<span class="rounded bg-indigo-100 px-2 py-0.5 text-xs text-indigo-800 font-normal">
{{ reset($ecData['addebiti'])['anno_gestione'] ?? 'Anno In Corso' }}
</span>
</div>
<span class="text-xs text-slate-500 font-normal">Suddivise per Gruppo (Ordinaria, Riscaldamento, Straordinaria)</span>
</div> </div>
@if(empty($ecData['addebiti'])) @if(empty($ecData['addebiti']))
<div class="p-6 text-center text-slate-500 text-xs">Nessun addebito preventivato o consuntivato per questo nominativo.</div> <div class="p-6 text-center text-slate-500 text-xs">Nessun addebito preventivato o consuntivato per questo nominativo.</div>
@ -597,26 +602,79 @@ class="inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-semi
<table class="w-full text-left text-xs"> <table class="w-full text-left text-xs">
<thead class="bg-slate-100 text-slate-700 font-semibold border-b border-slate-200"> <thead class="bg-slate-100 text-slate-700 font-semibold border-b border-slate-200">
<tr> <tr>
<th class="px-4 py-2.5">Anno Gestione</th> <th class="px-4 py-2.5">Codice Tabella</th>
<th class="px-4 py-2.5">Codice Tabella / Voci</th> <th class="px-4 py-2.5">Descrizione Tabella</th>
<th class="px-4 py-2.5">Tipo Gestione</th>
<th class="px-4 py-2.5 text-right">Millesimi (mm)</th> <th class="px-4 py-2.5 text-right">Millesimi (mm)</th>
<th class="px-4 py-2.5 text-right">Preventivo ()</th> <th class="px-4 py-2.5 text-right">Preventivo ()</th>
<th class="px-4 py-2.5 text-right">Consuntivo ()</th> <th class="px-4 py-2.5 text-right">Consuntivo ()</th>
<th class="px-4 py-2.5 text-right">Conguaglio ()</th> <th class="px-4 py-2.5 text-right">Conguaglio ()</th>
<th class="px-4 py-2.5 text-center">Voci Spesa</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-slate-100"> <tbody class="divide-y divide-slate-100">
@foreach($ecData['addebiti'] as $add) @foreach($ecData['addebiti'] as $addIndex => $add)
<tr class="hover:bg-slate-50 transition"> <tr class="hover:bg-indigo-50/50 transition cursor-pointer" onclick="document.getElementById('voc-spe-row-{{ $addIndex }}') ? document.getElementById('voc-spe-row-{{ $addIndex }}').classList.toggle('hidden') : null">
<td class="px-4 py-2 font-mono font-medium text-indigo-700">{{ $add['anno_gestione'] }}</td> <td class="px-4 py-2.5 font-mono font-bold text-indigo-700">{{ $add['cod_tabella'] }}</td>
<td class="px-4 py-2 font-semibold text-slate-900">{{ $add['cod_tabella'] }}</td> <td class="px-4 py-2.5 font-semibold text-slate-900">{{ $add['descrizione_tab'] }}</td>
<td class="px-4 py-2 text-right font-mono text-slate-600">{{ number_format($add['millesimi'], 2, ',', '.') }}</td> <td class="px-4 py-2.5">
<td class="px-4 py-2 text-right font-mono font-medium text-slate-800"> {{ number_format($add['preventivo_euro'], 2, ',', '.') }}</td> <span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-semibold {{ $add['tipo_label'] === 'Riscaldamento' ? 'bg-amber-100 text-amber-800' : ($add['tipo_label'] === 'Straordinaria' ? 'bg-rose-100 text-rose-800' : 'bg-slate-100 text-slate-800') }}">
<td class="px-4 py-2 text-right font-mono font-medium text-slate-800"> {{ number_format($add['consuntivo_euro'], 2, ',', '.') }}</td> {{ $add['tipo_label'] }}
<td class="px-4 py-2 text-right font-mono font-bold {{ $add['conguaglio_euro'] > 0 ? 'text-amber-600' : ($add['conguaglio_euro'] < 0 ? 'text-emerald-600' : 'text-slate-500') }}"> </span>
</td>
<td class="px-4 py-2.5 text-right font-mono text-slate-600">{{ number_format($add['millesimi'], 2, ',', '.') }}</td>
<td class="px-4 py-2.5 text-right font-mono font-medium text-slate-800"> {{ number_format($add['preventivo_euro'], 2, ',', '.') }}</td>
<td class="px-4 py-2.5 text-right font-mono font-medium text-slate-800"> {{ number_format($add['consuntivo_euro'], 2, ',', '.') }}</td>
<td class="px-4 py-2.5 text-right font-mono font-bold {{ $add['conguaglio_euro'] > 0 ? 'text-amber-600' : ($add['conguaglio_euro'] < 0 ? 'text-emerald-600' : 'text-slate-500') }}">
{{ number_format($add['conguaglio_euro'], 2, ',', '.') }} {{ number_format($add['conguaglio_euro'], 2, ',', '.') }}
</td> </td>
<td class="px-4 py-2.5 text-center">
@if(!empty($add['voci_spesa']))
<span class="inline-flex items-center gap-1 rounded bg-indigo-50 border border-indigo-200 px-2 py-0.5 text-xs font-semibold text-indigo-700">
<span>{{ count($add['voci_spesa']) }} voci</span>
<span>🔍</span>
</span>
@else
<span class="text-slate-400 text-xs"></span>
@endif
</td>
</tr> </tr>
@if(!empty($add['voci_spesa']))
<tr id="voc-spe-row-{{ $addIndex }}" class="hidden bg-slate-50/80 border-b border-indigo-100">
<td colspan="8" class="p-3">
<div class="rounded-lg border border-indigo-100 bg-white p-3 shadow-xs">
<div class="text-xs font-bold text-indigo-900 mb-2 flex items-center gap-2">
<span>📋 Voci di Spesa collegate alla Tabella <strong>{{ $add['cod_tabella'] }}</strong></span>
<span class="text-slate-500 font-normal">({{ count($add['voci_spesa']) }} voci da voc_spe)</span>
</div>
<table class="w-full text-left text-xs border border-slate-200 rounded">
<thead class="bg-indigo-50 text-indigo-900 font-semibold">
<tr>
<th class="px-3 py-1.5">Cod. Voce</th>
<th class="px-3 py-1.5">Descrizione Voce</th>
<th class="px-3 py-1.5 text-center">% Prop.</th>
<th class="px-3 py-1.5 text-center">% Inq.</th>
<th class="px-3 py-1.5 text-right">Preventivo Voce ()</th>
<th class="px-3 py-1.5 text-right">Consuntivo Voce ()</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
@foreach($add['voci_spesa'] as $voc)
<tr class="hover:bg-slate-50">
<td class="px-3 py-1.5 font-mono font-bold text-slate-700">{{ $voc['cod_voce'] }}</td>
<td class="px-3 py-1.5 text-slate-900 font-medium">{{ $voc['descrizione'] }}</td>
<td class="px-3 py-1.5 text-center font-mono text-slate-600">{{ number_format($voc['perc_proprietario'], 0) }}%</td>
<td class="px-3 py-1.5 text-center font-mono text-slate-600">{{ number_format($voc['perc_inquilino'], 0) }}%</td>
<td class="px-3 py-1.5 text-right font-mono text-slate-800"> {{ number_format($voc['preventivo_euro'], 2, ',', '.') }}</td>
<td class="px-3 py-1.5 text-right font-mono text-slate-800"> {{ number_format($voc['consuntivo_euro'], 2, ',', '.') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</td>
</tr>
@endif
@endforeach @endforeach
</tbody> </tbody>
</table> </table>