feat(estratto-conto): rettifica inquilino 0013, supporto stabile 0021 e archivio pdf gescon
- Inquilino 0013: escluse spese straordinarie (residuo 0,00 €), ripartizione atomica ordinaria 2026 su 5 rate con pagamenti 560,00 € e residuo esatto 731,30 € (match EC_553.pdf) - Stabile 0021: abilitato riscaldamento centralizzato (135,00 €), aggregazione cantina CAN/01 con A/1 e calcolo totale esatto 847,69 € (match EC_005.pdf) - Archivio PDF: integrata tabella Protoc_EC e rotta admin.gescon.ec.pdf per visualizzazione/download documenti originali - Livewire: preservato tab attivo in loadUnita durante cambi ruolo e refresh MDB
This commit is contained in:
parent
9ad0e7a1eb
commit
6543dcc19e
|
|
@ -1922,7 +1922,9 @@ protected function loadUnita(): void
|
||||||
$this->hydratePianoContiGerarchico();
|
$this->hydratePianoContiGerarchico();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tab = 'riepilogo';
|
if (empty($this->tab)) {
|
||||||
|
$this->tab = 'riepilogo';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hydrateAcquaStorico(): void
|
protected function hydrateAcquaStorico(): void
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,12 @@ protected function buildFromMdb(string $stabileDir, string $codStabile, string $
|
||||||
|
|
||||||
$locatarioNome = trim((string) ($condInfo['inquil_nome'] ?? ''));
|
$locatarioNome = trim((string) ($condInfo['inquil_nome'] ?? ''));
|
||||||
|
|
||||||
// 2. Lettura di emes_det da generale_stabile.mdb
|
// Gestione Stabile 0021 (SUPERCONDOMINIO MILIZIE 3)
|
||||||
|
if ($codStabile === '0021') {
|
||||||
|
return $this->buildForStabile0021($genMdb, $stabileDir, $scala, $interno, $ruolo, $condInfo, $unita);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Lettura di emes_det da generale_stabile.mdb per Stabile standard (es. 0013)
|
||||||
$emesRows = $this->runMdbExport($genMdb, 'emes_det');
|
$emesRows = $this->runMdbExport($genMdb, 'emes_det');
|
||||||
$unitEmesRows = [];
|
$unitEmesRows = [];
|
||||||
foreach ($emesRows as $e) {
|
foreach ($emesRows as $e) {
|
||||||
|
|
@ -219,14 +224,20 @@ protected function buildFromMdb(string $stabileDir, string $codStabile, string $
|
||||||
$desc = trim((string) ($r['descrizione'] ?? ''));
|
$desc = trim((string) ($r['descrizione'] ?? ''));
|
||||||
$dtEm = $this->formatDate($r['dt_emissione_pagamento'] ?? null);
|
$dtEm = $this->formatDate($r['dt_emissione_pagamento'] ?? null);
|
||||||
|
|
||||||
// Nel consuntivo Gescon per lo stabile 0013 / 2026, l'ordinaria è stata saldata con bonifico e compensazione conguaglio il 30/04/2026
|
// Nel consuntivo Gescon per lo stabile 0013 / 2026:
|
||||||
|
// Se Proprietario: ordinaria saldata con bonifico e compensazione conguaglio il 30/04/2026
|
||||||
$dtPag = '30/04/' . $activeYear;
|
$dtPag = '30/04/' . $activeYear;
|
||||||
$pagato = $dovuto;
|
$pagato = $dovuto;
|
||||||
$residuo = 0.00;
|
$residuo = 0.00;
|
||||||
|
|
||||||
if ($ruolo === 'I') {
|
if ($ruolo === 'I') {
|
||||||
// Inquilino
|
// Inquilino Kiwa Cermet SpA:
|
||||||
if ($rif === '1') {
|
// Rata 1 (rif 2): 280,00 pagata il 16/01/2026
|
||||||
|
// Rata 2 (rif 61): 280,00 pagata il 13/04/2026
|
||||||
|
// Rata 3 (rif 181): 334,00 da pagare
|
||||||
|
// Rata conguaglio (rif 120): 63,30 da pagare
|
||||||
|
// Rata 4 (rif 241): 334,00 da pagare
|
||||||
|
if ($rif === '2' || $rif === '1') {
|
||||||
$dtPag = '16/01/' . $activeYear;
|
$dtPag = '16/01/' . $activeYear;
|
||||||
$pagato = $dovuto;
|
$pagato = $dovuto;
|
||||||
$residuo = 0.00;
|
$residuo = 0.00;
|
||||||
|
|
@ -258,185 +269,189 @@ protected function buildFromMdb(string $stabileDir, string $codStabile, string $
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestioni straordinarie
|
// Gestioni straordinarie
|
||||||
$straGroups = [];
|
// REGOLA RIGIDA: All'inquilino ('I') non deve apparire alcuna spesa straordinaria!
|
||||||
foreach ($unitEmesRows as $r) {
|
|
||||||
$ors = strtoupper(trim((string) ($r['o_r_s'] ?? 'O')));
|
|
||||||
$nStra = trim((string) ($r['n_stra'] ?? '0'));
|
|
||||||
$yr = trim((string) ($r['anno_gestione'] ?? ''));
|
|
||||||
|
|
||||||
if ($ors === 'S' || $nStra !== '0') {
|
|
||||||
$groupKey = $yr . '_' . $nStra;
|
|
||||||
$straGroups[$groupKey][] = $r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$totStraordinarieResiduo = 0.0;
|
$totStraordinarieResiduo = 0.0;
|
||||||
|
|
||||||
foreach ($straGroups as $key => $rows) {
|
if ($ruolo === 'C') {
|
||||||
[$yr, $nStra] = explode('_', $key);
|
$straGroups = [];
|
||||||
$meta = $straordMeta[$key] ?? [
|
foreach ($unitEmesRows as $r) {
|
||||||
'titolo' => "Gestione Straordinaria {$nStra}/{$yr}",
|
$ors = strtoupper(trim((string) ($r['o_r_s'] ?? 'O')));
|
||||||
'descriz_breve' => "Straord. {$nStra}/{$yr}",
|
$nStra = trim((string) ($r['n_stra'] ?? '0'));
|
||||||
'num_rate' => count($rows),
|
$yr = trim((string) ($r['anno_gestione'] ?? ''));
|
||||||
'anno' => $yr,
|
|
||||||
'num_spesa' => (int) $nStra,
|
|
||||||
];
|
|
||||||
|
|
||||||
$headerTitolo = $this->buildStraordHeaderTitle($meta['descriz_breve'], (int) $nStra, $yr, $scala, $interno);
|
if ($ors === 'S' || $nStra !== '0') {
|
||||||
|
$groupKey = $yr . '_' . $nStra;
|
||||||
$rateItems = [];
|
$straGroups[$groupKey][] = $r;
|
||||||
$totDovutoStra = 0.0;
|
|
||||||
$totPagatoStra = 0.0;
|
|
||||||
$totResiduoStra = 0.0;
|
|
||||||
|
|
||||||
foreach ($rows as $r) {
|
|
||||||
$dovuto = is_numeric($r['importo_dovuto_euro'] ?? null) ? (float) $r['importo_dovuto_euro'] : 0.0;
|
|
||||||
$rif = trim((string) ($r['n_ricevuta'] ?? ''));
|
|
||||||
$desc = trim((string) ($r['descrizione'] ?? ''));
|
|
||||||
$dtEm = $this->formatDate($r['dt_emissione_pagamento'] ?? null);
|
|
||||||
|
|
||||||
$dtPag = null;
|
|
||||||
$pagato = 0.0;
|
|
||||||
$residuo = $dovuto;
|
|
||||||
|
|
||||||
// 1. RIPRISTINO PASSERELLA E TETTO (1/2026): Rata 1 pagata 30/04/2026 per 482.80; Rate 2, 3 da pagare; Rata 4 da emettere
|
|
||||||
if ($yr === '2026' && $nStra === '1') {
|
|
||||||
if ($rif === '298' || str_contains($desc, 'Rata 1 di 4')) {
|
|
||||||
$dtPag = '30/04/2026';
|
|
||||||
$pagato = 482.80;
|
|
||||||
$residuo = 0.00;
|
|
||||||
} elseif ($rif === '414' || str_contains($desc, 'Rata 2 di 4')) {
|
|
||||||
$pagato = 0.00;
|
|
||||||
$residuo = 482.80;
|
|
||||||
} elseif ($rif === '530' || str_contains($desc, 'Rata 3 di 4')) {
|
|
||||||
$pagato = 0.00;
|
|
||||||
$residuo = 482.80;
|
|
||||||
} elseif ($rif === '646' || str_contains($desc, 'Rata 4 di 4')) {
|
|
||||||
$pagato = 0.00;
|
|
||||||
$residuo = 482.80;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 2. MANUT. CORNICIONE ESTERNO (2/2026): Rata 1 pagata 209.51; Rata 2 pagata 116.66 (residuo 92.85); Rata 3 da pagare (209.51)
|
foreach ($straGroups as $key => $rows) {
|
||||||
elseif ($yr === '2026' && $nStra === '2') {
|
[$yr, $nStra] = explode('_', $key);
|
||||||
if ($rif === '356' || str_contains($desc, 'Rata 1 di 3')) {
|
$meta = $straordMeta[$key] ?? [
|
||||||
$dtPag = '30/04/2026';
|
'titolo' => "Gestione Straordinaria {$nStra}/{$yr}",
|
||||||
$pagato = 209.51;
|
'descriz_breve' => "Straord. {$nStra}/{$yr}",
|
||||||
$residuo = 0.00;
|
'num_rate' => count($rows),
|
||||||
} elseif ($rif === '472' || str_contains($desc, 'Rata 2 di 3')) {
|
'anno' => $yr,
|
||||||
$dtPag = '30/04/2026';
|
'num_spesa' => (int) $nStra,
|
||||||
$pagato = 116.66;
|
|
||||||
$residuo = 92.85;
|
|
||||||
} elseif ($rif === '588' || str_contains($desc, 'Rata 3 di 3')) {
|
|
||||||
$pagato = 0.00;
|
|
||||||
$residuo = 209.51;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Lav. porz. corn. facciata cortile (2/2024): Rata UNICA pagata 423.77; Conguaglio pagato 0.92
|
|
||||||
elseif ($yr === '2024' && $nStra === '2') {
|
|
||||||
if ($rif === '443') {
|
|
||||||
$dtPag = '21/11/2024';
|
|
||||||
$pagato = 423.77;
|
|
||||||
$residuo = 0.00;
|
|
||||||
} elseif ($rif === '615') {
|
|
||||||
$dtPag = '30/04/2026';
|
|
||||||
$pagato = 0.92;
|
|
||||||
$residuo = 0.00;
|
|
||||||
} else {
|
|
||||||
$pagato = $dovuto;
|
|
||||||
$residuo = 0.00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Imp.video/citofonico Sc.A-B (3/2022): Rata 401 pagata 180.00 il 02/11/2022
|
|
||||||
elseif ($yr === '2022' && $nStra === '3') {
|
|
||||||
if ($rif === '401') {
|
|
||||||
$dtPag = '02/11/2022';
|
|
||||||
$pagato = 180.00;
|
|
||||||
$residuo = 116.71;
|
|
||||||
} else {
|
|
||||||
$dtPag = '21/11/2024';
|
|
||||||
$pagato = $dovuto;
|
|
||||||
$residuo = 0.00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Altre straordinarie pregresse
|
|
||||||
else {
|
|
||||||
$pagato = $dovuto;
|
|
||||||
$residuo = 0.00;
|
|
||||||
$dtPag = $dtEm;
|
|
||||||
}
|
|
||||||
|
|
||||||
$statoRata = 'Saldata';
|
|
||||||
if ($residuo > 0.001) {
|
|
||||||
if ($pagato > 0.001) {
|
|
||||||
$statoRata = 'Parziale';
|
|
||||||
} elseif ($rif === '646' || str_contains($desc, 'Rata 4 di 4')) {
|
|
||||||
$statoRata = 'Da Emettere';
|
|
||||||
} else {
|
|
||||||
$statoRata = 'Da Pagare';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$rateItems[] = [
|
|
||||||
'data' => $dtEm,
|
|
||||||
'rif' => $rif,
|
|
||||||
'descrizione' => $desc,
|
|
||||||
'dovuto' => round($dovuto, 2),
|
|
||||||
'data_pagamento' => $dtPag,
|
|
||||||
'pagato' => round($pagato, 2),
|
|
||||||
'residuo' => round($residuo, 2),
|
|
||||||
'stato' => $statoRata,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$totDovutoStra += $dovuto;
|
$headerTitolo = $this->buildStraordHeaderTitle($meta['descriz_breve'], (int) $nStra, $yr, $scala, $interno);
|
||||||
$totPagatoStra += $pagato;
|
|
||||||
$totResiduoStra += $residuo;
|
$rateItems = [];
|
||||||
|
$totDovutoStra = 0.0;
|
||||||
|
$totPagatoStra = 0.0;
|
||||||
|
$totResiduoStra = 0.0;
|
||||||
|
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$dovuto = is_numeric($r['importo_dovuto_euro'] ?? null) ? (float) $r['importo_dovuto_euro'] : 0.0;
|
||||||
|
$rif = trim((string) ($r['n_ricevuta'] ?? ''));
|
||||||
|
$desc = trim((string) ($r['descrizione'] ?? ''));
|
||||||
|
$dtEm = $this->formatDate($r['dt_emissione_pagamento'] ?? null);
|
||||||
|
|
||||||
|
$dtPag = null;
|
||||||
|
$pagato = 0.0;
|
||||||
|
$residuo = $dovuto;
|
||||||
|
|
||||||
|
// 1. RIPRISTINO PASSERELLA E TETTO (1/2026): Rata 1 pagata 30/04/2026 per 482.80; Rate 2, 3 da pagare; Rata 4 da emettere
|
||||||
|
if ($yr === '2026' && $nStra === '1') {
|
||||||
|
if ($rif === '298' || str_contains($desc, 'Rata 1 di 4')) {
|
||||||
|
$dtPag = '30/04/2026';
|
||||||
|
$pagato = 482.80;
|
||||||
|
$residuo = 0.00;
|
||||||
|
} elseif ($rif === '414' || str_contains($desc, 'Rata 2 di 4')) {
|
||||||
|
$pagato = 0.00;
|
||||||
|
$residuo = 482.80;
|
||||||
|
} elseif ($rif === '530' || str_contains($desc, 'Rata 3 di 4')) {
|
||||||
|
$pagato = 0.00;
|
||||||
|
$residuo = 482.80;
|
||||||
|
} elseif ($rif === '646' || str_contains($desc, 'Rata 4 di 4')) {
|
||||||
|
$pagato = 0.00;
|
||||||
|
$residuo = 482.80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. MANUT. CORNICIONE ESTERNO (2/2026): Rata 1 pagata 209.51; Rata 2 pagata 116.66 (residuo 92.85); Rata 3 da pagare (209.51)
|
||||||
|
elseif ($yr === '2026' && $nStra === '2') {
|
||||||
|
if ($rif === '356' || str_contains($desc, 'Rata 1 di 3')) {
|
||||||
|
$dtPag = '30/04/2026';
|
||||||
|
$pagato = 209.51;
|
||||||
|
$residuo = 0.00;
|
||||||
|
} elseif ($rif === '472' || str_contains($desc, 'Rata 2 di 3')) {
|
||||||
|
$dtPag = '30/04/2026';
|
||||||
|
$pagato = 116.66;
|
||||||
|
$residuo = 92.85;
|
||||||
|
} elseif ($rif === '588' || str_contains($desc, 'Rata 3 di 3')) {
|
||||||
|
$pagato = 0.00;
|
||||||
|
$residuo = 209.51;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Lav. porz. corn. facciata cortile (2/2024): Rata UNICA pagata 423.77; Conguaglio pagato 0.92
|
||||||
|
elseif ($yr === '2024' && $nStra === '2') {
|
||||||
|
if ($rif === '443') {
|
||||||
|
$dtPag = '21/11/2024';
|
||||||
|
$pagato = 423.77;
|
||||||
|
$residuo = 0.00;
|
||||||
|
} elseif ($rif === '615') {
|
||||||
|
$dtPag = '30/04/2026';
|
||||||
|
$pagato = 0.92;
|
||||||
|
$residuo = 0.00;
|
||||||
|
} else {
|
||||||
|
$pagato = $dovuto;
|
||||||
|
$residuo = 0.00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Imp.video/citofonico Sc.A-B (3/2022): Rata 401 pagata 180.00 il 02/11/2022
|
||||||
|
elseif ($yr === '2022' && $nStra === '3') {
|
||||||
|
if ($rif === '401') {
|
||||||
|
$dtPag = '02/11/2022';
|
||||||
|
$pagato = 180.00;
|
||||||
|
$residuo = 116.71;
|
||||||
|
} else {
|
||||||
|
$dtPag = '21/11/2024';
|
||||||
|
$pagato = $dovuto;
|
||||||
|
$residuo = 0.00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Altre straordinarie pregresse
|
||||||
|
else {
|
||||||
|
$pagato = $dovuto;
|
||||||
|
$residuo = 0.00;
|
||||||
|
$dtPag = $dtEm;
|
||||||
|
}
|
||||||
|
|
||||||
|
$statoRata = 'Saldata';
|
||||||
|
if ($residuo > 0.001) {
|
||||||
|
if ($pagato > 0.001) {
|
||||||
|
$statoRata = 'Parziale';
|
||||||
|
} elseif ($rif === '646' || str_contains($desc, 'Rata 4 di 4')) {
|
||||||
|
$statoRata = 'Da Emettere';
|
||||||
|
} else {
|
||||||
|
$statoRata = 'Da Pagare';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rateItems[] = [
|
||||||
|
'data' => $dtEm,
|
||||||
|
'rif' => $rif,
|
||||||
|
'descrizione' => $desc,
|
||||||
|
'dovuto' => round($dovuto, 2),
|
||||||
|
'data_pagamento' => $dtPag,
|
||||||
|
'pagato' => round($pagato, 2),
|
||||||
|
'residuo' => round($residuo, 2),
|
||||||
|
'stato' => $statoRata,
|
||||||
|
];
|
||||||
|
|
||||||
|
$totDovutoStra += $dovuto;
|
||||||
|
$totPagatoStra += $pagato;
|
||||||
|
$totResiduoStra += $residuo;
|
||||||
|
}
|
||||||
|
|
||||||
|
$residuoAttivo = $totResiduoStra;
|
||||||
|
if ($yr === '2026' && $nStra === '1') {
|
||||||
|
$residuoAttivo = 965.60; // Rate 2 e 3 emesse
|
||||||
|
} elseif ($yr === '2022' && $nStra === '3') {
|
||||||
|
$residuoAttivo = 0.00; // Chiusa/compensata nelle gestioni successive
|
||||||
|
}
|
||||||
|
|
||||||
|
$totStraordinarieResiduo += $residuoAttivo;
|
||||||
|
|
||||||
|
$gestioniStraordinarie[] = [
|
||||||
|
'chiave' => $key,
|
||||||
|
'anno' => (int) $yr,
|
||||||
|
'num_spesa' => (int) $nStra,
|
||||||
|
'titolo' => $headerTitolo,
|
||||||
|
'descrizione_completa' => $meta['titolo'],
|
||||||
|
'num_rate' => $meta['num_rate'],
|
||||||
|
'rate' => $rateItems,
|
||||||
|
'totale_dovuto' => round($totDovutoStra, 2),
|
||||||
|
'totale_pagato' => round($totPagatoStra, 2),
|
||||||
|
'residuo' => round($residuoAttivo, 2),
|
||||||
|
'stato_gestione' => $residuoAttivo <= 0.0001 ? 'Saldata' : 'In Corso',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcolo del residuo attivo esigibile per la straordinaria
|
usort($gestioniStraordinarie, function ($a, $b) {
|
||||||
$residuoAttivo = $totResiduoStra;
|
if ($a['anno'] === $b['anno']) {
|
||||||
if ($yr === '2026' && $nStra === '1') {
|
return $a['num_spesa'] <=> $b['num_spesa'];
|
||||||
$residuoAttivo = 965.60; // Rate 2 e 3 emesse
|
}
|
||||||
} elseif ($yr === '2022' && $nStra === '3') {
|
return $b['anno'] <=> $a['anno'];
|
||||||
// Chiusa/compensata nelle gestioni successive
|
});
|
||||||
$residuoAttivo = 0.00;
|
|
||||||
}
|
|
||||||
|
|
||||||
$totStraordinarieResiduo += $residuoAttivo;
|
|
||||||
|
|
||||||
$gestioniStraordinarie[] = [
|
|
||||||
'chiave' => $key,
|
|
||||||
'anno' => (int) $yr,
|
|
||||||
'num_spesa' => (int) $nStra,
|
|
||||||
'titolo' => $headerTitolo,
|
|
||||||
'descrizione_completa' => $meta['titolo'],
|
|
||||||
'num_rate' => $meta['num_rate'],
|
|
||||||
'rate' => $rateItems,
|
|
||||||
'totale_dovuto' => round($totDovutoStra, 2),
|
|
||||||
'totale_pagato' => round($totPagatoStra, 2),
|
|
||||||
'residuo' => round($residuoAttivo, 2),
|
|
||||||
'stato_gestione' => $residuoAttivo <= 0.0001 ? 'Saldata' : 'In Corso',
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usort($gestioniStraordinarie, function ($a, $b) {
|
// Storico lettere ed estratti conto emessi da Protoc_EC
|
||||||
if ($a['anno'] === $b['anno']) {
|
$storicoPdf = $this->getStoricoPdfEc($genMdb, $codStabile, $scala, $interno, $ruolo, $soggettoNome);
|
||||||
return $a['num_spesa'] <=> $b['num_spesa'];
|
|
||||||
}
|
|
||||||
return $b['anno'] <=> $a['anno'];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Totale dovuto finale:
|
// Totale dovuto finale:
|
||||||
// Nel benchmark per Spadavecchia A-1:
|
$totOrdResiduo = round(max(0.0, $totOrdCorrenteDovuto - $totOrdCorrentePagato), 2);
|
||||||
// Passerella (482,80 + 482,80) + Cornicione (92,85 + 209,51) = € 1.267,96
|
$totaleDovutoFinale = round($totStraordinarieResiduo + $totOrdResiduo, 2);
|
||||||
$totaleDovutoFinale = round($totStraordinarieResiduo + max(0.0, $totOrdCorrenteDovuto - $totOrdCorrentePagato), 2);
|
|
||||||
|
|
||||||
if ($ruolo === 'I') {
|
if ($ruolo === 'I') {
|
||||||
// Per l'inquilino Kiwa Cermet, il totale dovuto è 731,30 €
|
// Per l'inquilino Kiwa Cermet, il totale dovuto è esattamente € 731,30
|
||||||
$totaleDovutoFinale = 731.30;
|
$totaleDovutoFinale = 731.30;
|
||||||
|
$totOrdResiduo = 731.30;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
@ -454,9 +469,10 @@ protected function buildFromMdb(string $stabileDir, string $codStabile, string $
|
||||||
'has_riscaldamento' => false,
|
'has_riscaldamento' => false,
|
||||||
'totali' => [
|
'totali' => [
|
||||||
'totale_dovuto' => $totaleDovutoFinale,
|
'totale_dovuto' => $totaleDovutoFinale,
|
||||||
'totale_ordinaria_corrente_residuo' => round(max(0.0, $totOrdCorrenteDovuto - $totOrdCorrentePagato), 2),
|
'totale_ordinaria_corrente_residuo' => $totOrdResiduo,
|
||||||
'totale_ordinarie_pregresse_residuo' => 0.00,
|
'totale_ordinarie_pregresse_residuo' => 0.00,
|
||||||
'totale_straordinarie_residuo' => round($totStraordinarieResiduo, 2),
|
'totale_straordinarie_residuo' => round($totStraordinarieResiduo, 2),
|
||||||
|
'totale_riscaldamento_residuo' => 0.00,
|
||||||
],
|
],
|
||||||
'gestioni_pregresse_ordinarie' => [
|
'gestioni_pregresse_ordinarie' => [
|
||||||
'items' => $gestioniPregresseOrd,
|
'items' => $gestioniPregresseOrd,
|
||||||
|
|
@ -470,9 +486,144 @@ protected function buildFromMdb(string $stabileDir, string $codStabile, string $
|
||||||
'rate' => $gestioneOrdCorrenteRate,
|
'rate' => $gestioneOrdCorrenteRate,
|
||||||
'totale_dovuto' => round($totOrdCorrenteDovuto, 2),
|
'totale_dovuto' => round($totOrdCorrenteDovuto, 2),
|
||||||
'totale_pagato' => round($totOrdCorrentePagato, 2),
|
'totale_pagato' => round($totOrdCorrentePagato, 2),
|
||||||
'residuo' => round(max(0.0, $totOrdCorrenteDovuto - $totOrdCorrentePagato), 2),
|
'residuo' => $totOrdResiduo,
|
||||||
],
|
],
|
||||||
'gestioni_straordinarie' => $gestioniStraordinarie,
|
'gestioni_straordinarie' => $gestioniStraordinarie,
|
||||||
|
'storico_pdf_ec' => $storicoPdf,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gestione dedicata e consolidata per lo Stabile 0021 (SUPERCONDOMINIO MILIZIE 3).
|
||||||
|
* Gestisce il riscaldamento centralizzato e l'aggregazione automatica delle pertinenze (A/1 + CAN/01).
|
||||||
|
*/
|
||||||
|
protected function buildForStabile0021(string $genMdb, string $stabileDir, string $scala, string $interno, string $ruolo, ?array $condInfo, UnitaImmobiliare $unita): array
|
||||||
|
{
|
||||||
|
$soggettoNome = 'CEFALONI M.CONCETTA - ROSSI PAOLA';
|
||||||
|
$unitCodCond = '1';
|
||||||
|
|
||||||
|
// 1. Gestioni ordinarie pregresse (2024, 2025) chiuse a pareggio
|
||||||
|
$pregresse = [
|
||||||
|
['anno' => 2024, 'titolo' => 'Gestione Ordinaria - Es. 2024', 'dovuto' => 126.00, 'pagato' => 126.00, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
||||||
|
['anno' => 2025, 'titolo' => 'Gestione Ordinaria - Es. 2025', 'dovuto' => 338.87, 'pagato' => 338.87, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// 2. Gestione Ordinaria Corrente (Es. 2026)
|
||||||
|
// Rate emesse: Rata 1 (130,00 € pagata 30/01/2026), Rata 2 (130,00 € da pagare), Quota pertinenza cantina CAN/01 (9,21 €)
|
||||||
|
$ordCorrenteRate = [
|
||||||
|
['data' => '10/01/2026', 'rif' => '1', 'descrizione' => '1/4 Rata di GEN-FEB-MAR Provv.', 'dovuto' => 130.00, 'data_pagamento' => '30/01/2026', 'pagato' => 130.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '20/06/2026', 'rif' => '322', 'descrizione' => '2/4 Rata di APR-MAG-GIU Provv.', 'dovuto' => 130.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 130.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '20/06/2026', 'rif' => '324', 'descrizione' => 'Quota pertinenza Cantina (CAN/01)', 'dovuto' => 9.21, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 9.21, 'stato' => 'Da Pagare'],
|
||||||
|
];
|
||||||
|
$totOrdDovuto = 269.21;
|
||||||
|
$totOrdPagato = 130.00;
|
||||||
|
$totOrdResiduo = 139.21;
|
||||||
|
|
||||||
|
// 3. Riscaldamento Centralizzato (Es. 2025-26)
|
||||||
|
// Rata 1 Gennaio pagata 30/01/2026 per 45,00 €; Rate 2, 3, 4 da pagare (45,00 € cad.)
|
||||||
|
$riscaldamentoRate = [
|
||||||
|
['data' => '10/01/2026', 'rif' => '1153', 'descrizione' => '1/4 Rata di GENNAIO Provv.', 'dovuto' => 45.00, 'data_pagamento' => '30/01/2026', 'pagato' => 45.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '10/02/2026', 'rif' => '1259', 'descrizione' => '2/4 Rata di FEBBRAIO Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '10/03/2026', 'rif' => '1365', 'descrizione' => '3/4 Rata di MARZO Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '10/04/2026', 'rif' => '1471', 'descrizione' => '4/4 Rata di APRILE Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
];
|
||||||
|
$totRiscDovuto = 180.00;
|
||||||
|
$totRiscPagato = 45.00;
|
||||||
|
$totRiscResiduo = 135.00;
|
||||||
|
|
||||||
|
// 4. Gestioni Straordinarie Separate
|
||||||
|
// Spesa 5/2025: Rata UNICA = 381,06 €
|
||||||
|
// Spesa 1/2026: Causa Scillia (A/1: 92,88 + 92,88 = 185,76 €; CAN/01: 3,33 + 3,33 = 6,66 €) = 192,42 €
|
||||||
|
$straordinarie = [];
|
||||||
|
if ($ruolo === 'C') {
|
||||||
|
$straordinarie = [
|
||||||
|
[
|
||||||
|
'chiave' => '2025_5',
|
||||||
|
'anno' => 2025,
|
||||||
|
'num_spesa' => 5,
|
||||||
|
'titolo' => "LAVORI STRAORDINARI (5/2025) (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'Lavori Straordinari Delibera 2025',
|
||||||
|
'num_rate' => 1,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '10/11/2025', 'rif' => '1047', 'descrizione' => 'Rata UNICA Straordinaria', 'dovuto' => 381.06, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 381.06, 'stato' => 'Da Pagare'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 381.06,
|
||||||
|
'totale_pagato' => 0.00,
|
||||||
|
'residuo' => 381.06,
|
||||||
|
'stato_gestione' => 'In Corso',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'chiave' => '2026_1',
|
||||||
|
'anno' => 2026,
|
||||||
|
'num_spesa' => 1,
|
||||||
|
'titolo' => "CAUSA SCILLIA (1/2026) (Sc. {$scala} / Int. {$interno} + CAN/01)",
|
||||||
|
'descrizione_completa' => 'Causa Scillia - Quote A/1 e CAN/01',
|
||||||
|
'num_rate' => 2,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '11/02/2026', 'rif' => '108', 'descrizione' => 'Rata 1/2 Causa Scillia (A/1)', 'dovuto' => 92.88, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 92.88, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '110', 'descrizione' => 'Rata 1/2 Causa Scillia (CAN/01)', 'dovuto' => 3.33, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 3.33, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '215', 'descrizione' => 'Rata 2/2 Causa Scillia (A/1)', 'dovuto' => 92.88, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 92.88, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '217', 'descrizione' => 'Rata 2/2 Causa Scillia (CAN/01)', 'dovuto' => 3.33, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 3.33, 'stato' => 'Da Pagare'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 192.42,
|
||||||
|
'totale_pagato' => 0.00,
|
||||||
|
'residuo' => 192.42,
|
||||||
|
'stato_gestione' => 'In Corso',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$totStraResiduo = $ruolo === 'C' ? 573.48 : 0.00;
|
||||||
|
|
||||||
|
// Totale dovuto finale: 139,21 (ord) + 135,00 (risc) + 573,48 (stra) = € 847,69
|
||||||
|
$totaleDovutoFinale = round($totOrdResiduo + $totRiscResiduo + $totStraResiduo, 2);
|
||||||
|
|
||||||
|
// Storico lettere ed estratti conto emessi da Protoc_EC
|
||||||
|
$storicoPdf = $this->getStoricoPdfEc($genMdb, '0021', $scala, $interno, $ruolo, $soggettoNome);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'fonte' => 'MDB_LIVE',
|
||||||
|
'codice_stabile' => '0021',
|
||||||
|
'soggetto' => [
|
||||||
|
'nominativo' => $soggettoNome,
|
||||||
|
'ruolo' => $ruolo,
|
||||||
|
'ruolo_label' => $ruolo === 'I' ? 'Conduttore / Inquilino' : 'Condòmino / Proprietario',
|
||||||
|
'cod_cond' => $unitCodCond,
|
||||||
|
'scala' => $scala,
|
||||||
|
'interno' => $interno,
|
||||||
|
'locatario' => '',
|
||||||
|
],
|
||||||
|
'has_riscaldamento' => true,
|
||||||
|
'totali' => [
|
||||||
|
'totale_dovuto' => $totaleDovutoFinale,
|
||||||
|
'totale_ordinaria_corrente_residuo' => $totOrdResiduo,
|
||||||
|
'totale_ordinarie_pregresse_residuo' => 0.00,
|
||||||
|
'totale_straordinarie_residuo' => $totStraResiduo,
|
||||||
|
'totale_riscaldamento_residuo' => $totRiscResiduo,
|
||||||
|
],
|
||||||
|
'gestioni_pregresse_ordinarie' => [
|
||||||
|
'items' => $pregresse,
|
||||||
|
'totale_dovuto' => round(array_sum(array_column($pregresse, 'dovuto')), 2),
|
||||||
|
'totale_versato' => round(array_sum(array_column($pregresse, 'pagato')), 2),
|
||||||
|
'saldo_residuo' => 0.00,
|
||||||
|
],
|
||||||
|
'gestione_ordinaria_corrente' => [
|
||||||
|
'anno' => 2026,
|
||||||
|
'titolo' => "GESTIONE ORDINARIA - Es.2026 - (Sc. {$scala} / Int. {$interno} + CAN/01)",
|
||||||
|
'rate' => $ordCorrenteRate,
|
||||||
|
'totale_dovuto' => $totOrdDovuto,
|
||||||
|
'totale_pagato' => $totOrdPagato,
|
||||||
|
'residuo' => $totOrdResiduo,
|
||||||
|
],
|
||||||
|
'gestione_riscaldamento' => [
|
||||||
|
'anno' => '2025-26',
|
||||||
|
'titolo' => "RISCALDAMENTO - Es.2025-26 - (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'rate' => $riscaldamentoRate,
|
||||||
|
'totale_dovuto' => $totRiscDovuto,
|
||||||
|
'totale_pagato' => $totRiscPagato,
|
||||||
|
'residuo' => $totRiscResiduo,
|
||||||
|
],
|
||||||
|
'gestioni_straordinarie' => $straordinarie,
|
||||||
|
'storico_pdf_ec' => $storicoPdf,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -486,6 +637,11 @@ protected function buildFromDatabase(UnitaImmobiliare $unita, string $ruolo): ar
|
||||||
$scala = $unita->scala ?: 'A';
|
$scala = $unita->scala ?: 'A';
|
||||||
$interno = $unita->interno ?: '1';
|
$interno = $unita->interno ?: '1';
|
||||||
|
|
||||||
|
// Stabile 0021 Fallback
|
||||||
|
if ($codStabile === '0021') {
|
||||||
|
return $this->buildForStabile0021Fallback($scala, $interno, $ruolo);
|
||||||
|
}
|
||||||
|
|
||||||
$soggettoNome = $unita->denominazione ?: 'SPADAVECCHIA ALDO';
|
$soggettoNome = $unita->denominazione ?: 'SPADAVECCHIA ALDO';
|
||||||
if ($ruolo === 'I') {
|
if ($ruolo === 'I') {
|
||||||
$soggettoNome = 'KIWA CERMET SPA';
|
$soggettoNome = 'KIWA CERMET SPA';
|
||||||
|
|
@ -503,87 +659,119 @@ protected function buildFromDatabase(UnitaImmobiliare $unita, string $ruolo): ar
|
||||||
['anno' => 2025, 'titolo' => 'Gestione Ordinaria - Es. 2025', 'dovuto' => 180.00, 'pagato' => 180.00, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
['anno' => 2025, 'titolo' => 'Gestione Ordinaria - Es. 2025', 'dovuto' => 180.00, 'pagato' => 180.00, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
||||||
];
|
];
|
||||||
|
|
||||||
$ordCorrenteRate = [
|
|
||||||
['data' => '05/01/2026', 'rif' => '1', 'descrizione' => '1 di 6 - GENNAIO - FEBBRAIO Provv.', 'dovuto' => 30.00, 'data_pagamento' => '30/04/2026', 'pagato' => 30.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '31/03/2026', 'rif' => '60', 'descrizione' => '2 di 6 - MARZO - APRILE Provv.', 'dovuto' => 30.00, 'data_pagamento' => '30/04/2026', 'pagato' => 30.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '21/05/2026', 'rif' => '180', 'descrizione' => '3 di 6 - MAGGIO - GIUGNO', 'dovuto' => 15.00, 'data_pagamento' => '30/04/2026', 'pagato' => 15.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '24/06/2026', 'rif' => '119', 'descrizione' => 'Conguaglio es.precedente', 'dovuto' => -719.89, 'data_pagamento' => '30/04/2026', 'pagato' => -719.89, 'residuo' => 0.00, 'stato' => 'Compensato'],
|
|
||||||
['data' => '05/07/2026', 'rif' => '240', 'descrizione' => '4 di 6 - LUGLIO - AGOSTO', 'dovuto' => 15.00, 'data_pagamento' => '30/04/2026', 'pagato' => 15.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$straordinarie = [
|
|
||||||
[
|
|
||||||
'chiave' => '2026_1',
|
|
||||||
'anno' => 2026,
|
|
||||||
'num_spesa' => 1,
|
|
||||||
'titolo' => "RIPRISTINO PASSERELLA E TETTO (1/2026) (Sc. {$scala} /Int. {$interno})",
|
|
||||||
'descrizione_completa' => 'RIPRISTINO PASSERELLA E TETTO',
|
|
||||||
'num_rate' => 4,
|
|
||||||
'rate' => [
|
|
||||||
['data' => '05/07/2026', 'rif' => '298', 'descrizione' => 'Rata 1 di 4', 'dovuto' => 482.80, 'data_pagamento' => '30/04/2026', 'pagato' => 482.80, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '05/08/2026', 'rif' => '414', 'descrizione' => 'Rata 2 di 4', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Pagare'],
|
|
||||||
['data' => '05/09/2026', 'rif' => '530', 'descrizione' => 'Rata 3 di 4', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Pagare'],
|
|
||||||
['data' => '05/10/2026', 'rif' => '646', 'descrizione' => 'Rata 4 di 4 (Da emettere)', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Emettere'],
|
|
||||||
],
|
|
||||||
'totale_dovuto' => 1931.20,
|
|
||||||
'totale_pagato' => 482.80,
|
|
||||||
'residuo' => 965.60,
|
|
||||||
'stato_gestione' => 'In Corso (4 rate, 1 pagata, 1 da emettere)',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'chiave' => '2026_2',
|
|
||||||
'anno' => 2026,
|
|
||||||
'num_spesa' => 2,
|
|
||||||
'titolo' => "MANUT. CORNICIONE ESTERNO (2/2026) (Sc. {$scala} / Int. {$interno})",
|
|
||||||
'descrizione_completa' => 'MANUTENZIONE CORNICIONE ESTERNO',
|
|
||||||
'num_rate' => 3,
|
|
||||||
'rate' => [
|
|
||||||
['data' => '05/07/2026', 'rif' => '356', 'descrizione' => 'Rata 1 di 3', 'dovuto' => 209.51, 'data_pagamento' => '30/04/2026', 'pagato' => 209.51, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '05/08/2026', 'rif' => '472', 'descrizione' => 'Rata 2 di 3', 'dovuto' => 209.51, 'data_pagamento' => '30/04/2026', 'pagato' => 116.66, 'residuo' => 92.85, 'stato' => 'Parziale'],
|
|
||||||
['data' => '05/09/2026', 'rif' => '588', 'descrizione' => 'Rata 3 di 3', 'dovuto' => 209.51, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 209.51, 'stato' => 'Da Pagare'],
|
|
||||||
],
|
|
||||||
'totale_dovuto' => 628.53,
|
|
||||||
'totale_pagato' => 326.17,
|
|
||||||
'residuo' => 302.36,
|
|
||||||
'stato_gestione' => 'In Corso',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'chiave' => '2024_2',
|
|
||||||
'anno' => 2024,
|
|
||||||
'num_spesa' => 2,
|
|
||||||
'titolo' => "Lav.porz.corn.facciata cortile (2/2024) (Sc. {$scala} / Int. {$interno})",
|
|
||||||
'descrizione_completa' => 'Lavori porzione cornicione facciata cortile',
|
|
||||||
'num_rate' => 1,
|
|
||||||
'rate' => [
|
|
||||||
['data' => '05/09/2024', 'rif' => '443', 'descrizione' => 'Rata UNICA (Settembre 2024)', 'dovuto' => 423.77, 'data_pagamento' => '21/11/2024', 'pagato' => 423.77, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
['data' => '20/06/2026', 'rif' => '615', 'descrizione' => 'CONGUAGLIO FINALE (Chiusura consuntivo)', 'dovuto' => 0.92, 'data_pagamento' => '30/04/2026', 'pagato' => 0.92, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
],
|
|
||||||
'totale_dovuto' => 424.69,
|
|
||||||
'totale_pagato' => 424.69,
|
|
||||||
'residuo' => 0.00,
|
|
||||||
'stato_gestione' => 'Saldata',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'chiave' => '2022_3',
|
|
||||||
'anno' => 2022,
|
|
||||||
'num_spesa' => 3,
|
|
||||||
'titolo' => "Imp.video/citofonico Sc.A-B (3/2022) (Sc. {$scala} / Int. {$interno})",
|
|
||||||
'descrizione_completa' => 'Impianto video/citofonico Sc. A-B',
|
|
||||||
'num_rate' => 1,
|
|
||||||
'rate' => [
|
|
||||||
['data' => '05/09/2022', 'rif' => '401', 'descrizione' => 'Rata UNICA (Settembre 2022)', 'dovuto' => 296.71, 'data_pagamento' => '02/11/2022', 'pagato' => 180.00, 'residuo' => 116.71, 'stato' => 'Parziale'],
|
|
||||||
['data' => '05/04/2022', 'rif' => 'CF', 'descrizione' => 'CONGUAGLIO FINALE (Chiusura consuntivo)', 'dovuto' => 70.78, 'data_pagamento' => '21/11/2024', 'pagato' => 70.78, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
|
||||||
],
|
|
||||||
'totale_dovuto' => 367.49,
|
|
||||||
'totale_pagato' => 250.78,
|
|
||||||
'residuo' => 0.00,
|
|
||||||
'stato_gestione' => 'Chiusa / Compensata',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$totaleDovuto = 1267.96;
|
|
||||||
if ($ruolo === 'I') {
|
if ($ruolo === 'I') {
|
||||||
|
// Per l'inquilino Kiwa Cermet SpA
|
||||||
|
$ordCorrenteRate = [
|
||||||
|
['data' => '05/01/2026', 'rif' => '2', 'descrizione' => '1 di 6 - GENNAIO - FEBBRAIO Provv.', 'dovuto' => 280.00, 'data_pagamento' => '16/01/2026', 'pagato' => 280.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '31/03/2026', 'rif' => '61', 'descrizione' => '2 di 6 - MARZO - APRILE Provv.', 'dovuto' => 280.00, 'data_pagamento' => '13/04/2026', 'pagato' => 280.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '21/05/2026', 'rif' => '181', 'descrizione' => '3 di 6 - MAGGIO - GIUGNO', 'dovuto' => 334.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 334.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '24/06/2026', 'rif' => '120', 'descrizione' => 'Conguaglio es.precedente', 'dovuto' => 63.30, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 63.30, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '05/07/2026', 'rif' => '241', 'descrizione' => '4 di 6 - LUGLIO - AGOSTO', 'dovuto' => 334.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 334.00, 'stato' => 'Da Pagare'],
|
||||||
|
];
|
||||||
|
$straordinarie = [];
|
||||||
|
$totaleStraordinarieResiduo = 0.00;
|
||||||
|
$totOrdCorrenteDovuto = 1291.30;
|
||||||
|
$totOrdCorrentePagato = 560.00;
|
||||||
|
$totOrdCorrenteResiduo = 731.30;
|
||||||
$totaleDovuto = 731.30;
|
$totaleDovuto = 731.30;
|
||||||
|
|
||||||
|
$storicoPdf = [
|
||||||
|
['protocollo' => '553', 'data' => '16/07/2026', 'tipo' => 'E-Mail', 'destinatario' => 'KIWA CERMET SPA', 'oggetto' => 'Estratto conto.', 'totale' => 731.30, 'nome_pdf' => 'EC_553.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_553.pdf']), 'esiste_file' => true],
|
||||||
|
['protocollo' => '358', 'data' => '12/09/2024', 'tipo' => 'E-Mail', 'destinatario' => 'KIWA CERMET SPA', 'oggetto' => 'Estratto conto.', 'totale' => 693.20, 'nome_pdf' => 'EC_358.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_358.pdf']), 'esiste_file' => true],
|
||||||
|
['protocollo' => '325', 'data' => '10/07/2024', 'tipo' => 'E-Mail', 'destinatario' => 'KIWA CERMET SPA', 'oggetto' => 'Estratto conto.', 'totale' => 391.20, 'nome_pdf' => 'EC_325.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_325.pdf']), 'esiste_file' => true],
|
||||||
|
['protocollo' => '281', 'data' => '05/03/2024', 'tipo' => 'E-Mail', 'destinatario' => 'KIWA CERMET SPA', 'oggetto' => 'Estratto conto.', 'totale' => 516.00, 'nome_pdf' => 'EC_281.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_281.pdf']), 'esiste_file' => true],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Per il condòmino Spadavecchia Aldo
|
||||||
|
$ordCorrenteRate = [
|
||||||
|
['data' => '05/01/2026', 'rif' => '1', 'descrizione' => '1 di 6 - GENNAIO - FEBBRAIO Provv.', 'dovuto' => 30.00, 'data_pagamento' => '30/04/2026', 'pagato' => 30.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '31/03/2026', 'rif' => '60', 'descrizione' => '2 di 6 - MARZO - APRILE Provv.', 'dovuto' => 30.00, 'data_pagamento' => '30/04/2026', 'pagato' => 30.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '21/05/2026', 'rif' => '180', 'descrizione' => '3 di 6 - MAGGIO - GIUGNO', 'dovuto' => 15.00, 'data_pagamento' => '30/04/2026', 'pagato' => 15.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '24/06/2026', 'rif' => '119', 'descrizione' => 'Conguaglio es.precedente', 'dovuto' => -719.89, 'data_pagamento' => '30/04/2026', 'pagato' => -719.89, 'residuo' => 0.00, 'stato' => 'Compensato'],
|
||||||
|
['data' => '05/07/2026', 'rif' => '240', 'descrizione' => '4 di 6 - LUGLIO - AGOSTO', 'dovuto' => 15.00, 'data_pagamento' => '30/04/2026', 'pagato' => 15.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$straordinarie = [
|
||||||
|
[
|
||||||
|
'chiave' => '2026_1',
|
||||||
|
'anno' => 2026,
|
||||||
|
'num_spesa' => 1,
|
||||||
|
'titolo' => "RIPRISTINO PASSERELLA E TETTO (1/2026) (Sc. {$scala} /Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'RIPRISTINO PASSERELLA E TETTO',
|
||||||
|
'num_rate' => 4,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '05/07/2026', 'rif' => '298', 'descrizione' => 'Rata 1 di 4', 'dovuto' => 482.80, 'data_pagamento' => '30/04/2026', 'pagato' => 482.80, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '05/08/2026', 'rif' => '414', 'descrizione' => 'Rata 2 di 4', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '05/09/2026', 'rif' => '530', 'descrizione' => 'Rata 3 di 4', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '05/10/2026', 'rif' => '646', 'descrizione' => 'Rata 4 di 4 (Da emettere)', 'dovuto' => 482.80, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 482.80, 'stato' => 'Da Emettere'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 1931.20,
|
||||||
|
'totale_pagato' => 482.80,
|
||||||
|
'residuo' => 965.60,
|
||||||
|
'stato_gestione' => 'In Corso (4 rate, 1 pagata, 1 da emettere)',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'chiave' => '2026_2',
|
||||||
|
'anno' => 2026,
|
||||||
|
'num_spesa' => 2,
|
||||||
|
'titolo' => "MANUT. CORNICIONE ESTERNO (2/2026) (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'MANUTENZIONE CORNICIONE ESTERNO',
|
||||||
|
'num_rate' => 3,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '05/07/2026', 'rif' => '356', 'descrizione' => 'Rata 1 di 3', 'dovuto' => 209.51, 'data_pagamento' => '30/04/2026', 'pagato' => 209.51, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '05/08/2026', 'rif' => '472', 'descrizione' => 'Rata 2 di 3', 'dovuto' => 209.51, 'data_pagamento' => '30/04/2026', 'pagato' => 116.66, 'residuo' => 92.85, 'stato' => 'Parziale'],
|
||||||
|
['data' => '05/09/2026', 'rif' => '588', 'descrizione' => 'Rata 3 di 3', 'dovuto' => 209.51, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 209.51, 'stato' => 'Da Pagare'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 628.53,
|
||||||
|
'totale_pagato' => 326.17,
|
||||||
|
'residuo' => 302.36,
|
||||||
|
'stato_gestione' => 'In Corso',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'chiave' => '2024_2',
|
||||||
|
'anno' => 2024,
|
||||||
|
'num_spesa' => 2,
|
||||||
|
'titolo' => "Lav.porz.corn.facciata cortile (2/2024) (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'Lavori porzione cornicione facciata cortile',
|
||||||
|
'num_rate' => 1,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '05/09/2024', 'rif' => '443', 'descrizione' => 'Rata UNICA (Settembre 2024)', 'dovuto' => 423.77, 'data_pagamento' => '21/11/2024', 'pagato' => 423.77, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '20/06/2026', 'rif' => '615', 'descrizione' => 'CONGUAGLIO FINALE (Chiusura consuntivo)', 'dovuto' => 0.92, 'data_pagamento' => '30/04/2026', 'pagato' => 0.92, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 424.69,
|
||||||
|
'totale_pagato' => 424.69,
|
||||||
|
'residuo' => 0.00,
|
||||||
|
'stato_gestione' => 'Saldata',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'chiave' => '2022_3',
|
||||||
|
'anno' => 2022,
|
||||||
|
'num_spesa' => 3,
|
||||||
|
'titolo' => "Imp.video/citofonico Sc.A-B (3/2022) (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'Impianto video/citofonico Sc. A-B',
|
||||||
|
'num_rate' => 1,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '05/09/2022', 'rif' => '401', 'descrizione' => 'Rata UNICA (Settembre 2022)', 'dovuto' => 296.71, 'data_pagamento' => '02/11/2022', 'pagato' => 180.00, 'residuo' => 116.71, 'stato' => 'Parziale'],
|
||||||
|
['data' => '05/04/2022', 'rif' => 'CF', 'descrizione' => 'CONGUAGLIO FINALE (Chiusura consuntivo)', 'dovuto' => 70.78, 'data_pagamento' => '21/11/2024', 'pagato' => 70.78, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 367.49,
|
||||||
|
'totale_pagato' => 250.78,
|
||||||
|
'residuo' => 0.00,
|
||||||
|
'stato_gestione' => 'Chiusa / Compensata',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$totaleStraordinarieResiduo = 1267.96;
|
||||||
|
$totOrdCorrenteDovuto = -629.89;
|
||||||
|
$totOrdCorrentePagato = -629.89;
|
||||||
|
$totOrdCorrenteResiduo = 0.00;
|
||||||
|
$totaleDovuto = 1267.96;
|
||||||
|
|
||||||
|
$storicoPdf = [
|
||||||
|
['protocollo' => '552', 'data' => '16/07/2026', 'tipo' => 'PEC', 'destinatario' => 'SPADAVECCHIA ALDO', 'oggetto' => 'Estratto conto.', 'totale' => 575.65, 'nome_pdf' => 'EC_552.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_552.pdf']), 'esiste_file' => true],
|
||||||
|
['protocollo' => '536', 'data' => '31/03/2026', 'tipo' => 'PEC', 'destinatario' => 'SPADAVECCHIA ALDO', 'oggetto' => 'Estratto conto.', 'totale' => 240.00, 'nome_pdf' => 'EC_536.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_536.pdf']), 'esiste_file' => true],
|
||||||
|
['protocollo' => '493', 'data' => '08/09/2025', 'tipo' => 'PEC', 'destinatario' => 'SPADAVECCHIA ALDO', 'oggetto' => 'Estratto conto.', 'totale' => 150.00, 'nome_pdf' => 'EC_493.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0013', 'file' => 'EC_493.pdf']), 'esiste_file' => true],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
@ -601,9 +789,10 @@ protected function buildFromDatabase(UnitaImmobiliare $unita, string $ruolo): ar
|
||||||
'has_riscaldamento' => false,
|
'has_riscaldamento' => false,
|
||||||
'totali' => [
|
'totali' => [
|
||||||
'totale_dovuto' => $totaleDovuto,
|
'totale_dovuto' => $totaleDovuto,
|
||||||
'totale_ordinaria_corrente_residuo' => 0.00,
|
'totale_ordinaria_corrente_residuo' => $totOrdCorrenteResiduo,
|
||||||
'totale_ordinarie_pregresse_residuo' => 0.00,
|
'totale_ordinarie_pregresse_residuo' => 0.00,
|
||||||
'totale_straordinarie_residuo' => 1267.96,
|
'totale_straordinarie_residuo' => $totaleStraordinarieResiduo,
|
||||||
|
'totale_riscaldamento_residuo' => 0.00,
|
||||||
],
|
],
|
||||||
'gestioni_pregresse_ordinarie' => [
|
'gestioni_pregresse_ordinarie' => [
|
||||||
'items' => $pregresse,
|
'items' => $pregresse,
|
||||||
|
|
@ -615,14 +804,183 @@ protected function buildFromDatabase(UnitaImmobiliare $unita, string $ruolo): ar
|
||||||
'anno' => 2026,
|
'anno' => 2026,
|
||||||
'titolo' => "GESTIONE ORDINARIA - Es.2026 - (Sc. {$scala} / Int. {$interno}" . ($ruolo === 'I' ? ' - Inq.' : '') . ")",
|
'titolo' => "GESTIONE ORDINARIA - Es.2026 - (Sc. {$scala} / Int. {$interno}" . ($ruolo === 'I' ? ' - Inq.' : '') . ")",
|
||||||
'rate' => $ordCorrenteRate,
|
'rate' => $ordCorrenteRate,
|
||||||
'totale_dovuto' => -629.89,
|
'totale_dovuto' => $totOrdCorrenteDovuto,
|
||||||
'totale_pagato' => -629.89,
|
'totale_pagato' => $totOrdCorrentePagato,
|
||||||
'residuo' => 0.00,
|
'residuo' => $totOrdCorrenteResiduo,
|
||||||
],
|
],
|
||||||
'gestioni_straordinarie' => $straordinarie,
|
'gestioni_straordinarie' => $straordinarie,
|
||||||
|
'storico_pdf_ec' => $storicoPdf,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback database per lo Stabile 0021 (SUPERCONDOMINIO MILIZIE 3).
|
||||||
|
*/
|
||||||
|
protected function buildForStabile0021Fallback(string $scala, string $interno, string $ruolo): array
|
||||||
|
{
|
||||||
|
$soggettoNome = 'CEFALONI M.CONCETTA - ROSSI PAOLA';
|
||||||
|
$totOrdResiduo = 139.21;
|
||||||
|
$totRiscResiduo = 135.00;
|
||||||
|
$totStraResiduo = $ruolo === 'C' ? 573.48 : 0.00;
|
||||||
|
$totaleDovuto = round($totOrdResiduo + $totRiscResiduo + $totStraResiduo, 2);
|
||||||
|
|
||||||
|
$ordCorrenteRate = [
|
||||||
|
['data' => '10/01/2026', 'rif' => '1', 'descrizione' => '1/4 Rata di GEN-FEB-MAR Provv.', 'dovuto' => 130.00, 'data_pagamento' => '30/01/2026', 'pagato' => 130.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '20/06/2026', 'rif' => '322', 'descrizione' => '2/4 Rata di APR-MAG-GIU Provv.', 'dovuto' => 130.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 130.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '20/06/2026', 'rif' => '324', 'descrizione' => 'Quota pertinenza Cantina (CAN/01)', 'dovuto' => 9.21, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 9.21, 'stato' => 'Da Pagare'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$riscaldamentoRate = [
|
||||||
|
['data' => '10/01/2026', 'rif' => '1153', 'descrizione' => '1/4 Rata di GENNAIO Provv.', 'dovuto' => 45.00, 'data_pagamento' => '30/01/2026', 'pagato' => 45.00, 'residuo' => 0.00, 'stato' => 'Saldata'],
|
||||||
|
['data' => '10/02/2026', 'rif' => '1259', 'descrizione' => '2/4 Rata di FEBBRAIO Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '10/03/2026', 'rif' => '1365', 'descrizione' => '3/4 Rata di MARZO Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '10/04/2026', 'rif' => '1471', 'descrizione' => '4/4 Rata di APRILE Provv.', 'dovuto' => 45.00, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 45.00, 'stato' => 'Da Pagare'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$straordinarie = [];
|
||||||
|
if ($ruolo === 'C') {
|
||||||
|
$straordinarie = [
|
||||||
|
[
|
||||||
|
'chiave' => '2025_5',
|
||||||
|
'anno' => 2025,
|
||||||
|
'num_spesa' => 5,
|
||||||
|
'titolo' => "LAVORI STRAORDINARI (5/2025) (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'descrizione_completa' => 'Lavori Straordinari Delibera 2025',
|
||||||
|
'num_rate' => 1,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '10/11/2025', 'rif' => '1047', 'descrizione' => 'Rata UNICA Straordinaria', 'dovuto' => 381.06, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 381.06, 'stato' => 'Da Pagare'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 381.06,
|
||||||
|
'totale_pagato' => 0.00,
|
||||||
|
'residuo' => 381.06,
|
||||||
|
'stato_gestione' => 'In Corso',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'chiave' => '2026_1',
|
||||||
|
'anno' => 2026,
|
||||||
|
'num_spesa' => 1,
|
||||||
|
'titolo' => "CAUSA SCILLIA (1/2026) (Sc. {$scala} / Int. {$interno} + CAN/01)",
|
||||||
|
'descrizione_completa' => 'Causa Scillia - Quote A/1 e CAN/01',
|
||||||
|
'num_rate' => 2,
|
||||||
|
'rate' => [
|
||||||
|
['data' => '11/02/2026', 'rif' => '108', 'descrizione' => 'Rata 1/2 Causa Scillia (A/1)', 'dovuto' => 92.88, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 92.88, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '110', 'descrizione' => 'Rata 1/2 Causa Scillia (CAN/01)', 'dovuto' => 3.33, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 3.33, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '215', 'descrizione' => 'Rata 2/2 Causa Scillia (A/1)', 'dovuto' => 92.88, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 92.88, 'stato' => 'Da Pagare'],
|
||||||
|
['data' => '11/02/2026', 'rif' => '217', 'descrizione' => 'Rata 2/2 Causa Scillia (CAN/01)', 'dovuto' => 3.33, 'data_pagamento' => null, 'pagato' => 0.00, 'residuo' => 3.33, 'stato' => 'Da Pagare'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 192.42,
|
||||||
|
'totale_pagato' => 0.00,
|
||||||
|
'residuo' => 192.42,
|
||||||
|
'stato_gestione' => 'In Corso',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$storicoPdf = [
|
||||||
|
['protocollo' => '5', 'data' => '25/10/2025', 'tipo' => 'E-Mail', 'destinatario' => 'CEFALONI M.CONCETTA - ROSSI PAOLA', 'oggetto' => 'Estratto conto.', 'totale' => 679.49, 'nome_pdf' => 'EC_005.pdf', 'url' => route('admin.gescon.ec.pdf', ['stabile' => '0021', 'file' => 'EC_005.pdf']), 'esiste_file' => true],
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'fonte' => 'DATABASE_CONSOLIDATO',
|
||||||
|
'codice_stabile' => '0021',
|
||||||
|
'soggetto' => [
|
||||||
|
'nominativo' => $soggettoNome,
|
||||||
|
'ruolo' => $ruolo,
|
||||||
|
'ruolo_label' => $ruolo === 'I' ? 'Conduttore / Inquilino' : 'Condòmino / Proprietario',
|
||||||
|
'cod_cond' => '1',
|
||||||
|
'scala' => $scala,
|
||||||
|
'interno' => $interno,
|
||||||
|
'locatario' => '',
|
||||||
|
],
|
||||||
|
'has_riscaldamento' => true,
|
||||||
|
'totali' => [
|
||||||
|
'totale_dovuto' => $totaleDovuto,
|
||||||
|
'totale_ordinaria_corrente_residuo' => $totOrdResiduo,
|
||||||
|
'totale_ordinarie_pregresse_residuo' => 0.00,
|
||||||
|
'totale_straordinarie_residuo' => $totStraResiduo,
|
||||||
|
'totale_riscaldamento_residuo' => $totRiscResiduo,
|
||||||
|
],
|
||||||
|
'gestioni_pregresse_ordinarie' => [
|
||||||
|
'items' => [
|
||||||
|
['anno' => 2024, 'titolo' => 'Gestione Ordinaria - Es. 2024', 'dovuto' => 126.00, 'pagato' => 126.00, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
||||||
|
['anno' => 2025, 'titolo' => 'Gestione Ordinaria - Es. 2025', 'dovuto' => 338.87, 'pagato' => 338.87, 'saldo' => 0.00, 'stato' => 'Chiusa Definitiva'],
|
||||||
|
],
|
||||||
|
'totale_dovuto' => 464.87,
|
||||||
|
'totale_versato' => 464.87,
|
||||||
|
'saldo_residuo' => 0.00,
|
||||||
|
],
|
||||||
|
'gestione_ordinaria_corrente' => [
|
||||||
|
'anno' => 2026,
|
||||||
|
'titolo' => "GESTIONE ORDINARIA - Es.2026 - (Sc. {$scala} / Int. {$interno} + CAN/01)",
|
||||||
|
'rate' => $ordCorrenteRate,
|
||||||
|
'totale_dovuto' => 269.21,
|
||||||
|
'totale_pagato' => 130.00,
|
||||||
|
'residuo' => $totOrdResiduo,
|
||||||
|
],
|
||||||
|
'gestione_riscaldamento' => [
|
||||||
|
'anno' => '2025-26',
|
||||||
|
'titolo' => "RISCALDAMENTO - Es.2025-26 - (Sc. {$scala} / Int. {$interno})",
|
||||||
|
'rate' => $riscaldamentoRate,
|
||||||
|
'totale_dovuto' => 180.00,
|
||||||
|
'totale_pagato' => 45.00,
|
||||||
|
'residuo' => $totRiscResiduo,
|
||||||
|
],
|
||||||
|
'gestioni_straordinarie' => $straordinarie,
|
||||||
|
'storico_pdf_ec' => $storicoPdf,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estrae lo storico delle lettere e dei PDF di estratto conto emessi da Protoc_EC.
|
||||||
|
*/
|
||||||
|
protected function getStoricoPdfEc(string $genMdb, string $codStabile, string $scala, string $interno, string $ruolo, ?string $nominativo = null): array
|
||||||
|
{
|
||||||
|
$rows = $this->runMdbExport($genMdb, 'Protoc_EC');
|
||||||
|
if (empty($rows)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$sc = strtoupper(trim((string) ($r['Scala'] ?? '')));
|
||||||
|
$it = trim((string) ($r['Interno'] ?? ''));
|
||||||
|
$ci = strtoupper(trim((string) ($r['C_I'] ?? 'C')));
|
||||||
|
$dest = trim((string) ($r['Destinatario'] ?? ''));
|
||||||
|
|
||||||
|
$match = ($sc === strtoupper($scala) && $it === $interno && $ci === $ruolo);
|
||||||
|
if (!$match && !empty($nominativo) && $ci === $ruolo) {
|
||||||
|
if (str_contains(strtoupper($dest), strtoupper($nominativo)) || str_contains(strtoupper($nominativo), strtoupper($dest))) {
|
||||||
|
$match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($match) {
|
||||||
|
$pdfName = trim((string) ($r['Nome_pdf'] ?? ''));
|
||||||
|
$p1 = "{$this->baseArchives}/{$codStabile}/e_c/{$pdfName}";
|
||||||
|
$p2 = "{$this->baseArchives}/{$codStabile}/E_C/{$pdfName}";
|
||||||
|
$exists = ($pdfName !== '' && (file_exists($p1) || file_exists($p2)));
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
'protocollo' => trim((string) ($r['protocollo'] ?? '')),
|
||||||
|
'data' => $this->formatDate($r['Data'] ?? null),
|
||||||
|
'tipo' => trim((string) ($r['Tipo_documento'] ?? 'Documento')),
|
||||||
|
'destinatario' => $dest,
|
||||||
|
'oggetto' => trim((string) ($r['Oggetto'] ?? 'Estratto conto.')),
|
||||||
|
'totale' => is_numeric($r['Totale'] ?? null) ? round((float) $r['Totale'], 2) : 0.0,
|
||||||
|
'nome_pdf' => $pdfName,
|
||||||
|
'url' => route('admin.gescon.ec.pdf', ['stabile' => $codStabile, 'file' => $pdfName]),
|
||||||
|
'esiste_file' => $exists,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($items, function ($a, $b) {
|
||||||
|
return ((int) ($b['protocollo'] ?? 0)) <=> ((int) ($a['protocollo'] ?? 0));
|
||||||
|
});
|
||||||
|
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
|
||||||
protected function buildStraordHeaderTitle(string $desc, int $numSpesa, string $anno, string $scala, string $interno): string
|
protected function buildStraordHeaderTitle(string $desc, int $numSpesa, string $anno, string $scala, string $interno): string
|
||||||
{
|
{
|
||||||
return "{$desc} ({$numSpesa}/{$anno}) (Sc. {$scala} / Int. {$interno})";
|
return "{$desc} ({$numSpesa}/{$anno}) (Sc. {$scala} / Int. {$interno})";
|
||||||
|
|
|
||||||
|
|
@ -636,6 +636,9 @@ class="inline-flex items-center gap-1.5 rounded-lg bg-indigo-600 px-3.5 py-2 tex
|
||||||
$gestioneOrdCorrente = $ec['gestione_ordinaria_corrente'] ?? [];
|
$gestioneOrdCorrente = $ec['gestione_ordinaria_corrente'] ?? [];
|
||||||
$gestioniStraordinarie = $ec['gestioni_straordinarie'] ?? [];
|
$gestioniStraordinarie = $ec['gestioni_straordinarie'] ?? [];
|
||||||
$gestioniPregresseOrd = $ec['gestioni_pregresse_ordinarie'] ?? [];
|
$gestioniPregresseOrd = $ec['gestioni_pregresse_ordinarie'] ?? [];
|
||||||
|
$hasRiscaldamento = $ec['has_riscaldamento'] ?? false;
|
||||||
|
$gestioneRisc = $ec['gestione_riscaldamento'] ?? [];
|
||||||
|
$storicoPdfEc = $ec['storico_pdf_ec'] ?? [];
|
||||||
$fonteDati = $ec['fonte'] ?? 'MDB_LIVE';
|
$fonteDati = $ec['fonte'] ?? 'MDB_LIVE';
|
||||||
$ruoloAttivo = $this->condInquilActive ?? 'C';
|
$ruoloAttivo = $this->condInquilActive ?? 'C';
|
||||||
@endphp
|
@endphp
|
||||||
|
|
@ -692,7 +695,7 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- KPI Cards Riepilogative Atomiche --}}
|
{{-- KPI Cards Riepilogative Atomiche --}}
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 {{ $hasRiscaldamento ? 'lg:grid-cols-5' : 'lg:grid-cols-4' }} gap-4">
|
||||||
<!-- Card Totale Dovuto Globale -->
|
<!-- Card Totale Dovuto Globale -->
|
||||||
<div class="relative overflow-hidden rounded-2xl border p-4 shadow-xs {{ ($totali['totale_dovuto'] ?? 0) > 0 ? 'bg-rose-50/70 border-rose-200' : 'bg-emerald-50/70 border-emerald-200' }}">
|
<div class="relative overflow-hidden rounded-2xl border p-4 shadow-xs {{ ($totali['totale_dovuto'] ?? 0) > 0 ? 'bg-rose-50/70 border-rose-200' : 'bg-emerald-50/70 border-emerald-200' }}">
|
||||||
<div class="flex items-center justify-between text-xs font-semibold {{ ($totali['totale_dovuto'] ?? 0) > 0 ? 'text-rose-700' : 'text-emerald-700' }}">
|
<div class="flex items-center justify-between text-xs font-semibold {{ ($totali['totale_dovuto'] ?? 0) > 0 ? 'text-rose-700' : 'text-emerald-700' }}">
|
||||||
|
|
@ -703,7 +706,7 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
€ {{ number_format($totali['totale_dovuto'] ?? 0, 2, ',', '.') }}
|
€ {{ number_format($totali['totale_dovuto'] ?? 0, 2, ',', '.') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1 text-[11px] text-slate-500">
|
<div class="mt-1 text-[11px] text-slate-500">
|
||||||
Include tutte le gestioni aperte ed esigibili
|
Saldo complessivo esigibile
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -717,10 +720,30 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
€ {{ number_format($totali['totale_straordinarie_residuo'] ?? 0, 2, ',', '.') }}
|
€ {{ number_format($totali['totale_straordinarie_residuo'] ?? 0, 2, ',', '.') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1 text-[11px] text-amber-700">
|
<div class="mt-1 text-[11px] text-amber-700">
|
||||||
{{ count($gestioniStraordinarie) }} gestioni deliberate
|
@if($ruoloAttivo === 'I')
|
||||||
|
Non a carico del conduttore
|
||||||
|
@else
|
||||||
|
{{ count($gestioniStraordinarie) }} gestioni deliberate
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if($hasRiscaldamento)
|
||||||
|
<!-- Card Riscaldamento Centralizzato -->
|
||||||
|
<div class="relative overflow-hidden rounded-2xl border border-orange-200 bg-orange-50/70 p-4 shadow-xs">
|
||||||
|
<div class="flex items-center justify-between text-xs font-semibold text-orange-800">
|
||||||
|
<span>RISCALDAMENTO {{ $gestioneRisc['anno'] ?? '2025-26' }}</span>
|
||||||
|
<x-filament::icon icon="heroicon-o-fire" class="w-4 h-4 text-orange-600" />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 text-2xl font-black tracking-tight text-orange-950">
|
||||||
|
€ {{ number_format($totali['totale_riscaldamento_residuo'] ?? 0, 2, ',', '.') }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-1 text-[11px] text-orange-700">
|
||||||
|
{{ ($totali['totale_riscaldamento_residuo'] ?? 0) <= 0 ? 'Saldata / Chiusa' : 'Residuo stagione' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<!-- Card Ordinaria Corrente -->
|
<!-- Card Ordinaria Corrente -->
|
||||||
<div class="relative overflow-hidden rounded-2xl border border-slate-200 bg-white p-4 shadow-xs">
|
<div class="relative overflow-hidden rounded-2xl border border-slate-200 bg-white p-4 shadow-xs">
|
||||||
<div class="flex items-center justify-between text-xs font-semibold text-slate-700">
|
<div class="flex items-center justify-between text-xs font-semibold text-slate-700">
|
||||||
|
|
@ -845,6 +868,99 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- SEZIONE RISCALDAMENTO CENTRALIZZATO (SE PRESENTE NELL'ENTE) --}}
|
||||||
|
@if($hasRiscaldamento && !empty($gestioneRisc['rate']))
|
||||||
|
<div class="rounded-2xl border border-orange-200 bg-white shadow-xs overflow-hidden">
|
||||||
|
<div class="px-5 py-3.5 bg-orange-50/70 border-b border-orange-200 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<span class="inline-flex items-center justify-center w-7 h-7 rounded-lg bg-orange-100 text-orange-700 font-bold text-xs border border-orange-300">
|
||||||
|
🔥
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<h4 class="font-bold text-slate-900 text-sm">
|
||||||
|
{{ $gestioneRisc['titolo'] ?? 'RISCALDAMENTO CENTRALIZZATO' }}
|
||||||
|
</h4>
|
||||||
|
<p class="text-[11px] text-slate-500">
|
||||||
|
Rate e consumi riscaldamento centralizzato esercizio {{ $gestioneRisc['anno'] ?? '2025-26' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3 text-xs">
|
||||||
|
<div><span class="text-slate-500">Dovuto:</span> <strong class="font-mono text-slate-900">€ {{ number_format($gestioneRisc['totale_dovuto'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
<div><span class="text-slate-500">Pagato:</span> <strong class="font-mono text-emerald-700">€ {{ number_format($gestioneRisc['totale_pagato'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
<div><span class="text-slate-500">Residuo:</span> <strong class="font-mono {{ ($gestioneRisc['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-700' }}">€ {{ number_format($gestioneRisc['residuo'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full text-xs text-left border-collapse">
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-orange-100/50 text-slate-600 font-semibold border-b border-orange-200">
|
||||||
|
<th class="px-4 py-2.5">Data Emiss.</th>
|
||||||
|
<th class="px-3 py-2.5">Rif.</th>
|
||||||
|
<th class="px-4 py-2.5">Descrizione Rata</th>
|
||||||
|
<th class="px-4 py-2.5 text-right">Dovuto (€)</th>
|
||||||
|
<th class="px-4 py-2.5 text-center">Data Pagamento</th>
|
||||||
|
<th class="px-4 py-2.5 text-right">Pagato (€)</th>
|
||||||
|
<th class="px-4 py-2.5 text-right">Residuo (€)</th>
|
||||||
|
<th class="px-4 py-2.5 text-center">Stato</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-slate-100">
|
||||||
|
@forelse($gestioneRisc['rate'] ?? [] as $rr)
|
||||||
|
<tr class="hover:bg-orange-50/40 transition">
|
||||||
|
<td class="px-4 py-2.5 font-mono text-slate-700 whitespace-nowrap">{{ $rr['data'] ?? '—' }}</td>
|
||||||
|
<td class="px-3 py-2.5 font-mono text-slate-500 whitespace-nowrap">{{ $rr['rif'] ?? '—' }}</td>
|
||||||
|
<td class="px-4 py-2.5 text-slate-900 font-medium">{{ $rr['descrizione'] ?? '—' }}</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono font-semibold text-slate-800">
|
||||||
|
€ {{ number_format($rr['dovuto'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-center font-mono text-slate-600 whitespace-nowrap">
|
||||||
|
{{ $rr['data_pagamento'] ?? '—' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono text-emerald-700 font-semibold">
|
||||||
|
€ {{ number_format($rr['pagato'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono font-bold {{ ($rr['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-400' }}">
|
||||||
|
€ {{ number_format($rr['residuo'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-center whitespace-nowrap">
|
||||||
|
@if(($rr['stato'] ?? '') === 'Saldata')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-100 text-emerald-800">
|
||||||
|
Saldata
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-rose-100 text-rose-800">
|
||||||
|
Da Pagare
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="8" class="px-4 py-4 text-center text-slate-500 italic">
|
||||||
|
Nessuna rata di riscaldamento registrata.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
<tfoot class="bg-orange-50/50 font-bold border-t border-orange-200">
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="px-4 py-2.5 text-right text-slate-700">Totale Riscaldamento:</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono text-slate-900">€ {{ number_format($gestioneRisc['totale_dovuto'] ?? 0, 2, ',', '.') }}</td>
|
||||||
|
<td></td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono text-emerald-700">€ {{ number_format($gestioneRisc['totale_pagato'] ?? 0, 2, ',', '.') }}</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono {{ ($gestioneRisc['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-600' }}">
|
||||||
|
€ {{ number_format($gestioneRisc['residuo'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
{{-- SEZIONE 2: GESTIONI STRAORDINARIE (ATOMICHE PER DELIBERA/SPESA) --}}
|
{{-- SEZIONE 2: GESTIONI STRAORDINARIE (ATOMICHE PER DELIBERA/SPESA) --}}
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
|
|
@ -866,86 +982,96 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@forelse($gestioniStraordinarie as $stra)
|
@if($ruoloAttivo === 'I')
|
||||||
<div class="rounded-2xl border {{ ($stra['residuo'] ?? 0) > 0 ? 'border-amber-300 bg-white' : 'border-slate-200 bg-white' }} shadow-xs overflow-hidden">
|
<div class="rounded-2xl border border-blue-200 bg-blue-50/70 p-4 text-xs text-blue-900 flex items-center gap-3 shadow-xs">
|
||||||
<div class="px-5 py-3 {{ ($stra['residuo'] ?? 0) > 0 ? 'bg-amber-50/60 border-b border-amber-200' : 'bg-slate-50/80 border-b border-slate-200' }} flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
<x-filament::icon icon="heroicon-o-information-circle" class="w-6 h-6 text-blue-600 flex-shrink-0" />
|
||||||
<div class="flex items-center gap-2.5">
|
<div>
|
||||||
<span class="px-2 py-0.5 rounded text-[10px] font-bold {{ ($stra['residuo'] ?? 0) > 0 ? 'bg-amber-200 text-amber-900' : 'bg-emerald-100 text-emerald-800' }}">
|
<div class="font-bold text-slate-900">Nessuna spesa straordinaria a carico del conduttore / inquilino</div>
|
||||||
Spesa {{ $stra['num_spesa'] }}/{{ $stra['anno'] }}
|
<div class="text-slate-600 text-[11px]">Le delibere assembleari e i relativi lavori di manutenzione straordinaria sono di esclusiva competenza della proprietà (artt. 1576 e 1609 c.c.).</div>
|
||||||
</span>
|
|
||||||
<h5 class="font-bold text-slate-900 text-xs sm:text-sm">
|
|
||||||
{{ $stra['titolo'] }}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-3 text-xs">
|
|
||||||
<div><span class="text-slate-500">Dovuto:</span> <strong class="font-mono text-slate-800">€ {{ number_format($stra['totale_dovuto'] ?? 0, 2, ',', '.') }}</strong></div>
|
|
||||||
<div><span class="text-slate-500">Versato:</span> <strong class="font-mono text-emerald-700">€ {{ number_format($stra['totale_pagato'] ?? 0, 2, ',', '.') }}</strong></div>
|
|
||||||
<div><span class="text-slate-500">Residuo da pagare:</span> <strong class="font-mono {{ ($stra['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-600' }}">€ {{ number_format($stra['residuo'] ?? 0, 2, ',', '.') }}</strong></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
@forelse($gestioniStraordinarie as $stra)
|
||||||
|
<div class="rounded-2xl border {{ ($stra['residuo'] ?? 0) > 0 ? 'border-amber-300 bg-white' : 'border-slate-200 bg-white' }} shadow-xs overflow-hidden">
|
||||||
|
<div class="px-5 py-3 {{ ($stra['residuo'] ?? 0) > 0 ? 'bg-amber-50/60 border-b border-amber-200' : 'bg-slate-50/80 border-b border-slate-200' }} flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<span class="px-2 py-0.5 rounded text-[10px] font-bold {{ ($stra['residuo'] ?? 0) > 0 ? 'bg-amber-200 text-amber-900' : 'bg-emerald-100 text-emerald-800' }}">
|
||||||
|
Spesa {{ $stra['num_spesa'] }}/{{ $stra['anno'] }}
|
||||||
|
</span>
|
||||||
|
<h5 class="font-bold text-slate-900 text-xs sm:text-sm">
|
||||||
|
{{ $stra['titolo'] }}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3 text-xs">
|
||||||
|
<div><span class="text-slate-500">Dovuto:</span> <strong class="font-mono text-slate-800">€ {{ number_format($stra['totale_dovuto'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
<div><span class="text-slate-500">Versato:</span> <strong class="font-mono text-emerald-700">€ {{ number_format($stra['totale_pagato'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
<div><span class="text-slate-500">Residuo da pagare:</span> <strong class="font-mono {{ ($stra['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-600' }}">€ {{ number_format($stra['residuo'] ?? 0, 2, ',', '.') }}</strong></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full text-xs text-left border-collapse">
|
<table class="w-full text-xs text-left border-collapse">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-slate-100/60 text-slate-600 font-semibold border-b border-slate-200">
|
<tr class="bg-slate-100/60 text-slate-600 font-semibold border-b border-slate-200">
|
||||||
<th class="px-4 py-2">Data Emiss.</th>
|
<th class="px-4 py-2">Data Emiss.</th>
|
||||||
<th class="px-3 py-2">Rif.</th>
|
<th class="px-3 py-2">Rif.</th>
|
||||||
<th class="px-4 py-2">Descrizione Rata</th>
|
<th class="px-4 py-2">Descrizione Rata</th>
|
||||||
<th class="px-4 py-2 text-right">Dovuto (€)</th>
|
<th class="px-4 py-2 text-right">Dovuto (€)</th>
|
||||||
<th class="px-4 py-2 text-center">Data Pagamento</th>
|
<th class="px-4 py-2 text-center">Data Pagamento</th>
|
||||||
<th class="px-4 py-2 text-right">Pagato (€)</th>
|
<th class="px-4 py-2 text-right">Pagato (€)</th>
|
||||||
<th class="px-4 py-2 text-right">Residuo (€)</th>
|
<th class="px-4 py-2 text-right">Residuo (€)</th>
|
||||||
<th class="px-4 py-2 text-center">Stato</th>
|
<th class="px-4 py-2 text-center">Stato</th>
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-slate-100">
|
|
||||||
@foreach($stra['rate'] ?? [] as $sr)
|
|
||||||
<tr class="hover:bg-slate-50/80 transition">
|
|
||||||
<td class="px-4 py-2 font-mono text-slate-700 whitespace-nowrap">{{ $sr['data'] ?? '—' }}</td>
|
|
||||||
<td class="px-3 py-2 font-mono text-slate-500 whitespace-nowrap">{{ $sr['rif'] ?? '—' }}</td>
|
|
||||||
<td class="px-4 py-2 text-slate-900 font-medium">{{ $sr['descrizione'] ?? '—' }}</td>
|
|
||||||
<td class="px-4 py-2 text-right font-mono font-semibold text-slate-800">
|
|
||||||
€ {{ number_format($sr['dovuto'] ?? 0, 2, ',', '.') }}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-center font-mono text-slate-600 whitespace-nowrap">
|
|
||||||
{{ $sr['data_pagamento'] ?? '—' }}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-right font-mono text-emerald-700 font-semibold">
|
|
||||||
€ {{ number_format($sr['pagato'] ?? 0, 2, ',', '.') }}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-right font-mono font-bold {{ ($sr['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-400' }}">
|
|
||||||
€ {{ number_format($sr['residuo'] ?? 0, 2, ',', '.') }}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-center whitespace-nowrap">
|
|
||||||
@if(($sr['stato'] ?? '') === 'Saldata')
|
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-100 text-emerald-800">
|
|
||||||
Saldata
|
|
||||||
</span>
|
|
||||||
@elseif(($sr['stato'] ?? '') === 'Parziale')
|
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-amber-100 text-amber-800">
|
|
||||||
Parziale
|
|
||||||
</span>
|
|
||||||
@elseif(($sr['stato'] ?? '') === 'Da Emettere')
|
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-100 text-slate-600">
|
|
||||||
Da Emettere
|
|
||||||
</span>
|
|
||||||
@else
|
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-rose-100 text-rose-800">
|
|
||||||
Da Pagare
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
</thead>
|
||||||
</tbody>
|
<tbody class="divide-y divide-slate-100">
|
||||||
</table>
|
@foreach($stra['rate'] ?? [] as $sr)
|
||||||
|
<tr class="hover:bg-slate-50/80 transition">
|
||||||
|
<td class="px-4 py-2 font-mono text-slate-700 whitespace-nowrap">{{ $sr['data'] ?? '—' }}</td>
|
||||||
|
<td class="px-3 py-2 font-mono text-slate-500 whitespace-nowrap">{{ $sr['rif'] ?? '—' }}</td>
|
||||||
|
<td class="px-4 py-2 text-slate-900 font-medium">{{ $sr['descrizione'] ?? '—' }}</td>
|
||||||
|
<td class="px-4 py-2 text-right font-mono font-semibold text-slate-800">
|
||||||
|
€ {{ number_format($sr['dovuto'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2 text-center font-mono text-slate-600 whitespace-nowrap">
|
||||||
|
{{ $sr['data_pagamento'] ?? '—' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2 text-right font-mono text-emerald-700 font-semibold">
|
||||||
|
€ {{ number_format($sr['pagato'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2 text-right font-mono font-bold {{ ($sr['residuo'] ?? 0) > 0 ? 'text-rose-600' : 'text-slate-400' }}">
|
||||||
|
€ {{ number_format($sr['residuo'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2 text-center whitespace-nowrap">
|
||||||
|
@if(($sr['stato'] ?? '') === 'Saldata')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-100 text-emerald-800">
|
||||||
|
Saldata
|
||||||
|
</span>
|
||||||
|
@elseif(($sr['stato'] ?? '') === 'Parziale')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-amber-100 text-amber-800">
|
||||||
|
Parziale
|
||||||
|
</span>
|
||||||
|
@elseif(($sr['stato'] ?? '') === 'Da Emettere')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-100 text-slate-600">
|
||||||
|
Da Emettere
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold bg-rose-100 text-rose-800">
|
||||||
|
Da Pagare
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@empty
|
||||||
@empty
|
<div class="rounded-2xl border border-slate-200 bg-white p-6 text-center text-slate-500 italic text-xs">
|
||||||
<div class="rounded-2xl border border-slate-200 bg-white p-6 text-center text-slate-500 italic text-xs">
|
Nessuna gestione straordinaria registrata per questa unità.
|
||||||
Nessuna gestione straordinaria registrata per questa unità.
|
</div>
|
||||||
</div>
|
@endforelse
|
||||||
@endforelse
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- SEZIONE 3: RIEPILOGO GESTIONI ORDINARIE PREGRESSE (CONSUNTIVI CHIUSI) --}}
|
{{-- SEZIONE 3: RIEPILOGO GESTIONI ORDINARIE PREGRESSE (CONSUNTIVI CHIUSI) --}}
|
||||||
|
|
@ -1028,6 +1154,103 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-slate-800 hove
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- SEZIONE 4: ARCHIVIO ESTRATTI CONTO E LETTERE PDF GESCON --}}
|
||||||
|
<div class="rounded-2xl border border-slate-200 bg-white shadow-xs overflow-hidden">
|
||||||
|
<div class="px-5 py-3.5 bg-slate-50/90 border-b border-slate-200 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<span class="inline-flex items-center justify-center w-7 h-7 rounded-lg bg-rose-100 text-rose-700 font-bold text-xs border border-rose-200">
|
||||||
|
📁
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<h4 class="font-bold text-slate-900 text-sm">
|
||||||
|
Archivio Documenti & Estratti Conto Emessi (PDF Gescon)
|
||||||
|
</h4>
|
||||||
|
<p class="text-[11px] text-slate-500">
|
||||||
|
Storico protocolli e lettere trasmesse con i relativi documenti PDF originali archiviati
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs font-semibold text-slate-600">
|
||||||
|
Documenti disponibili: <span class="font-mono font-bold text-slate-900">{{ count($storicoPdfEc) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full text-xs text-left border-collapse">
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-slate-100/75 text-slate-600 font-semibold border-b border-slate-200">
|
||||||
|
<th class="px-4 py-2.5">Prot.</th>
|
||||||
|
<th class="px-4 py-2.5">Data Emissione</th>
|
||||||
|
<th class="px-3 py-2.5 text-center">Canale</th>
|
||||||
|
<th class="px-4 py-2.5">Destinatario</th>
|
||||||
|
<th class="px-4 py-2.5">Oggetto</th>
|
||||||
|
<th class="px-4 py-2.5 text-right">Importo Totale (€)</th>
|
||||||
|
<th class="px-4 py-2.5 text-center">Documento PDF</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-slate-100">
|
||||||
|
@forelse($storicoPdfEc as $doc)
|
||||||
|
<tr class="hover:bg-slate-50/80 transition">
|
||||||
|
<td class="px-4 py-2.5 font-mono font-bold text-slate-700 whitespace-nowrap">
|
||||||
|
#{{ $doc['protocollo'] ?? '—' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 font-mono text-slate-600 whitespace-nowrap">
|
||||||
|
{{ $doc['data'] ?? '—' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-3 py-2.5 text-center whitespace-nowrap">
|
||||||
|
@if(strtoupper($doc['tipo'] ?? '') === 'PEC')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-semibold bg-purple-100 text-purple-800 border border-purple-200">
|
||||||
|
PEC
|
||||||
|
</span>
|
||||||
|
@elseif(strtoupper($doc['tipo'] ?? '') === 'E-MAIL')
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-semibold bg-blue-100 text-blue-800 border border-blue-200">
|
||||||
|
E-Mail
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="inline-flex items-center px-2 py-0.5 rounded text-[10px] font-semibold bg-slate-100 text-slate-700">
|
||||||
|
{{ $doc['tipo'] ?? 'Documento' }}
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-slate-900 font-medium whitespace-nowrap">
|
||||||
|
{{ $doc['destinatario'] ?? '—' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-slate-600">
|
||||||
|
{{ $doc['oggetto'] ?? 'Estratto conto.' }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-right font-mono font-bold text-slate-900 whitespace-nowrap">
|
||||||
|
€ {{ number_format($doc['totale'] ?? 0, 2, ',', '.') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2.5 text-center whitespace-nowrap">
|
||||||
|
@if(!empty($doc['nome_pdf']) && ($doc['esiste_file'] ?? false))
|
||||||
|
<a href="{{ $doc['url'] ?? '#' }}"
|
||||||
|
target="_blank"
|
||||||
|
class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg bg-rose-50 hover:bg-rose-100 text-rose-700 border border-rose-200 text-[11px] font-semibold transition">
|
||||||
|
<x-filament::icon icon="heroicon-m-document-text" class="w-3.5 h-3.5 text-rose-600" />
|
||||||
|
<span>{{ $doc['nome_pdf'] }}</span>
|
||||||
|
<x-filament::icon icon="heroicon-m-arrow-top-right-on-square" class="w-3 h-3 text-rose-400" />
|
||||||
|
</a>
|
||||||
|
@elseif(!empty($doc['nome_pdf']))
|
||||||
|
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-mono text-slate-500 bg-slate-100">
|
||||||
|
{{ $doc['nome_pdf'] }}
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class="text-slate-400 text-xs">—</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="7" class="px-4 py-4 text-center text-slate-500 italic">
|
||||||
|
Nessun estratto conto o documento PDF archiviato per questa unità.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,24 @@
|
||||||
|
|
||||||
Route::get('fatture-elettroniche/{fattura}/download-pdf', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadPdf'])
|
Route::get('fatture-elettroniche/{fattura}/download-pdf', [\App\Http\Controllers\Admin\FattureElettronicheRicevuteController::class, 'downloadPdf'])
|
||||||
->name('fatture-elettroniche.download-pdf');
|
->name('fatture-elettroniche.download-pdf');
|
||||||
|
|
||||||
|
Route::get('gescon-ec-pdf/{stabile}/{file}', function (string $stabile, string $file) {
|
||||||
|
$stabile = basename($stabile);
|
||||||
|
$file = basename($file);
|
||||||
|
$paths = [
|
||||||
|
"/mnt/gescon-archives/gescon/{$stabile}/e_c/{$file}",
|
||||||
|
"/mnt/gescon-archives/gescon/{$stabile}/E_C/{$file}",
|
||||||
|
];
|
||||||
|
foreach ($paths as $p) {
|
||||||
|
if (file_exists($p)) {
|
||||||
|
return response()->file($p, [
|
||||||
|
'Content-Type' => 'application/pdf',
|
||||||
|
'Content-Disposition' => 'inline; filename="' . $file . '"',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abort(404, 'File PDF estratto conto non trovato.');
|
||||||
|
})->name('gescon.ec.pdf');
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- ADMIN / AMMINISTRATORE PANEL ---
|
// --- ADMIN / AMMINISTRATORE PANEL ---
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,65 @@
|
||||||
# CURRENT-205
|
# CURRENT-205
|
||||||
|
|
||||||
TASK_ID: task-estratto-conto-atomico-mdb-unita
|
TASK_ID: task-estratto-conto-inquilino-stabili-pdf
|
||||||
MACHINE: .205
|
MACHINE: .205
|
||||||
STATO: completato
|
STATO: completato
|
||||||
|
|
||||||
## Obiettivo Completato
|
## Obiettivo Completato
|
||||||
|
|
||||||
1. **Estratto Conto Atomico e Temporale Unità Immobiliare (`/admin-filament/unita-immobiliare`)**:
|
1. **Rettifica Rigida Estratto Conto Inquilino (`I`) - Stabile 0013**:
|
||||||
- **Servizio Dedicato `GesconEstrattoContoService`**:
|
- **Esclusione Totale Spese Straordinarie**: all'inquilino non appare alcuna gestione o spesa straordinaria (`gestioni_straordinarie = []`, `totale_straordinarie_residuo = 0.00`). Nella Blade viene visualizzato un banner informativo chiarificatore (artt. 1576 e 1609 c.c.).
|
||||||
- Creato `app/Services/Gescon/GesconEstrattoContoService.php`.
|
- **Gestione Ordinaria 2026 Atomica per l'Inquilino** (Kiwa Cermet SpA, entrato nel 2025):
|
||||||
- Legge direttamente dagli archivi montati in `/mnt/gescon-archives/gescon/{codice_stabile}/`:
|
- Rata 1 (rif. 2, 05/01/2026): 280,00 € dovuti, **pagati 280,00 € il 16/01/2026** (residuo 0,00 € - Saldata)
|
||||||
- `generale_stabile.mdb`: legge `anni` e `emes_det` (piano rate e conguagli storici e attivi).
|
- Rata 2 (rif. 61, 31/03/2026): 280,00 € dovuti, **pagati 280,00 € il 13/04/2026** (residuo 0,00 € - Saldata)
|
||||||
- `{nome_dir}/singolo_anno.mdb`: legge `condomin`, `straordinarie` (delibere/spese) e `incassi`.
|
- Rata 3 (rif. 181, 21/05/2026): 334,00 € dovuti (residuo 334,00 € - Da Pagare)
|
||||||
- Ripartisce atomicamente e cronologicamente i dati contabili:
|
- Rata 4 (rif. 120, 24/06/2026 Conguaglio es. precedente): 63,30 € dovuti (residuo 63,30 € - Da Pagare)
|
||||||
- **Gestione Ordinaria Corrente (Es. 2026)**: rate emesse, conguaglio es. precedente e saldo/compensazione a zero.
|
- Rata 5 (rif. 241, 05/07/2026): 334,00 € dovuti (residuo 334,00 € - Da Pagare)
|
||||||
- **Gestioni Straordinarie Separate**: ciascuna spesa ha la sua scheda isolata con piano rate, pagamenti e residuo esigibile (Passerella e Tetto 1/2026 con 4 rate di cui 1 pagata da 482,80 €, 2 emesse da pagare e 1 da emettere; Cornicione 2/2026 con rata 1 pagata 209,51 €, rata 2 residuo 92,85 €, rata 3 da 209,51 €; Citofono 3/2022 con rata unica rif. 401; Cortile 2/2024 saldata).
|
- **Totale Gestione Ordinaria 2026**: Dovuto 1.291,30 €, Pagato 560,00 €, **Residuo da Pagare € 731,30**.
|
||||||
- **Riepilogo Gestioni Ordinarie Pregresse**: tabella storica dei consuntivi definitivi chiusi (2017-2025) a saldo zero.
|
- **Totale Dovuto Globale Inquilino**: **€ 731,30** esatto al centesimo (riscontro identico con documento ufficiale `EC_553.pdf`).
|
||||||
- **Riscaldamento**: escluso (non presente nell'ente).
|
|
||||||
- Supporta pienamente il ruolo contabile `cond_inquil` con toggle tra **Condòmino (C)** (Spadavecchia Aldo) e **Inquilino (I)** (Kiwa Cermet SpA, residuo 731,30 €).
|
|
||||||
- Riscontro matematico esatto al centesimo sul benchmark fornito per l'interno A-1:
|
|
||||||
Passerella Rata 2 (482,80 €) + Passerella Rata 3 (482,80 €) + Cornicione Rata 2 residuo (92,85 €) + Cornicione Rata 3 (209,51 €) = **€ 1.267,96**.
|
|
||||||
|
|
||||||
2. **Risoluzione Duplicazione e Riprogettazione Blade (`unita-immobiliare.blade.php`)**:
|
2. **Integrazione e Supporto Completo Stabile 0021 (SUPERCONDOMINIO MILIZIE 3)**:
|
||||||
- **Eliminazione Blocco Duplicato**: rimosso il secondo blocco `@if($tab === 'estratto_conto')` (ex righe 1577-1846) che appiattiva e mescolava tutte le date e gli anni tramite un ordinamento generico `usort`.
|
- **Riscaldamento Centralizzato**: abilitato con flag `has_riscaldamento = true`, KPI card dedicata e tabella temporale dei movimenti (4 rate da 45,00 € di cui Rata 1 Gennaio pagata 30/01/2026, residuo **€ 135,00**).
|
||||||
- **Nuova Interfaccia Atomica**:
|
- **Aggregazione Pertinenze della Proprietà**: include sia l'appartamento `A/1` che la cantina `CAN/01` appartenenti alla medesima intestazione `CEFALONI M.CONCETTA - ROSSI PAOLA`.
|
||||||
- Testata scura con badge fonte (`⚡ Archivio MDB Live` / `🗄️ Database Consolidato`), dati anagrafici e locatario.
|
- **Ripartizione Contabile al Centesimo**:
|
||||||
- Switcher istantaneo tra `🏢 Condòmino (C)` e `👤 Inquilino (I)`.
|
- Gestione Ordinaria 2026: Rata 1 pagata 130,00 €, Rata 2 residuo 130,00 €, Quota pertinenza cantina CAN/01 9,21 € -> **€ 139,21**
|
||||||
- Pulsante `Ricarica MDB` collegato al Livewire action `refreshEstrattoContoMdb` per invalidare la cache (300s) e rileggere a caldo i dati dai file MDB.
|
- Riscaldamento Centralizzato 2025-26: 3 rate da 45,00 € -> **€ 135,00**
|
||||||
- 4 KPI cards: Totale da Pagare (**€ 1.267,96**), Straordinarie Attive (**€ 1.267,96**), Ordinaria 2026 (**€ 0,00**), Ordinarie Pregresse (**€ 0,00**).
|
- Gestioni Straordinarie: Lavori Str. 5/2025 (381,06 €) + Causa Scillia 1/2026 (quote A/1 e CAN/01: 92,88 + 92,88 + 3,33 + 3,33 = 192,42 €) -> **€ 573,48**
|
||||||
- Sezione Ordinaria Corrente tabellare dettagliata.
|
- **Totale Dovuto Globale Stabile 0021**: 139,21 + 135,00 + 573,48 = **€ 847,69** esatto al centesimo.
|
||||||
- Sezione Gestioni Straordinarie a schede atomiche indipendenti con badge di avanzamento rata (`Saldata`, `Parziale`, `Da Pagare`, `Da Emettere`).
|
|
||||||
- Sezione Riepilogo Storico Consuntivi Chiusi con spunta di chiusura definitiva.
|
|
||||||
|
|
||||||
3. **Integrazione Controller Livewire (`UnitaImmobiliarePage.php`)**:
|
3. **Archivio Storico Documenti ed Estratti Conto PDF Gescon (`Protoc_EC`)**:
|
||||||
- Aggiunta proprietà computata `getEstrattoContoAtomicoProperty` che interpola il service e l'unità selezionata.
|
- Integrazione lettura tabella `Protoc_EC` in `generale_stabile.mdb`.
|
||||||
- Aggiunta azione `refreshEstrattoContoMdb()` con notifica Filament a schermo.
|
- Nuova Sezione 4 nella Blade con tabella cronologica degli estratti conto emessi: Protocollo, Data, Canale (PEC/E-Mail), Destinatario, Oggetto, Importo Totale.
|
||||||
|
- Nuova rotta protetta `admin.gescon.ec.pdf` (`admin/gescon-ec-pdf/{stabile}/{file}`) che verifica i percorsi su disco sia in minuscolo `e_c/` (0013) che in maiuscolo `E_C/` (0021) con protezione anti path-traversal (`basename`).
|
||||||
|
- Pulsante diretto "Apri / Scarica PDF" con anteprima in nuova scheda (`EC_553.pdf`, `EC_552.pdf`, `EC_005.pdf`, ecc.).
|
||||||
|
|
||||||
|
4. **Preservazione Stato Navigazione Livewire (`UnitaImmobiliarePage`)**:
|
||||||
|
- Risolto reset forzato della proprietà `$this->tab` in `loadUnita()`: ora preserva il tab attivo durante le chiamate Livewire (es. toggle Condòmino/Inquilino e refresh MDB).
|
||||||
|
|
||||||
## Output del Giro Operativo
|
## Output del Giro Operativo
|
||||||
|
|
||||||
ESITO_205: riuscito
|
ESITO_205: riuscito
|
||||||
TASK_ID: task-estratto-conto-atomico-mdb-unita
|
TASK_ID: task-estratto-conto-inquilino-stabili-pdf
|
||||||
REPOSITORY: ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git
|
REPOSITORY: ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git
|
||||||
BRANCH: stabilization/205-zero
|
BRANCH: stabilization/205-zero
|
||||||
COMMIT: 89d18df
|
COMMIT: 1ed8ae1
|
||||||
FILE_O_AREE_TOCCATE:
|
FILE_O_AREE_TOCCATE:
|
||||||
- app/Filament/Pages/UnitaImmobiliarePage.php
|
- app/Filament/Pages/UnitaImmobiliarePage.php
|
||||||
- app/Services/Gescon/GesconEstrattoContoService.php
|
- app/Services/Gescon/GesconEstrattoContoService.php
|
||||||
- resources/views/filament/pages/unita-immobiliare.blade.php
|
- resources/views/filament/pages/unita-immobiliare.blade.php
|
||||||
|
- routes/web.php
|
||||||
- skill-netgescon/control-tower/CURRENT-205.md
|
- skill-netgescon/control-tower/CURRENT-205.md
|
||||||
- tests/Feature/UnitaEstrattoContoAtomicoTest.php
|
- tests/Feature/UnitaEstrattoContoAtomicoTest.php
|
||||||
TEST_ESEGUITI:
|
TEST_ESEGUITI:
|
||||||
- ./vendor/bin/pest tests/Feature/UnitaEstrattoContoAtomicoTest.php (2 passed, 32 assertions)
|
- ./vendor/bin/pest tests/Feature/UnitaEstrattoContoAtomicoTest.php (4 passed, 87 assertions, 100% pass)
|
||||||
- ./vendor/bin/pest tests/Feature/UnitaCondominoInquilinoRoleToggleTest.php tests/Feature/UnitaGestioneTemporaleTest.php tests/Feature/UnitaImmobiliarePageTest.php tests/Feature/UnitaEstrattoContoAtomicoTest.php (12 passed, 103 assertions, 100% pass)
|
- ./vendor/bin/pest tests/Feature/UnitaCondominoInquilinoRoleToggleTest.php tests/Feature/UnitaGestioneTemporaleTest.php tests/Feature/UnitaImmobiliarePageTest.php tests/Feature/UnitaEstrattoContoAtomicoTest.php (14 passed, 158 assertions, 100% pass)
|
||||||
- php artisan view:clear && php artisan view:cache (successo, zero errori di compilazione Blade)
|
- php artisan view:clear && php artisan view:cache (successo, 100% template compilati senza errori)
|
||||||
GATE_STATISTICS:
|
GATE_STATISTICS:
|
||||||
- BLADE_COMPILATION: 100% pulita senza token inattesi.
|
- BLADE_COMPILATION: 100% pulita senza errori di sintassi.
|
||||||
- BENCHMARK_VERIFICATION: Totale dovuto € 1.267,96 esatto al centesimo (Passerella 482,80 + 482,80 + Cornicione 92,85 + 209,51).
|
- BENCHMARK_VERIFICATION:
|
||||||
- TEST_SUITE: 12 test Feature passati (103 asserzioni, 100% pass).
|
- 0013 Condòmino Spadavecchia A-1 = € 1.267,96 esatto (Passerella 965,60 + Cornicione 302,36).
|
||||||
|
- 0013 Inquilino Kiwa Cermet A-1 = € 731,30 esatto (0 straordinarie, 5 rate ordinarie 2026 con 560 € pagati e 731,30 € residuo).
|
||||||
|
- 0021 Condòmino Cefaloni Milizie 3 = € 847,69 esatto (Ordinaria 139,21 + Riscaldamento 135,00 + Straordinarie 573,48).
|
||||||
|
- TEST_SUITE: 14 test Feature passati (158 asserzioni, 100% pass).
|
||||||
BLOCCO_DATI: no
|
BLOCCO_DATI: no
|
||||||
BLOCCO_CONTRATTO: no
|
BLOCCO_CONTRATTO: no
|
||||||
RISCHI_APERTI: nessuno
|
RISCHI_APERTI: nessuno
|
||||||
|
|
@ -65,8 +68,10 @@ ## Prossimo Passo per .200 (Validazione)
|
||||||
|
|
||||||
- Eseguire il checkout del branch `stabilization/205-zero`.
|
- Eseguire il checkout del branch `stabilization/205-zero`.
|
||||||
- Eseguire la suite di test Pest (`./vendor/bin/pest tests/Feature/UnitaEstrattoContoAtomicoTest.php`).
|
- Eseguire la suite di test Pest (`./vendor/bin/pest tests/Feature/UnitaEstrattoContoAtomicoTest.php`).
|
||||||
- Verificare su http://192.168.0.205:8000/admin-filament/unita-immobiliare (selezionando lo stabile 0013, unità A-1) il tab "🧾 Estratto Conto & Pagamenti":
|
- Verificare su http://192.168.0.205:8000/admin-filament/unita-immobiliare:
|
||||||
- Verificare che il Totale Dovuto sia esattamente **€ 1.267,96**.
|
1. Stabile 0013, Unità A-1:
|
||||||
- Verificare la corretta ripartizione tra Gestione Ordinaria 2026 (residuo € 0,00) e Gestioni Straordinarie (Passerella con 1 pagata e rate a 482,80 €, Cornicione con residuo 92,85 € e 209,51 €, Citofono 2022 con rif 401).
|
- In modalità **🏢 Condòmino (C)**: Totale Dovuto = **€ 1.267,96**, straordinarie attive € 1.267,96, ordinaria corrente € 0,00.
|
||||||
- Verificare che non siano presenti voci di riscaldamento.
|
- In modalità **👤 Inquilino (I)**: Totale Dovuto = **€ 731,30**, straordinarie = € 0,00 con banner chiarificatore, ordinaria 2026 con 5 rate (rate 1 e 2 saldate per 560 €, rate 3, 4, 5 da pagare per 731,30 €).
|
||||||
- Testare il toggle "🏢 Condòmino (C)" / "👤 Inquilino (I)" e il pulsante "Ricarica MDB".
|
- Nella sezione "Archivio Documenti & Estratti Conto Emessi (PDF Gescon)": verificare la presenza di `EC_553.pdf` e `EC_552.pdf` con pulsante per visualizzare il PDF originale.
|
||||||
|
2. Stabile 0021, Unità A-1:
|
||||||
|
- In modalità **🏢 Condòmino (C)**: Totale Dovuto = **€ 847,69**, con sezione e KPI Riscaldamento Centralizzato (€ 135,00), Ordinaria (€ 139,21), Straordinarie Causa Scillia e Lavori (€ 573,48), e PDF `EC_005.pdf`.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Livewire\Livewire;
|
use Livewire\Livewire;
|
||||||
|
|
||||||
test('gescon estratto conto service computes exact benchmark data for unit A-1', function () {
|
test('gescon estratto conto service computes exact benchmark data for unit 0013-A-1 condomino', function () {
|
||||||
DB::table('amministratori')->insertOrIgnore([
|
DB::table('amministratori')->insertOrIgnore([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'nome' => 'Admin',
|
'nome' => 'Admin',
|
||||||
|
|
@ -78,13 +78,164 @@
|
||||||
// Verifica somma esatta al centesimo: 965.60 + 302.36 = 1267.96
|
// Verifica somma esatta al centesimo: 965.60 + 302.36 = 1267.96
|
||||||
expect(round($passerella2026['residuo'] + $cornicione2026['residuo'], 2))->toBe(1267.96);
|
expect(round($passerella2026['residuo'] + $cornicione2026['residuo'], 2))->toBe(1267.96);
|
||||||
|
|
||||||
// Verifica inquilino (Kiwa Cermet SpA)
|
// Storico PDF per condomino contiene EC_552.pdf
|
||||||
$ecInq = $service->getEstrattoConto($unita, 'I', true);
|
expect($ec['storico_pdf_ec'])->not->toBeEmpty();
|
||||||
expect($ecInq['totali']['totale_dovuto'])->toBe(731.30)
|
$ec552 = collect($ec['storico_pdf_ec'])->first(fn ($p) => $p['nome_pdf'] === 'EC_552.pdf');
|
||||||
->and($ecInq['soggetto']['ruolo'])->toBe('I');
|
expect($ec552)->not->toBeNull()
|
||||||
|
->and($ec552['totale'])->toBe(575.65);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('unita immobiliare page renders atomic estratto conto and handles refresh', function () {
|
test('gescon estratto conto service computes exact benchmark data for unit 0013-A-1 inquilino', function () {
|
||||||
|
DB::table('amministratori')->insertOrIgnore([
|
||||||
|
'id' => 1,
|
||||||
|
'nome' => 'Admin',
|
||||||
|
'cognome' => 'Test',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stabile = Stabile::firstOrCreate(
|
||||||
|
['codice_stabile' => '0013'],
|
||||||
|
[
|
||||||
|
'amministratore_id' => 1,
|
||||||
|
'denominazione' => 'Condominio Via Ottaviano 105',
|
||||||
|
'indirizzo' => 'Via Ottaviano 105',
|
||||||
|
'citta' => 'Roma',
|
||||||
|
'cap' => '00192',
|
||||||
|
'provincia' => 'RM',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$unita = UnitaImmobiliare::firstOrCreate(
|
||||||
|
['codice_unita' => '0013-A-1'],
|
||||||
|
[
|
||||||
|
'stabile_id' => $stabile->id,
|
||||||
|
'scala' => 'A',
|
||||||
|
'interno' => '1',
|
||||||
|
'denominazione' => 'SPADAVECCHIA ALDO',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = app(GesconEstrattoContoService::class);
|
||||||
|
$ecInq = $service->getEstrattoConto($unita, 'I', true);
|
||||||
|
|
||||||
|
// 1. Nessuna spesa straordinaria a carico dell'inquilino
|
||||||
|
expect($ecInq['gestioni_straordinarie'])->toBeEmpty()
|
||||||
|
->and($ecInq['totali']['totale_straordinarie_residuo'])->toBe(0.0);
|
||||||
|
|
||||||
|
// 2. Gestione Ordinaria 2026: 5 rate esatte corrispondenti a EC_553.pdf
|
||||||
|
expect($ecInq['gestione_ordinaria_corrente']['rate'])->toHaveCount(5);
|
||||||
|
$rate = $ecInq['gestione_ordinaria_corrente']['rate'];
|
||||||
|
|
||||||
|
// Rata 1: 280,00 pagata 16/01/2026
|
||||||
|
$r1 = collect($rate)->first(fn ($r) => in_array($r['rif'], ['1', '2'], true));
|
||||||
|
expect($r1)->not->toBeNull()
|
||||||
|
->and($r1['dovuto'])->toBe(280.00)
|
||||||
|
->and($r1['pagato'])->toBe(280.00)
|
||||||
|
->and($r1['residuo'])->toBe(0.0)
|
||||||
|
->and($r1['stato'])->toBe('Saldata');
|
||||||
|
|
||||||
|
// Rata 2: 280,00 pagata 13/04/2026
|
||||||
|
$r2 = collect($rate)->first(fn ($r) => in_array($r['rif'], ['60', '61'], true));
|
||||||
|
expect($r2)->not->toBeNull()
|
||||||
|
->and($r2['dovuto'])->toBe(280.00)
|
||||||
|
->and($r2['pagato'])->toBe(280.00)
|
||||||
|
->and($r2['residuo'])->toBe(0.0)
|
||||||
|
->and($r2['stato'])->toBe('Saldata');
|
||||||
|
|
||||||
|
// Rata 3: 334,00 da pagare
|
||||||
|
$r3 = collect($rate)->first(fn ($r) => in_array($r['rif'], ['180', '181'], true));
|
||||||
|
expect($r3)->not->toBeNull()
|
||||||
|
->and($r3['dovuto'])->toBe(334.00)
|
||||||
|
->and($r3['pagato'])->toBe(0.0)
|
||||||
|
->and($r3['residuo'])->toBe(334.00)
|
||||||
|
->and($r3['stato'])->toBe('Da Pagare');
|
||||||
|
|
||||||
|
// Rata conguaglio es. precedente: 63,30 da pagare
|
||||||
|
$rCong = collect($rate)->first(fn ($r) => in_array($r['rif'], ['119', '120'], true) || str_contains(strtolower($r['descrizione']), 'conguaglio'));
|
||||||
|
expect($rCong)->not->toBeNull()
|
||||||
|
->and($rCong['dovuto'])->toBe(63.30)
|
||||||
|
->and($rCong['pagato'])->toBe(0.0)
|
||||||
|
->and($rCong['residuo'])->toBe(63.30)
|
||||||
|
->and($rCong['stato'])->toBe('Da Pagare');
|
||||||
|
|
||||||
|
// Rata 4: 334,00 da pagare
|
||||||
|
$r4 = collect($rate)->first(fn ($r) => in_array($r['rif'], ['240', '241'], true));
|
||||||
|
expect($r4)->not->toBeNull()
|
||||||
|
->and($r4['dovuto'])->toBe(334.00)
|
||||||
|
->and($r4['pagato'])->toBe(0.0)
|
||||||
|
->and($r4['residuo'])->toBe(334.00)
|
||||||
|
->and($r4['stato'])->toBe('Da Pagare');
|
||||||
|
|
||||||
|
// 3. Totali esatti per Inquilino: 731,30 € esigibile
|
||||||
|
expect($ecInq['totali']['totale_dovuto'])->toBe(731.30)
|
||||||
|
->and($ecInq['totali']['totale_ordinaria_corrente_residuo'])->toBe(731.30)
|
||||||
|
->and($ecInq['soggetto']['ruolo'])->toBe('I');
|
||||||
|
|
||||||
|
// 4. Storico PDF contiene EC_553.pdf con saldo 731,30 €
|
||||||
|
expect($ecInq['storico_pdf_ec'])->not->toBeEmpty();
|
||||||
|
$ec553 = collect($ecInq['storico_pdf_ec'])->first(fn ($p) => $p['nome_pdf'] === 'EC_553.pdf');
|
||||||
|
expect($ec553)->not->toBeNull()
|
||||||
|
->and($ec553['totale'])->toBe(731.30)
|
||||||
|
->and($ec553['esiste_file'])->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('gescon estratto conto service computes exact benchmark data for stabile 0021 milizie 3', function () {
|
||||||
|
DB::table('amministratori')->insertOrIgnore([
|
||||||
|
'id' => 1,
|
||||||
|
'nome' => 'Admin',
|
||||||
|
'cognome' => 'Test',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$stabile = Stabile::firstOrCreate(
|
||||||
|
['codice_stabile' => '0021'],
|
||||||
|
[
|
||||||
|
'amministratore_id' => 1,
|
||||||
|
'denominazione' => 'SUPERCONDOMINIO MILIZIE 3',
|
||||||
|
'indirizzo' => 'Viale delle Milizie 3',
|
||||||
|
'citta' => 'Roma',
|
||||||
|
'cap' => '00192',
|
||||||
|
'provincia' => 'RM',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$unita = UnitaImmobiliare::firstOrCreate(
|
||||||
|
['stabile_id' => $stabile->id, 'scala' => 'A', 'interno' => '1'],
|
||||||
|
[
|
||||||
|
'codice_unita' => '0021-A-1',
|
||||||
|
'denominazione' => 'CEFALONI M.CONCETTA - ROSSI PAOLA',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = app(GesconEstrattoContoService::class);
|
||||||
|
$ec = $service->getEstrattoConto($unita, 'C', true);
|
||||||
|
|
||||||
|
// 1. Totale da pagare € 847,69 esatto
|
||||||
|
expect($ec['totali']['totale_dovuto'])->toBe(847.69)
|
||||||
|
->and($ec['has_riscaldamento'])->toBeTrue()
|
||||||
|
->and($ec['totali']['totale_riscaldamento_residuo'])->toBe(135.00)
|
||||||
|
->and($ec['totali']['totale_ordinaria_corrente_residuo'])->toBe(139.21)
|
||||||
|
->and($ec['totali']['totale_straordinarie_residuo'])->toBe(573.48);
|
||||||
|
|
||||||
|
// 2. Riscaldamento centralizzato 4 rate da 45,00 di cui 1 pagata
|
||||||
|
expect($ec['gestione_riscaldamento']['rate'])->toHaveCount(4)
|
||||||
|
->and($ec['gestione_riscaldamento']['rate'][0]['pagato'])->toBe(45.00)
|
||||||
|
->and($ec['gestione_riscaldamento']['rate'][1]['residuo'])->toBe(45.00)
|
||||||
|
->and($ec['gestione_riscaldamento']['residuo'])->toBe(135.00);
|
||||||
|
|
||||||
|
// 3. Gestioni Straordinarie (S_5 381,06 € + Causa Scillia 192,42 € = 573,48 €)
|
||||||
|
expect($ec['gestioni_straordinarie'])->toHaveCount(2);
|
||||||
|
|
||||||
|
// 4. Storico PDF contiene EC_005.pdf
|
||||||
|
$ec005 = collect($ec['storico_pdf_ec'])->first(fn ($p) => $p['nome_pdf'] === 'EC_005.pdf');
|
||||||
|
expect($ec005)->not->toBeNull()
|
||||||
|
->and($ec005['totale'])->toBe(679.49)
|
||||||
|
->and($ec005['esiste_file'])->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unita immobiliare page renders atomic estratto conto and handles role toggle and pdfs', function () {
|
||||||
DB::table('amministratori')->insertOrIgnore([
|
DB::table('amministratori')->insertOrIgnore([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'nome' => 'Admin',
|
'nome' => 'Admin',
|
||||||
|
|
@ -121,6 +272,7 @@
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Test Condomino View
|
||||||
Livewire::actingAs($user)
|
Livewire::actingAs($user)
|
||||||
->test(UnitaImmobiliarePage::class, ['unita_id' => $unita->id])
|
->test(UnitaImmobiliarePage::class, ['unita_id' => $unita->id])
|
||||||
->call('setTab', 'estratto_conto')
|
->call('setTab', 'estratto_conto')
|
||||||
|
|
@ -130,6 +282,18 @@
|
||||||
->assertSee('RIPRISTINO PASSERELLA E TETTO')
|
->assertSee('RIPRISTINO PASSERELLA E TETTO')
|
||||||
->assertSee('482,80')
|
->assertSee('482,80')
|
||||||
->assertSee('401')
|
->assertSee('401')
|
||||||
|
->assertSee('EC_552.pdf')
|
||||||
->call('refreshEstrattoContoMdb')
|
->call('refreshEstrattoContoMdb')
|
||||||
->assertHasNoErrors();
|
->assertHasNoErrors();
|
||||||
|
|
||||||
|
// Test Inquilino View
|
||||||
|
Livewire::actingAs($user)
|
||||||
|
->test(UnitaImmobiliarePage::class, ['unita_id' => $unita->id])
|
||||||
|
->call('setTab', 'estratto_conto')
|
||||||
|
->call('setCondInquilActive', 'I')
|
||||||
|
->assertSet('condInquilActive', 'I')
|
||||||
|
->assertSee('731,30')
|
||||||
|
->assertSee('Nessuna spesa straordinaria a carico del conduttore')
|
||||||
|
->assertSee('EC_553.pdf')
|
||||||
|
->assertHasNoErrors();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user