252 lines
8.9 KiB
PHP
252 lines
8.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Contatore;
|
|
use App\Models\LetturaContatore;
|
|
use App\Models\UnitaImmobiliare;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Carbon\Carbon;
|
|
|
|
class GesconCoreMigrationService
|
|
{
|
|
/**
|
|
* Esporta una tabella MDB in array di righe associative.
|
|
*/
|
|
private function mdbExportToRows(string $mdbPath, array $tableCandidates): array
|
|
{
|
|
$binTables = trim((string) @shell_exec('command -v mdb-tables')) ?: '/usr/bin/mdb-tables';
|
|
$binExport = trim((string) @shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
if (! is_file($mdbPath) || ! is_readable($mdbPath)) {
|
|
return [];
|
|
}
|
|
|
|
$tables = @shell_exec(sprintf('%s -1 %s 2>/dev/null', escapeshellarg($binTables), escapeshellarg($mdbPath))) ?: '';
|
|
$table = null;
|
|
if ($tables) {
|
|
$names = array_filter(preg_split('/\r?\n/', trim($tables)));
|
|
foreach ($tableCandidates as $cand) {
|
|
foreach ($names as $n) {
|
|
if (strcasecmp($n, $cand) === 0) {
|
|
$table = $n;
|
|
break 2;
|
|
}
|
|
}
|
|
}
|
|
if (! $table) {
|
|
foreach ($tableCandidates as $cand) {
|
|
foreach ($names as $n) {
|
|
if (stripos($n, $cand) !== false) {
|
|
$table = $n;
|
|
break 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (! $table) {
|
|
return [];
|
|
}
|
|
|
|
$csv = @shell_exec(sprintf('%s -d "," %s %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg($mdbPath), escapeshellarg($table))) ?: '';
|
|
if ($csv === '') {
|
|
return [];
|
|
}
|
|
|
|
$lines = preg_split('/\r?\n/', trim($csv));
|
|
if (count($lines) < 2) {
|
|
return [];
|
|
}
|
|
|
|
$headers = str_getcsv(array_shift($lines));
|
|
$headers = array_map(fn($h) => strtolower(trim((string)$h)), $headers);
|
|
|
|
$results = [];
|
|
foreach ($lines as $line) {
|
|
if (trim($line) === '') {
|
|
continue;
|
|
}
|
|
$row = str_getcsv($line);
|
|
if (count($row) !== count($headers)) {
|
|
$row = array_pad($row, count($headers), null);
|
|
}
|
|
$results[] = array_combine($headers, $row);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Importa le letture acqua dal file master generale_stabile.mdb.
|
|
*/
|
|
public function importLettureAcqua(string $stabileCode, string $rootPath): int
|
|
{
|
|
$generaleMdb = rtrim($rootPath, '/') . '/' . $stabileCode . '/generale_stabile.mdb';
|
|
if (! is_file($generaleMdb)) {
|
|
return 0;
|
|
}
|
|
|
|
// 1. Build map from acqua_gen: Rif_ute => Rif_anno
|
|
$acquaGen = $this->mdbExportToRows($generaleMdb, ['acqua_gen', 'Acqua_gen', 'ACQUA_GEN']);
|
|
$acquaGenMap = [];
|
|
foreach ($acquaGen as $gen) {
|
|
$rifUte = $gen['rif_ute'] ?? null;
|
|
$rifAnno = $gen['rif_anno'] ?? null;
|
|
if ($rifUte !== null) {
|
|
$acquaGenMap[$rifUte] = $rifAnno;
|
|
}
|
|
}
|
|
|
|
// 2. Load acqua_dett rows (including versioned variants like acqua_dett1)
|
|
$rows1 = $this->mdbExportToRows($generaleMdb, ['acqua_dett', 'Acqua_dett', 'ACQUA_DETT']);
|
|
$rows2 = $this->mdbExportToRows($generaleMdb, ['acqua_dett1', 'Acqua_dett1', 'ACQUA_DETT1']);
|
|
$acquaDett = array_merge($rows1, $rows2);
|
|
if (empty($acquaDett)) {
|
|
return 0;
|
|
}
|
|
|
|
// 3. Resolve Stabile ID
|
|
$stabile = DB::table('stabili')
|
|
->where('codice_stabile', $stabileCode)
|
|
->first();
|
|
if (! $stabile) {
|
|
return 0;
|
|
}
|
|
|
|
$count = 0;
|
|
|
|
foreach ($acquaDett as $row) {
|
|
$rifUte = $row['rif_ute'] ?? null;
|
|
$idCond = $row['id_cond'] ?? null;
|
|
$condInq = strtoupper(trim((string) ($row['cond_inquil'] ?? 'C')));
|
|
$tCodCond = trim((string) ($row['t_cod_cond'] ?? ''));
|
|
|
|
if ($idCond === null || $rifUte === null) {
|
|
continue;
|
|
}
|
|
|
|
// Resolve year from general map
|
|
$year = $acquaGenMap[$rifUte] ?? '2025';
|
|
|
|
// Find Unita ID by legacy_cond_id
|
|
$unita = DB::table('unita_immobiliari')
|
|
->where('stabile_id', $stabile->id)
|
|
->where('legacy_cond_id', $idCond)
|
|
->first();
|
|
|
|
$unitaId = $unita?->id ?? null;
|
|
|
|
if (! $unitaId) {
|
|
// Try fallback to staging condomin
|
|
$condomin = DB::connection('gescon_import')
|
|
->table('condomin')
|
|
->where('cod_stabile', $stabileCode)
|
|
->where('id_cond', $idCond)
|
|
->first();
|
|
|
|
if ($condomin) {
|
|
$scala = $condomin->scala ? trim((string) $condomin->scala) : 'A';
|
|
$interno = $condomin->interno ? trim((string) $condomin->interno) : '';
|
|
if ($interno !== '') {
|
|
$unita = DB::table('unita_immobiliari')
|
|
->where('stabile_id', $stabile->id)
|
|
->where('scala', $scala)
|
|
->where('interno', $interno)
|
|
->first();
|
|
$unitaId = $unita?->id ?? null;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! $unitaId) {
|
|
continue;
|
|
}
|
|
|
|
// Validate: check t_cod_cond match in unita_anagrafica_periodo for that period/year
|
|
$dataLettura = $year . '-12-31';
|
|
|
|
$periodi = DB::table('unita_anagrafica_periodo')
|
|
->where('unita_immobiliare_id', $unitaId)
|
|
->where('data_inizio', '<=', $dataLettura)
|
|
->where(function ($q) use ($dataLettura) {
|
|
$q->whereNull('data_fine')->orWhere('data_fine', '>=', $dataLettura);
|
|
})
|
|
->get();
|
|
|
|
$valid = false;
|
|
foreach ($periodi as $p) {
|
|
$meta = json_decode($p->legacy_metadata, true);
|
|
$pCodCond = trim((string) ($meta['cod_cond'] ?? ''));
|
|
if ($pCodCond !== '' && strcasecmp($pCodCond, $tCodCond) === 0) {
|
|
$valid = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! $valid) {
|
|
// If not valid in pivot timeline, skip reading as requested
|
|
continue;
|
|
}
|
|
|
|
// Resolve readings
|
|
$readings = [
|
|
[
|
|
'precedente' => isset($row['lett_vecchia_1']) ? (float) $row['lett_vecchia_1'] : 0.0,
|
|
'attuale' => isset($row['lett_nuova_1']) ? (float) $row['lett_nuova_1'] : 0.0,
|
|
'num' => 1
|
|
],
|
|
[
|
|
'precedente' => isset($row['lett_vecchia_2']) ? (float) $row['lett_vecchia_2'] : 0.0,
|
|
'attuale' => isset($row['lett_nuova_2']) ? (float) $row['lett_nuova_2'] : 0.0,
|
|
'num' => 2
|
|
],
|
|
[
|
|
'precedente' => isset($row['lett_vecchia_3']) ? (float) $row['lett_vecchia_3'] : 0.0,
|
|
'attuale' => isset($row['lett_nuova_3']) ? (float) $row['lett_nuova_3'] : 0.0,
|
|
'num' => 3
|
|
]
|
|
];
|
|
|
|
foreach ($readings as $reading) {
|
|
if ($reading['attuale'] == 0.0 && $reading['precedente'] == 0.0) {
|
|
continue;
|
|
}
|
|
|
|
// Find or create Contatore for this unit
|
|
$contatore = Contatore::firstOrCreate(
|
|
[
|
|
'stabile_id' => $stabile->id,
|
|
'unita_immobiliare_id' => $unitaId,
|
|
'tipo_contatore' => 'acqua_fredda',
|
|
'numero_contatore' => 'ACQ-' . $unitaId . '-' . $reading['num'],
|
|
],
|
|
[
|
|
'attivo' => true,
|
|
'note' => 'Creato automaticamente da importazione acqua_dett',
|
|
]
|
|
);
|
|
|
|
// Insert reading
|
|
LetturaContatore::updateOrCreate(
|
|
[
|
|
'contatore_id' => $contatore->id,
|
|
'data_lettura' => $dataLettura,
|
|
],
|
|
[
|
|
'lettura_precedente' => $reading['precedente'],
|
|
'lettura_attuale' => $reading['attuale'],
|
|
'tipo_lettura' => 'manuale',
|
|
'validata' => true,
|
|
'note' => 'Importata da acqua_dett. Ruolo legacy: ' . $condInq . ', cod_cond: ' . $tCodCond,
|
|
]
|
|
);
|
|
|
|
$count++;
|
|
}
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
}
|