import { Body, Controller, Delete, Get, Header, Param, ParseBoolPipe, ParseIntPipe, Patch, Post, Query, UseGuards, UsePipes, ValidationPipe } from "@nestjs/common"; import { Shifts } from "@prisma/client"; import { CreateShiftDto } from "../dtos/create-shift.dto"; import { UpdateShiftsDto } from "../dtos/update-shift.dto"; import { RolesAllowed } from "src/common/decorators/roles.decorators"; import { Roles as RoleEnum } from '.prisma/client'; import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; import { ShiftsCommandService } from "../services/shifts-command.service"; import { SearchShiftsDto } from "../dtos/search-shift.dto"; import { OverviewRow, ShiftsQueryService } from "../services/shifts-query.service"; import { GetShiftsOverviewDto } from "../dtos/get-shift-overview.dto"; @ApiTags('Shifts') @ApiBearerAuth('access-token') // @UseGuards() @Controller('shifts') export class ShiftsController { constructor( private readonly shiftsService: ShiftsQueryService, private readonly shiftsApprovalService: ShiftsCommandService, private readonly shiftsValidationService: ShiftsQueryService, ){} @Post() //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) @ApiOperation({ summary: 'Create shift' }) @ApiResponse({ status: 201, description: 'Shift created',type: CreateShiftDto }) @ApiResponse({ status: 400, description: 'Incomplete task or invalid data' }) create(@Body() dto: CreateShiftDto): Promise { return this.shiftsService.create(dto); } @Get() //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) @ApiOperation({ summary: 'Find all shifts' }) @ApiResponse({ status: 201, description: 'List of shifts found',type: CreateShiftDto, isArray: true }) @ApiResponse({ status: 400, description: 'List of shifts not found' }) @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) findAll(@Query() filters: SearchShiftsDto) { return this.shiftsService.findAll(filters); } @Get(':id') //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) @ApiOperation({ summary: 'Find shift' }) @ApiResponse({ status: 201, description: 'Shift found',type: CreateShiftDto }) @ApiResponse({ status: 400, description: 'Shift not found' }) findOne(@Param('id', ParseIntPipe) id: number): Promise { return this.shiftsService.findOne(id); } @Patch(':id') //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) @ApiOperation({ summary: 'Update shift' }) @ApiResponse({ status: 201, description: 'Shift updated',type: CreateShiftDto }) @ApiResponse({ status: 400, description: 'Shift not found' }) update(@Param('id', ParseIntPipe) id: number,@Body() dto: UpdateShiftsDto): Promise { return this.shiftsService.update(id, dto); } @Delete(':id') //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) @ApiOperation({ summary: 'Delete shift' }) @ApiResponse({ status: 201, description: 'Shift deleted',type: CreateShiftDto }) @ApiResponse({ status: 400, description: 'Shift not found' }) remove(@Param('id', ParseIntPipe) id: number): Promise { return this.shiftsService.remove(id); } @Patch('approval/:id') //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) async approve(@Param('id', ParseIntPipe) id: number, @Body('is_approved', ParseBoolPipe) isApproved: boolean) { return this.shiftsApprovalService.updateApproval(id, isApproved); } @Get('summary') async getSummary( @Query() query: GetShiftsOverviewDto): Promise { return this.shiftsValidationService.getSummary(query.period_id); } @Get('export.csv') @Header('Content-Type', 'text/csv; charset=utf-8') @Header('Content-Disposition', 'attachment; filename="shifts-validation.csv"') async exportCsv(@Query() query: GetShiftsOverviewDto): Promise{ const rows = await this.shiftsValidationService.getSummary(query.period_id); //CSV Headers const header = [ 'full_name', 'supervisor', 'total_regular_hrs', 'total_evening_hrs', 'total_overtime_hrs', 'total_expenses', 'total_mileage', 'is_validated' ].join(',') + '\n'; //CSV rows const body = rows.map(r => { const esc = (str: string) => `"${str.replace(/"/g, '""')}"`; return [ esc(r.full_name), esc(r.supervisor), r.total_regular_hrs.toFixed(2), r.total_evening_hrs.toFixed(2), r.total_overtime_hrs.toFixed(2), r.total_expenses.toFixed(2), r.total_mileage.toFixed(2), r.is_validated, ].join(','); }).join('\n'); return Buffer.from('\uFEFF' + header + body, 'utf8'); } }