diff --git a/api-v3/src/inspection-visits/inspection-planning-create.service.ts b/api-v3/src/inspection-visits/inspection-planning-create.service.ts index 51d7c8c..e702716 100644 --- a/api-v3/src/inspection-visits/inspection-planning-create.service.ts +++ b/api-v3/src/inspection-visits/inspection-planning-create.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, ConflictException, Injectable } from '@nestjs/common'; +import { BadRequestException, ConflictException, Injectable, Logger } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { administrationAuditContext, isUniqueViolation } from '../administration/common/administration-audit'; import { AuditService } from '../audit/audit.service'; @@ -16,6 +16,8 @@ import { InspectionVisitsService } from './inspection-visits.service'; */ @Injectable() export class InspectionPlanningCreateService { + private readonly logger = new Logger(InspectionPlanningCreateService.name); + constructor( private readonly dataSource: DataSource, private readonly audit: AuditService, @@ -42,10 +44,13 @@ export class InspectionPlanningCreateService { }); } + let stage = 'transaction:start'; try { const visitId = await this.dataSource.transaction(async (manager) => { + stage = 'scope:validate'; await validateInspectionPlanningScope(manager, dto.operationalAreaId, scopeAssetId); + stage = 'operator:validate'; const [context] = await manager.query(` SELECT relation.id FROM area_company_relations relation @@ -71,6 +76,7 @@ export class InspectionPlanningCreateService { }); } + stage = 'inspector:validate'; const [inspector] = await manager.query(` SELECT user_account.id FROM users user_account @@ -93,6 +99,7 @@ export class InspectionPlanningCreateService { }); } + stage = 'code:next'; const code = await nextInspectionVisitCode(manager, plannedStartAt); const visit = manager.getRepository(InspectionVisit).create({ code, @@ -112,8 +119,11 @@ export class InspectionPlanningCreateService { createdBy: principal.userId, updatedBy: principal.userId, }); + + stage = 'visit:save'; await manager.getRepository(InspectionVisit).save(visit); + stage = 'member:insert'; await manager.query(` INSERT INTO inspection_visit_members (visit_id,user_id,included,assigned_by) VALUES ($1::uuid,$2::uuid,true,$3::uuid) @@ -121,6 +131,7 @@ export class InspectionPlanningCreateService { // El checklist sigue el alcance físico del Yacimiento. No usa // assets.operator_company_id, que en F6 es sólo snapshot histórico. + stage = 'checklist:insert'; await manager.query(` INSERT INTO inspection_visit_checklist_items ( visit_id,generation_number,finding_id,asset_id,item_kind, @@ -156,6 +167,7 @@ export class InspectionPlanningCreateService { ORDER BY finding.created_at,finding.id `, [visit.id, dto.operationalAreaId, scopeAssetId, plannedStartAt.toISOString().slice(0, 10)]); + stage = 'audit:record'; await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.INSPECTION_VISIT_CREATED, @@ -176,7 +188,8 @@ export class InspectionPlanningCreateService { return visit.id; }); - return this.visits.getById(visitId); + stage = 'view:load'; + return await this.visits.getById(visitId); } catch (error) { if (isUniqueViolation(error)) { throw new ConflictException({ @@ -184,6 +197,10 @@ export class InspectionPlanningCreateService { message: 'El identificador de Inspección ya existe; volvé a intentar', }); } + const technical = error instanceof Error + ? `${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ''}` + : String(error); + this.logger.error(`F6.1 inspection create failed at ${stage}: ${technical}`); throw error; } }