diff --git a/api-v3/test/unit/f6-1-presentation-territory-source.test.ts b/api-v3/test/unit/f6-1-presentation-territory-source.test.ts new file mode 100644 index 0000000..a1358bc --- /dev/null +++ b/api-v3/test/unit/f6-1-presentation-territory-source.test.ts @@ -0,0 +1,86 @@ +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(); + 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); +});