Precarga únicamente la fuente aprobada Tablas de yacimiento y areas(1).xlsx con jerarquía Departamento → Área → Yacimiento, concesiones y Operadoras. Corrige además el CHECK legacy F4 para permitir contexto físico de Área sin snapshot obligatorio de Empresa. El reset preserva usuarios/RBAC y catálogos/configuración técnica, y valida cardinalidades exactas antes de completar.
87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import test from 'node:test';
|
|
import { F61_PRESENTATION_TERRITORY_SOURCE } from '../../src/reference-data/f6-1-presentation-territory-source';
|
|
|
|
function key(value: string): string {
|
|
return value.normalize('NFD')
|
|
.replace(/[\u0300-\u036f]/g, '')
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, ' ')
|
|
.trim()
|
|
.replace(/\s+/g, ' ');
|
|
}
|
|
|
|
test('F6.1 presentation territory snapshot matches the approved spreadsheet cardinalities', () => {
|
|
const source = F61_PRESENTATION_TERRITORY_SOURCE;
|
|
const rows = source.rows;
|
|
|
|
assert.equal(source.file, 'Tablas de yacimiento y areas(1).xlsx');
|
|
assert.equal(source.sheet, 'cr26e_tabla1');
|
|
assert.equal(source.sha256, 'afc8991eed0c0175cf121b6e11e6ca7cc5459ba371c5a186966706e386033cdb');
|
|
assert.equal(rows.length, 230);
|
|
|
|
const areas = new Map<string, typeof rows[number][]>();
|
|
for (const row of rows) {
|
|
const id = key(row.area);
|
|
const current = areas.get(id) ?? [];
|
|
current.push(row);
|
|
areas.set(id, current);
|
|
}
|
|
|
|
const pairs = new Set(rows.map((row) => `${key(row.area)}|${key(row.yacimiento)}`));
|
|
const departments = new Set(rows.map((row) => key(row.departamento)));
|
|
const companies = new Set(
|
|
rows
|
|
.map((row) => row.empresaOperadora)
|
|
.filter((name) => key(name) !== key('Sin Empresa Operadora'))
|
|
.map(key),
|
|
);
|
|
const areasWithoutOperator = [...areas.values()]
|
|
.filter((sameArea) => key(sameArea[0]!.empresaOperadora) === key('Sin Empresa Operadora'));
|
|
const concessions = new Set(rows.map((row) => row.tipoConcesion));
|
|
|
|
assert.equal(areas.size, 64);
|
|
assert.equal(pairs.size, 230);
|
|
assert.equal(departments.size, 7);
|
|
assert.equal(companies.size, 12);
|
|
assert.equal(areasWithoutOperator.length, 17);
|
|
assert.deepEqual([...concessions].sort((a, b) => a.localeCompare(b, 'es')), ['Exploración', 'Explotación']);
|
|
|
|
for (const [area, sameArea] of areas) {
|
|
assert.equal(new Set(sameArea.map((row) => key(row.departamento))).size, 1, `${area}: Departamento conflictivo`);
|
|
assert.equal(new Set(sameArea.map((row) => key(row.tipoConcesion))).size, 1, `${area}: concesión conflictiva`);
|
|
assert.equal(new Set(sameArea.map((row) => key(row.empresaOperadora))).size, 1, `${area}: Operadora conflictiva`);
|
|
}
|
|
});
|
|
|
|
test('F6.1 presentation reset preserves system masters and enforces the physical hierarchy', () => {
|
|
const migration = readFileSync(
|
|
resolve(process.cwd(), 'src/database/migrations/1790094600000-f6-1-presentation-territory-reset.ts'),
|
|
'utf8',
|
|
);
|
|
|
|
assert.match(migration, /TRUNCATE TABLE assets CASCADE/);
|
|
assert.match(migration, /TRUNCATE TABLE audit_events/);
|
|
assert.doesNotMatch(migration, /TRUNCATE TABLE users/i);
|
|
assert.doesNotMatch(migration, /TRUNCATE TABLE roles/i);
|
|
assert.doesNotMatch(migration, /TRUNCATE TABLE permissions/i);
|
|
assert.doesNotMatch(migration, /TRUNCATE TABLE inventory_families/i);
|
|
assert.doesNotMatch(migration, /TRUNCATE TABLE finding_catalog_items/i);
|
|
|
|
assert.match(migration, /area_company_relations/);
|
|
assert.match(migration, /area_legal_rights/);
|
|
assert.match(migration, /key\(row\.empresaOperadora\)!==key\(NO_OPERATOR\)/);
|
|
for (const contract of [
|
|
/total_assets:313/,
|
|
/companies:12/,
|
|
/departments:7/,
|
|
/areas:64/,
|
|
/yacimientos:230/,
|
|
/legal_rights:64/,
|
|
/operators:47/,
|
|
/areas_without_operator:17/,
|
|
]) assert.match(migration, contract);
|
|
});
|