refactor(employees): adapted logics to match new userModuleAccess and cleaned module of unused methods
This commit is contained in:
parent
ddb469cd8e
commit
98180dd16b
|
|
@ -465,7 +465,7 @@
|
||||||
},
|
},
|
||||||
"/employees/profile": {
|
"/employees/profile": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "EmployeesController_findOneProfile",
|
"operationId": "EmployeesController_findProfile",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "employee_email",
|
"name": "employee_email",
|
||||||
|
|
@ -500,6 +500,30 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/employees": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "EmployeesController_createEmployee",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/EmployeeDetailedDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Employees"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/preferences/update": {
|
"/preferences/update": {
|
||||||
"patch": {
|
"patch": {
|
||||||
"operationId": "PreferencesController_updatePreferences",
|
"operationId": "PreferencesController_updatePreferences",
|
||||||
|
|
@ -660,6 +684,10 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {}
|
"properties": {}
|
||||||
},
|
},
|
||||||
|
"EmployeeDetailedDto": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
},
|
||||||
"PreferencesDto": {
|
"PreferencesDto": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {}
|
"properties": {}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ model Employees {
|
||||||
supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
|
supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
|
||||||
supervisor_id Int?
|
supervisor_id Int?
|
||||||
|
|
||||||
external_payroll_id Int
|
external_payroll_id Int @default(autoincrement())
|
||||||
company_code Int
|
company_code Int
|
||||||
first_work_day DateTime @db.Date
|
first_work_day DateTime @db.Date
|
||||||
last_work_day DateTime? @db.Date
|
last_work_day DateTime? @db.Date
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
|
||||||
|
|
||||||
|
export const Access = createParamDecorator(
|
||||||
|
(data:string, ctx: ExecutionContext) => {
|
||||||
|
const request = ctx.switchToHttp().getRequest();
|
||||||
|
const user = request.user;
|
||||||
|
return data ? user?.[data] : user;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
|
|
||||||
|
|
||||||
export const Access = createParamDecorator(
|
|
||||||
(data: string, ctx: ExecutionContext) => {
|
|
||||||
const request = ctx.switchToHttp().getRequest();
|
|
||||||
const user = request.user;
|
|
||||||
return data ? user?.[data] : user;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
29
src/common/pipes/module-accessvalidation.pipe.ts
Normal file
29
src/common/pipes/module-accessvalidation.pipe.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { PipeTransform } from "@nestjs/common";
|
||||||
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
|
export class ModuleAccessValidationPipe implements PipeTransform {
|
||||||
|
constructor(private readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
|
async transform(value: any) {
|
||||||
|
const { email, access } = value ?? {};
|
||||||
|
const user = await this.prisma.users.findUnique({
|
||||||
|
where: { email },
|
||||||
|
select: {
|
||||||
|
user_module_access: {
|
||||||
|
select: {
|
||||||
|
dashboard: true,
|
||||||
|
employee_list: true,
|
||||||
|
employee_management: true,
|
||||||
|
personal_profile: true,
|
||||||
|
timesheets: true,
|
||||||
|
timesheets_approval: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!Boolean(access)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,82 +1,65 @@
|
||||||
import { Controller, Get, Req, Query } from "@nestjs/common";
|
import { Controller, Get, Query, Body, Post } from "@nestjs/common";
|
||||||
|
import { Access } from "src/common/decorators/module-access.decorators";
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { Access } from "src/common/guards/module-access.guard";
|
|
||||||
import { GLOBAL_CONTROLLER_ROLES } from "src/common/shared/role-groupes";
|
import { GLOBAL_CONTROLLER_ROLES } from "src/common/shared/role-groupes";
|
||||||
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto";
|
||||||
import { EmployeeProfileItemDto } from "src/identity-and-account/employees/dtos/profil-employee.dto";
|
import { EmployeeDto } from "src/identity-and-account/employees/dtos/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";
|
import { EmployeesService } from "src/identity-and-account/employees/services/employees.service";
|
||||||
import { AccessGetService } from "src/identity-and-account/user-module-access/services/module-access-get.service";
|
import { AccessGetService } from "src/identity-and-account/user-module-access/services/module-access-get.service";
|
||||||
|
//TODO: create a custom decorator to replace the findModuleAcces call function
|
||||||
|
|
||||||
@RolesAllowed(...GLOBAL_CONTROLLER_ROLES)
|
@RolesAllowed(...GLOBAL_CONTROLLER_ROLES)
|
||||||
@Controller('employees')
|
@Controller('employees')
|
||||||
export class EmployeesController {
|
export class EmployeesController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly employeesService: EmployeesService,
|
private readonly employeesService: EmployeesService,
|
||||||
private readonly accessGetService: AccessGetService,
|
private readonly accessGetService: AccessGetService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Get('profile')
|
@Get('profile')
|
||||||
async findOneProfile(
|
async findProfile(@Access('email') email: string, @Query('employee_email') employee_email?: string,
|
||||||
@Access('email') email:string,
|
): Promise<Result<Partial<EmployeeDetailedDto>, string>> {
|
||||||
@Query('employee_email') employee_email?: string,
|
const granted_access = await this.accessGetService.findModuleAccess(email);
|
||||||
): Promise<Result<EmployeeProfileItemDto, string>> {
|
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
||||||
//fetch the current user granted access
|
if (!granted_access.data.employee_management) {
|
||||||
const granted_access = await this.accessGetService.findModuleAccess(email);
|
return await this.employeesService.findOwnProfile(email);
|
||||||
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
} else if (granted_access.data.employee_management) {
|
||||||
//check if credentials are enough to use this resource
|
return await this.employeesService.findOneDetailedProfile(employee_email ?? email);
|
||||||
if (!granted_access.data.personal_profile) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
} else {
|
||||||
|
return { success: false, error: 'INVALID_USER'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return this.employeesService.findOneProfile(employee_email ?? email);
|
@Get('employee-list')
|
||||||
}
|
async findListEmployees(@Access('email') email: string
|
||||||
|
): Promise<Result<EmployeeDto[], string>> {
|
||||||
|
const granted_access = await this.accessGetService.findModuleAccess(email);
|
||||||
|
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
||||||
|
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
||||||
|
return this.employeesService.findListEmployees();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
async createEmployee(@Access('email') email: string, @Body() dto: EmployeeDetailedDto
|
||||||
|
): Promise<Result<boolean, string>> {
|
||||||
|
const granted_access = await this.accessGetService.findModuleAccess(email);
|
||||||
|
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
||||||
|
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
||||||
|
return await this.employeesService.createEmployee(dto);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: create a custom decorator to replace the findModuleAcces call function
|
// @Patch()
|
||||||
|
// async updateOrArchiveOrRestore(@Req() req, @Body() dto: UpdateEmployeeDto,) {
|
||||||
@Get('employee-list')
|
// // if last_work_day is set => archive the employee
|
||||||
async findListEmployees(@Req() req): Promise<Result<EmployeeListItemDto[], string>> {
|
// // else if employee is archived and first_work_day or last_work_day = null => restore
|
||||||
const email = req.user?.email;
|
// //otherwise => standard update
|
||||||
//fetch the current user granted access
|
// const email = req.user?.email;
|
||||||
const granted_access = await this.accessGetService.findModuleAccess(email);
|
// const result = await this.archiveService.patchEmployee(email, dto);
|
||||||
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
// if (!result) {
|
||||||
//check if credentials are enough to use this resource
|
// throw new NotFoundException(`Employee with email: ${email} is not found in active or archive.`)
|
||||||
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
// }
|
||||||
|
// return result;
|
||||||
const employee_list = await this.employeesService.findListEmployees();
|
//
|
||||||
if (!employee_list.success) return { success: false, error: employee_list.error };
|
|
||||||
return { success: true, data: employee_list.data };
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Patch()
|
|
||||||
// async updateOrArchiveOrRestore(@Req() req, @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 email = req.user?.email;
|
|
||||||
// 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()
|
|
||||||
// async create(@Body() dto: CreateEmployeeDto, @Req() req): Promise<Result<Employees, string>> {
|
|
||||||
// try {
|
|
||||||
// const email = req.user?.email;
|
|
||||||
// //fetch the current user granted access
|
|
||||||
// const granted_access = await this.accessgetService.findModuleAccess(email);
|
|
||||||
// if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
|
||||||
// //check if credentials are enough to use this resource
|
|
||||||
// if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
|
||||||
|
|
||||||
// const created_employee = await this.employeesService.create(dto);
|
|
||||||
// return { success: true, data: created_employee };
|
|
||||||
// } catch (error) {
|
|
||||||
// return { success: false, error: 'UNAUTHORIZED_USER' };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
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 { UserDto } from 'src/identity-and-account/users-management/dtos/user.dto';
|
|
||||||
|
|
||||||
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: '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: 'i_cant_do_this_sam@targointernet.com',
|
|
||||||
description: 'Employee`s email',
|
|
||||||
})
|
|
||||||
@IsEmail()
|
|
||||||
@IsOptional()
|
|
||||||
email: string;
|
|
||||||
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
is_supervisor: boolean;
|
|
||||||
|
|
||||||
@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: 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:'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: '25/03/3019',
|
|
||||||
description: 'Employee`s last working day',
|
|
||||||
required: false,
|
|
||||||
})
|
|
||||||
@IsDateString()
|
|
||||||
@IsOptional()
|
|
||||||
last_work_day?: string;
|
|
||||||
|
|
||||||
user?: UserDto;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { IsBoolean, IsDateString, IsEmail, IsInt, IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator';
|
||||||
|
import { ModuleAccess } from 'src/identity-and-account/user-module-access/dtos/module-acces.dto';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
|
||||||
|
export class EmployeeDetailedDto {
|
||||||
|
@IsString() @IsNotEmpty() first_name: string;
|
||||||
|
@IsString() @IsNotEmpty() last_name: string;
|
||||||
|
@IsString() employee_full_name: string;
|
||||||
|
@IsString() @IsOptional() supervisor_full_name: string;
|
||||||
|
@IsOptional() @IsBoolean() is_supervisor: boolean;
|
||||||
|
@IsString() company_name: string;
|
||||||
|
@IsString() @IsOptional() job_title: string;
|
||||||
|
@IsEmail() @IsOptional() email: string;
|
||||||
|
@IsString() phone_number: string;
|
||||||
|
@IsDateString() first_work_day: string;
|
||||||
|
@IsDateString() @IsOptional() last_work_day?: string;
|
||||||
|
@IsString() @IsOptional() residence?: string;
|
||||||
|
@IsInt() @IsPositive() @Type(() => Number) external_payroll_id: number;
|
||||||
|
@Type(() => ModuleAccess) module_access: ModuleAccess;
|
||||||
|
}
|
||||||
12
src/identity-and-account/employees/dtos/employee.dto.ts
Normal file
12
src/identity-and-account/employees/dtos/employee.dto.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
import { IsEmail, IsInt, IsOptional, IsString } from "class-validator";
|
||||||
|
|
||||||
|
export class EmployeeDto {
|
||||||
|
@IsString() first_name!: string;
|
||||||
|
@IsString() last_name!: string;
|
||||||
|
@IsString() @IsEmail() email!: string;
|
||||||
|
@IsString() @IsOptional() supervisor_full_name: string | '';
|
||||||
|
@IsString() company_name: number;
|
||||||
|
@IsString() @IsOptional() job_title: string;
|
||||||
|
@IsInt() @Type(()=> Number) external_payroll_id: number;
|
||||||
|
}
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
export class EmployeeListItemDto {
|
|
||||||
first_name: string;
|
|
||||||
last_name: string;
|
|
||||||
email: string;
|
|
||||||
supervisor_full_name: string | null;
|
|
||||||
company_name: number | null;
|
|
||||||
job_title: string | null;
|
|
||||||
external_payroll_id: number;
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
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;
|
|
||||||
external_payroll_id: number;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
phone_number: string;
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { EmployeesController } from './controllers/employees.controller';
|
import { EmployeesController } from './controllers/employees.controller';
|
||||||
import { EmployeesService } from './services/employees.service';
|
import { EmployeesService } from './services/employees.service';
|
||||||
import { EmployeesArchivalService } from 'src/identity-and-account/employees/services/employees-archival.service';
|
|
||||||
import { AccessGetService } from 'src/identity-and-account/user-module-access/services/module-access-get.service';
|
import { AccessGetService } from 'src/identity-and-account/user-module-access/services/module-access-get.service';
|
||||||
import { EmailToIdResolver } from 'src/common/mappers/email-id.mapper';
|
import { EmailToIdResolver } from 'src/common/mappers/email-id.mapper';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
controllers: [EmployeesController],
|
controllers: [EmployeesController],
|
||||||
providers: [EmployeesService, EmployeesArchivalService, AccessGetService, EmailToIdResolver],
|
providers: [EmployeesService, AccessGetService, EmailToIdResolver],
|
||||||
exports: [EmployeesService ],
|
exports: [EmployeesService ],
|
||||||
})
|
})
|
||||||
export class EmployeesModule {}
|
export class EmployeesModule {}
|
||||||
|
|
|
||||||
|
|
@ -1,173 +1,173 @@
|
||||||
import { Injectable } from "@nestjs/common";
|
// import { Injectable } from "@nestjs/common";
|
||||||
import { Employees, Users } from "@prisma/client";
|
// import { Employees, Users } from "@prisma/client";
|
||||||
import { UpdateEmployeeDto } from "src/identity-and-account/employees/dtos/update-employee.dto";
|
// // 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 { toDateOrUndefined, toDateOrNull } from "src/identity-and-account/employees/utils/employee.utils";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
// import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
@Injectable()
|
// @Injectable()
|
||||||
export class EmployeesArchivalService {
|
// export class EmployeesArchivalService {
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
// constructor(private readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
async patchEmployee(email: string, dto: UpdateEmployeeDto): Promise<Employees | null> {
|
// async patchEmployee(email: string, dto: UpdateEmployeeDto): Promise<Employees | null> {
|
||||||
// 1) Tenter sur employés actifs
|
// // 1) Tenter sur employés actifs
|
||||||
const active = await this.prisma.employees.findFirst({
|
// const active = await this.prisma.employees.findFirst({
|
||||||
where: { user: { email } },
|
// where: { user: { email } },
|
||||||
include: { user: true },
|
// include: { user: true },
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (active) {
|
// if (active) {
|
||||||
// Archivage : si on reçoit un last_work_day défini et que l'employé n’est pas déjà terminé
|
// // 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) {
|
// // if (dto.last_work_day !== undefined && active.last_work_day == null && dto.last_work_day !== null) {
|
||||||
// return this.archiveOnTermination(active, dto);
|
// // return this.archiveOnTermination(active, dto);
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// Sinon, update standard (split Users/Employees)
|
// // Sinon, update standard (split Users/Employees)
|
||||||
const {
|
// const {
|
||||||
first_name,
|
// first_name,
|
||||||
last_name,
|
// last_name,
|
||||||
email: new_email,
|
// email: new_email,
|
||||||
phone_number,
|
// phone_number,
|
||||||
residence,
|
// residence,
|
||||||
external_payroll_id,
|
// external_payroll_id,
|
||||||
company_code,
|
// company_code,
|
||||||
job_title,
|
// job_title,
|
||||||
first_work_day,
|
// first_work_day,
|
||||||
last_work_day,
|
// last_work_day,
|
||||||
supervisor_id,
|
// supervisor_id,
|
||||||
is_supervisor,
|
// is_supervisor,
|
||||||
} = dto as any;
|
// } = dto as any;
|
||||||
|
|
||||||
const first_work_d = toDateOrUndefined(first_work_day);
|
// const first_work_d = toDateOrUndefined(first_work_day);
|
||||||
const last_work_d = Object.prototype.hasOwnProperty('last_work_day')
|
// const last_work_d = Object.prototype.hasOwnProperty('last_work_day')
|
||||||
? toDateOrNull(last_work_day ?? null)
|
// ? toDateOrNull(last_work_day ?? null)
|
||||||
: undefined;
|
// : undefined;
|
||||||
|
|
||||||
await this.prisma.$transaction(async (transaction) => {
|
// await this.prisma.$transaction(async (transaction) => {
|
||||||
if (
|
// if (
|
||||||
first_name !== undefined ||
|
// first_name !== undefined ||
|
||||||
last_name !== undefined ||
|
// last_name !== undefined ||
|
||||||
new_email !== undefined ||
|
// new_email !== undefined ||
|
||||||
phone_number !== undefined ||
|
// phone_number !== undefined ||
|
||||||
residence !== undefined
|
// residence !== undefined
|
||||||
) {
|
// ) {
|
||||||
await transaction.users.update({
|
// await transaction.users.update({
|
||||||
where: { id: active.user_id },
|
// where: { id: active.user_id },
|
||||||
data: {
|
// data: {
|
||||||
...(first_name !== undefined ? { first_name } : {}),
|
// ...(first_name !== undefined ? { first_name } : {}),
|
||||||
...(last_name !== undefined ? { last_name } : {}),
|
// ...(last_name !== undefined ? { last_name } : {}),
|
||||||
...(email !== undefined ? { email: new_email } : {}),
|
// ...(email !== undefined ? { email: new_email } : {}),
|
||||||
...(phone_number !== undefined ? { phone_number } : {}),
|
// ...(phone_number !== undefined ? { phone_number } : {}),
|
||||||
...(residence !== undefined ? { residence } : {}),
|
// ...(residence !== undefined ? { residence } : {}),
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
const updated = await transaction.employees.update({
|
// const updated = await transaction.employees.update({
|
||||||
where: { id: active.id },
|
// where: { id: active.id },
|
||||||
data: {
|
// data: {
|
||||||
...(external_payroll_id !== undefined ? { external_payroll_id } : {}),
|
// ...(external_payroll_id !== undefined ? { external_payroll_id } : {}),
|
||||||
...(company_code !== undefined ? { company_code } : {}),
|
// ...(company_code !== undefined ? { company_code } : {}),
|
||||||
...(job_title !== undefined ? { job_title } : {}),
|
// ...(job_title !== undefined ? { job_title } : {}),
|
||||||
...(first_work_d !== undefined ? { first_work_day: first_work_d } : {}),
|
// ...(first_work_d !== undefined ? { first_work_day: first_work_d } : {}),
|
||||||
...(last_work_d !== undefined ? { last_work_day: last_work_d } : {}),
|
// ...(last_work_d !== undefined ? { last_work_day: last_work_d } : {}),
|
||||||
...(is_supervisor !== undefined ? { is_supervisor } : {}),
|
// ...(is_supervisor !== undefined ? { is_supervisor } : {}),
|
||||||
...(supervisor_id !== undefined ? { supervisor_id } : {}),
|
// ...(supervisor_id !== undefined ? { supervisor_id } : {}),
|
||||||
},
|
// },
|
||||||
include: { user: true },
|
// 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 } });
|
// const user = await this.prisma.users.findUnique({ where: { email } });
|
||||||
if (!user) return null;
|
// if (!user) return null;
|
||||||
// 2) Pas trouvé en actifs → regarder en archive (pour restauration)
|
// // 2) Pas trouvé en actifs → regarder en archive (pour restauration)
|
||||||
// const archived = await this.prisma.employeesArchive.findFirst({
|
// // const archived = await this.prisma.employeesArchive.findFirst({
|
||||||
// where: { user_id: user.id },
|
// // where: { user_id: user.id },
|
||||||
// include: { user: true },
|
// // include: { user: true },
|
||||||
// });
|
// // });
|
||||||
|
|
||||||
// if (archived) {
|
// // if (archived) {
|
||||||
// // Condition de restauration : last_work_day === null ou first_work_day fourni
|
// // // Condition de restauration : last_work_day === null ou first_work_day fourni
|
||||||
// const restore = dto.last_work_day === null || dto.first_work_day != null;
|
// // const restore = dto.last_work_day === null || dto.first_work_day != null;
|
||||||
// if (restore) {
|
// // if (restore) {
|
||||||
// return this.restoreEmployee(archived, dto);
|
// // return this.restoreEmployee(archived, dto);
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
// 3) Ni actif, ni archivé → 404 dans le controller
|
// // 3) Ni actif, ni archivé → 404 dans le controller
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//transfers the employee to archive and then delete from employees table
|
// //transfers the employee to archive and then delete from employees table
|
||||||
// private async archiveOnTermination(active: Employees & { user: Users }, dto: UpdateEmployeeDto): Promise<EmployeesArchive> {
|
// // private async archiveOnTermination(active: Employees & { user: Users }, dto: UpdateEmployeeDto): Promise<EmployeesArchive> {
|
||||||
// const last_work_d = toDateOrNull(dto.last_work_day!);
|
// // const last_work_d = toDateOrNull(dto.last_work_day!);
|
||||||
// if (!last_work_d) throw new Error('invalide last_work_day for archive');
|
// // if (!last_work_d) throw new Error('invalide last_work_day for archive');
|
||||||
// return this.prisma.$transaction(async transaction => {
|
// // return this.prisma.$transaction(async transaction => {
|
||||||
// //detach crew from supervisor if employee is a supervisor
|
// // //detach crew from supervisor if employee is a supervisor
|
||||||
// await transaction.employees.updateMany({
|
// // await transaction.employees.updateMany({
|
||||||
// where: { supervisor_id: active.id },
|
// // where: { supervisor_id: active.id },
|
||||||
// data: { supervisor_id: null },
|
// // data: { supervisor_id: null },
|
||||||
// })
|
// // })
|
||||||
// const archived = await transaction.employeesArchive.create({
|
// // const archived = await transaction.employeesArchive.create({
|
||||||
// data: {
|
// // data: {
|
||||||
// employee_id: active.id,
|
// // employee_id: active.id,
|
||||||
// user_id: active.user_id,
|
// // user_id: active.user_id,
|
||||||
// first_name: active.user.first_name,
|
// // first_name: active.user.first_name,
|
||||||
// last_name: active.user.last_name,
|
// // last_name: active.user.last_name,
|
||||||
// company_code: active.company_code,
|
// // company_code: active.company_code,
|
||||||
// job_title: active.job_title,
|
// // job_title: active.job_title,
|
||||||
// first_work_day: active.first_work_day,
|
// // first_work_day: active.first_work_day,
|
||||||
// last_work_day: last_work_d,
|
// // last_work_day: last_work_d,
|
||||||
// supervisor_id: active.supervisor_id ?? null,
|
// // supervisor_id: active.supervisor_id ?? null,
|
||||||
// is_supervisor: active.is_supervisor,
|
// // is_supervisor: active.is_supervisor,
|
||||||
// external_payroll_id: active.external_payroll_id,
|
// // external_payroll_id: active.external_payroll_id,
|
||||||
// },
|
// // },
|
||||||
// include: { user: true }
|
// // include: { user: true }
|
||||||
// });
|
// // });
|
||||||
// //delete from employees table
|
// // //delete from employees table
|
||||||
// await transaction.employees.delete({ where: { id: active.id } });
|
// // await transaction.employees.delete({ where: { id: active.id } });
|
||||||
// //return archived employee
|
// // //return archived employee
|
||||||
// return archived
|
// // return archived
|
||||||
// });
|
// // });
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// //transfers the employee from archive to the employees table
|
// // //transfers the employee from archive to the employees table
|
||||||
// private async restoreEmployee(archived: EmployeesArchive & { user: Users }, dto: UpdateEmployeeDto): Promise<Employees> {
|
// // private async restoreEmployee(archived: EmployeesArchive & { user: Users }, dto: UpdateEmployeeDto): Promise<Employees> {
|
||||||
// // const first_work_d = toDateOrUndefined(dto.first_work_day);
|
// // // const first_work_d = toDateOrUndefined(dto.first_work_day);
|
||||||
// return this.prisma.$transaction(async transaction => {
|
// // return this.prisma.$transaction(async transaction => {
|
||||||
// //restores the archived employee into the employees table
|
// // //restores the archived employee into the employees table
|
||||||
// const restored = await transaction.employees.create({
|
// // const restored = await transaction.employees.create({
|
||||||
// data: {
|
// // data: {
|
||||||
// user_id: archived.user_id,
|
// // user_id: archived.user_id,
|
||||||
// company_code: archived.company_code,
|
// // company_code: archived.company_code,
|
||||||
// job_title: archived.job_title,
|
// // job_title: archived.job_title,
|
||||||
// first_work_day: archived.first_work_day,
|
// // first_work_day: archived.first_work_day,
|
||||||
// last_work_day: null,
|
// // last_work_day: null,
|
||||||
// is_supervisor: archived.is_supervisor ?? false,
|
// // is_supervisor: archived.is_supervisor ?? false,
|
||||||
// external_payroll_id: archived.external_payroll_id,
|
// // external_payroll_id: archived.external_payroll_id,
|
||||||
// },
|
// // },
|
||||||
// });
|
// // });
|
||||||
// //deleting archived entry by id
|
// // //deleting archived entry by id
|
||||||
// await transaction.employeesArchive.delete({ where: { id: archived.id } });
|
// // await transaction.employeesArchive.delete({ where: { id: archived.id } });
|
||||||
|
|
||||||
// //return restored employee
|
// // //return restored employee
|
||||||
// return restored;
|
// // return restored;
|
||||||
// });
|
// // });
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// //fetches all archived employees
|
// // //fetches all archived employees
|
||||||
// async findAllArchived(): Promise<EmployeesArchive[]> {
|
// // async findAllArchived(): Promise<EmployeesArchive[]> {
|
||||||
// return this.prisma.employeesArchive.findMany();
|
// // return this.prisma.employeesArchive.findMany();
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// //fetches an archived employee
|
// // //fetches an archived employee
|
||||||
// async findOneArchived(id: number): Promise<EmployeesArchive> {
|
// // async findOneArchived(id: number): Promise<EmployeesArchive> {
|
||||||
// return this.prisma.employeesArchive.findUniqueOrThrow({ where: { id } });
|
// // return this.prisma.employeesArchive.findUniqueOrThrow({ where: { id } });
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,139 +1,225 @@
|
||||||
import { Injectable, NotFoundException } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
import { Employees, Users } from "@prisma/client";
|
import { Users } from "@prisma/client";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||||
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto";
|
||||||
import { EmployeeProfileItemDto } from "src/identity-and-account/employees/dtos/profil-employee.dto";
|
import { EmployeeDto } from "src/identity-and-account/employees/dtos/employee.dto";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EmployeesService {
|
export class EmployeesService {
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
constructor(
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
|
) { }
|
||||||
|
|
||||||
async findListEmployees(): Promise<Result<EmployeeListItemDto[], string>> {
|
async findListEmployees(): Promise<Result<EmployeeDto[], string>> {
|
||||||
return {success: true, data:await this.prisma.employees.findMany({
|
const employee_list = await this.prisma.employees.findMany({
|
||||||
select: {
|
select: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
first_name: true,
|
first_name: true,
|
||||||
last_name: true,
|
last_name: true,
|
||||||
email: true,
|
email: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
supervisor: {
|
supervisor: {
|
||||||
select: {
|
select: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
first_name: true,
|
first_name: true,
|
||||||
last_name: true,
|
last_name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
job_title: true,
|
job_title: true,
|
||||||
company_code: true,
|
company_code: true,
|
||||||
external_payroll_id: true,
|
external_payroll_id: 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,
|
|
||||||
external_payroll_id: r.external_payroll_id,
|
|
||||||
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<Result<EmployeeProfileItemDto, string>> {
|
}
|
||||||
const employee = await this.prisma.employees.findFirst({
|
}).then(rows => rows.map(r => ({
|
||||||
where: { user: { email } },
|
first_name: r.user.first_name,
|
||||||
select: {
|
last_name: r.user.last_name,
|
||||||
user: {
|
email: r.user.email,
|
||||||
select: {
|
company_name: r.company_code,
|
||||||
first_name: true,
|
job_title: r.job_title ?? '',
|
||||||
last_name: true,
|
external_payroll_id: r.external_payroll_id,
|
||||||
email: true,
|
employee_full_name: `${r.user.first_name} ${r.user.last_name}`,
|
||||||
phone_number: true,
|
supervisor_full_name: `${r.supervisor?.user.first_name} ${r.supervisor?.user.last_name}`,
|
||||||
residence: true,
|
})),
|
||||||
},
|
)
|
||||||
},
|
return {
|
||||||
supervisor: {
|
success: true,
|
||||||
select: {
|
data: employee_list,
|
||||||
user: {
|
}
|
||||||
select: {
|
}
|
||||||
first_name: true,
|
|
||||||
last_name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
job_title: true,
|
|
||||||
company_code: true,
|
|
||||||
first_work_day: true,
|
|
||||||
last_work_day: true,
|
|
||||||
external_payroll_id: true,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!employee)return {success: false, error: `Employee with email ${email} not found`};
|
|
||||||
|
|
||||||
return {
|
async findOwnProfile(email: string): Promise<Result<Partial<EmployeeDetailedDto>, string>> {
|
||||||
success: true,
|
const user_id = await this.emailResolver.resolveUserIdWithEmail(email);
|
||||||
data: {
|
if (!user_id.success) return { success: false, error: 'INVALID_USER' };
|
||||||
first_name: employee.user.first_name,
|
|
||||||
last_name: employee.user.last_name,
|
|
||||||
email: employee.user.email,
|
|
||||||
residence: employee.user.residence,
|
|
||||||
phone_number: employee.user.phone_number,
|
|
||||||
company_name: employee.company_code,
|
|
||||||
job_title: employee.job_title,
|
|
||||||
external_payroll_id: employee.external_payroll_id,
|
|
||||||
employee_full_name: `${employee.user.first_name} ${employee.user.last_name}`,
|
|
||||||
first_work_day: employee.first_work_day.toISOString().slice(0, 10),
|
|
||||||
last_work_day: employee.last_work_day ? employee.last_work_day.toISOString().slice(0, 10) : null,
|
|
||||||
supervisor_full_name: employee.supervisor ? `${employee.supervisor.user.first_name}, ${employee.supervisor.user.last_name}` : null,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async create(dto: CreateEmployeeDto): Promise<Employees> {
|
const existing_profile = await this.prisma.employees.findUnique({
|
||||||
const {
|
where: { user_id: user_id.data },
|
||||||
first_name,
|
select: {
|
||||||
last_name,
|
user: {
|
||||||
email,
|
select: {
|
||||||
phone_number,
|
first_name: true,
|
||||||
residence,
|
last_name: true,
|
||||||
external_payroll_id,
|
email: true,
|
||||||
company_code,
|
},
|
||||||
job_title,
|
},
|
||||||
first_work_day,
|
company_code: true,
|
||||||
last_work_day,
|
job_title: true,
|
||||||
is_supervisor,
|
external_payroll_id: true,
|
||||||
} = dto;
|
supervisor: {
|
||||||
|
select: {
|
||||||
|
id: true, user: {
|
||||||
|
select: {
|
||||||
|
first_name: true, last_name: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!existing_profile) return { success: false, error: 'EMPLOYEE_NOT_FOUND' };
|
||||||
|
|
||||||
return this.prisma.$transaction(async (transaction) => {
|
let company_name = 'Solucom';
|
||||||
const user: Users = await transaction.users.create({
|
if (existing_profile.company_code === 271583) {
|
||||||
data: {
|
company_name = 'Targo';
|
||||||
first_name,
|
}
|
||||||
last_name,
|
|
||||||
email,
|
return {
|
||||||
phone_number,
|
success: true, data: {
|
||||||
residence,
|
first_name: existing_profile.user.first_name,
|
||||||
},
|
last_name: existing_profile.user.last_name,
|
||||||
});
|
email: existing_profile.user.email,
|
||||||
return transaction.employees.create({
|
supervisor_full_name: `${existing_profile.supervisor?.user.first_name} ${existing_profile.supervisor?.user.last_name}`,
|
||||||
data: {
|
company_name: company_name,
|
||||||
user_id: user.id,
|
job_title: existing_profile.job_title ?? '',
|
||||||
external_payroll_id,
|
external_payroll_id: existing_profile.external_payroll_id,
|
||||||
company_code,
|
}
|
||||||
job_title,
|
}
|
||||||
first_work_day,
|
}
|
||||||
last_work_day,
|
|
||||||
is_supervisor,
|
async findOneDetailedProfile(email: string): Promise<Result<EmployeeDetailedDto, string>> {
|
||||||
},
|
const user_id = await this.emailResolver.resolveUserIdWithEmail(email);
|
||||||
});
|
if (!user_id.success) return { success: false, error: 'INVALID_USER' };
|
||||||
});
|
|
||||||
}
|
const employee = await this.prisma.employees.findUnique({
|
||||||
|
where: { user_id: user_id.data },
|
||||||
|
select: {
|
||||||
|
user: {
|
||||||
|
select: {
|
||||||
|
first_name: true,
|
||||||
|
last_name: true,
|
||||||
|
email: true,
|
||||||
|
phone_number: true,
|
||||||
|
residence: true,
|
||||||
|
user_module_access: {
|
||||||
|
select: {
|
||||||
|
dashboard: true,
|
||||||
|
employee_list: true,
|
||||||
|
employee_management: true,
|
||||||
|
personal_profile: true,
|
||||||
|
timesheets: true,
|
||||||
|
timesheets_approval: 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,
|
||||||
|
external_payroll_id: true,
|
||||||
|
is_supervisor: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!employee) return { success: false, error: `EMPLOYEE_NOT_FOUND` };
|
||||||
|
if (!employee.user) return { success: false, error: 'USER_NOT_FOUND' };
|
||||||
|
|
||||||
|
let company_name = 'Solucom';
|
||||||
|
if (employee.company_code === 271583) {
|
||||||
|
company_name = 'Targo';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
first_name: employee.user.first_name,
|
||||||
|
last_name: employee.user.last_name,
|
||||||
|
email: employee.user.email,
|
||||||
|
residence: employee.user.residence ?? '',
|
||||||
|
phone_number: employee.user.phone_number,
|
||||||
|
company_name: company_name,
|
||||||
|
is_supervisor: employee.is_supervisor ?? false,
|
||||||
|
job_title: employee.job_title ?? '',
|
||||||
|
external_payroll_id: employee.external_payroll_id,
|
||||||
|
employee_full_name: `${employee.user.first_name} ${employee.user.last_name}`,
|
||||||
|
first_work_day: employee.first_work_day.toISOString().slice(0, 10),
|
||||||
|
last_work_day: employee.last_work_day ? employee.last_work_day.toISOString().slice(0, 10) : undefined,
|
||||||
|
supervisor_full_name: `${employee.supervisor?.user.first_name}, ${employee.supervisor?.user.last_name}`,
|
||||||
|
module_access: {
|
||||||
|
dashboard: employee.user.user_module_access?.dashboard ?? false,
|
||||||
|
employee_list: employee.user.user_module_access?.employee_list ?? false,
|
||||||
|
employee_management: employee.user.user_module_access?.employee_management ?? false,
|
||||||
|
personal_profile: employee.user.user_module_access?.personal_profile ?? false,
|
||||||
|
timesheets: employee.user.user_module_access?.timesheets ?? false,
|
||||||
|
timesheets_approval: employee.user.user_module_access?.timesheets_approval ?? false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async createEmployee(dto: EmployeeDetailedDto): Promise<Result<boolean, string>> {
|
||||||
|
let company_code = 271585;
|
||||||
|
if (dto.company_name === 'Targo') {
|
||||||
|
company_code = 271583;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.prisma.$transaction(async (tx) => {
|
||||||
|
const user: Users = await tx.users.create({
|
||||||
|
data: {
|
||||||
|
first_name: dto.first_name,
|
||||||
|
last_name: dto.last_name,
|
||||||
|
email: dto.email,
|
||||||
|
phone_number: dto.phone_number,
|
||||||
|
residence: dto.residence,
|
||||||
|
user_module_access: {
|
||||||
|
create: {
|
||||||
|
dashboard: dto.module_access.dashboard,
|
||||||
|
employee_list: dto.module_access.employee_list,
|
||||||
|
employee_management: dto.module_access.employee_management,
|
||||||
|
personal_profile: dto.module_access.personal_profile,
|
||||||
|
timesheets: dto.module_access.timesheets,
|
||||||
|
timesheets_approval: dto.module_access.timesheets_approval,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return tx.employees.create({
|
||||||
|
data: {
|
||||||
|
user_id: user.id,
|
||||||
|
company_code: company_code,
|
||||||
|
job_title: dto.job_title,
|
||||||
|
first_work_day: dto.first_work_day,
|
||||||
|
last_work_day: dto.last_work_day,
|
||||||
|
is_supervisor: dto.is_supervisor,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return { success: true, data: true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ import { Module } from "@nestjs/common";
|
||||||
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||||
import { EmployeesController } from "src/identity-and-account/employees/controllers/employees.controller";
|
import { EmployeesController } from "src/identity-and-account/employees/controllers/employees.controller";
|
||||||
import { EmployeesModule } from "src/identity-and-account/employees/employees.module";
|
import { EmployeesModule } from "src/identity-and-account/employees/employees.module";
|
||||||
import { EmployeesArchivalService } from "src/identity-and-account/employees/services/employees-archival.service";
|
|
||||||
import { EmployeesService } from "src/identity-and-account/employees/services/employees.service";
|
import { EmployeesService } from "src/identity-and-account/employees/services/employees.service";
|
||||||
import { PreferencesController } from "src/identity-and-account/preferences/controllers/preferences.controller";
|
import { PreferencesController } from "src/identity-and-account/preferences/controllers/preferences.controller";
|
||||||
import { PreferencesModule } from "src/identity-and-account/preferences/preferences.module";
|
import { PreferencesModule } from "src/identity-and-account/preferences/preferences.module";
|
||||||
|
|
@ -27,7 +26,6 @@ import { UsersModule } from "src/identity-and-account/users-management/users.mod
|
||||||
ModuleAccessController,
|
ModuleAccessController,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
EmployeesArchivalService,
|
|
||||||
EmployeesService,
|
EmployeesService,
|
||||||
PreferencesService,
|
PreferencesService,
|
||||||
UsersService,
|
UsersService,
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,20 @@ import { Body, Controller, Get, Patch, Query, Req } from "@nestjs/common";
|
||||||
import { PreferencesService } from "../services/preferences.service";
|
import { PreferencesService } from "../services/preferences.service";
|
||||||
import { PreferencesDto } from "../dtos/preferences.dto";
|
import { PreferencesDto } from "../dtos/preferences.dto";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
import { Access } from "src/common/decorators/module-access.decorators";
|
||||||
|
|
||||||
@Controller('preferences')
|
@Controller('preferences')
|
||||||
export class PreferencesController {
|
export class PreferencesController {
|
||||||
constructor(private readonly service: PreferencesService){}
|
constructor(private readonly service: PreferencesService) { }
|
||||||
|
|
||||||
@Patch('update')
|
@Patch('update')
|
||||||
async updatePreferences(
|
async updatePreferences(@Access('email') email: string, @Body() payload: PreferencesDto
|
||||||
@Req()req,
|
|
||||||
@Body() payload: PreferencesDto
|
|
||||||
): Promise<Result<PreferencesDto, string>> {
|
): Promise<Result<PreferencesDto, string>> {
|
||||||
const email = req.user?.email;
|
|
||||||
return this.service.updatePreferences(email, payload);
|
return this.service.updatePreferences(email, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async findPreferences(@Req() req, @Query() employee_email?:string) {
|
async findPreferences(@Access('email') email: string, @Query() employee_email?: string) {
|
||||||
const email = req.user?.email;
|
|
||||||
return this.service.findPreferences(email, employee_email);
|
return this.service.findPreferences(email, employee_email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { Body, Controller, Get, Patch, Query, Req } from "@nestjs/common";
|
import { Body, Controller, Get, Patch, Query, Req } from "@nestjs/common";
|
||||||
|
import { Access } from "src/common/decorators/module-access.decorators";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { ModuleAccess } from "src/identity-and-account/user-module-access/dtos/module-acces.dto";
|
import { ModuleAccess } from "src/identity-and-account/user-module-access/dtos/module-acces.dto";
|
||||||
import { AccessGetService } from "src/identity-and-account/user-module-access/services/module-access-get.service";
|
import { AccessGetService } from "src/identity-and-account/user-module-access/services/module-access-get.service";
|
||||||
|
|
@ -12,67 +13,25 @@ export class ModuleAccessController {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async findAccess(
|
async findAccess(@Access('email') email: string, @Query('employee_email') employee_email?: string
|
||||||
@Req() req,
|
|
||||||
@Query('employee_email') employee_email?: string
|
|
||||||
): Promise<Result<boolean, string>> {
|
): Promise<Result<boolean, string>> {
|
||||||
try {
|
const granted_access = await this.getService.findModuleAccess(email);
|
||||||
const email: string = req.user?.email;
|
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
||||||
|
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
||||||
|
|
||||||
//fetch the current user granted access
|
await this.getService.findModuleAccess(email, employee_email);
|
||||||
const granted_access = await this.getService.findModuleAccess(email);
|
return { success: true, data: true };
|
||||||
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
|
||||||
//check if credentials are enough to use this resource
|
|
||||||
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
|
||||||
|
|
||||||
await this.getService.findModuleAccess(email, employee_email);
|
|
||||||
return { success: true, data: true };
|
|
||||||
} catch (error) {
|
|
||||||
return { success: false, error: 'UNAUTORIZED_USER' };
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@Patch('update')
|
@Patch('update')
|
||||||
async updateAccess(
|
async updateAccess(@Access('email') email: string, @Body() dto: ModuleAccess, @Query('employee_email') employee_email?: string
|
||||||
@Req() req,
|
|
||||||
@Body() dto: ModuleAccess,
|
|
||||||
@Query('employee_email') employee_email?: string
|
|
||||||
): Promise<Result<boolean, string>> {
|
): Promise<Result<boolean, string>> {
|
||||||
try {
|
const granted_access = await this.getService.findModuleAccess(email);
|
||||||
const email: string = req.user?.email;
|
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
||||||
|
//check if credentials are enough to use this resource
|
||||||
|
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
||||||
|
|
||||||
//fetch the current user granted access
|
await this.updateService.updateModuleAccess(email, dto, employee_email);
|
||||||
const granted_access = await this.getService.findModuleAccess(email);
|
return { success: true, data: true };
|
||||||
if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
|
||||||
//check if credentials are enough to use this resource
|
|
||||||
if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
|
||||||
|
|
||||||
await this.updateService.updateModuleAccess(email, dto, employee_email);
|
|
||||||
return { success: true, data: true };
|
|
||||||
} catch (error) {
|
|
||||||
return { success: false, error: 'UNAUTORIZED_USER' };
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// @Patch('revoke')
|
|
||||||
// async revokeModuleAccess(
|
|
||||||
// @Req() req,
|
|
||||||
// @Query('employee_email') employee_email?: string
|
|
||||||
// ) {
|
|
||||||
// try {
|
|
||||||
// const email: string = req.user?.email;
|
|
||||||
|
|
||||||
// //fetch the current user granted access
|
|
||||||
// const granted_access = await this.getService.findModuleAccess(email);
|
|
||||||
// if (!granted_access.success) return { success: false, error: 'INVALID_USER' };
|
|
||||||
|
|
||||||
// //check if credentials are enough to use this resource
|
|
||||||
// if (!granted_access.data.employee_management) return { success: false, error: 'UNAUTHORIZED_ACCESS' };
|
|
||||||
|
|
||||||
// await this.updateService.revokeModuleAccess(email, employee_email);
|
|
||||||
// return { success: true, data: true };
|
|
||||||
// } catch (error) {
|
|
||||||
// return { success: false, error: 'UNAUTORIZED_USER' };
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { Roles } from '@prisma/client';
|
|
||||||
|
|
||||||
export class UserDto {
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'd67f05be-6dd1-464f-b5f7-31b325e21b4a',
|
|
||||||
description: 'User`s unique UUID (primary key)',
|
|
||||||
})
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'Aragorn',
|
|
||||||
description: 'user`s first name',
|
|
||||||
})
|
|
||||||
first_name: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'Elessar',
|
|
||||||
description: 'user`s last name',
|
|
||||||
})
|
|
||||||
last_name: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'king@arnor-gondor.gov',
|
|
||||||
description: 'Unique email address',
|
|
||||||
})
|
|
||||||
email: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 5141234567,
|
|
||||||
description: 'Unique phone number',
|
|
||||||
})
|
|
||||||
phone_number: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'Minas Tirith, Gondor',
|
|
||||||
description: 'residence address (optional)',
|
|
||||||
required: false,
|
|
||||||
})
|
|
||||||
residence?: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 'EMPLOYEE',
|
|
||||||
enum: Roles,
|
|
||||||
description: 'User`s given role',
|
|
||||||
})
|
|
||||||
role: Roles;
|
|
||||||
}
|
|
||||||
|
|
@ -6,18 +6,6 @@ import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
export abstract class AbstractUserService {
|
export abstract class AbstractUserService {
|
||||||
constructor(protected readonly prisma: PrismaService) { }
|
constructor(protected readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
// findAll(): Promise<Users[]> {
|
|
||||||
// return this.prisma.users.findMany();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async findOne(id: string): Promise<Users> {
|
|
||||||
// const user = await this.prisma.users.findUnique({ where: { id } });
|
|
||||||
// if (!user) {
|
|
||||||
// throw new NotFoundException(`User #${id} not found`);
|
|
||||||
// }
|
|
||||||
// return user;
|
|
||||||
// }
|
|
||||||
|
|
||||||
async findOneByEmail(email: string): Promise<Partial<Users>> {
|
async findOneByEmail(email: string): Promise<Partial<Users>> {
|
||||||
const user = await this.prisma.users.findUnique({
|
const user = await this.prisma.users.findUnique({
|
||||||
where: { email },
|
where: { email },
|
||||||
|
|
@ -58,9 +46,4 @@ export abstract class AbstractUserService {
|
||||||
|
|
||||||
return clean_user;
|
return clean_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
// async remove(id: string): Promise<Users> {
|
|
||||||
// await this.findOne(id);
|
|
||||||
// return this.prisma.users.delete({ where: { id } });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user