130 lines
5.0 KiB
TypeScript
130 lines
5.0 KiB
TypeScript
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { DataSource } from 'typeorm';
|
|
import type { ListFindingCatalogQueryDto } from './dto/list-finding-catalog-query.dto';
|
|
import { FindingCatalogService } from './finding-catalog.service';
|
|
|
|
@Injectable()
|
|
export class F3FindingCatalogResolverService {
|
|
constructor(
|
|
private readonly dataSource: DataSource,
|
|
private readonly contextualCatalog: FindingCatalogService,
|
|
) {}
|
|
|
|
async listApplicableForAsset(assetId: string, query: ListFindingCatalogQueryDto) {
|
|
const [asset] = await this.dataSource.query(`
|
|
SELECT asset.id,asset.code,asset.name,
|
|
type.code AS "typeCode",
|
|
asset.inventory_family_id AS "familyId",
|
|
family.code AS "familyCode",family.name AS "familyName",family.level AS "familyLevel",
|
|
family.is_active AS "familyActive"
|
|
FROM assets asset
|
|
JOIN asset_types type ON type.id=asset.asset_type_id
|
|
LEFT JOIN inventory_families family ON family.id=asset.inventory_family_id
|
|
WHERE asset.id=$1::uuid
|
|
`, [assetId]) as Array<{
|
|
id: string;
|
|
code: string;
|
|
name: string;
|
|
typeCode: string;
|
|
familyId: string | null;
|
|
familyCode: string | null;
|
|
familyName: string | null;
|
|
familyLevel: string | null;
|
|
familyActive: boolean | null;
|
|
}>;
|
|
if (!asset) {
|
|
throw new NotFoundException({ code: 'ASSET_NOT_FOUND', message: 'Registro de Inventario no encontrado' });
|
|
}
|
|
|
|
const other = {
|
|
enabled: true,
|
|
code: 'OTHER',
|
|
label: 'OTROS',
|
|
help: 'Usalo cuando el Hallazgo no exista entre los asociados a este Inventario. Quedará registrado para revisión en oficina.',
|
|
};
|
|
|
|
if (asset.typeCode.toLowerCase() === 'yacimiento') {
|
|
const contextual = await this.contextualCatalog.listApplicableForAsset(assetId, query);
|
|
return {
|
|
...contextual,
|
|
inventoryFamily: null,
|
|
catalogSource: 'ASSET_TYPE' as const,
|
|
configurationReason: contextual.configurationReason
|
|
?? 'Hallazgos asociados al tipo Yacimiento. OTROS permanece siempre disponible.',
|
|
other,
|
|
};
|
|
}
|
|
|
|
if (!asset.familyId || asset.familyActive !== true) {
|
|
return {
|
|
asset: { id: asset.id, code: asset.code, name: asset.name },
|
|
inventoryFamily: null,
|
|
catalogSource: 'INVENTORY_FAMILY' as const,
|
|
typeConfigured: false,
|
|
configurationReason: 'El elemento todavía no tiene una clasificación técnica activa.',
|
|
categories: [],
|
|
items: [],
|
|
other,
|
|
};
|
|
}
|
|
|
|
const filters = [
|
|
'mapping.inventory_family_id=$1::uuid',
|
|
'item.is_active=true',
|
|
'category.is_active=true',
|
|
'merge_record.source_item_id IS NULL',
|
|
];
|
|
const params: unknown[] = [asset.familyId];
|
|
if (query.categoryId) {
|
|
params.push(query.categoryId);
|
|
filters.push(`category.id=$${params.length}::uuid`);
|
|
}
|
|
if (query.search?.trim()) {
|
|
params.push(`%${query.search.trim()}%`);
|
|
const token = `$${params.length}`;
|
|
filters.push(`(item.title ILIKE ${token} OR COALESCE(item.legal_basis,'') ILIKE ${token} OR COALESCE(item.glossary,'') ILIKE ${token})`);
|
|
}
|
|
|
|
const where = filters.join(' AND ');
|
|
const [categories, items] = await Promise.all([
|
|
this.dataSource.query(`
|
|
SELECT DISTINCT category.id,category.code,category.name,category.sort_order AS "sortOrder"
|
|
FROM finding_catalog_item_inventory_families mapping
|
|
JOIN finding_catalog_items item ON item.id=mapping.catalog_item_id
|
|
JOIN finding_categories category ON category.id=item.category_id
|
|
LEFT JOIN finding_catalog_item_merges merge_record ON merge_record.source_item_id=item.id
|
|
WHERE ${where}
|
|
ORDER BY category.sort_order,category.name,category.id
|
|
`, params),
|
|
this.dataSource.query(`
|
|
SELECT item.id,item.category_id AS "categoryId",item.code,
|
|
item.source_number AS "sourceNumber",item.title,item.legal_basis AS "legalBasis",
|
|
item.glossary,item.suggested_severity AS "suggestedSeverity",item.revision,
|
|
category.name AS "categoryName"
|
|
FROM finding_catalog_item_inventory_families mapping
|
|
JOIN finding_catalog_items item ON item.id=mapping.catalog_item_id
|
|
JOIN finding_categories category ON category.id=item.category_id
|
|
LEFT JOIN finding_catalog_item_merges merge_record ON merge_record.source_item_id=item.id
|
|
WHERE ${where}
|
|
ORDER BY category.sort_order,item.source_number,item.code
|
|
`, params),
|
|
]);
|
|
|
|
return {
|
|
asset: { id: asset.id, code: asset.code, name: asset.name },
|
|
inventoryFamily: {
|
|
id: asset.familyId,
|
|
code: asset.familyCode,
|
|
name: asset.familyName,
|
|
level: asset.familyLevel,
|
|
},
|
|
catalogSource: 'INVENTORY_FAMILY' as const,
|
|
typeConfigured: true,
|
|
configurationReason: `Hallazgos asociados a la clasificación técnica ${asset.familyName ?? asset.familyCode ?? ''}`.trim(),
|
|
categories,
|
|
items,
|
|
other,
|
|
};
|
|
}
|
|
}
|