Plazo único por Acta, respuestas de empresa con PDF, fecha comprometida, estados administrativos, cola y calendario por Acta.
48 lines
3.8 KiB
TypeScript
48 lines
3.8 KiB
TypeScript
|
|
import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Query, Req, Res, UploadedFile, UseInterceptors } from '@nestjs/common';
|
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
import type { Response } from 'express';
|
|
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 { ActAdministrationService, MAX_ACT_RESPONSE_BYTES, type UploadedActResponseFile } from './act-administration.service';
|
|
import { CreateActCompanyResponseDto } from './dto/create-act-company-response.dto';
|
|
import { ListActAdministrationQueryDto } from './dto/list-act-administration-query.dto';
|
|
import { SetActResponseDeadlineDto } from './dto/set-act-response-deadline.dto';
|
|
|
|
@Controller('act-administration')
|
|
export class ActAdministrationQueueController {
|
|
constructor(private readonly administration: ActAdministrationService) {}
|
|
@Get('queue') @RequirePermissions('inspection_acts.read') queue(@Query() query: ListActAdministrationQueryDto) { return this.administration.queue(query); }
|
|
@Get('calendar') @RequirePermissions('inspection_acts.read') calendar(@Query('from') from?: string, @Query('to') to?: string) { return this.administration.calendar(from, to); }
|
|
}
|
|
|
|
@Controller('inspection-acts/:actId/administration')
|
|
export class ActAdministrationController {
|
|
constructor(private readonly administration: ActAdministrationService) {}
|
|
@Get() @RequirePermissions('inspection_acts.read') get(@Param('actId', new ParseUUIDPipe({ version: '4' })) actId: string) { return this.administration.detail(actId); }
|
|
@Patch('deadline') @RequirePermissions('inspection_findings.follow_up')
|
|
setDeadline(@Param('actId', new ParseUUIDPipe({ version: '4' })) actId: string, @Body() dto: SetActResponseDeadlineDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext) { return this.administration.setDeadline(actId, dto, principal, request); }
|
|
@Post('responses') @RequirePermissions('inspection_findings.follow_up')
|
|
@UseInterceptors(FileInterceptor('file', { limits: { fileSize: MAX_ACT_RESPONSE_BYTES, files: 1 } }))
|
|
addResponse(@Param('actId', new ParseUUIDPipe({ version: '4' })) actId: string, @Body() dto: CreateActCompanyResponseDto, @UploadedFile() file: UploadedActResponseFile | undefined, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext) { return this.administration.addResponse(actId, dto, file, principal, request); }
|
|
}
|
|
|
|
@Controller('act-company-responses')
|
|
export class ActCompanyResponseContentController {
|
|
constructor(private readonly administration: ActAdministrationService) {}
|
|
@Get(':responseId/content') @RequirePermissions('inspection_acts.read')
|
|
async content(@Param('responseId', new ParseUUIDPipe({ version: '4' })) responseId: string, @Query('download') download: string | undefined, @Res() response: Response): Promise<void> {
|
|
const item = await this.administration.responseContent(responseId);
|
|
const disposition = download === '1' ? 'attachment' : 'inline';
|
|
const fallbackName = item.originalName.replace(/[^\x20-\x7e]/g, '_').replace(/["\\]/g, '_');
|
|
response.setHeader('Content-Type', 'application/pdf');
|
|
response.setHeader('Content-Length', String(item.sizeBytes));
|
|
response.setHeader('Content-Disposition', `${disposition}; filename="${fallbackName}"; filename*=UTF-8''${encodeURIComponent(item.originalName)}`);
|
|
response.setHeader('Cache-Control', 'private, no-store');
|
|
response.setHeader('X-Content-Type-Options', 'nosniff');
|
|
response.setHeader('Content-Security-Policy', "sandbox; default-src 'none'");
|
|
await new Promise<void>((resolveSend, rejectSend) => response.sendFile(item.filePath, (error) => error ? rejectSend(error) : resolveSend()));
|
|
}
|
|
}
|