diff --git a/api-v3/src/asset-master/inventory-structure.service.ts b/api-v3/src/asset-master/inventory-structure.service.ts index 196f427..9424d9f 100644 --- a/api-v3/src/asset-master/inventory-structure.service.ts +++ b/api-v3/src/asset-master/inventory-structure.service.ts @@ -38,8 +38,10 @@ type ParentRow = { typeCode: string; inventoryFamilyId: string | null; }; +type IdRow = { id: string }; const TYPE_CODE_BY_KIND: Record, string> = { + DEPARTAMENTO: 'departamento', AREA: 'area', YACIMIENTO: 'yacimiento', INSTALACION: 'instalacion', @@ -47,7 +49,8 @@ const TYPE_CODE_BY_KIND: Record, stri }; const PARENT_TYPE_BY_KIND: Record = { EMPRESA: null, - AREA: null, + DEPARTAMENTO: null, + AREA: 'departamento', YACIMIENTO: 'area', INSTALACION: 'yacimiento', SUBINSTALACION: 'instalacion', @@ -70,22 +73,24 @@ export class InventoryStructureService { SELECT id,code,name FROM asset_types WHERE ( - lower(code) IN ('area','yacimiento','instalacion','subinstalacion') + lower(code) IN ('departamento','area','yacimiento','instalacion','subinstalacion') OR operational_role='COMPANY' ) AND is_active=true ORDER BY CASE WHEN operational_role='COMPANY' THEN 0 - WHEN lower(code)='area' THEN 1 - WHEN lower(code)='yacimiento' THEN 2 - WHEN lower(code)='instalacion' THEN 3 - WHEN lower(code)='subinstalacion' THEN 4 ELSE 9 END + WHEN lower(code)='departamento' THEN 1 + WHEN lower(code)='area' THEN 2 + WHEN lower(code)='yacimiento' THEN 3 + WHEN lower(code)='instalacion' THEN 4 + WHEN lower(code)='subinstalacion' THEN 5 ELSE 9 END `)) as StructureTypeRow[]; const company = types.find((item) => ['empresa','organizacion'].includes(item.code.toLowerCase())); + const departamento = types.find((item) => item.code.toLowerCase()==='departamento'); const area = types.find((item) => item.code.toLowerCase()==='area'); const yacimiento = types.find((item) => item.code.toLowerCase()==='yacimiento'); const instalacion = types.find((item) => item.code.toLowerCase()==='instalacion'); const subinstalacion = types.find((item) => item.code.toLowerCase()==='subinstalacion'); - if (!company || !area || !yacimiento || !instalacion || !subinstalacion) { + if (!company || !departamento || !area || !yacimiento || !instalacion || !subinstalacion) { throw new ConflictException({ code: 'INVENTORY_STRUCTURE_TYPES_INCOMPLETE', message: 'La configuración maestra de Empresa e Inventario todavía no está completa', @@ -109,7 +114,8 @@ export class InventoryStructureService { { kind: 'EMPRESA', label: 'Empresa', type: company, parentKind: null, requiresFamily: false }, ], levels: [ - { kind: 'AREA', label: 'Área', type: area, parentKind: null, requiresFamily: false }, + { kind: 'DEPARTAMENTO', label: 'Departamento', type: departamento, parentKind: null, requiresFamily: false }, + { kind: 'AREA', label: 'Área', type: area, parentKind: 'DEPARTAMENTO', requiresFamily: false }, { kind: 'YACIMIENTO', label: 'Yacimiento', type: yacimiento, parentKind: 'AREA', requiresFamily: false }, { kind: 'INSTALACION', label: 'Instalación', type: instalacion, parentKind: 'YACIMIENTO', requiresFamily: true }, { kind: 'SUBINSTALACION', label: 'Subinstalación', type: subinstalacion, parentKind: 'INSTALACION', requiresFamily: true }, @@ -121,7 +127,7 @@ export class InventoryStructureService { async parents(kindValue: string, search?: string) { const kind = kindValue.toUpperCase() as InventoryStructureKind; - if (!(kind in PARENT_TYPE_BY_KIND) || kind === 'AREA' || kind === 'EMPRESA') { + if (!(kind in PARENT_TYPE_BY_KIND) || kind === 'DEPARTAMENTO' || kind === 'EMPRESA') { throw new BadRequestException({ code: 'INVENTORY_STRUCTURE_PARENT_KIND_INVALID', message: 'El nivel indicado no requiere un registro padre', @@ -153,7 +159,7 @@ export class InventoryStructureService { AND asset.information_status<>'INACTIVE' ${searchSql} ORDER BY asset.name,asset.code - LIMIT 80 + LIMIT 100 `, parameters); return { data: rows }; } @@ -169,7 +175,9 @@ export class InventoryStructureService { const parent = await this.requireParent(manager, dto.kind, dto.parentId ?? null); const family = await this.requireFamily(manager, dto.kind, dto.familyId ?? null, parent); const generatedCode = dto.code?.trim().toUpperCase() || this.generatedCode(dto.kind, dto.name); - const operationalAreaId = parent ? await this.resolveAreaId(manager, parent) : null; + const operationalAreaId = parent && ['YACIMIENTO','INSTALACION','SUBINSTALACION'].includes(dto.kind) + ? await this.resolveAreaId(manager, parent) + : null; const inserted = (await manager.query(` INSERT INTO assets ( @@ -193,9 +201,9 @@ export class InventoryStructureService { AssetInformationStatus.DRAFT, AssetOperationalStatus.UNKNOWN, AssetDataOrigin.MANUAL, - dto.kind === 'EMPRESA' ? 'Maestro de Empresas F5' : 'Estructura de Inventario F5', + dto.kind === 'EMPRESA' ? 'Maestro manual de Empresas F5.1' : 'Estructura manual de Inventario F5.1', dto.kind === 'EMPRESA' ? 'inventory-master:empresa' : `inventory-structure:${dto.kind.toLowerCase()}`, - family ? `Familia técnica: ${family.code} · ${family.name}` : null, + family ? `Clasificación técnica: ${family.code} · ${family.name}` : null, principal.userId, ])) as Array<{ id: string }>; const id = inserted[0]?.id; @@ -225,7 +233,7 @@ export class InventoryStructureService { id, parent?.id ?? null, operationalAreaId, - dto.kind === 'EMPRESA' ? 'Alta guiada de Empresa independiente F5' : 'Alta guiada de estructura de Inventario F5', + dto.kind === 'EMPRESA' ? 'Alta manual de Empresa independiente F5.1' : 'Alta manual de estructura de Inventario F5.1', versionNumber, request.requestId, principal.userId, @@ -285,7 +293,7 @@ export class InventoryStructureService { code: 'INVENTORY_ROOT_MUST_NOT_HAVE_PARENT', message: kind === 'EMPRESA' ? 'Una Empresa es un maestro independiente y no puede tener padre' - : 'Un Área es un registro raíz y no puede tener padre', + : 'Un Departamento es un registro raíz y no puede tener padre', }); } return null; @@ -309,7 +317,7 @@ export class InventoryStructureService { if (parent.typeCode.toLowerCase() !== expectedType) { throw new BadRequestException({ code: 'INVENTORY_STRUCTURE_PARENT_INVALID', - message: 'La jerarquía requerida es Área → Yacimiento → Instalación → Subinstalación', + message: 'La jerarquía requerida es Departamento → Área → Yacimiento → Instalación → Subinstalación', }); } return parent; @@ -349,13 +357,13 @@ export class InventoryStructureService { if (!expectedLevel) { if (familyId) throw new BadRequestException({ code: 'INVENTORY_STRUCTURE_FAMILY_NOT_ALLOWED', - message: 'Empresa, Área y Yacimiento no llevan familia técnica', + message: 'Empresa, Departamento, Área y Yacimiento no llevan clasificación técnica', }); return null; } if (!familyId) throw new BadRequestException({ code: 'INVENTORY_STRUCTURE_FAMILY_REQUIRED', - message: `Elegí la familia técnica de la ${kind.toLowerCase()}`, + message: `Elegí la clasificación técnica de la ${kind.toLowerCase()}`, }); const rows = (await manager.query(` SELECT family.id,family.code,family.name,family.level, @@ -369,22 +377,27 @@ export class InventoryStructureService { LIMIT 1 `, [familyId])) as FamilyRow[]; const family = rows[0]; - if (!family) throw new NotFoundException({ code: 'INVENTORY_FAMILY_NOT_FOUND', message: 'La familia técnica no existe' }); + if (!family) throw new NotFoundException({ code: 'INVENTORY_FAMILY_NOT_FOUND', message: 'La clasificación técnica no existe' }); if (family.level !== expectedLevel) throw new BadRequestException({ code: 'INVENTORY_FAMILY_LEVEL_INVALID', - message: 'La familia técnica no corresponde al nivel seleccionado', + message: 'La clasificación técnica no corresponde al nivel seleccionado', }); if (kind === 'SUBINSTALACION' && family.parentFamilyId !== parent?.inventoryFamilyId) { throw new BadRequestException({ code: 'INVENTORY_SUBINSTALLATION_FAMILY_PARENT_INVALID', - message: 'La Subinstalación elegida no pertenece a la familia de la Instalación seleccionada', + message: 'La Subinstalación elegida no pertenece a la clasificación de la Instalación seleccionada', }); } return family; } private generatedCode(kind: InventoryStructureKind, name: string): string { - const prefix = kind === 'EMPRESA' ? 'EMP' : kind === 'YACIMIENTO' ? 'YAC' : kind === 'INSTALACION' ? 'INST' : kind === 'SUBINSTALACION' ? 'SUB' : 'AREA'; + const prefix = kind === 'EMPRESA' ? 'EMP' + : kind === 'DEPARTAMENTO' ? 'DEP' + : kind === 'AREA' ? 'AREA' + : kind === 'YACIMIENTO' ? 'YAC' + : kind === 'INSTALACION' ? 'INST' + : 'SUB'; const readable = name .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') @@ -417,5 +430,3 @@ export class InventoryStructureService { return rows[0]; } } - -type IdRow = { id: string };