Corrige creación de Inspección, separa Departamento→Área→Yacimiento, elimina el UPDATE oculto de checklist en lectura, integra Preparación para campo como etapa de Inspección, limita operaciones Android al Yacimiento, preserva scope en edición, auto-incluye Inventarios accionables, valida Operadora a plannedStartAt y recompila Android 0.15.2/vc24 con el ícono exacto de presentación.
95 lines
5.4 KiB
TypeScript
95 lines
5.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
function source(path: string) {
|
|
return readFileSync(resolve(process.cwd(), path), 'utf8');
|
|
}
|
|
|
|
test('F6 models concrete Installation 1→N Subinstallations while each child keeps exactly one physical parent', () => {
|
|
const asset = source('src/database/entities/asset.entity.ts');
|
|
const migration = source('src/database/migrations/1790091000000-f6-solid-inventory-model.ts');
|
|
|
|
assert.match(asset, /@Column\(\{ name: 'parent_id', type: 'uuid', nullable: true \}\)/);
|
|
assert.match(asset, /parentId!: string \| null/);
|
|
assert.match(migration, /IF child_type='subinstalacion' THEN/);
|
|
assert.match(migration, /IF NEW\.parent_id IS NULL THEN/);
|
|
assert.doesNotMatch(asset, /parentIds!/);
|
|
});
|
|
|
|
test('F6 makes technical Installation↔Subinstallation compatibility truly many-to-many', () => {
|
|
const migration = source('src/database/migrations/1790091000000-f6-solid-inventory-model.ts');
|
|
const catalog = source('src/asset-master/inventory-family-catalog.service.ts');
|
|
|
|
assert.match(migration, /PRIMARY KEY \(child_family_id,parent_family_id\)/);
|
|
assert.match(catalog, /parentFamilyIds: string\[\]/);
|
|
assert.match(catalog, /requestedIds:string\[\]/);
|
|
assert.match(catalog, /INSERT INTO inventory_family_parent_rules\(child_family_id,parent_family_id\)/);
|
|
assert.match(catalog, /UNNEST\(\$2::uuid\[\]\)/);
|
|
assert.match(catalog, /ON CONFLICT \(child_family_id,parent_family_id\) DO NOTHING/);
|
|
});
|
|
|
|
test('F6 database rejects a Subinstallation classification incompatible with its concrete Installation parent', () => {
|
|
const migration = source('src/database/migrations/1790091000000-f6-solid-inventory-model.ts');
|
|
|
|
assert.match(migration, /SELECT inventory_family_id INTO parent_family FROM assets WHERE id=NEW\.parent_id/);
|
|
assert.match(migration, /rule\.child_family_id=NEW\.inventory_family_id AND rule\.parent_family_id=parent_family/);
|
|
assert.match(migration, /La clasificación de Subinstalación no es compatible con la Instalación padre/);
|
|
});
|
|
|
|
test('F6 technical values are defined by classification and cannot leak between families', () => {
|
|
const migration = source('src/database/migrations/1790091000000-f6-solid-inventory-model.ts');
|
|
const service = source('src/asset-master/inventory-technical-values.service.ts');
|
|
|
|
assert.match(migration, /CREATE TABLE IF NOT EXISTS inventory_family_attribute_definitions/);
|
|
assert.match(migration, /CREATE TABLE IF NOT EXISTS asset_inventory_attribute_values/);
|
|
assert.match(migration, /El campo técnico no pertenece a la clasificación del Inventario/);
|
|
assert.match(service, /inventory_family_attribute_definitions/);
|
|
assert.match(service, /asset_inventory_attribute_values/);
|
|
});
|
|
|
|
test('F6 field findings resolve by exact technical classification and keep OTROS available', () => {
|
|
const resolver = source('src/inspection-findings/f3-finding-catalog-resolver.service.ts');
|
|
|
|
assert.match(resolver, /mapping\.inventory_family_id=\$1::uuid/);
|
|
assert.match(resolver, /asset\.inventory_family_id AS "familyId"/);
|
|
assert.doesNotMatch(resolver, /category\.code='f5model'/);
|
|
assert.match(resolver, /code: 'OTHER'/);
|
|
assert.match(resolver, /label: 'OTROS'/);
|
|
});
|
|
|
|
test('F6.1 mobile finding gate uses Yacimiento scope and temporal Area operator relation instead of Inventory company ownership', () => {
|
|
const fieldFindings = source('src/inspection-visits/field-findings.service.ts');
|
|
|
|
assert.match(fieldFindings, /WITH RECURSIVE ancestors/);
|
|
assert.match(fieldFindings, /COALESCE\(visit\.scope_asset_id, visit\.operational_area_id\)/);
|
|
assert.match(fieldFindings, /AS "insideScope"/);
|
|
assert.match(fieldFindings, /FROM area_company_relations relation/);
|
|
assert.match(fieldFindings, /relation\.relation_role='OPERATOR'/);
|
|
assert.doesNotMatch(fieldFindings, /asset\.operator_company_id=visit\.operator_company_id/);
|
|
});
|
|
|
|
test('F6 field-created technical Inventory may be provisional only until the selected family is assigned', () => {
|
|
const migration = source('src/database/migrations/1790091000000-f6-solid-inventory-model.ts');
|
|
const fieldStructure = source('src/inspection-visits/f3-field-inventory-structure.service.ts');
|
|
const fieldFindings = source('src/inspection-visits/field-findings.service.ts');
|
|
|
|
assert.match(migration, /NEW\.data_origin='FIELD_SURVEY' AND NEW\.information_status='DRAFT'/);
|
|
assert.match(fieldStructure, /SET inventory_family_id=\$2::uuid/);
|
|
assert.match(fieldFindings, /FIELD_FINDING_FAMILY_REQUIRED/);
|
|
});
|
|
|
|
test('F6.1 Android roots search and reload at the Inspection Yacimiento with legacy Area fallback', () => {
|
|
const model = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/data/DhMobile.kt');
|
|
const viewModel = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/MainViewModel.kt');
|
|
const screen = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/F3VisitRoot.kt');
|
|
|
|
assert.match(model, /data class VisitDetail[\s\S]*val scopeAsset: AssetSummary\? = null/);
|
|
assert.match(viewModel, /var inventoryParentId: String\? by mutableStateOf\(null\)/);
|
|
assert.match(viewModel, /currentVisit\.scopeAsset\?\.id \?: currentVisit\.operationalArea\?\.id/);
|
|
assert.match(viewModel, /visit\?\.scopeAsset\?\.id \?: visit\?\.operationalArea\?\.id/);
|
|
assert.match(viewModel, /repository\.fieldInventory\(currentVisit\.id, null, effectiveParentId\)/);
|
|
assert.match(screen, /model\.loadFieldTypes\(item\.id\)/);
|
|
});
|