Files
Investidor-V2/tools/repair-territory-designations.php
2026-09-29 08:41:57 +02:00

59 lines
3.0 KiB
PHP

<?php
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\DB;
require __DIR__.'/../vendor/autoload.php';
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
if (! $app->environment('local') || DB::connection()->getDriverName() !== 'pgsql') {
throw new RuntimeException('Local PostgreSQL only.');
}
$root = storage_path('app/private/');
$before = json_decode(file_get_contents($root.'territory-workbook-candidates-before-designation-fix.json'), true, 512, JSON_THROW_ON_ERROR);
$after = json_decode(file_get_contents($root.'territory-workbook-candidates.json'), true, 512, JSON_THROW_ON_ERROR);
if (($after['mapping_version'] ?? 0) !== 2 || $before['checksum'] !== $after['checksum'] || hash_file('sha256', 'C:/Mac/Home/Documents/eBAU/cartografia_moz.xlsx') !== $after['checksum']) {
throw new RuntimeException('Source or mapping mismatch.');
}
$old = array_column($before['nodes'], null, 'id');
$new = array_column($after['nodes'], null, 'id');
$result = DB::transaction(function () use ($old, $new, $after) {
DB::select('SELECT pg_advisory_xact_lock(280926, 150000)');
$renamed = $quarantined = 0;
foreach ($old as $id => $prior) {
$record = DB::table('geo_locations')->where('id', $id)->where('source_system', 'cartografia-workbook')->where('external_id', $after['checksum'].':'.$id)->lockForUpdate()->first();
if (! $record || $record->parent_id !== $prior['parent_id'] || $record->code !== $prior['code'] || $record->location_type !== $prior['location_type']) {
throw new RuntimeException('Existing reference changed: '.$id);
}
$desired = $new[$id] ?? null;
if (! $desired) {
if ($record->deleted_at === null) {
DB::table('geo_locations')->where('id', $id)->update(['data_classification' => 'internal', 'deleted_at' => now(), 'version_no' => $record->version_no + 1]);
$quarantined++;
}
continue;
}
if ($record->name === $desired['name']) {
continue;
}
if ($record->name !== $prior['name'] || $record->deleted_at !== null) {
throw new RuntimeException('Manual edit must not be overwritten: '.$id);
}
DB::table('geo_locations')->where('id', $id)->update(['name' => $desired['name'], 'version_no' => $record->version_no + 1]);
$renamed++;
}
foreach ($new as $id => $node) {
if (! isset($old[$id])) {
throw new RuntimeException('Unexpected identity change: '.$id);
}
}
$result = ['renamed' => $renamed, 'quarantined' => $quarantined, 'mapping_version' => 2, 'checksum' => $after['checksum']];
if ($renamed || $quarantined) {
DB::table('audit_events')->insert(['source_system' => 'cartografia-workbook', 'entity_type' => 'geo_locations', 'action' => 'designation_mapping_corrected', 'after_data' => json_encode($result, JSON_THROW_ON_ERROR)]);
}
return $result;
});
echo json_encode($result, JSON_THROW_ON_ERROR).PHP_EOL;