import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Put, Query, Req, } from '@nestjs/common'; import { CurrentAuth } from '../auth/decorators/current-auth.decorator'; import { RequirePermissions } from '../authorization/decorators/require-permissions.decorator'; import type { AuthPrincipal, RequestWithContext } from '../common/http/request-context'; import { assertMobileInspector } from '../inspection-operations/mobile-inspector-policy'; import { CancelInspectionVisitDto } from './dto/cancel-inspection-visit.dto'; import { CloseInspectionVisitDto } from './dto/close-inspection-visit.dto'; import { CreateInspectionVisitDto } from './dto/create-inspection-visit.dto'; import { ExcludeInspectionVisitAssetDto } from './dto/exclude-inspection-visit-asset.dto'; import { ListInspectionVisitsQueryDto } from './dto/list-inspection-visits-query.dto'; import { OpenMobileInspectionDto } from './dto/open-mobile-inspection.dto'; import { ReplaceInspectionVisitAssetsDto } from './dto/replace-inspection-visit-assets.dto'; import { ReplaceInspectionVisitTeamDto } from './dto/replace-inspection-visit-team.dto'; import { UpdateInspectionVisitDto } from './dto/update-inspection-visit.dto'; import { InspectionPlanningCreateService } from './inspection-planning-create.service'; import { InspectionPlanningHierarchyService } from './inspection-planning-hierarchy.service'; import { InspectionVisitLifecycleService } from './inspection-visit-lifecycle.service'; import { InspectionVisitsService } from './inspection-visits.service'; @Controller('inspection-visits') export class InspectionVisitsController { constructor( private readonly visits: InspectionVisitsService, private readonly lifecycle: InspectionVisitLifecycleService, private readonly planningHierarchy: InspectionPlanningHierarchyService, private readonly planningCreate: InspectionPlanningCreateService, ) {} @Get() @RequirePermissions('inspections.read') list(@Query() query: ListInspectionVisitsQueryDto) { return this.visits.list(query); } @Get('assignees') @RequirePermissions('inspections.assign') assignees() { return this.visits.listAssignees(); } @Get('planning-context/departments') @RequirePermissions('inspections.read') planningDepartments() { return this.planningHierarchy.departments(); } @Get('planning-context/departments/:departmentId/areas') @RequirePermissions('inspections.read') planningAreasForDepartment( @Param('departmentId', new ParseUUIDPipe({ version: '4' })) departmentId: string, ) { return this.planningHierarchy.areasForDepartment(departmentId); } @Get('planning-context/areas/:areaId/yacimientos') @RequirePermissions('inspections.read') planningYacimientos( @Param('areaId', new ParseUUIDPipe({ version: '4' })) areaId: string, ) { return this.planningHierarchy.yacimientosForArea(areaId); } /** Compatibilidad con clientes anteriores: lista todas las Áreas. */ @Get('planning-context/areas') @RequirePermissions('inspections.read') planningAreas() { return this.visits.listPlanningAreas(); } @Get('planning-context/areas/:areaId/operators') @RequirePermissions('inspections.read') planningOperators( @Param('areaId', new ParseUUIDPipe({ version: '4' })) areaId: string, @Query('at') at?: string, ) { return this.planningHierarchy.operatorsForArea(areaId, at); } @Get('mobile/planning-context/areas') @RequirePermissions('inspections.execute') mobilePlanningAreas(@CurrentAuth() principal: AuthPrincipal) { assertMobileInspector(principal); return this.visits.listPlanningAreas(); } @Get('mobile/planning-context/areas/:areaId/operators') @RequirePermissions('inspections.execute') mobilePlanningOperators( @Param('areaId', new ParseUUIDPipe({ version: '4' })) areaId: string, @CurrentAuth() principal: AuthPrincipal, ) { assertMobileInspector(principal); return this.visits.listPlanningOperators(areaId); } @Post('mobile/open') @RequirePermissions('inspections.execute') async openMobile( @Body() dto: OpenMobileInspectionDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { assertMobileInspector(principal); // Android conserva por compatibilidad el alcance a nivel Área hasta que su // flujo también solicite Yacimiento. No se mezcla con la creación WEB F6.1. const created = await this.visits.create({ operationalAreaId: dto.operationalAreaId, operatorCompanyId: dto.operatorCompanyId, plannedStartAt: new Date().toISOString(), leadInspectorUserId: principal.userId, }, principal, request); await this.lifecycle.plan(created.id, principal, request); return this.lifecycle.start(created.id, principal, request); } @Get(':id') @RequirePermissions('inspections.read') get(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) { return this.visits.getById(id); } @Post() @RequirePermissions('inspections.manage', 'inspections.assign') create( @Body() dto: CreateInspectionVisitDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.planningCreate.create(dto, principal, request); } @Patch(':id') @RequirePermissions('inspections.manage') update( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Body() dto: UpdateInspectionVisitDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.update(id, dto, principal, request); } @Put(':id/assets') @RequirePermissions('inspections.manage') replaceAssets( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Body() dto: ReplaceInspectionVisitAssetsDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.replaceAssets(id, dto, principal, request); } @Post(':id/checklist/generate') @RequirePermissions('inspections.manage') generateChecklist( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.generateChecklist(id, principal, request); } @Post(':id/assets/:assetId/exclude') @RequirePermissions('inspections.manage') excludeAsset( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Param('assetId', new ParseUUIDPipe({ version: '4' })) assetId: string, @Body() dto: ExcludeInspectionVisitAssetDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.excludeAsset(id, assetId, dto.reason, principal, request); } @Post(':id/assets/:assetId/include') @RequirePermissions('inspections.manage') includeAsset( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Param('assetId', new ParseUUIDPipe({ version: '4' })) assetId: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.includeAsset(id, assetId, principal, request); } @Put(':id/team') @RequirePermissions('inspections.assign') replaceTeam( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Body() dto: ReplaceInspectionVisitTeamDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.visits.replaceTeam(id, dto, principal, request); } @Post(':id/plan') @RequirePermissions('inspections.manage') plan( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.lifecycle.plan(id, principal, request); } @Post(':id/unplan') @RequirePermissions('inspections.manage') unplan( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.lifecycle.unplan(id, principal, request); } @Post(':id/start') @RequirePermissions('inspections.execute') start( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.lifecycle.start(id, principal, request); } @Post(':id/close') @RequirePermissions('inspections.execute') close( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Body() dto: CloseInspectionVisitDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.lifecycle.close(id, dto, principal, request); } @Post(':id/cancel') @RequirePermissions('inspections.manage') cancel( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @Body() dto: CancelInspectionVisitDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.lifecycle.cancel(id, dto, principal, request); } }