feat(swagger): swagger docs for update function from employees.controller.ts and update.dto. small fixes to archival.service.ts

This commit is contained in:
Matthieu Haineault 2025-07-29 16:21:37 -04:00
parent 5274bf41c1
commit 9762790fbc
4 changed files with 90 additions and 64 deletions

View File

@ -1236,7 +1236,7 @@
"operationId": "EmployeesController_findAll", "operationId": "EmployeesController_findAll",
"parameters": [], "parameters": [],
"responses": { "responses": {
"201": { "200": {
"description": "List of employees found", "description": "List of employees found",
"content": { "content": {
"application/json": { "application/json": {
@ -1278,7 +1278,7 @@
} }
], ],
"responses": { "responses": {
"201": { "200": {
"description": "Employee found", "description": "Employee found",
"content": { "content": {
"application/json": { "application/json": {
@ -1302,6 +1302,37 @@
"Employees" "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": { "patch": {
"operationId": "EmployeesController_updateOrArchiveOrRestore", "operationId": "EmployeesController_updateOrArchiveOrRestore",
"parameters": [ "parameters": [
@ -1309,8 +1340,9 @@
"name": "id", "name": "id",
"required": true, "required": true,
"in": "path", "in": "path",
"description": "Identifier of the employee",
"schema": { "schema": {
"type": "string" "type": "number"
} }
} }
], ],
@ -1326,33 +1358,7 @@
}, },
"responses": { "responses": {
"200": { "200": {
"description": "" "description": "Employee updated or restored",
}
},
"security": [
{
"access-token": []
}
],
"tags": [
"Employees"
]
},
"delete": {
"operationId": "EmployeesController_remove",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"type": "number"
}
}
],
"responses": {
"201": {
"description": "Employee deleted",
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
@ -1361,16 +1367,29 @@
} }
} }
}, },
"400": { "202": {
"description": "Employee not found" "description": "Employee archived successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EmployeeEntity"
}
}
}
},
"404": {
"description": "Employee not found in active or archive"
} }
}, },
"security": [ "security": [
{
"access-token": []
},
{ {
"access-token": [] "access-token": []
} }
], ],
"summary": "Delete employee", "summary": "Update, archive or restore an employee",
"tags": [ "tags": [
"Employees" "Employees"
] ]
@ -2898,13 +2917,17 @@
"format": "date-time", "format": "date-time",
"type": "string", "type": "string",
"example": "23/09/3018", "example": "23/09/3018",
"description": "Employee`s first working day" "description": "New hire date or undefined"
}, },
"last_work_day": { "last_work_day": {
"format": "date-time", "format": "date-time",
"type": "string", "type": "string",
"example": "25/03/3019", "example": "25/03/3019",
"description": "Employee`s last working day" "description": "Termination date (null to restore)"
},
"supervisor_id": {
"type": "number",
"description": "Supervisor ID"
} }
} }
}, },

View File

@ -1,5 +1,6 @@
import { Injectable, Logger } from "@nestjs/common"; 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 { ExpensesService } from "src/modules/expenses/services/expenses.service";
import { LeaveRequestsService } from "src/modules/leave-requests/services/leave-request.service"; import { LeaveRequestsService } from "src/modules/leave-requests/services/leave-request.service";
import { ShiftsService } from "src/modules/shifts/services/shifts.service"; import { ShiftsService } from "src/modules/shifts/services/shifts.service";
@ -15,14 +16,14 @@ export class ArchivalService {
private readonly shiftsService: ShiftsService, private readonly shiftsService: ShiftsService,
private readonly leaveRequestsService: LeaveRequestsService, private readonly leaveRequestsService: LeaveRequestsService,
) {} ) {}
@Cron('0 0 3 * * 1', {timeZone:'America/Toronto'}) // chaque premier lundi du mois à 03h00 @Cron('0 0 3 * * 1', {timeZone:'America/Toronto'}) // chaque premier lundi du mois à 03h00
async handleMonthlyArchival() { async handleMonthlyArchival() {
const today = new Date(); const today = new Date();
const dayOfMonth = today.getDate(); const dayOfMonth = today.getDate();
if (dayOfMonth > 7) { 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; return;
} }
@ -34,7 +35,7 @@ export class ArchivalService {
await this.leaveRequestsService.archiveExpired(); await this.leaveRequestsService.archiveExpired();
this.logger.log('archivation process done'); this.logger.log('archivation process done');
} catch (err) { } catch (err) {
this.logger.log('an error occured during archivation ', err); this.logger.error('an error occured during archivation process ', err);
} }
} }
} }

View File

@ -4,7 +4,7 @@ import { EmployeesService } from '../services/employees.service';
import { CreateEmployeeDto } from '../dtos/create-employee.dto'; import { CreateEmployeeDto } from '../dtos/create-employee.dto';
import { UpdateEmployeeDto } from '../dtos/update-employee.dto'; import { UpdateEmployeeDto } from '../dtos/update-employee.dto';
import { RolesAllowed } from '../../../common/decorators/roles.decorators'; 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 { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard';
import { EmployeeEntity } from '../dtos/swagger-entities/employees.entity'; import { EmployeeEntity } from '../dtos/swagger-entities/employees.entity';
@ -27,7 +27,7 @@ export class EmployeesController {
@Get() @Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING)
@ApiOperation({summary: 'Find all employees' }) @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' }) @ApiResponse({ status: 400, description: 'List of employees not found' })
findAll(): Promise<Employees[]> { findAll(): Promise<Employees[]> {
return this.employeesService.findAll(); return this.employeesService.findAll();
@ -36,38 +36,35 @@ export class EmployeesController {
@Get(':id') @Get(':id')
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING ) @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING )
@ApiOperation({summary: 'Find employee' }) @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' }) @ApiResponse({ status: 400, description: 'Employee not found' })
findOne(@Param('id', ParseIntPipe) id: number): Promise<Employees> { findOne(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
return this.employeesService.findOne(id); 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<Employees> {
return this.employeesService.update(id, dto);
}
@Delete(':id') @Delete(':id')
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR ) @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR )
@ApiOperation({summary: 'Delete employee' }) @ApiOperation({summary: 'Delete employee' })
@ApiResponse({ status: 201, description: 'Employee deleted', type: EmployeeEntity }) @ApiParam({ name: 'id', type: Number, description: 'Identifier of the employee to delete' })
@ApiResponse({ status: 400, description: 'Employee not found' }) @ApiResponse({ status: 204, description: 'Employee deleted' })
@ApiResponse({ status: 404, description: 'Employee not found' })
remove(@Param('id', ParseIntPipe) id: number): Promise<Employees> { remove(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
return this.employeesService.remove(id); return this.employeesService.remove(id);
} }
@Patch(':id') @Patch(':id')
async updateOrArchiveOrRestore( @RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@Param('id') id: string, @ApiBearerAuth('access-token')
@Body() dto: UpdateEmployeeDto, @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); const result = await this.employeesService.patchEmployee(+id, dto);
if(!result) { if(!result) {
throw new NotFoundException(`Employee #${ id } not found in active or archive.`) throw new NotFoundException(`Employee #${ id } not found in active or archive.`)

View File

@ -1,8 +1,13 @@
import { PartialType } from '@nestjs/swagger'; import { ApiProperty, PartialType } from '@nestjs/swagger';
import { CreateEmployeeDto } from './create-employee.dto'; import { CreateEmployeeDto } from './create-employee.dto';
export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) { export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) {
first_work_day?: Date; @ApiProperty({ required: false, type: Date, description: 'New hire date or undefined' })
last_work_day?: Date; first_work_day?: Date;
supervisor_id?: number;
@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;
} }