diff --git a/api-v3/src/inspection-visits/inspection-visit-lifecycle.service.ts b/api-v3/src/inspection-visits/inspection-visit-lifecycle.service.ts index e420083..013bfbe 100644 --- a/api-v3/src/inspection-visits/inspection-visit-lifecycle.service.ts +++ b/api-v3/src/inspection-visits/inspection-visit-lifecycle.service.ts @@ -43,7 +43,6 @@ export class InspectionVisitLifecycleService { }); } await this.validatePlanningContext(manager, visit); - const before = visit.status; visit.status = InspectionVisitStatus.PLANNED; visit.cancellationReason = null; visit.updatedBy = principal.userId; @@ -53,7 +52,7 @@ export class InspectionVisitLifecycleService { action: AuditAction.INSPECTION_VISIT_STATUS_CHANGED, entityType: 'inspection_visit', entityId: id, - beforeData: { status: before }, + beforeData: { status: InspectionVisitStatus.DRAFT }, afterData: { status: InspectionVisitStatus.PLANNED }, metadata: { transition: 'PLAN' }, }, manager); @@ -61,6 +60,48 @@ export class InspectionVisitLifecycleService { return this.visits.getById(id); } + async unplan( + id: string, + principal: AuthPrincipal, + request: RequestWithContext, + ) { + await this.dataSource.transaction(async (manager) => { + const visit = await this.lockVisit(manager, id); + if (visit.status !== InspectionVisitStatus.PLANNED) { + throw new ConflictException({ + code: 'INSPECTION_NOT_PLANNED_FOR_UNPLAN', + message: 'Sólo una Inspección planificada puede volver a borrador', + }); + } + const [startedAct] = await manager.query(` + SELECT 1 + FROM inspection_acts act + WHERE act.visit_id=$1 + AND act.status NOT IN ('DRAFT','CANCELLED') + LIMIT 1 + `, [id]) as unknown[]; + if (startedAct) { + throw new ConflictException({ + code: 'INSPECTION_UNPLAN_ACT_ALREADY_ADVANCED', + message: 'La Inspección ya tiene un Acta avanzada y no puede volver a borrador', + }); + } + visit.status = InspectionVisitStatus.DRAFT; + visit.updatedBy = principal.userId; + await manager.getRepository(InspectionVisit).save(visit); + await this.audit.record({ + ...administrationAuditContext(principal, request), + action: AuditAction.INSPECTION_VISIT_STATUS_CHANGED, + entityType: 'inspection_visit', + entityId: id, + beforeData: { status: InspectionVisitStatus.PLANNED }, + afterData: { status: InspectionVisitStatus.DRAFT }, + metadata: { transition: 'UNPLAN', explicitAction: true }, + }, manager); + }); + return this.visits.getById(id); + } + async start( id: string, principal: AuthPrincipal,