fix(gescon-import): correct date formats and description mapping, remove read window and show registered badge

This commit is contained in:
michele 2026-07-07 19:03:47 +02:00
parent ab82c315fe
commit 30b4f89a7b
3 changed files with 36 additions and 35 deletions

View File

@ -3867,10 +3867,18 @@ public function getRiscaldamentoTariffeRowsProperty(): array
$activeYear = $this->resolveActiveAnnoGestione(); $activeYear = $this->resolveActiveAnnoGestione();
// Carica le voci di spesa collegate al riscaldamento per lo stabile // Trova le gestioni attive per questo stabile ed anno
$gestioneIds = \App\Models\GestioneContabile::query()
->where('stabile_id', $stabileId)
->where('anno_gestione', $activeYear)
->pluck('id')
->all();
// Carica le voci di spesa collegate al riscaldamento per lo stabile e la gestione dell'anno attivo
$voci = \App\Models\VoceSpesa::query() $voci = \App\Models\VoceSpesa::query()
->where('stabile_id', $stabileId) ->where('stabile_id', $stabileId)
->where('attiva', true) ->where('attiva', true)
->whereIn('gestione_contabile_id', $gestioneIds)
->where(function ($query): void { ->where(function ($query): void {
$query->where('tipo_gestione', 'riscaldamento') $query->where('tipo_gestione', 'riscaldamento')
->orWhere('tipo', 'riscaldamento') ->orWhere('tipo', 'riscaldamento')
@ -3884,13 +3892,6 @@ public function getRiscaldamentoTariffeRowsProperty(): array
->orderBy('codice') ->orderBy('codice')
->get(); ->get();
// Trova le gestioni attive per questo stabile ed anno
$gestioneIds = \App\Models\GestioneContabile::query()
->where('stabile_id', $stabileId)
->where('anno_gestione', $activeYear)
->pluck('id')
->all();
$rows = []; $rows = [];
foreach ($voci as $voce) { foreach ($voci as $voce) {
$consuntivo = 0.0; $consuntivo = 0.0;

View File

@ -176,7 +176,7 @@ private function scanGestioniFromMdb(string $mdbPath, int $year): array
$straordinarie = []; $straordinarie = [];
foreach ($operazioni as $op) { foreach ($operazioni as $op) {
$g = strtoupper(trim($op['Gestione'] ?? '')); $g = strtoupper(trim($op['gestione'] ?? ''));
if ($g === 'R') { if ($g === 'R') {
$hasRiscaldamento = true; $hasRiscaldamento = true;
} elseif ($g === 'S') { } elseif ($g === 'S') {
@ -384,12 +384,12 @@ private function importRitenuteFOrGestione(GestioneContabile $gestione, string $
RegistroRitenuteAcconto::create([ RegistroRitenuteAcconto::create([
'tenant_id' => $this->tenantId, 'tenant_id' => $this->tenantId,
'gestione_id' => $gestione->id, 'gestione_id' => $gestione->id,
'numero_progressivo' => $ra['Rif_RDA'], 'numero_progressivo' => $ra['rif_rda'],
'data_competenza' => $this->parseGesconDate($ra['data_oper']), 'data_competenza' => $this->parseGesconDate($ra['data_oper']),
'imponibile' => (float) ($ra['imponibile_operazione'] ?? 0), 'imponibile' => (float) ($ra['imponibile_operazione'] ?? 0),
'aliquota_ritenuta' => (float) ($ra['aliquota'] ?? 20), 'aliquota_ritenuta' => (float) ($ra['aliquota'] ?? 20),
'importo_ritenuta' => (float) ($ra['ritenuta'] ?? 0), 'importo_ritenuta' => (float) ($ra['ritenuta'] ?? 0),
'rif_rda' => $ra['Rif_RDA'], 'rif_rda' => $ra['rif_rda'],
'stato_versamento' => 'da_versare', 'stato_versamento' => 'da_versare',
'metadati_gescon' => json_encode($ra), 'metadati_gescon' => json_encode($ra),
]); ]);
@ -537,11 +537,11 @@ private function importOperazioni(string $year, string $mdbPath): int
{ {
$imported = 0; $imported = 0;
// Query MDB per operazioni
$operazioni = $this->queryMdb($mdbPath, " $operazioni = $this->queryMdb($mdbPath, "
SELECT * SELECT *
FROM Operazioni FROM Operazioni
"); ");
echo "DEBUG: Found " . count($operazioni) . " operations in MDB for year {$year}\n";
usort($operazioni, function($a, $b) { usort($operazioni, function($a, $b) {
$idA = (int) ($a['id_operaz'] ?? 0); $idA = (int) ($a['id_operaz'] ?? 0);
@ -589,7 +589,7 @@ private function importOperazioni(string $year, string $mdbPath): int
'tenant_id' => $this->tenantId, 'tenant_id' => $this->tenantId,
'gestione_id' => $gestioneId, 'gestione_id' => $gestioneId,
'legacy_id' => $opId, 'legacy_id' => $opId,
'descrizione' => $op['note'] ?? $op['descrizione'] ?? $op['natura'] ?? 'Operazione', 'descrizione' => (trim($op['benef'] ?? '') !== '') ? trim($op['benef']) : ((trim($op['note'] ?? '') !== '') ? trim($op['note']) : ((trim($op['descrizione'] ?? '') !== '') ? trim($op['descrizione']) : 'Operazione')),
'data_operazione' => $this->parseGesconDate($dtSpe), 'data_operazione' => $this->parseGesconDate($dtSpe),
'compet' => $competClean, 'compet' => $competClean,
'natura2' => $natura2Clean, 'natura2' => $natura2Clean,
@ -609,6 +609,7 @@ private function importOperazioni(string $year, string $mdbPath): int
$imported++; $imported++;
} catch (\Exception $e) { } catch (\Exception $e) {
echo "Error importing operazione " . ($op['id_operaz'] ?? 'unknown') . " for year {$year}: " . $e->getMessage() . "\n";
Log::error("Error importing operazione", [ Log::error("Error importing operazione", [
'year' => $year, 'year' => $year,
'operazione' => $op, 'operazione' => $op,
@ -646,7 +647,7 @@ private function importIncassi(string $year, string $mdbPath): int
'gestione_id' => $gestioneId, 'gestione_id' => $gestioneId,
'condominio_id' => $this->gestioni[$year]['ordinaria']->stabile_id ?? 1, 'condominio_id' => $this->gestioni[$year]['ordinaria']->stabile_id ?? 1,
'conto_bancario_id' => $this->resolveContoBancarioId($mdbPath, $inc['cod_cassa'] ?? null), 'conto_bancario_id' => $this->resolveContoBancarioId($mdbPath, $inc['cod_cassa'] ?? null),
'id_incasso_gescon' => $inc['ID_incasso'] ?? null, 'id_incasso_gescon' => $inc['id_incasso'] ?? null,
'cod_cond_gescon' => $inc['cod_cond'] ?? null, 'cod_cond_gescon' => $inc['cod_cond'] ?? null,
'cond_inquil' => $inc['cond_inquil'] ?? null, 'cond_inquil' => $inc['cond_inquil'] ?? null,
'n_riferimento' => $inc['n_riferimento'] ?? null, 'n_riferimento' => $inc['n_riferimento'] ?? null,
@ -704,12 +705,12 @@ private function importRitenuteAcconto(string $year, string $mdbPath): int
RegistroRitenuteAcconto::create([ RegistroRitenuteAcconto::create([
'tenant_id' => $this->tenantId, 'tenant_id' => $this->tenantId,
'gestione_id' => $gestioneId, 'gestione_id' => $gestioneId,
'numero_progressivo' => $ra['Rif_RDA'], 'numero_progressivo' => $ra['rif_rda'],
'data_competenza' => $this->parseGesconDate($ra['dt_spe'] ?? null), 'data_competenza' => $this->parseGesconDate($ra['dt_spe'] ?? null),
'imponibile' => (float) ($ra['imponibile_operazione'] ?? 0), 'imponibile' => (float) ($ra['imponibile_operazione'] ?? 0),
'aliquota_ritenuta' => (float) ($ra['aliquota'] ?? 20), 'aliquota_ritenuta' => (float) ($ra['aliquota'] ?? 20),
'importo_ritenuta' => (float) ($ra['ritenuta'] ?? 0), 'importo_ritenuta' => (float) ($ra['ritenuta'] ?? 0),
'rif_rda' => $ra['Rif_RDA'], 'rif_rda' => $ra['rif_rda'],
'stato_versamento' => 'da_versare', // Default 'stato_versamento' => 'da_versare', // Default
'metadati_gescon' => json_encode($ra), 'metadati_gescon' => json_encode($ra),
]); ]);
@ -753,13 +754,13 @@ private function importIncassiEstrattoConto(string $year, string $mdbPath): int
'tenant_id' => $this->tenantId, 'tenant_id' => $this->tenantId,
'gestione_id' => $gestioneId, 'gestione_id' => $gestioneId,
'id_gescon' => $inc['protocollo'] ?? null, 'id_gescon' => $inc['protocollo'] ?? null,
'data_operazione' => $this->parseGesconDate($inc['Data_pag'] ?? null), 'data_operazione' => $this->parseGesconDate($inc['data_pag'] ?? null),
'data_valuta' => $this->parseGesconDate($inc['Data_pag'] ?? null), 'data_valuta' => $this->parseGesconDate($inc['data_pag'] ?? null),
'importo' => (float) ($inc['Importo'] ?? 0), 'importo' => (float) ($inc['importo'] ?? 0),
'descrizione' => trim(($inc['Descrizione_Aggiuntiva'] ?? '') . ' ' . ($inc['Nome_condomino'] ?? '')), 'descrizione' => trim(($inc['descrizione_aggiuntiva'] ?? '') . ' ' . ($inc['nome_condomino'] ?? '')),
'ordinante' => $inc['Nome_condomino'] ?? null, 'ordinante' => $inc['nome_condomino'] ?? null,
'riferimento_bancario' => $inc['Num_incasso'] ?? null, 'riferimento_bancario' => $inc['num_incasso'] ?? null,
'file_origine' => $inc['Nome_file_pdf'] ?? null, 'file_origine' => $inc['nome_file_pdf'] ?? null,
'stato' => 'da_riconciliare', 'stato' => 'da_riconciliare',
'metadati_gescon' => json_encode($inc), 'metadati_gescon' => json_encode($inc),
]); ]);
@ -820,7 +821,7 @@ private function importRateEmesse(string $year, string $mdbPath): int
private function determineGestioneId(string $year, array $operazione): int private function determineGestioneId(string $year, array $operazione): int
{ {
$gestione = $operazione['gestione'] ?? 'O'; $gestione = $operazione['gestione'] ?? 'O';
$nStra = (int) ($operazione['N_STRA'] ?? 0); $nStra = (int) ($operazione['n_stra'] ?? 0);
switch (strtoupper($gestione)) { switch (strtoupper($gestione)) {
case 'R': case 'R':
@ -940,7 +941,7 @@ private function parseMdbOutput(string $output): array
return []; return [];
} }
$headers = array_map('trim', explode("\t", array_shift($lines))); $headers = array_map('strtolower', array_map('trim', explode("\t", array_shift($lines))));
$headerCount = count($headers); $headerCount = count($headers);
$data = []; $data = [];
@ -1019,7 +1020,12 @@ private function parseGesconDate($dateValue): ?string
} }
// Prova vari formati date Gescon/Access // Prova vari formati date Gescon/Access
$formats = ['Y-m-d', 'd/m/Y', 'm/d/Y', 'Y-m-d H:i:s']; $formats = [
'm/d/y H:i:s', 'd/m/y H:i:s',
'd/m/y', 'm/d/y', 'y-m-d',
'Y-m-d H:i:s', 'd/m/Y H:i:s', 'm/d/Y H:i:s',
'Y-m-d', 'd/m/Y', 'm/d/Y',
];
foreach ($formats as $format) { foreach ($formats as $format) {
$date = \DateTime::createFromFormat($format, $dateValue); $date = \DateTime::createFromFormat($format, $dateValue);

View File

@ -213,7 +213,6 @@ class="inline-flex items-center rounded-md border border-cyan-300 bg-white px-3
<th class="px-2 py-2 text-left">Fattura</th> <th class="px-2 py-2 text-left">Fattura</th>
<th class="px-2 py-2 text-left">Servizio / codici</th> <th class="px-2 py-2 text-left">Servizio / codici</th>
<th class="px-2 py-2 text-left">Periodo FE</th> <th class="px-2 py-2 text-left">Periodo FE</th>
<th class="px-2 py-2 text-left">Finestra lettura</th>
<th class="px-2 py-2 text-right">Mc</th> <th class="px-2 py-2 text-right">Mc</th>
<th class="px-2 py-2 text-right">Spesa</th> <th class="px-2 py-2 text-right">Spesa</th>
<th class="px-2 py-2 text-left">Azioni</th> <th class="px-2 py-2 text-left">Azioni</th>
@ -241,6 +240,8 @@ class="rounded border-cyan-300 text-cyan-600 focus:ring-cyan-500">
<span class="inline-flex items-center rounded-md bg-green-50 dark:bg-green-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-green-700 dark:text-green-300 ring-1 ring-inset ring-green-600/20">Pagata il {{ $row['registrata_data_pagamento'] }}</span> <span class="inline-flex items-center rounded-md bg-green-50 dark:bg-green-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-green-700 dark:text-green-300 ring-1 ring-inset ring-green-600/20">Pagata il {{ $row['registrata_data_pagamento'] }}</span>
@elseif($row['registrata_stato'] === 'da_pagare') @elseif($row['registrata_stato'] === 'da_pagare')
<span class="inline-flex items-center rounded-md bg-amber-50 dark:bg-amber-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-amber-700 dark:text-amber-300 ring-1 ring-inset ring-amber-600/20">Debito ( {{ number_format($row['registrata_netto_da_pagare'], 2, ',', '.') }})</span> <span class="inline-flex items-center rounded-md bg-amber-50 dark:bg-amber-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-amber-700 dark:text-amber-300 ring-1 ring-inset ring-amber-600/20">Debito ( {{ number_format($row['registrata_netto_da_pagare'], 2, ',', '.') }})</span>
@elseif(!empty($row['legacy_id']))
<span class="inline-flex items-center rounded-md bg-cyan-50 dark:bg-cyan-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-600/20">Registrata in Prima Nota</span>
@else @else
<span class="inline-flex items-center rounded-md bg-gray-50 dark:bg-gray-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-gray-700 dark:text-gray-300 ring-1 ring-inset ring-gray-600/20">Da registrare</span> <span class="inline-flex items-center rounded-md bg-gray-50 dark:bg-gray-950/30 px-1.5 py-0.5 text-[10px] font-semibold text-gray-700 dark:text-gray-300 ring-1 ring-inset ring-gray-600/20">Da registrare</span>
@endif @endif
@ -270,13 +271,6 @@ class="rounded border-cyan-300 text-cyan-600 focus:ring-cyan-500">
</div> </div>
@endif @endif
</td> </td>
<td class="px-2 py-2 align-top">
@if($row['ha_finestra'])
<span class="inline-block rounded bg-emerald-100 px-1.5 py-0.5 font-semibold text-emerald-700">{{ $row['finestra_label'] }}</span>
@else
<span class="text-gray-400"></span>
@endif
</td>
<td class="px-2 py-2 text-right align-top whitespace-nowrap">{{ number_format((float) ($row['totale_mc'] ?? 0), 3, ',', '.') }}</td> <td class="px-2 py-2 text-right align-top whitespace-nowrap">{{ number_format((float) ($row['totale_mc'] ?? 0), 3, ',', '.') }}</td>
<td class="px-2 py-2 text-right align-top whitespace-nowrap">{{ number_format((float) ($row['totale_spesa'] ?? 0), 2, ',', '.') }}</td> <td class="px-2 py-2 text-right align-top whitespace-nowrap">{{ number_format((float) ($row['totale_spesa'] ?? 0), 2, ',', '.') }}</td>
<td class="px-2 py-2 align-top"> <td class="px-2 py-2 align-top">
@ -290,7 +284,7 @@ class="rounded border-cyan-300 text-cyan-600 focus:ring-cyan-500">
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="8" class="px-2 py-4 text-center text-cyan-700 dark:text-cyan-300">Nessuna FE riscaldamento estratta nello storico attivo.</td> <td colspan="7" class="px-2 py-4 text-center text-cyan-700 dark:text-cyan-300">Nessuna FE riscaldamento estratta nello storico attivo.</td>
</tr> </tr>
@endforelse @endforelse
</tbody> </tbody>