Files
dh-inspeccion-v2/api-v3/test/unit/f3-1-chronological-merge.test.ts
admin 35d4630581 F5 · Inventario operativo, territorio y catálogo autorizado (#25)
* fix(web): simplify inventory administration menu

* fix(web): remove legacy imports and function catalog routes

* fix(web): remove redundant inspections lifecycle legend

* feat(inventory): distinguish physical instances from structural records

* fix(dashboard): align inventory and act follow-up metrics

* fix(web): align dashboard summary contract

* fix(web): clarify dashboard act and report concepts

* feat(inventory): mark field-created records as real instances

* feat(inventory): map physical instance flag on asset entity

* fix(inventory): keep field yacimientos structural

* feat(inventory): classify future concrete instances at database level

* fix(inventory): count only installation and subinstallation instances

* feat(inventory): add authoritative F5 source snapshot

* feat(inventory): preload authoritative territory model

* feat(inventory): preload authoritative technical catalog

* fix(findings): use only authoritative F5 family catalog

* fix(inventory): preserve non-hierarchical operator snapshot compatibility

* feat(inventory): add inventory-only asset filter

* feat(inventory): add inventory-only tree filter

* feat(inventory): add inventory browser query contract

* feat(inventory): add area-owned inventory browser

* feat(inventory): expose area-owned inventory browser

* refactor(inventory): remove function catalog and add inventory browser

* fix(inventory): make operator relation temporal and non-owning

* feat(web): add inventory browser API client

* feat(inventory): extend inventory browser filters

* feat(inventory): add real inventory list endpoint logic

* feat(inventory): expose real inventory list

* feat(web): add real inventory list client

* refactor(web): make inventory hierarchy area-owned

* fix(web): show only real inventory instances

* fix(web): style act follow-up tabs and F5 inventory context

* fix(web): load F5 flow styles

* fix(inventory): apply area-owned operational guard on F5 up

* fix(inventory): treat company on asset as non-owning creation snapshot

* fix(inventory): resolve field inventory by area hierarchy, not company ownership

* fix(inventory): preserve custom catalog and apply authoritative universal findings

* fix(inventory): harden authoritative catalog migration checks

* fix(inventory): make authoritative territory preload safely reversible

* feat(inventory): allow independent company master creation

* fix(inventory): make guided creation area-owned and support companies

* feat(web): expose independent company master in inventory setup

* feat(web): create companies independently from physical inventory hierarchy

* fix(inventory): merge by physical area and preserve sealed documents

* test(inventory): lock F5 authoritative model and merge invariants

* feat(inventory): add family administration DTOs

* feat(inventory): administer installation and subinstallation classifications

* feat(inventory): expose family classification administration

* feat(web): add inventory classification administration API

* fix(web): configure finding applicability by inventory classification

* fix(web): redefine inventory configuration around hierarchy classifications and columns

* chore(release): identify F5 inventory model

* chore(release): bump API for F5 inventory model

* test(release): expect F5 health metadata

* chore(release): align WEB package with F5 inventory cut

* chore(release): expose F5 WEB phase

* test(dashboard): expect inspector activity and act follow-up metrics

* test(dashboard): route F5 summary query mocks explicitly

* ci: rehearse all migrations on clean PostGIS before merge

* ci: prove F5 migrations revert and reapply cleanly

* test(f5): align operational navigation contract

* test(f5): align operator lifecycle with area-owned inventory

* test(f5): make merge compatibility area-based

* test(f5): distinguish literal and normalized yacimiento counts

* test(f5): model normalized yacimiento collision explicitly

* ci(f5): bootstrap historical admin prerequisite in clean migration rehearsal

* ci(f5): bypass irreversible historical reset in clean rehearsal

* fix(f5): make territory SQL parameter types explicit

* fix(f5): guarantee canonical inventory hierarchy before territory preload

* ci(f5): include canonical hierarchy migration in rollback gate

* fix(f5): type relation backup markers explicitly

* fix(f5): make catalog SQL text parameter types explicit
2026-09-08 23:18:15 -03:00

57 lines
2.7 KiB
TypeScript

import 'reflect-metadata';
import assert from 'node:assert/strict';
import test from 'node:test';
import { readFileSync } from 'node:fs';
const migration = readFileSync(
'src/database/migrations/1789844600000-phase-f3-1-asset-chronological-merge.ts',
'utf8',
);
const service = readFileSync('src/asset-master/inventory-merge.service.ts', 'utf8');
const controller = readFileSync('src/asset-master/inventory-merge.controller.ts', 'utf8');
test('F3.1 registra cada fusión como evento append-only con snapshots', () => {
assert.match(migration, /CREATE TABLE asset_merges/);
assert.match(migration, /source_snapshot jsonb NOT NULL/);
assert.match(migration, /canonical_snapshot jsonb NOT NULL/);
assert.match(migration, /UNIQUE \(source_asset_id\)/);
assert.match(migration, /BEFORE UPDATE OR DELETE ON asset_merges/);
assert.match(migration, /append-only/);
});
test('F3.1/F5 sólo permite fusionar Instalaciones o Subinstalaciones compatibles dentro de la misma Área física', () => {
assert.match(service, /MERGEABLE_TYPES = new Set\(\['instalacion', 'subinstalacion'\]\)/);
assert.match(service, /INVENTORY_MERGE_TYPE_INVALID/);
assert.match(service, /resolvePhysicalAreaId/);
assert.match(service, /INVENTORY_MERGE_AREA_MISMATCH/);
assert.match(service, /INVENTORY_MERGE_PARENT_MISMATCH/);
assert.match(service, /INVENTORY_MERGE_CHILD_FAMILY_CONFLICT/);
assert.doesNotMatch(service, /source\.operatorCompanyId\s*!==\s*canonical\.operatorCompanyId/);
});
test('F3.1 preserva referencias históricas y sólo reubica hijos actuales', () => {
assert.match(service, /historyPolicy: 'HISTORICAL_REFERENCES_PRESERVED'/);
assert.match(service, /historicalReferencesRewritten: false/);
assert.doesNotMatch(service, /UPDATE\s+inspection_findings/i);
assert.doesNotMatch(service, /UPDATE\s+inspection_act_assets/i);
assert.doesNotMatch(service, /UPDATE\s+inspection_visit_assets/i);
assert.match(service, /Reparentado por fusión cronológica/);
assert.match(service, /AssetVersionChangeType\.UPDATED/);
});
test('F3.1 expone estado/merge en WEB y conciliación de alta nacida en la inspección para APK', () => {
assert.match(controller, /:id\/merge-status/);
assert.match(controller, /:id\/merge/);
assert.match(controller, /:assetId\/merge/);
assert.match(controller, /assets\.create/);
assert.match(controller, /inspections\.execute/);
assert.match(service, /FIELD_MERGE_SOURCE_MUST_BE_DISCOVERY/);
assert.match(service, /assertMobileInspector\(principal\)/);
});
test('F3.1 resuelve cadenas de merge hacia un canónico final y detecta ciclos', () => {
assert.match(service, /WITH RECURSIVE chain/);
assert.match(service, /INVENTORY_MERGE_CYCLE/);
assert.match(service, /aliasesFor/);
});