clean(): file cleaning
This commit is contained in:
parent
7968359bfe
commit
1589df979f
|
|
@ -637,25 +637,16 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/preferences": {
|
"/preferences/update_preferences": {
|
||||||
"patch": {
|
"patch": {
|
||||||
"operationId": "PreferencesController_updatePreferences",
|
"operationId": "PreferencesController_updatePreferences",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "PreferencesDto",
|
|
||||||
"required": true,
|
|
||||||
"in": "body",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/PreferencesDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"required": true,
|
"required": true,
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "number"
|
"$ref": "#/components/schemas/PreferencesDto"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Controller, Get, Patch, Param, Body, NotFoundException, Req, Post } from "@nestjs/common";
|
import { Controller, Get, Patch, Param, Body, NotFoundException, Req, Post } from "@nestjs/common";
|
||||||
import { Employees } from "@prisma/client";
|
import { Employees } from "@prisma/client";
|
||||||
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 { GLOBAL_CONTROLLER_ROLES, MANAGER_ROLES } from "src/common/shared/role-groupes";
|
import { GLOBAL_CONTROLLER_ROLES, MANAGER_ROLES } from "src/common/shared/role-groupes";
|
||||||
import { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
import { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
||||||
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
||||||
|
|
@ -18,14 +19,14 @@ export class EmployeesController {
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Get('profile')
|
@Get('profile')
|
||||||
findOneProfile(@Req() req): Promise<EmployeeProfileItemDto> {
|
findOneProfile(@Req() req): Promise<Result<EmployeeProfileItemDto,string>> {
|
||||||
const email = req.user?.email;
|
const email = req.user?.email;
|
||||||
return this.employeesService.findOneProfile(email);
|
return this.employeesService.findOneProfile(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('employee-list')
|
@Get('employee-list')
|
||||||
@RolesAllowed(...MANAGER_ROLES)
|
@RolesAllowed(...MANAGER_ROLES)
|
||||||
findListEmployees(): Promise<EmployeeListItemDto[]> {
|
findListEmployees(): Promise<Result<EmployeeListItemDto[], string>> {
|
||||||
return this.employeesService.findListEmployees();
|
return this.employeesService.findListEmployees();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Injectable, NotFoundException } from "@nestjs/common";
|
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||||
import { Employees, Users } from "@prisma/client";
|
import { Employees, Users } from "@prisma/client";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
import { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
||||||
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
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 { EmployeeProfileItemDto } from "src/identity-and-account/employees/dtos/profil-employee.dto";
|
||||||
|
|
@ -9,8 +10,8 @@ import { PrismaService } from "src/prisma/prisma.service";
|
||||||
export class EmployeesService {
|
export class EmployeesService {
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
constructor(private readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
findListEmployees(): Promise<EmployeeListItemDto[]> {
|
async findListEmployees(): Promise<Result<EmployeeListItemDto[], string>> {
|
||||||
return this.prisma.employees.findMany({
|
return {success: true, data:await this.prisma.employees.findMany({
|
||||||
select: {
|
select: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
|
|
@ -41,11 +42,11 @@ export class EmployeesService {
|
||||||
employee_full_name: `${r.user.first_name} ${r.user.last_name}`,
|
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,
|
supervisor_full_name: r.supervisor ? `${r.supervisor.user.first_name} ${r.supervisor.user.last_name}` : null,
|
||||||
})),
|
})),
|
||||||
);
|
)}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneProfile(email: string): Promise<EmployeeProfileItemDto> {
|
async findOneProfile(email: string): Promise<Result<EmployeeProfileItemDto, string>> {
|
||||||
const emp = await this.prisma.employees.findFirst({
|
const employee = await this.prisma.employees.findFirst({
|
||||||
where: { user: { email } },
|
where: { user: { email } },
|
||||||
select: {
|
select: {
|
||||||
user: {
|
user: {
|
||||||
|
|
@ -73,20 +74,23 @@ export class EmployeesService {
|
||||||
last_work_day: true,
|
last_work_day: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!emp) throw new NotFoundException(`Employee with email ${email} not found`);
|
if (!employee)return {success: false, error: `Employee with email ${email} not found`};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
first_name: emp.user.first_name,
|
success: true,
|
||||||
last_name: emp.user.last_name,
|
data: {
|
||||||
email: emp.user.email,
|
first_name: employee.user.first_name,
|
||||||
residence: emp.user.residence,
|
last_name: employee.user.last_name,
|
||||||
phone_number: emp.user.phone_number,
|
email: employee.user.email,
|
||||||
company_name: emp.company_code,
|
residence: employee.user.residence,
|
||||||
job_title: emp.job_title,
|
phone_number: employee.user.phone_number,
|
||||||
employee_full_name: `${emp.user.first_name} ${emp.user.last_name}`,
|
company_name: employee.company_code,
|
||||||
first_work_day: emp.first_work_day.toISOString().slice(0, 10),
|
job_title: employee.job_title,
|
||||||
last_work_day: emp.last_work_day ? emp.last_work_day.toISOString().slice(0, 10) : null,
|
employee_full_name: `${employee.user.first_name} ${employee.user.last_name}`,
|
||||||
supervisor_full_name: emp.supervisor ? `${emp.supervisor.user.first_name}, ${emp.supervisor.user.last_name}` : null,
|
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,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,107 +132,4 @@ export class EmployeesService {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//_____________________________________________________________________________________________
|
|
||||||
// Deprecated or unused methods
|
|
||||||
//_____________________________________________________________________________________________
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// findAll(): Promise<Employees[]> {
|
|
||||||
// return this.prisma.employees.findMany({
|
|
||||||
// include: { user: true },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async findOne(email: string): Promise<Employees> {
|
|
||||||
// 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;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async update(
|
|
||||||
// email: string,
|
|
||||||
// dto: UpdateEmployeeDto,
|
|
||||||
// ): Promise<Employees> {
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// async remove(email: string): Promise<Employees> {
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
import { Body, Controller, Patch } from "@nestjs/common";
|
import { Body, Controller, Patch, 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";
|
||||||
|
|
||||||
@Controller('preferences')
|
@Controller('preferences')
|
||||||
export class PreferencesController {
|
export class PreferencesController {
|
||||||
constructor(private readonly service: PreferencesService){}
|
constructor(private readonly service: PreferencesService){}
|
||||||
|
|
||||||
@Patch()
|
@Patch('update_preferences')
|
||||||
async updatePreferences(
|
async updatePreferences(
|
||||||
@Body() user_id: number,
|
@Req()req,
|
||||||
@Body() payload: PreferencesDto
|
@Body() payload: PreferencesDto
|
||||||
) {
|
): Promise<Result<PreferencesDto, string>> {
|
||||||
return this.service.updatePreferences(user_id, payload);
|
const email = req.user?.email;
|
||||||
|
return this.service.updatePreferences(email, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,25 +1,11 @@
|
||||||
import { IsInt } from "class-validator";
|
import { IsInt } from "class-validator";
|
||||||
|
|
||||||
export class PreferencesDto {
|
export class PreferencesDto {
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
notifications: number;
|
notifications: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
dark_mode: number;
|
dark_mode: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
lang_switch: number;
|
lang_switch: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
lefty_mode: number;
|
lefty_mode: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
employee_list_display: number;
|
employee_list_display: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
validation_display: number;
|
validation_display: number;
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
timesheet_display: number;
|
timesheet_display: number;
|
||||||
}
|
}
|
||||||
|
|
@ -2,14 +2,24 @@ import { PreferencesDto } from "../dtos/preferences.dto";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
import { Preferences } from "@prisma/client";
|
import { Preferences } from "@prisma/client";
|
||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PreferencesService {
|
export class PreferencesService {
|
||||||
constructor( private readonly prisma: PrismaService ){}
|
constructor(
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
|
|
||||||
async updatePreferences(user_id: number, dto: PreferencesDto ): Promise<Preferences> {
|
) { }
|
||||||
return this.prisma.preferences.update({
|
|
||||||
where: { id: user_id },
|
async updatePreferences(email: string, dto: PreferencesDto): Promise<Result<Preferences, string>> {
|
||||||
|
const user_id = await this.emailResolver.resolveUserIdWithEmail(email);
|
||||||
|
if (!user_id.success) return { success: false, error: user_id.error }
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: await this.prisma.preferences.update({
|
||||||
|
where: { user_id: user_id.data },
|
||||||
data: {
|
data: {
|
||||||
notifications: dto.notifications,
|
notifications: dto.notifications,
|
||||||
dark_mode: dto.dark_mode,
|
dark_mode: dto.dark_mode,
|
||||||
|
|
@ -20,6 +30,7 @@ export class PreferencesService {
|
||||||
timesheet_display: dto.timesheet_display,
|
timesheet_display: dto.timesheet_display,
|
||||||
},
|
},
|
||||||
include: { user: true },
|
include: { user: true },
|
||||||
});
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,35 +1,25 @@
|
||||||
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MileageService {
|
export class MileageService {
|
||||||
private readonly logger = new Logger(MileageService.name);
|
|
||||||
|
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
constructor(private readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
public async calculateReimbursement(amount: number, bank_code_id: number): Promise<number> {
|
public async calculateReimbursement(amount: number, bank_code_id: number): Promise<Result<number, string>> {
|
||||||
if(amount < 0) {
|
if (amount < 0) return { success: false, error: 'The amount must be higher than 0' };
|
||||||
throw new BadRequestException(`The amount most be higher than 0`);
|
|
||||||
}
|
|
||||||
|
|
||||||
//fetch modifier
|
//fetch modifier
|
||||||
const bank_code = await this.prisma.bankCodes.findUnique({
|
const bank_code = await this.prisma.bankCodes.findUnique({
|
||||||
where: { id: bank_code_id },
|
where: { id: bank_code_id },
|
||||||
select: { modifier: true, type: true },
|
select: { modifier: true, type: true },
|
||||||
});
|
});
|
||||||
|
if (!bank_code) return { success: false, error: `bank_code ${bank_code_id} not found` }
|
||||||
if(!bank_code) {
|
|
||||||
throw new BadRequestException(`bank_code ${bank_code_id} not found`);
|
|
||||||
}
|
|
||||||
if(bank_code.type !== 'mileage') {
|
|
||||||
this.logger.warn(`bank_code ${bank_code_id} of type ${bank_code.type} is used for mileage`)
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate total amount to reimburs
|
//calculate total amount to reimburs
|
||||||
const reimboursement = amount * bank_code.modifier;
|
const reimboursement = amount * bank_code.modifier;
|
||||||
const result = parseFloat(reimboursement.toFixed(2));
|
const result = parseFloat(reimboursement.toFixed(2));
|
||||||
this.logger.debug(`calculateReimbursement -> amount= ${amount}, modifier= ${bank_code.modifier}, total= ${result}`);
|
return { success: true, data: result };
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ import { Prisma, PrismaClient } from '@prisma/client';
|
||||||
import { getWeekStart, getWeekEnd, computeHours } from 'src/common/utils/date-utils';
|
import { getWeekStart, getWeekEnd, computeHours } from 'src/common/utils/date-utils';
|
||||||
import { PrismaService } from 'src/prisma/prisma.service';
|
import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
import { DAILY_LIMIT_HOURS, WEEKLY_LIMIT_HOURS } from 'src/common/utils/constants.utils';
|
import { DAILY_LIMIT_HOURS, WEEKLY_LIMIT_HOURS } from 'src/common/utils/constants.utils';
|
||||||
|
import { Result } from 'src/common/errors/result-error.factory';
|
||||||
|
|
||||||
|
|
||||||
type Tx = Prisma.TransactionClient | PrismaClient;
|
type Tx = Prisma.TransactionClient | PrismaClient;
|
||||||
|
|
@ -26,13 +27,11 @@ type WeekOvertimeSummary = {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OvertimeService {
|
export class OvertimeService {
|
||||||
|
|
||||||
private logger = new Logger(OvertimeService.name);
|
|
||||||
|
|
||||||
private INCLUDED_TYPES = ['EMERGENCY', 'EVENING', 'OVERTIME', 'REGULAR'] as const; // included types for weekly overtime calculation
|
private INCLUDED_TYPES = ['EMERGENCY', 'EVENING', 'OVERTIME', 'REGULAR'] as const; // included types for weekly overtime calculation
|
||||||
|
|
||||||
constructor(private prisma: PrismaService) { }
|
constructor(private prisma: PrismaService) { }
|
||||||
|
|
||||||
async getWeekOvertimeSummary( timesheet_id: number, date: Date, tx?: Tx ): Promise<WeekOvertimeSummary>{
|
async getWeekOvertimeSummary(timesheet_id: number, date: Date, tx?: Tx): Promise<Result<WeekOvertimeSummary, string>> {
|
||||||
const db = tx ?? this.prisma;
|
const db = tx ?? this.prisma;
|
||||||
|
|
||||||
const week_start = getWeekStart(date);
|
const week_start = getWeekStart(date);
|
||||||
|
|
@ -88,14 +87,9 @@ export class OvertimeService {
|
||||||
}
|
}
|
||||||
const total_overtime = weekly_overtime + daily_kept_sum;
|
const total_overtime = weekly_overtime + daily_kept_sum;
|
||||||
|
|
||||||
this.logger.debug(
|
|
||||||
`[OVERTIME][SUMMARY][ts=${timesheet_id}] week=${week_start.toISOString().slice(0,10)}..${week_end
|
|
||||||
.toISOString()
|
|
||||||
.slice(0,10)} week_total=${week_total_hours.toFixed(2)}h weekly=${weekly_overtime.toFixed(
|
|
||||||
2,
|
|
||||||
)}h daily_kept=${daily_kept_sum.toFixed(2)}h total=${total_overtime.toFixed(2)}h`,
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
week_start: week_start.toISOString().slice(0, 10),
|
week_start: week_start.toISOString().slice(0, 10),
|
||||||
week_end: week_end.toISOString().slice(0, 10),
|
week_end: week_end.toISOString().slice(0, 10),
|
||||||
week_total_hours,
|
week_total_hours,
|
||||||
|
|
@ -103,6 +97,7 @@ export class OvertimeService {
|
||||||
daily_overtime_kept: daily_kept_sum,
|
daily_overtime_kept: daily_kept_sum,
|
||||||
total_overtime,
|
total_overtime,
|
||||||
breakdown,
|
breakdown,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import { getYearStart, roundToQuarterHour } from "src/common/utils/date-utils";
|
import { getYearStart, roundToQuarterHour } from "src/common/utils/date-utils";
|
||||||
import { Injectable, Logger } from "@nestjs/common";
|
import { Injectable, Logger } from "@nestjs/common";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SickLeaveService {
|
export class SickLeaveService {
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
constructor(private readonly prisma: PrismaService) { }
|
||||||
|
|
||||||
private readonly logger = new Logger(SickLeaveService.name);
|
|
||||||
|
|
||||||
//switch employeeId for email
|
//switch employeeId for email
|
||||||
async calculateSickLeavePay(
|
async calculateSickLeavePay(
|
||||||
employee_id: number,
|
employee_id: number,
|
||||||
|
|
@ -15,9 +14,9 @@ export class SickLeaveService {
|
||||||
days_requested: number,
|
days_requested: number,
|
||||||
hours_per_day: number,
|
hours_per_day: number,
|
||||||
modifier: number,
|
modifier: number,
|
||||||
): Promise<number> {
|
): Promise<Result<number, string>> {
|
||||||
if (days_requested <= 0 || hours_per_day <= 0 || modifier <= 0) {
|
if (days_requested <= 0 || hours_per_day <= 0 || modifier <= 0) {
|
||||||
return 0;
|
return { success: true, data: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
//sets the year to jan 1st to dec 31st
|
//sets the year to jan 1st to dec 31st
|
||||||
|
|
@ -38,13 +37,10 @@ export class SickLeaveService {
|
||||||
shifts.map((shift) => shift.date.toISOString().slice(0, 10)),
|
shifts.map((shift) => shift.date.toISOString().slice(0, 10)),
|
||||||
);
|
);
|
||||||
const days_worked = worked_dates.size;
|
const days_worked = worked_dates.size;
|
||||||
this.logger.debug(
|
|
||||||
`Sick leave: days worked= ${days_worked} in ${period_start.toDateString()} -> ${period_end.toDateString()}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
//less than 30 worked days returns 0
|
//less than 30 worked days returns 0
|
||||||
if (days_worked < 30) {
|
if (days_worked < 30) {
|
||||||
return 0;
|
return { success: true, data: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
//default 3 days allowed after 30 worked days
|
//default 3 days allowed after 30 worked days
|
||||||
|
|
@ -70,16 +66,9 @@ export class SickLeaveService {
|
||||||
//cap of 10 days
|
//cap of 10 days
|
||||||
if (acquired_days > 10) acquired_days = 10;
|
if (acquired_days > 10) acquired_days = 10;
|
||||||
|
|
||||||
this.logger.debug(
|
|
||||||
`Sick leave: threshold Date = ${threshold_date.toDateString()}, bonusMonths = ${months}, acquired Days = ${acquired_days}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const payable_days = Math.min(acquired_days, days_requested);
|
const payable_days = Math.min(acquired_days, days_requested);
|
||||||
const raw_hours = payable_days * hours_per_day * modifier;
|
const raw_hours = payable_days * hours_per_day * modifier;
|
||||||
const rounded = roundToQuarterHour(raw_hours);
|
const rounded = roundToQuarterHour(raw_hours);
|
||||||
this.logger.debug(
|
return {success:true, data: rounded};
|
||||||
`Sick leave pay: days= ${payable_days}, hoursPerDay= ${hours_per_day}, modifier= ${modifier}, hours= ${rounded}`,
|
|
||||||
);
|
|
||||||
return rounded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,27 @@
|
||||||
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VacationService {
|
export class VacationService {
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(
|
||||||
private readonly logger = new Logger(VacationService.name);
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
|
) {}
|
||||||
|
|
||||||
//switch employeeId for email
|
//switch employeeId for email
|
||||||
async calculateVacationPay(employee_id: number, start_date: Date, days_requested: number, modifier: number): Promise<number> {
|
async calculateVacationPay(email: string, start_date: Date, days_requested: number, modifier: number): Promise<Result<number, string>> {
|
||||||
|
const employee_id = await this.emailResolver.findIdByEmail(email);
|
||||||
|
if(!employee_id.success) return { success: false, error: employee_id.error}
|
||||||
|
|
||||||
//fetch hiring date
|
//fetch hiring date
|
||||||
const employee = await this.prisma.employees.findUnique({
|
const employee = await this.prisma.employees.findUnique({
|
||||||
where: { id: employee_id },
|
where: { id: employee_id.data },
|
||||||
select: { first_work_day: true },
|
select: { first_work_day: true },
|
||||||
});
|
});
|
||||||
if(!employee) {
|
if(!employee) return { success:false, error:`Employee #${employee_id} not found`}
|
||||||
throw new NotFoundException(`Employee #${employee_id} not found`);
|
|
||||||
}
|
|
||||||
const hire_date = employee.first_work_day;
|
const hire_date = employee.first_work_day;
|
||||||
|
|
||||||
//sets "year" to may 1st to april 30th
|
//sets "year" to may 1st to april 30th
|
||||||
|
|
@ -26,8 +31,6 @@ export class VacationService {
|
||||||
const period_start = new Date(year_of_request, 4, 1); //may = 4
|
const period_start = new Date(year_of_request, 4, 1); //may = 4
|
||||||
const period_end = new Date(year_of_request + 1, 4, 0); //day 0 of may == april 30th
|
const period_end = new Date(year_of_request + 1, 4, 0); //day 0 of may == april 30th
|
||||||
|
|
||||||
this.logger.debug(`Vacation period for request: ${period_start.toDateString()} -> ${period_end.toDateString()}`);
|
|
||||||
|
|
||||||
//steps to reach to get more vacation weeks in years
|
//steps to reach to get more vacation weeks in years
|
||||||
const checkpoint = [5, 10, 15];
|
const checkpoint = [5, 10, 15];
|
||||||
const anniversaries = checkpoint.map(years => {
|
const anniversaries = checkpoint.map(years => {
|
||||||
|
|
@ -36,8 +39,6 @@ export class VacationService {
|
||||||
return anniversary_date;
|
return anniversary_date;
|
||||||
}).filter(d => d>= period_start && d <= period_end).sort((a,b) => a.getTime() - b.getTime());
|
}).filter(d => d>= period_start && d <= period_end).sort((a,b) => a.getTime() - b.getTime());
|
||||||
|
|
||||||
this.logger.debug(`anniversatries steps during the period: ${anniversaries.map(date => date.toDateString()).join(',') || 'aucun'}`);
|
|
||||||
|
|
||||||
const boundaries = [period_start, ...anniversaries,period_end];
|
const boundaries = [period_start, ...anniversaries,period_end];
|
||||||
//calculate prorata per segment
|
//calculate prorata per segment
|
||||||
let total_vacation_days = 0;
|
let total_vacation_days = 0;
|
||||||
|
|
@ -67,10 +68,8 @@ export class VacationService {
|
||||||
|
|
||||||
const raw_hours = payable_days * 8 * modifier;
|
const raw_hours = payable_days * 8 * modifier;
|
||||||
const rounded_hours = Math.round(raw_hours * 4) / 4;
|
const rounded_hours = Math.round(raw_hours * 4) / 4;
|
||||||
this.logger.debug(`Vacation pay: entitledDays=${total_vacation_days.toFixed(2)}, requestedDays=${days_requested},
|
|
||||||
payableDays=${payable_days.toFixed(2)}, hours=${rounded_hours}`);
|
|
||||||
|
|
||||||
return rounded_hours;
|
return {success:true, data:rounded_hours};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user