From 02ebb23d7a006661e584778ef746fbfa540c1a96 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Wed, 5 Nov 2025 08:36:24 -0500 Subject: [PATCH] refactor(employees): uncomment module and comment archival parts(needs refactoring) --- .../controllers/employees.controller.ts | 168 ++++--- .../employees/dtos/create-employee.dto.ts | 208 ++++----- .../employees/dtos/list-employee.dto.ts | 16 +- .../employees/dtos/profil-employee.dto.ts | 26 +- .../employees/dtos/update-employee.dto.ts | 36 +- .../services/employees-archival.service.ts | 308 ++++++------- .../employees/services/employees.service.ts | 418 +++++++++--------- .../employees/utils/employee.utils.ts | 18 +- 8 files changed, 594 insertions(+), 604 deletions(-) diff --git a/src/identity-and-account/employees/controllers/employees.controller.ts b/src/identity-and-account/employees/controllers/employees.controller.ts index 4828d91..dabca96 100644 --- a/src/identity-and-account/employees/controllers/employees.controller.ts +++ b/src/identity-and-account/employees/controllers/employees.controller.ts @@ -1,99 +1,89 @@ -// import { Body,Controller,Get,NotFoundException,Param,Patch } from '@nestjs/common'; -// 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, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; -// import { EmployeeListItemDto } from '../dtos/list-employee.dto'; -// import { EmployeesArchivalService } from '../services/employees-archival.service'; -// import { EmployeeProfileItemDto } from 'src/modules/employees/dtos/profil-employee.dto'; +import { Controller, Get, Patch, Param, Body, NotFoundException } from "@nestjs/common"; +import { ApiBearerAuth, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger"; +import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto"; +import { EmployeeProfileItemDto } from "src/identity-and-account/employees/dtos/profil-employee.dto"; +import { UpdateEmployeeDto } from "src/identity-and-account/employees/dtos/update-employee.dto"; +import { EmployeesArchivalService } from "src/identity-and-account/employees/services/employees-archival.service"; +import { EmployeesService } from "src/identity-and-account/employees/services/employees.service"; -// @ApiTags('Employees') -// @ApiBearerAuth('access-token') -// // @UseGuards() -// @Controller('employees') -// export class EmployeesController { -// constructor( -// private readonly employeesService: EmployeesService, -// private readonly archiveService: EmployeesArchivalService, -// ) {} +@ApiBearerAuth('access-token') +// @UseGuards() +@Controller('employees') +export class EmployeesController { + constructor( + private readonly employeesService: EmployeesService, + private readonly archiveService: EmployeesArchivalService, + ) {} -// @Get('employee-list') -// //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) -// @ApiOperation({summary: 'Find all employees with scoped info' }) -// @ApiResponse({ status: 200, description: 'List of employees with scoped info found', type: EmployeeListItemDto, isArray: true }) -// @ApiResponse({ status: 400, description: 'List of employees with scoped info not found' }) -// findListEmployees(): Promise { -// return this.employeesService.findListEmployees(); -// } + @Get('employee-list') + //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) -// @Patch(':email') -// //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) -// @ApiBearerAuth('access-token') -// @ApiOperation({ summary: 'Update, archive or restore an employee' }) -// @ApiParam({ name: 'email', type: Number, description: 'Email of the employee' }) -// @ApiResponse({ status: 200, description: 'Employee updated or restored', type: CreateEmployeeDto }) -// @ApiResponse({ status: 202, description: 'Employee archived successfully', type: CreateEmployeeDto }) -// @ApiResponse({ status: 404, description: 'Employee not found in active or archive' }) -// async updateOrArchiveOrRestore(@Param('email') email: 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.archiveService.patchEmployee(email, dto); -// if(!result) { -// throw new NotFoundException(`Employee with email: ${ email } is not found in active or archive.`) -// } -// return result; -// } + findListEmployees(): Promise { + return this.employeesService.findListEmployees(); + } -// //_____________________________________________________________________________________________ -// // Deprecated or unused methods -// //_____________________________________________________________________________________________ + @Patch(':email') + //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) + @ApiBearerAuth('access-token') + async updateOrArchiveOrRestore(@Param('email') email: 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.archiveService.patchEmployee(email, dto); + if(!result) { + throw new NotFoundException(`Employee with email: ${ email } is not found in active or archive.`) + } + return result; + } -// // @Post() -// // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) -// // @ApiOperation({summary: 'Create employee' }) -// // @ApiResponse({ status: 201, description: 'Employee created', type: CreateEmployeeDto }) -// // @ApiResponse({ status: 400, description: 'Incomplete task or invalid data' }) -// // create(@Body() dto: CreateEmployeeDto): Promise { -// // return this.employeesService.create(dto); -// // } -// // @Get() -// // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) -// // @ApiOperation({summary: 'Find all employees' }) -// // @ApiResponse({ status: 200, description: 'List of employees found', type: CreateEmployeeDto, isArray: true }) -// // @ApiResponse({ status: 400, description: 'List of employees not found' }) -// // findAll(): Promise { -// // return this.employeesService.findAll(); -// // } + //_____________________________________________________________________________________________ + // Deprecated or unused methods + //_____________________________________________________________________________________________ + + // @Post() + // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) + // @ApiOperation({summary: 'Create employee' }) + // @ApiResponse({ status: 201, description: 'Employee created', type: CreateEmployeeDto }) + // @ApiResponse({ status: 400, description: 'Incomplete task or invalid data' }) + // create(@Body() dto: CreateEmployeeDto): Promise { + // return this.employeesService.create(dto); + // } + // @Get() + // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING) + // @ApiOperation({summary: 'Find all employees' }) + // @ApiResponse({ status: 200, description: 'List of employees found', type: CreateEmployeeDto, isArray: true }) + // @ApiResponse({ status: 400, description: 'List of employees not found' }) + // findAll(): Promise { + // return this.employeesService.findAll(); + // } -// // @Get(':email') -// // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING ) -// // @ApiOperation({summary: 'Find employee' }) -// // @ApiResponse({ status: 200, description: 'Employee found', type: CreateEmployeeDto }) -// // @ApiResponse({ status: 400, description: 'Employee not found' }) -// // findOne(@Param('email', ParseIntPipe) email: string): Promise { -// // return this.employeesService.findOne(email); -// // } + // @Get(':email') + // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING ) + // @ApiOperation({summary: 'Find employee' }) + // @ApiResponse({ status: 200, description: 'Employee found', type: CreateEmployeeDto }) + // @ApiResponse({ status: 400, description: 'Employee not found' }) + // findOne(@Param('email', ParseIntPipe) email: string): Promise { + // return this.employeesService.findOne(email); + // } -// @Get('profile/:email') -// @ApiOperation({summary: 'Find employee profile' }) -// @ApiParam({ name: 'email', type: String, description: 'Identifier of the employee' }) -// @ApiResponse({ status: 200, description: 'Employee profile found', type: EmployeeProfileItemDto }) -// @ApiResponse({ status: 400, description: 'Employee profile not found' }) -// findOneProfile(@Param('email') email: string): Promise { -// return this.employeesService.findOneProfile(email); -// } + @Get('profile/:email') + @ApiOperation({summary: 'Find employee profile' }) + @ApiParam({ name: 'email', type: String, description: 'Identifier of the employee' }) + @ApiResponse({ status: 200, description: 'Employee profile found', type: EmployeeProfileItemDto }) + @ApiResponse({ status: 400, description: 'Employee profile not found' }) + findOneProfile(@Param('email') email: string): Promise { + return this.employeesService.findOneProfile(email); + } -// // @Delete(':email') -// // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR ) -// // @ApiOperation({summary: 'Delete employee' }) -// // @ApiParam({ name: 'email', type: Number, description: 'Email of the employee to delete' }) -// // @ApiResponse({ status: 204, description: 'Employee deleted' }) -// // @ApiResponse({ status: 404, description: 'Employee not found' }) -// // remove(@Param('email', ParseIntPipe) email: string): Promise { -// // return this.employeesService.remove(email); -// // } + // @Delete(':email') + // //@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR ) + // @ApiOperation({summary: 'Delete employee' }) + // @ApiParam({ name: 'email', type: Number, description: 'Email of the employee to delete' }) + // @ApiResponse({ status: 204, description: 'Employee deleted' }) + // @ApiResponse({ status: 404, description: 'Employee not found' }) + // remove(@Param('email', ParseIntPipe) email: string): Promise { + // return this.employeesService.remove(email); + // } -// } +} diff --git a/src/identity-and-account/employees/dtos/create-employee.dto.ts b/src/identity-and-account/employees/dtos/create-employee.dto.ts index 4fbbaaa..89279ef 100644 --- a/src/identity-and-account/employees/dtos/create-employee.dto.ts +++ b/src/identity-and-account/employees/dtos/create-employee.dto.ts @@ -1,118 +1,118 @@ -// import { -// Allow, -// IsBoolean, -// IsDateString, -// IsEmail, -// IsInt, -// IsNotEmpty, -// IsOptional, -// IsPositive, -// IsString, -// IsUUID, -// } from 'class-validator'; -// import { Type } from 'class-transformer'; -// import { ApiProperty } from '@nestjs/swagger'; +import { + Allow, + IsBoolean, + IsDateString, + IsEmail, + IsInt, + IsNotEmpty, + IsOptional, + IsPositive, + IsString, + IsUUID, +} from 'class-validator'; +import { Type } from 'class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; -// export class CreateEmployeeDto { -// @ApiProperty({ -// example: 1, -// description: 'Unique ID of an employee(primary-key, auto-incremented)', -// }) -// @Allow() -// id: number; +export class CreateEmployeeDto { + @ApiProperty({ + example: 1, + description: 'Unique ID of an employee(primary-key, auto-incremented)', + }) + @Allow() + id: number; -// @ApiProperty({ -// example: '0e6e2e1f-b157-4c7c-ae3f-999b3e4f914d', -// description: 'UUID of the user linked to that employee', -// }) -// @IsUUID() -// @IsOptional() -// user_id?: string; + @ApiProperty({ + example: '0e6e2e1f-b157-4c7c-ae3f-999b3e4f914d', + description: 'UUID of the user linked to that employee', + }) + @IsUUID() + @IsOptional() + user_id?: string; -// @ApiProperty({ -// example: 'Frodo', -// description: 'Employee`s first name', -// }) -// @IsString() -// @IsNotEmpty() -// first_name: string; + @ApiProperty({ + example: 'Frodo', + description: 'Employee`s first name', + }) + @IsString() + @IsNotEmpty() + first_name: string; -// @ApiProperty({ -// example: 'Baggins', -// description: 'Employee`s last name', -// }) -// @IsString() -// @IsNotEmpty() -// last_name: string; + @ApiProperty({ + example: 'Baggins', + description: 'Employee`s last name', + }) + @IsString() + @IsNotEmpty() + last_name: string; -// @ApiProperty({ -// example: 'i_cant_do_this_sam@targointernet.com', -// description: 'Employee`s email', -// }) -// @IsEmail() -// @IsOptional() -// email: string; + @ApiProperty({ + example: 'i_cant_do_this_sam@targointernet.com', + description: 'Employee`s email', + }) + @IsEmail() + @IsOptional() + email: string; -// @IsOptional() -// @IsBoolean() -// is_supervisor: boolean; + @IsOptional() + @IsBoolean() + is_supervisor: boolean; -// @ApiProperty({ -// example: '82538437464', -// description: 'Employee`s phone number', -// }) -// @IsString() -// phone_number: string; + @ApiProperty({ + example: '82538437464', + description: 'Employee`s phone number', + }) + @IsString() + phone_number: string; -// @ApiProperty({ -// example: '1 Bagshot Row, Hobbiton, The Shire, Middle-earth', -// description: 'Employee`s residence', -// required: false, -// }) -// @IsString() -// @IsOptional() -// residence?: string; + @ApiProperty({ + example: '1 Bagshot Row, Hobbiton, The Shire, Middle-earth', + description: 'Employee`s residence', + required: false, + }) + @IsString() + @IsOptional() + residence?: string; -// @ApiProperty({ -// example: 7464, -// description: 'external ID for the pay system', -// }) -// @IsInt() -// @IsPositive() -// @Type(() => Number) -// external_payroll_id: number; + @ApiProperty({ + example: 7464, + description: 'external ID for the pay system', + }) + @IsInt() + @IsPositive() + @Type(() => Number) + external_payroll_id: number; -// @ApiProperty({ -// example: 335567447, -// description: 'Employee`s company code', -// }) -// @IsInt() -// @IsPositive() -// @Type(() => Number) -// company_code: number; + @ApiProperty({ + example: 335567447, + description: 'Employee`s company code', + }) + @IsInt() + @IsPositive() + @Type(() => Number) + company_code: number; -// @ApiProperty({ -// example:'technicient', -// description: 'employee`s job title', -// }) -// @IsString() -// @IsOptional() -// job_title: string; + @ApiProperty({ + example:'technicient', + description: 'employee`s job title', + }) + @IsString() + @IsOptional() + job_title: string; -// @ApiProperty({ -// example: '23/09/3018', -// description: 'Employee`s first working day', -// }) -// @IsDateString() -// first_work_day: string; + @ApiProperty({ + example: '23/09/3018', + description: 'Employee`s first working day', + }) + @IsDateString() + first_work_day: string; -// @ApiProperty({ -// example: '25/03/3019', -// description: 'Employee`s last working day', -// required: false, -// }) -// @IsDateString() -// @IsOptional() -// last_work_day?: string; -// } + @ApiProperty({ + example: '25/03/3019', + description: 'Employee`s last working day', + required: false, + }) + @IsDateString() + @IsOptional() + last_work_day?: string; +} diff --git a/src/identity-and-account/employees/dtos/list-employee.dto.ts b/src/identity-and-account/employees/dtos/list-employee.dto.ts index 6adbe3f..39abf03 100644 --- a/src/identity-and-account/employees/dtos/list-employee.dto.ts +++ b/src/identity-and-account/employees/dtos/list-employee.dto.ts @@ -1,8 +1,8 @@ -// export class EmployeeListItemDto { -// first_name: string; -// last_name: string; -// email: string; -// supervisor_full_name: string | null; -// company_name: number | null; -// job_title: string | null; -// } \ No newline at end of file +export class EmployeeListItemDto { + first_name: string; + last_name: string; + email: string; + supervisor_full_name: string | null; + company_name: number | null; + job_title: string | null; +} \ No newline at end of file diff --git a/src/identity-and-account/employees/dtos/profil-employee.dto.ts b/src/identity-and-account/employees/dtos/profil-employee.dto.ts index adbf38e..c6836cf 100644 --- a/src/identity-and-account/employees/dtos/profil-employee.dto.ts +++ b/src/identity-and-account/employees/dtos/profil-employee.dto.ts @@ -1,13 +1,13 @@ -// export class EmployeeProfileItemDto { -// first_name: string; -// last_name: string; -// employee_full_name: string; -// supervisor_full_name: string | null; -// company_name: number | null; -// job_title: string | null; -// email: string | null; -// phone_number: string; -// first_work_day: string; -// last_work_day?: string | null; -// residence: string | null; -// } \ No newline at end of file +export class EmployeeProfileItemDto { + first_name: string; + last_name: string; + employee_full_name: string; + supervisor_full_name: string | null; + company_name: number | null; + job_title: string | null; + email: string | null; + phone_number: string; + first_work_day: string; + last_work_day?: string | null; + residence: string | null; +} \ No newline at end of file diff --git a/src/identity-and-account/employees/dtos/update-employee.dto.ts b/src/identity-and-account/employees/dtos/update-employee.dto.ts index 1efbbfd..334a01a 100644 --- a/src/identity-and-account/employees/dtos/update-employee.dto.ts +++ b/src/identity-and-account/employees/dtos/update-employee.dto.ts @@ -1,22 +1,22 @@ -// import { ApiProperty, PartialType } from '@nestjs/swagger'; -// import { CreateEmployeeDto } from './create-employee.dto'; -// import { IsDateString, IsOptional, Max } from 'class-validator'; +import { ApiProperty, PartialType } from '@nestjs/swagger'; +import { CreateEmployeeDto } from './create-employee.dto'; +import { IsDateString, IsOptional, Max } from 'class-validator'; -// export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) { -// @ApiProperty({ required: false, type: Date, description: 'New hire date or undefined' }) -// @IsDateString() -// @IsOptional() -// first_work_day?: string; +export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) { + @ApiProperty({ required: false, type: Date, description: 'New hire date or undefined' }) + @IsDateString() + @IsOptional() + first_work_day?: string; -// @ApiProperty({ required: false, type: Date, description: 'Termination date (null to restore)' }) -// @IsDateString() -// @IsOptional() -// last_work_day?: string; + @ApiProperty({ required: false, type: Date, description: 'Termination date (null to restore)' }) + @IsDateString() + @IsOptional() + last_work_day?: string; -// @ApiProperty({ required: false, type: Number, description: 'Supervisor ID' }) -// @IsOptional() -// supervisor_id?: number; + @ApiProperty({ required: false, type: Number, description: 'Supervisor ID' }) + @IsOptional() + supervisor_id?: number; -// @IsOptional() -// phone_number: string; -// } + @IsOptional() + phone_number: string; +} diff --git a/src/identity-and-account/employees/services/employees-archival.service.ts b/src/identity-and-account/employees/services/employees-archival.service.ts index 6046e94..2aa184a 100644 --- a/src/identity-and-account/employees/services/employees-archival.service.ts +++ b/src/identity-and-account/employees/services/employees-archival.service.ts @@ -1,173 +1,173 @@ -// import { Injectable } from "@nestjs/common"; -// import { Employees, EmployeesArchive, Users } from "@prisma/client"; -// import { PrismaService } from "src/prisma/prisma.service"; -// import { UpdateEmployeeDto } from "../dtos/update-employee.dto"; -// import { toDateOrUndefined, toDateOrNull } from "../utils/employee.utils"; +import { Injectable } from "@nestjs/common"; +import { Employees, Users } from "@prisma/client"; +import { UpdateEmployeeDto } from "src/identity-and-account/employees/dtos/update-employee.dto"; +import { toDateOrUndefined, toDateOrNull } from "src/identity-and-account/employees/utils/employee.utils"; +import { PrismaService } from "src/prisma/prisma.service"; -// @Injectable() -// export class EmployeesArchivalService { -// constructor(private readonly prisma: PrismaService) { } +@Injectable() +export class EmployeesArchivalService { + constructor(private readonly prisma: PrismaService) { } -// async patchEmployee(email: string, dto: UpdateEmployeeDto): Promise { -// // 1) Tenter sur employés actifs -// const active = await this.prisma.employees.findFirst({ -// where: { user: { email } }, -// include: { user: true }, -// }); + async patchEmployee(email: string, dto: UpdateEmployeeDto): Promise { + // 1) Tenter sur employés actifs + const active = await this.prisma.employees.findFirst({ + where: { user: { email } }, + include: { user: true }, + }); -// if (active) { -// // Archivage : si on reçoit un last_work_day défini et que l'employé n’est pas déjà terminé -// if (dto.last_work_day !== undefined && active.last_work_day == null && dto.last_work_day !== null) { -// return this.archiveOnTermination(active, dto); -// } + if (active) { + // Archivage : si on reçoit un last_work_day défini et que l'employé n’est pas déjà terminé + // if (dto.last_work_day !== undefined && active.last_work_day == null && dto.last_work_day !== null) { + // return this.archiveOnTermination(active, dto); + // } -// // Sinon, update standard (split Users/Employees) -// const { -// first_name, -// last_name, -// email: new_email, -// phone_number, -// residence, -// external_payroll_id, -// company_code, -// job_title, -// first_work_day, -// last_work_day, -// supervisor_id, -// is_supervisor, -// } = dto as any; + // Sinon, update standard (split Users/Employees) + const { + first_name, + last_name, + email: new_email, + phone_number, + residence, + external_payroll_id, + company_code, + job_title, + first_work_day, + last_work_day, + supervisor_id, + is_supervisor, + } = dto as any; -// const first_work_d = toDateOrUndefined(first_work_day); -// const last_work_d = Object.prototype.hasOwnProperty('last_work_day') -// ? toDateOrNull(last_work_day ?? null) -// : undefined; + const first_work_d = toDateOrUndefined(first_work_day); + const last_work_d = Object.prototype.hasOwnProperty('last_work_day') + ? toDateOrNull(last_work_day ?? null) + : undefined; -// await this.prisma.$transaction(async (transaction) => { -// if ( -// first_name !== undefined || -// last_name !== undefined || -// new_email !== undefined || -// phone_number !== undefined || -// residence !== undefined -// ) { -// await transaction.users.update({ -// where: { id: active.user_id }, -// data: { -// ...(first_name !== undefined ? { first_name } : {}), -// ...(last_name !== undefined ? { last_name } : {}), -// ...(email !== undefined ? { email: new_email } : {}), -// ...(phone_number !== undefined ? { phone_number } : {}), -// ...(residence !== undefined ? { residence } : {}), -// }, -// }); + await this.prisma.$transaction(async (transaction) => { + if ( + first_name !== undefined || + last_name !== undefined || + new_email !== undefined || + phone_number !== undefined || + residence !== undefined + ) { + await transaction.users.update({ + where: { id: active.user_id }, + data: { + ...(first_name !== undefined ? { first_name } : {}), + ...(last_name !== undefined ? { last_name } : {}), + ...(email !== undefined ? { email: new_email } : {}), + ...(phone_number !== undefined ? { phone_number } : {}), + ...(residence !== undefined ? { residence } : {}), + }, + }); -// } + } -// const updated = await transaction.employees.update({ -// where: { id: active.id }, -// data: { -// ...(external_payroll_id !== undefined ? { external_payroll_id } : {}), -// ...(company_code !== undefined ? { company_code } : {}), -// ...(job_title !== undefined ? { job_title } : {}), -// ...(first_work_d !== undefined ? { first_work_day: first_work_d } : {}), -// ...(last_work_d !== undefined ? { last_work_day: last_work_d } : {}), -// ...(is_supervisor !== undefined ? { is_supervisor } : {}), -// ...(supervisor_id !== undefined ? { supervisor_id } : {}), -// }, -// include: { user: true }, -// }); + const updated = await transaction.employees.update({ + where: { id: active.id }, + data: { + ...(external_payroll_id !== undefined ? { external_payroll_id } : {}), + ...(company_code !== undefined ? { company_code } : {}), + ...(job_title !== undefined ? { job_title } : {}), + ...(first_work_d !== undefined ? { first_work_day: first_work_d } : {}), + ...(last_work_d !== undefined ? { last_work_day: last_work_d } : {}), + ...(is_supervisor !== undefined ? { is_supervisor } : {}), + ...(supervisor_id !== undefined ? { supervisor_id } : {}), + }, + include: { user: true }, + }); -// return updated; -// }); + return updated; + }); -// return this.prisma.employees.findFirst({ where: { user: { email } } }); -// } + return this.prisma.employees.findFirst({ where: { user: { email } } }); + } -// const user = await this.prisma.users.findUnique({ where: { email } }); -// if (!user) return null; -// // 2) Pas trouvé en actifs → regarder en archive (pour restauration) -// const archived = await this.prisma.employeesArchive.findFirst({ -// where: { user_id: user.id }, -// include: { user: true }, -// }); + const user = await this.prisma.users.findUnique({ where: { email } }); + if (!user) return null; + // 2) Pas trouvé en actifs → regarder en archive (pour restauration) + // const archived = await this.prisma.employeesArchive.findFirst({ + // where: { user_id: user.id }, + // include: { user: true }, + // }); -// if (archived) { -// // Condition de restauration : last_work_day === null ou first_work_day fourni -// const restore = dto.last_work_day === null || dto.first_work_day != null; -// if (restore) { -// return this.restoreEmployee(archived, dto); -// } -// } -// // 3) Ni actif, ni archivé → 404 dans le controller -// return null; -// } + // if (archived) { + // // Condition de restauration : last_work_day === null ou first_work_day fourni + // const restore = dto.last_work_day === null || dto.first_work_day != null; + // if (restore) { + // return this.restoreEmployee(archived, dto); + // } + // } + // 3) Ni actif, ni archivé → 404 dans le controller + return null; + } -// //transfers the employee to archive and then delete from employees table -// private async archiveOnTermination(active: Employees & { user: Users }, dto: UpdateEmployeeDto): Promise { -// const last_work_d = toDateOrNull(dto.last_work_day!); -// if (!last_work_d) throw new Error('invalide last_work_day for archive'); -// return this.prisma.$transaction(async transaction => { -// //detach crew from supervisor if employee is a supervisor -// await transaction.employees.updateMany({ -// where: { supervisor_id: active.id }, -// data: { supervisor_id: null }, -// }) -// const archived = await transaction.employeesArchive.create({ -// data: { -// employee_id: active.id, -// user_id: active.user_id, -// first_name: active.user.first_name, -// last_name: active.user.last_name, -// company_code: active.company_code, -// job_title: active.job_title, -// first_work_day: active.first_work_day, -// last_work_day: last_work_d, -// supervisor_id: active.supervisor_id ?? null, -// is_supervisor: active.is_supervisor, -// external_payroll_id: active.external_payroll_id, -// }, -// include: { user: true } -// }); -// //delete from employees table -// await transaction.employees.delete({ where: { id: active.id } }); -// //return archived employee -// return archived -// }); -// } + //transfers the employee to archive and then delete from employees table + // private async archiveOnTermination(active: Employees & { user: Users }, dto: UpdateEmployeeDto): Promise { + // const last_work_d = toDateOrNull(dto.last_work_day!); + // if (!last_work_d) throw new Error('invalide last_work_day for archive'); + // return this.prisma.$transaction(async transaction => { + // //detach crew from supervisor if employee is a supervisor + // await transaction.employees.updateMany({ + // where: { supervisor_id: active.id }, + // data: { supervisor_id: null }, + // }) + // const archived = await transaction.employeesArchive.create({ + // data: { + // employee_id: active.id, + // user_id: active.user_id, + // first_name: active.user.first_name, + // last_name: active.user.last_name, + // company_code: active.company_code, + // job_title: active.job_title, + // first_work_day: active.first_work_day, + // last_work_day: last_work_d, + // supervisor_id: active.supervisor_id ?? null, + // is_supervisor: active.is_supervisor, + // external_payroll_id: active.external_payroll_id, + // }, + // include: { user: true } + // }); + // //delete from employees table + // await transaction.employees.delete({ where: { id: active.id } }); + // //return archived employee + // return archived + // }); + // } -// //transfers the employee from archive to the employees table -// private async restoreEmployee(archived: EmployeesArchive & { user: Users }, dto: UpdateEmployeeDto): Promise { -// // const first_work_d = toDateOrUndefined(dto.first_work_day); -// return this.prisma.$transaction(async transaction => { -// //restores the archived employee into the employees table -// const restored = await transaction.employees.create({ -// data: { -// user_id: archived.user_id, -// company_code: archived.company_code, -// job_title: archived.job_title, -// first_work_day: archived.first_work_day, -// last_work_day: null, -// is_supervisor: archived.is_supervisor ?? false, -// external_payroll_id: archived.external_payroll_id, -// }, -// }); -// //deleting archived entry by id -// await transaction.employeesArchive.delete({ where: { id: archived.id } }); + // //transfers the employee from archive to the employees table + // private async restoreEmployee(archived: EmployeesArchive & { user: Users }, dto: UpdateEmployeeDto): Promise { + // // const first_work_d = toDateOrUndefined(dto.first_work_day); + // return this.prisma.$transaction(async transaction => { + // //restores the archived employee into the employees table + // const restored = await transaction.employees.create({ + // data: { + // user_id: archived.user_id, + // company_code: archived.company_code, + // job_title: archived.job_title, + // first_work_day: archived.first_work_day, + // last_work_day: null, + // is_supervisor: archived.is_supervisor ?? false, + // external_payroll_id: archived.external_payroll_id, + // }, + // }); + // //deleting archived entry by id + // await transaction.employeesArchive.delete({ where: { id: archived.id } }); -// //return restored employee -// return restored; -// }); -// } + // //return restored employee + // return restored; + // }); + // } -// //fetches all archived employees -// async findAllArchived(): Promise { -// return this.prisma.employeesArchive.findMany(); -// } + // //fetches all archived employees + // async findAllArchived(): Promise { + // return this.prisma.employeesArchive.findMany(); + // } -// //fetches an archived employee -// async findOneArchived(id: number): Promise { -// return this.prisma.employeesArchive.findUniqueOrThrow({ where: { id } }); -// } + // //fetches an archived employee + // async findOneArchived(id: number): Promise { + // return this.prisma.employeesArchive.findUniqueOrThrow({ where: { id } }); + // } -// } +} diff --git a/src/identity-and-account/employees/services/employees.service.ts b/src/identity-and-account/employees/services/employees.service.ts index b44bf7d..50873b6 100644 --- a/src/identity-and-account/employees/services/employees.service.ts +++ b/src/identity-and-account/employees/services/employees.service.ts @@ -1,230 +1,230 @@ -// import { Injectable, NotFoundException } from '@nestjs/common'; -// import { PrismaService } from 'src/prisma/prisma.service'; -// import { EmployeeListItemDto } from '../dtos/list-employee.dto'; -// import { EmployeeProfileItemDto } from '../dtos/profil-employee.dto'; +import { Injectable, NotFoundException } from "@nestjs/common"; +import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto"; +import { EmployeeProfileItemDto } from "src/identity-and-account/employees/dtos/profil-employee.dto"; +import { PrismaService } from "src/prisma/prisma.service"; -// @Injectable() -// export class EmployeesService { -// constructor(private readonly prisma: PrismaService) { } +@Injectable() +export class EmployeesService { + constructor(private readonly prisma: PrismaService) { } -// findListEmployees(): Promise { -// return this.prisma.employees.findMany({ -// select: { -// user: { -// select: { -// first_name: true, -// last_name: true, -// email: true, -// }, -// }, -// supervisor: { -// select: { -// user: { -// select: { -// first_name: true, -// last_name: true, -// }, -// }, -// }, -// }, -// job_title: true, -// company_code: true, -// } -// }).then(rows => rows.map(r => ({ -// first_name: r.user.first_name, -// last_name: r.user.last_name, -// email: r.user.email, -// company_name: r.company_code, -// job_title: r.job_title, -// employee_full_name: `${r.user.first_name} ${r.user.last_name}`, -// supervisor_full_name: r.supervisor ? `${r.supervisor.user.first_name} ${r.supervisor.user.last_name}` : null, -// })), -// ); -// } + findListEmployees(): Promise { + return this.prisma.employees.findMany({ + select: { + user: { + select: { + first_name: true, + last_name: true, + email: true, + }, + }, + supervisor: { + select: { + user: { + select: { + first_name: true, + last_name: true, + }, + }, + }, + }, + job_title: true, + company_code: true, + } + }).then(rows => rows.map(r => ({ + first_name: r.user.first_name, + last_name: r.user.last_name, + email: r.user.email, + company_name: r.company_code, + job_title: r.job_title, + employee_full_name: `${r.user.first_name} ${r.user.last_name}`, + supervisor_full_name: r.supervisor ? `${r.supervisor.user.first_name} ${r.supervisor.user.last_name}` : null, + })), + ); + } -// async findOneProfile(email: string): Promise { -// const emp = await this.prisma.employees.findFirst({ -// where: { user: { email } }, -// select: { -// user: { -// select: { -// first_name: true, -// last_name: true, -// email: true, -// phone_number: true, -// residence: true, -// }, -// }, -// supervisor: { -// select: { -// user: { -// select: { -// first_name: true, -// last_name: true, -// }, -// }, -// }, -// }, -// job_title: true, -// company_code: true, -// first_work_day: true, -// last_work_day: true, -// } -// }); -// if (!emp) throw new NotFoundException(`Employee with email ${email} not found`); + async findOneProfile(email: string): Promise { + const emp = await this.prisma.employees.findFirst({ + where: { user: { email } }, + select: { + user: { + select: { + first_name: true, + last_name: true, + email: true, + phone_number: true, + residence: true, + }, + }, + supervisor: { + select: { + user: { + select: { + first_name: true, + last_name: true, + }, + }, + }, + }, + job_title: true, + company_code: true, + first_work_day: true, + last_work_day: true, + } + }); + if (!emp) throw new NotFoundException(`Employee with email ${email} not found`); -// return { -// first_name: emp.user.first_name, -// last_name: emp.user.last_name, -// email: emp.user.email, -// residence: emp.user.residence, -// phone_number: emp.user.phone_number, -// company_name: emp.company_code, -// job_title: emp.job_title, -// employee_full_name: `${emp.user.first_name} ${emp.user.last_name}`, -// first_work_day: emp.first_work_day.toISOString().slice(0, 10), -// last_work_day: emp.last_work_day ? emp.last_work_day.toISOString().slice(0, 10) : null, -// supervisor_full_name: emp.supervisor ? `${emp.supervisor.user.first_name}, ${emp.supervisor.user.last_name}` : null, -// }; -// } + return { + first_name: emp.user.first_name, + last_name: emp.user.last_name, + email: emp.user.email, + residence: emp.user.residence, + phone_number: emp.user.phone_number, + company_name: emp.company_code, + job_title: emp.job_title, + employee_full_name: `${emp.user.first_name} ${emp.user.last_name}`, + first_work_day: emp.first_work_day.toISOString().slice(0, 10), + last_work_day: emp.last_work_day ? emp.last_work_day.toISOString().slice(0, 10) : null, + supervisor_full_name: emp.supervisor ? `${emp.supervisor.user.first_name}, ${emp.supervisor.user.last_name}` : null, + }; + } -// //_____________________________________________________________________________________________ -// // Deprecated or unused methods -// //_____________________________________________________________________________________________ + //_____________________________________________________________________________________________ + // Deprecated or unused methods + //_____________________________________________________________________________________________ -// // async create(dto: CreateEmployeeDto): Promise { -// // const { -// // first_name, -// // last_name, -// // email, -// // phone_number, -// // residence, -// // external_payroll_id, -// // company_code, -// // job_title, -// // first_work_day, -// // last_work_day, -// // is_supervisor, -// // } = dto; + // async create(dto: CreateEmployeeDto): Promise { + // const { + // first_name, + // last_name, + // email, + // phone_number, + // residence, + // external_payroll_id, + // company_code, + // job_title, + // first_work_day, + // last_work_day, + // is_supervisor, + // } = dto; -// // return this.prisma.$transaction(async (transaction) => { -// // const user: Users = await transaction.users.create({ -// // data: { -// // first_name, -// // last_name, -// // email, -// // phone_number, -// // residence, -// // }, -// // }); -// // return transaction.employees.create({ -// // data: { -// // user_id: user.id, -// // external_payroll_id, -// // company_code, -// // job_title, -// // first_work_day, -// // last_work_day, -// // is_supervisor, -// // }, -// // }); -// // }); -// // } + // return this.prisma.$transaction(async (transaction) => { + // const user: Users = await transaction.users.create({ + // data: { + // first_name, + // last_name, + // email, + // phone_number, + // residence, + // }, + // }); + // return transaction.employees.create({ + // data: { + // user_id: user.id, + // external_payroll_id, + // company_code, + // job_title, + // first_work_day, + // last_work_day, + // is_supervisor, + // }, + // }); + // }); + // } -// // findAll(): Promise { -// // return this.prisma.employees.findMany({ -// // include: { user: true }, -// // }); -// // } + // findAll(): Promise { + // return this.prisma.employees.findMany({ + // include: { user: true }, + // }); + // } -// // async findOne(email: string): Promise { -// // const emp = await this.prisma.employees.findFirst({ -// // where: { user: { email } }, -// // include: { user: true }, -// // }); + // async findOne(email: string): Promise { + // const emp = await this.prisma.employees.findFirst({ + // where: { user: { email } }, + // include: { user: true }, + // }); -// // //add search for archived employees -// // if (!emp) { -// // throw new NotFoundException(`Employee with email: ${email} not found`); -// // } -// // return emp; -// // } + // //add search for archived employees + // if (!emp) { + // throw new NotFoundException(`Employee with email: ${email} not found`); + // } + // return emp; + // } -// // async update( -// // email: string, -// // dto: UpdateEmployeeDto, -// // ): Promise { -// // const emp = await this.findOne(email); + // async update( + // email: string, + // dto: UpdateEmployeeDto, + // ): Promise { + // const emp = await this.findOne(email); -// // const { -// // first_name, -// // last_name, -// // phone_number, -// // residence, -// // external_payroll_id, -// // company_code, -// // job_title, -// // first_work_day, -// // last_work_day, -// // is_supervisor, -// // email: new_email, -// // } = dto; + // const { + // first_name, + // last_name, + // phone_number, + // residence, + // external_payroll_id, + // company_code, + // job_title, + // first_work_day, + // last_work_day, + // is_supervisor, + // email: new_email, + // } = dto; -// // return this.prisma.$transaction(async (transaction) => { -// // if( -// // first_name !== undefined || -// // last_name !== undefined || -// // new_email !== undefined || -// // phone_number !== undefined || -// // residence !== undefined -// // ){ -// // await transaction.users.update({ -// // where: { id: emp.user_id }, -// // data: { -// // ...(first_name !== undefined && { first_name }), -// // ...(last_name !== undefined && { last_name }), -// // ...(email !== undefined && { email }), -// // ...(phone_number !== undefined && { phone_number }), -// // ...(residence !== undefined && { residence }), -// // }, -// // }); -// // } + // return this.prisma.$transaction(async (transaction) => { + // if( + // first_name !== undefined || + // last_name !== undefined || + // new_email !== undefined || + // phone_number !== undefined || + // residence !== undefined + // ){ + // await transaction.users.update({ + // where: { id: emp.user_id }, + // data: { + // ...(first_name !== undefined && { first_name }), + // ...(last_name !== undefined && { last_name }), + // ...(email !== undefined && { email }), + // ...(phone_number !== undefined && { phone_number }), + // ...(residence !== undefined && { residence }), + // }, + // }); + // } -// // const updated = await transaction.employees.update({ -// // where: { id: emp.id }, -// // data: { -// // ...(external_payroll_id !== undefined && { external_payroll_id }), -// // ...(company_code !== undefined && { company_code }), -// // ...(first_work_day !== undefined && { first_work_day }), -// // ...(last_work_day !== undefined && { last_work_day }), -// // ...(job_title !== undefined && { job_title }), -// // ...(is_supervisor !== undefined && { is_supervisor }), -// // }, -// // }); -// // return updated; -// // }); -// // } + // const updated = await transaction.employees.update({ + // where: { id: emp.id }, + // data: { + // ...(external_payroll_id !== undefined && { external_payroll_id }), + // ...(company_code !== undefined && { company_code }), + // ...(first_work_day !== undefined && { first_work_day }), + // ...(last_work_day !== undefined && { last_work_day }), + // ...(job_title !== undefined && { job_title }), + // ...(is_supervisor !== undefined && { is_supervisor }), + // }, + // }); + // return updated; + // }); + // } -// // async remove(email: string): Promise { + // async remove(email: string): Promise { -// // const emp = await this.findOne(email); + // const emp = await this.findOne(email); -// // return this.prisma.$transaction(async (transaction) => { -// // await transaction.employees.updateMany({ -// // where: { supervisor_id: emp.id }, -// // data: { supervisor_id: null }, -// // }); -// // const deleted_employee = await transaction.employees.delete({ -// // where: {id: emp.id }, -// // }); -// // await transaction.users.delete({ -// // where: { id: emp.user_id }, -// // }); -// // return deleted_employee; -// // }); -// // } + // return this.prisma.$transaction(async (transaction) => { + // await transaction.employees.updateMany({ + // where: { supervisor_id: emp.id }, + // data: { supervisor_id: null }, + // }); + // const deleted_employee = await transaction.employees.delete({ + // where: {id: emp.id }, + // }); + // await transaction.users.delete({ + // where: { id: emp.user_id }, + // }); + // return deleted_employee; + // }); + // } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/identity-and-account/employees/utils/employee.utils.ts b/src/identity-and-account/employees/utils/employee.utils.ts index 04f2540..3534f3d 100644 --- a/src/identity-and-account/employees/utils/employee.utils.ts +++ b/src/identity-and-account/employees/utils/employee.utils.ts @@ -1,9 +1,9 @@ -// export function toDateOrNull(v?: string | null): Date | null { -// if (!v) return null; -// const day = new Date(v); -// return isNaN(day.getTime()) ? null : day; -// } -// export function toDateOrUndefined(v?: string | null): Date | undefined { -// const day = toDateOrNull(v ?? undefined); -// return day === null ? undefined : day; -// } \ No newline at end of file +export function toDateOrNull(v?: string | null): Date | null { + if (!v) return null; + const day = new Date(v); + return isNaN(day.getTime()) ? null : day; +} +export function toDateOrUndefined(v?: string | null): Date | undefined { + const day = toDateOrNull(v ?? undefined); + return day === null ? undefined : day; +} \ No newline at end of file