F3.1 APK: usar catálogo familiar y limitar Hallazgos a niveles técnicos

This commit is contained in:
2026-09-07 14:44:30 -03:00
parent 76b688ac82
commit 7329cee080
@@ -2,7 +2,7 @@ import { BadRequestException, ConflictException, Injectable, NotFoundException }
import { DataSource } from 'typeorm';
import type { AuthPrincipal, RequestWithContext } from '../common/http/request-context';
import type { CreateInspectionFindingDto } from '../inspection-findings/dto/create-inspection-finding.dto';
import { FindingCatalogService } from '../inspection-findings/finding-catalog.service';
import { F3FindingCatalogResolverService } from '../inspection-findings/f3-finding-catalog-resolver.service';
import { InspectionFindingsService } from '../inspection-findings/inspection-findings.service';
import { assertMobileInspector } from '../inspection-operations/mobile-inspector-policy';
import type { CreateFieldFindingDto } from './dto/create-field-finding.dto';
@@ -32,7 +32,7 @@ interface FieldFindingGate {
export class FieldFindingsService {
constructor(
private readonly dataSource: DataSource,
private readonly catalog: FindingCatalogService,
private readonly catalog: F3FindingCatalogResolverService,
private readonly findings: InspectionFindingsService,
) {}
@@ -112,6 +112,8 @@ export class FieldFindingsService {
company.code AS "companyCode",
company.name AS "companyName",
asset.id AS "assetId",
asset_type.code AS "assetTypeCode",
asset.inventory_family_id AS "inventoryFamilyId",
asset.operational_area_id AS "assetAreaId",
asset.operator_company_id AS "assetCompanyId",
EXISTS (
@@ -158,6 +160,7 @@ export class FieldFindingsService {
LEFT JOIN assets company ON company.id = visit.operator_company_id
LEFT JOIN assets asset ON asset.id = $2::uuid
AND asset.information_status <> 'INACTIVE'
LEFT JOIN asset_types asset_type ON asset_type.id=asset.asset_type_id
WHERE visit.id = $1::uuid
`, [visitId, assetId, principal.userId]) as Array<{
visitId: string;
@@ -170,6 +173,8 @@ export class FieldFindingsService {
companyCode: string | null;
companyName: string | null;
assetId: string | null;
assetTypeCode: string | null;
inventoryFamilyId: string | null;
assetAreaId: string | null;
assetCompanyId: string | null;
assigned: boolean;
@@ -186,7 +191,7 @@ export class FieldFindingsService {
if (row.visitStatus !== 'IN_PROGRESS') {
throw new ConflictException({
code: 'FIELD_FINDING_VISIT_NOT_IN_PROGRESS',
message: 'Los hallazgos sólo pueden registrarse cuando la inspección está en curso',
message: 'Los Hallazgos sólo pueden registrarse cuando la inspección está en curso',
});
}
if (!row.assigned) {
@@ -207,6 +212,18 @@ export class FieldFindingsService {
message: 'Registro de Inventario no encontrado',
});
}
if (!['instalacion', 'subinstalacion'].includes(String(row.assetTypeCode).toLowerCase())) {
throw new BadRequestException({
code: 'FIELD_FINDING_TECHNICAL_LEVEL_REQUIRED',
message: 'Los Hallazgos se registran sobre una Instalación o Subinstalación, no sobre Área/Yacimiento',
});
}
if (!row.inventoryFamilyId) {
throw new ConflictException({
code: 'FIELD_FINDING_FAMILY_REQUIRED',
message: 'La Instalación/Subinstalación debe tener una familia técnica u Otro antes de registrar Hallazgos',
});
}
if (row.assetAreaId !== row.areaId || row.assetCompanyId !== row.companyId) {
throw new BadRequestException({
code: 'FIELD_FINDING_INVENTORY_OUTSIDE_CONTEXT',
@@ -216,7 +233,7 @@ export class FieldFindingsService {
if (!row.selected) {
throw new ConflictException({
code: 'FIELD_FINDING_INVENTORY_NOT_SELECTED',
message: 'Seleccioná el Inventario dentro de la inspección antes de registrar un hallazgo',
message: 'Seleccioná el Inventario dentro de la inspección antes de registrar un Hallazgo',
});
}
@@ -230,7 +247,7 @@ export class FieldFindingsService {
if (!readyForFinding) {
throw new ConflictException({
code: 'FIELD_FINDING_CAPTURE_REQUIRED',
message: 'Antes del hallazgo, el Inventario creado en campo debe tener GPS y al menos una foto',
message: 'Antes del Hallazgo, el Inventario creado en campo debe tener GPS y al menos una foto',
capture: { captureRequired, hasGeometry, creationGpsCaptured, fieldPhotoCount },
});
}
@@ -264,7 +281,7 @@ export class FieldFindingsService {
if (rows.length === 0) {
throw new ConflictException({
code: 'FIELD_FINDING_DRAFT_ACT_REQUIRED',
message: 'La inspección no tiene un Acta borrador abierta para registrar hallazgos',
message: 'La inspección no tiene un Acta borrador abierta para registrar Hallazgos',
});
}
if (rows.length > 1) {