From 9762790fbc70e088a578fcd3fc720fa8cb887dc1 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Tue, 29 Jul 2025 16:21:37 -0400 Subject: [PATCH] feat(swagger): swagger docs for update function from employees.controller.ts and update.dto. small fixes to archival.service.ts --- docs/swagger/swagger-spec.json | 93 ++++++++++++------- .../archival/services/archival.service.ts | 9 +- .../controllers/employees.controller.ts | 39 ++++---- .../employees/dtos/update-employee.dto.ts | 13 ++- 4 files changed, 90 insertions(+), 64 deletions(-) diff --git a/docs/swagger/swagger-spec.json b/docs/swagger/swagger-spec.json index 2d6d040..3810127 100644 --- a/docs/swagger/swagger-spec.json +++ b/docs/swagger/swagger-spec.json @@ -1236,7 +1236,7 @@ "operationId": "EmployeesController_findAll", "parameters": [], "responses": { - "201": { + "200": { "description": "List of employees found", "content": { "application/json": { @@ -1278,7 +1278,7 @@ } ], "responses": { - "201": { + "200": { "description": "Employee found", "content": { "application/json": { @@ -1302,6 +1302,37 @@ "Employees" ] }, + "delete": { + "operationId": "EmployeesController_remove", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Identifier of the employee to delete", + "schema": { + "type": "number" + } + } + ], + "responses": { + "204": { + "description": "Employee deleted" + }, + "404": { + "description": "Employee not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Delete employee", + "tags": [ + "Employees" + ] + }, "patch": { "operationId": "EmployeesController_updateOrArchiveOrRestore", "parameters": [ @@ -1309,8 +1340,9 @@ "name": "id", "required": true, "in": "path", + "description": "Identifier of the employee", "schema": { - "type": "string" + "type": "number" } } ], @@ -1326,33 +1358,7 @@ }, "responses": { "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Employees" - ] - }, - "delete": { - "operationId": "EmployeesController_remove", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Employee deleted", + "description": "Employee updated or restored", "content": { "application/json": { "schema": { @@ -1361,16 +1367,29 @@ } } }, - "400": { - "description": "Employee not found" + "202": { + "description": "Employee archived successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmployeeEntity" + } + } + } + }, + "404": { + "description": "Employee not found in active or archive" } }, "security": [ + { + "access-token": [] + }, { "access-token": [] } ], - "summary": "Delete employee", + "summary": "Update, archive or restore an employee", "tags": [ "Employees" ] @@ -2898,13 +2917,17 @@ "format": "date-time", "type": "string", "example": "23/09/3018", - "description": "Employee`s first working day" + "description": "New hire date or undefined" }, "last_work_day": { "format": "date-time", "type": "string", "example": "25/03/3019", - "description": "Employee`s last working day" + "description": "Termination date (null to restore)" + }, + "supervisor_id": { + "type": "number", + "description": "Supervisor ID" } } }, diff --git a/src/modules/archival/services/archival.service.ts b/src/modules/archival/services/archival.service.ts index 989c6dd..2a8b497 100644 --- a/src/modules/archival/services/archival.service.ts +++ b/src/modules/archival/services/archival.service.ts @@ -1,5 +1,6 @@ import { Injectable, Logger } from "@nestjs/common"; -import { Cron, Timeout } from "@nestjs/schedule"; +import { Cron } from "@nestjs/schedule"; +import { ApiInternalServerErrorResponse, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; import { ExpensesService } from "src/modules/expenses/services/expenses.service"; import { LeaveRequestsService } from "src/modules/leave-requests/services/leave-request.service"; import { ShiftsService } from "src/modules/shifts/services/shifts.service"; @@ -15,14 +16,14 @@ export class ArchivalService { private readonly shiftsService: ShiftsService, private readonly leaveRequestsService: LeaveRequestsService, ) {} - + @Cron('0 0 3 * * 1', {timeZone:'America/Toronto'}) // chaque premier lundi du mois à 03h00 async handleMonthlyArchival() { const today = new Date(); const dayOfMonth = today.getDate(); if (dayOfMonth > 7) { - this.logger.log('Archive {awaiting 1st monday of the month for archivation process}') + this.logger.warn('Archive {awaiting 1st monday of the month for archivation process}') return; } @@ -34,7 +35,7 @@ export class ArchivalService { await this.leaveRequestsService.archiveExpired(); this.logger.log('archivation process done'); } catch (err) { - this.logger.log('an error occured during archivation ', err); + this.logger.error('an error occured during archivation process ', err); } } } \ No newline at end of file diff --git a/src/modules/employees/controllers/employees.controller.ts b/src/modules/employees/controllers/employees.controller.ts index 2b30577..f0ba727 100644 --- a/src/modules/employees/controllers/employees.controller.ts +++ b/src/modules/employees/controllers/employees.controller.ts @@ -4,7 +4,7 @@ import { EmployeesService } from '../services/employees.service'; import { CreateEmployeeDto } from '../dtos/create-employee.dto'; import { UpdateEmployeeDto } from '../dtos/update-employee.dto'; import { RolesAllowed } from '../../../common/decorators/roles.decorators'; -import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard'; import { EmployeeEntity } from '../dtos/swagger-entities/employees.entity'; @@ -27,7 +27,7 @@ export class EmployeesController { @Get() @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) @ApiOperation({summary: 'Find all employees' }) - @ApiResponse({ status: 201, description: 'List of employees found', type: EmployeeEntity, isArray: true }) + @ApiResponse({ status: 200, description: 'List of employees found', type: EmployeeEntity, isArray: true }) @ApiResponse({ status: 400, description: 'List of employees not found' }) findAll(): Promise { return this.employeesService.findAll(); @@ -36,38 +36,35 @@ export class EmployeesController { @Get(':id') @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING ) @ApiOperation({summary: 'Find employee' }) - @ApiResponse({ status: 201, description: 'Employee found', type: EmployeeEntity }) + @ApiResponse({ status: 200, description: 'Employee found', type: EmployeeEntity }) @ApiResponse({ status: 400, description: 'Employee not found' }) findOne(@Param('id', ParseIntPipe) id: number): Promise { return this.employeesService.findOne(id); } - @Patch(':id') - @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING ) - @ApiOperation({summary: 'Update employee' }) - @ApiResponse({ status: 201, description: 'Employee updated', type: EmployeeEntity }) - @ApiResponse({ status: 400, description: 'Employee not found' }) - update( - @Param('id', ParseIntPipe) id: number, - @Body() dto: UpdateEmployeeDto, - ): Promise { - return this.employeesService.update(id, dto); - } - @Delete(':id') @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR ) @ApiOperation({summary: 'Delete employee' }) - @ApiResponse({ status: 201, description: 'Employee deleted', type: EmployeeEntity }) - @ApiResponse({ status: 400, description: 'Employee not found' }) + @ApiParam({ name: 'id', type: Number, description: 'Identifier of the employee to delete' }) + @ApiResponse({ status: 204, description: 'Employee deleted' }) + @ApiResponse({ status: 404, description: 'Employee not found' }) remove(@Param('id', ParseIntPipe) id: number): Promise { return this.employeesService.remove(id); } @Patch(':id') - async updateOrArchiveOrRestore( - @Param('id') id: string, - @Body() dto: UpdateEmployeeDto, - ) { + @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) + @ApiBearerAuth('access-token') + @ApiOperation({ summary: 'Update, archive or restore an employee' }) + @ApiParam({ name: 'id', type: Number, description: 'Identifier of the employee' }) + @ApiResponse({ status: 200, description: 'Employee updated or restored', type: EmployeeEntity }) + @ApiResponse({ status: 202, description: 'Employee archived successfully', type: EmployeeEntity }) + @ApiResponse({ status: 404, description: 'Employee not found in active or archive' }) + @Patch(':id') + async updateOrArchiveOrRestore(@Param('id') id: string, @Body() dto: UpdateEmployeeDto,) { + // if last_work_day is set => archive the employee + // else if employee is archived and first_work_day or last_work_day = null => restore + //otherwise => standard update const result = await this.employeesService.patchEmployee(+id, dto); if(!result) { throw new NotFoundException(`Employee #${ id } not found in active or archive.`) diff --git a/src/modules/employees/dtos/update-employee.dto.ts b/src/modules/employees/dtos/update-employee.dto.ts index c0558fb..01b44de 100644 --- a/src/modules/employees/dtos/update-employee.dto.ts +++ b/src/modules/employees/dtos/update-employee.dto.ts @@ -1,8 +1,13 @@ -import { PartialType } from '@nestjs/swagger'; +import { ApiProperty, PartialType } from '@nestjs/swagger'; import { CreateEmployeeDto } from './create-employee.dto'; export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) { - first_work_day?: Date; - last_work_day?: Date; - supervisor_id?: number; + @ApiProperty({ required: false, type: Date, description: 'New hire date or undefined' }) + first_work_day?: Date; + + @ApiProperty({ required: false, type: Date, description: 'Termination date (null to restore)' }) + last_work_day?: Date; + + @ApiProperty({ required: false, type: Number, description: 'Supervisor ID' }) + supervisor_id?: number; }