clean(): file cleaning
This commit is contained in:
parent
7968359bfe
commit
1589df979f
|
|
@ -637,25 +637,16 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/preferences": {
|
||||
"/preferences/update_preferences": {
|
||||
"patch": {
|
||||
"operationId": "PreferencesController_updatePreferences",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "PreferencesDto",
|
||||
"required": true,
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PreferencesDto"
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "number"
|
||||
"$ref": "#/components/schemas/PreferencesDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Controller, Get, Patch, Param, Body, NotFoundException, Req, Post } from "@nestjs/common";
|
||||
import { Employees } from "@prisma/client";
|
||||
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 { CreateEmployeeDto } from "src/identity-and-account/employees/dtos/create-employee.dto";
|
||||
import { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-employee.dto";
|
||||
|
|
@ -18,14 +19,14 @@ export class EmployeesController {
|
|||
) { }
|
||||
|
||||
@Get('profile')
|
||||
findOneProfile(@Req() req): Promise<EmployeeProfileItemDto> {
|
||||
findOneProfile(@Req() req): Promise<Result<EmployeeProfileItemDto,string>> {
|
||||
const email = req.user?.email;
|
||||
return this.employeesService.findOneProfile(email);
|
||||
}
|
||||
|
||||
@Get('employee-list')
|
||||
@RolesAllowed(...MANAGER_ROLES)
|
||||
findListEmployees(): Promise<EmployeeListItemDto[]> {
|
||||
findListEmployees(): Promise<Result<EmployeeListItemDto[], string>> {
|
||||
return this.employeesService.findListEmployees();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||
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 { EmployeeListItemDto } from "src/identity-and-account/employees/dtos/list-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 {
|
||||
constructor(private readonly prisma: PrismaService) { }
|
||||
|
||||
findListEmployees(): Promise<EmployeeListItemDto[]> {
|
||||
return this.prisma.employees.findMany({
|
||||
async findListEmployees(): Promise<Result<EmployeeListItemDto[], string>> {
|
||||
return {success: true, data:await this.prisma.employees.findMany({
|
||||
select: {
|
||||
user: {
|
||||
select: {
|
||||
|
|
@ -41,11 +42,11 @@ export class EmployeesService {
|
|||
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<EmployeeProfileItemDto> {
|
||||
const emp = await this.prisma.employees.findFirst({
|
||||
async findOneProfile(email: string): Promise<Result<EmployeeProfileItemDto, string>> {
|
||||
const employee = await this.prisma.employees.findFirst({
|
||||
where: { user: { email } },
|
||||
select: {
|
||||
user: {
|
||||
|
|
@ -73,20 +74,23 @@ export class EmployeesService {
|
|||
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 {
|
||||
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,
|
||||
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: employee.company_code,
|
||||
job_title: employee.job_title,
|
||||
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,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -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 { PreferencesDto } from "../dtos/preferences.dto";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
|
||||
@Controller('preferences')
|
||||
export class PreferencesController {
|
||||
constructor(private readonly service: PreferencesService){}
|
||||
|
||||
@Patch()
|
||||
@Patch('update_preferences')
|
||||
async updatePreferences(
|
||||
@Body() user_id: number,
|
||||
@Req()req,
|
||||
@Body() payload: PreferencesDto
|
||||
) {
|
||||
return this.service.updatePreferences(user_id, payload);
|
||||
): Promise<Result<PreferencesDto, string>> {
|
||||
const email = req.user?.email;
|
||||
return this.service.updatePreferences(email, payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,25 +1,11 @@
|
|||
import { IsInt } from "class-validator";
|
||||
|
||||
export class PreferencesDto {
|
||||
|
||||
@IsInt()
|
||||
notifications: number;
|
||||
|
||||
@IsInt()
|
||||
dark_mode: number;
|
||||
|
||||
@IsInt()
|
||||
lang_switch: number;
|
||||
|
||||
@IsInt()
|
||||
lefty_mode: number;
|
||||
|
||||
@IsInt()
|
||||
employee_list_display: number;
|
||||
|
||||
@IsInt()
|
||||
validation_display: number;
|
||||
|
||||
@IsInt()
|
||||
timesheet_display: number;
|
||||
}
|
||||
|
|
@ -2,14 +2,24 @@ import { PreferencesDto } from "../dtos/preferences.dto";
|
|||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { Preferences } from "@prisma/client";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||
|
||||
@Injectable()
|
||||
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: {
|
||||
notifications: dto.notifications,
|
||||
dark_mode: dto.dark_mode,
|
||||
|
|
@ -20,6 +30,7 @@ export class PreferencesService {
|
|||
timesheet_display: dto.timesheet_display,
|
||||
},
|
||||
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";
|
||||
|
||||
@Injectable()
|
||||
export class MileageService {
|
||||
private readonly logger = new Logger(MileageService.name);
|
||||
|
||||
constructor(private readonly prisma: PrismaService) { }
|
||||
|
||||
public async calculateReimbursement(amount: number, bank_code_id: number): Promise<number> {
|
||||
if(amount < 0) {
|
||||
throw new BadRequestException(`The amount most be higher than 0`);
|
||||
}
|
||||
public async calculateReimbursement(amount: number, bank_code_id: number): Promise<Result<number, string>> {
|
||||
if (amount < 0) return { success: false, error: 'The amount must be higher than 0' };
|
||||
|
||||
//fetch modifier
|
||||
const bank_code = await this.prisma.bankCodes.findUnique({
|
||||
where: { id: bank_code_id },
|
||||
select: { modifier: true, type: true },
|
||||
});
|
||||
|
||||
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`)
|
||||
}
|
||||
if (!bank_code) return { success: false, error: `bank_code ${bank_code_id} not found` }
|
||||
|
||||
//calculate total amount to reimburs
|
||||
const reimboursement = amount * bank_code.modifier;
|
||||
const result = parseFloat(reimboursement.toFixed(2));
|
||||
this.logger.debug(`calculateReimbursement -> amount= ${amount}, modifier= ${bank_code.modifier}, total= ${result}`);
|
||||
return result;
|
||||
return { success: true, data: result };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { Prisma, PrismaClient } from '@prisma/client';
|
|||
import { getWeekStart, getWeekEnd, computeHours } from 'src/common/utils/date-utils';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
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;
|
||||
|
|
@ -26,13 +27,11 @@ type WeekOvertimeSummary = {
|
|||
@Injectable()
|
||||
export class OvertimeService {
|
||||
|
||||
private logger = new Logger(OvertimeService.name);
|
||||
|
||||
private INCLUDED_TYPES = ['EMERGENCY', 'EVENING', 'OVERTIME', 'REGULAR'] as const; // included types for weekly overtime calculation
|
||||
|
||||
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 week_start = getWeekStart(date);
|
||||
|
|
@ -88,14 +87,9 @@ export class OvertimeService {
|
|||
}
|
||||
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 {
|
||||
success: true,
|
||||
data: {
|
||||
week_start: week_start.toISOString().slice(0, 10),
|
||||
week_end: week_end.toISOString().slice(0, 10),
|
||||
week_total_hours,
|
||||
|
|
@ -103,6 +97,7 @@ export class OvertimeService {
|
|||
daily_overtime_kept: daily_kept_sum,
|
||||
total_overtime,
|
||||
breakdown,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { getYearStart, roundToQuarterHour } from "src/common/utils/date-utils";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
|
||||
@Injectable()
|
||||
export class SickLeaveService {
|
||||
constructor(private readonly prisma: PrismaService) { }
|
||||
|
||||
private readonly logger = new Logger(SickLeaveService.name);
|
||||
|
||||
//switch employeeId for email
|
||||
async calculateSickLeavePay(
|
||||
employee_id: number,
|
||||
|
|
@ -15,9 +14,9 @@ export class SickLeaveService {
|
|||
days_requested: number,
|
||||
hours_per_day: number,
|
||||
modifier: number,
|
||||
): Promise<number> {
|
||||
): Promise<Result<number, string>> {
|
||||
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
|
||||
|
|
@ -38,13 +37,10 @@ export class SickLeaveService {
|
|||
shifts.map((shift) => shift.date.toISOString().slice(0, 10)),
|
||||
);
|
||||
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
|
||||
if (days_worked < 30) {
|
||||
return 0;
|
||||
return { success: true, data: 0 };
|
||||
}
|
||||
|
||||
//default 3 days allowed after 30 worked days
|
||||
|
|
@ -70,16 +66,9 @@ export class SickLeaveService {
|
|||
//cap of 10 days
|
||||
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 raw_hours = payable_days * hours_per_day * modifier;
|
||||
const rounded = roundToQuarterHour(raw_hours);
|
||||
this.logger.debug(
|
||||
`Sick leave pay: days= ${payable_days}, hoursPerDay= ${hours_per_day}, modifier= ${modifier}, hours= ${rounded}`,
|
||||
);
|
||||
return rounded;
|
||||
return {success:true, data: rounded};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,27 @@
|
|||
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";
|
||||
|
||||
@Injectable()
|
||||
export class VacationService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
private readonly logger = new Logger(VacationService.name);
|
||||
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly emailResolver: EmailToIdResolver,
|
||||
) {}
|
||||
|
||||
//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
|
||||
const employee = await this.prisma.employees.findUnique({
|
||||
where: { id: employee_id },
|
||||
where: { id: employee_id.data },
|
||||
select: { first_work_day: true },
|
||||
});
|
||||
if(!employee) {
|
||||
throw new NotFoundException(`Employee #${employee_id} not found`);
|
||||
}
|
||||
if(!employee) return { success:false, error:`Employee #${employee_id} not found`}
|
||||
|
||||
const hire_date = employee.first_work_day;
|
||||
|
||||
//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_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
|
||||
const checkpoint = [5, 10, 15];
|
||||
const anniversaries = checkpoint.map(years => {
|
||||
|
|
@ -36,8 +39,6 @@ export class VacationService {
|
|||
return anniversary_date;
|
||||
}).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];
|
||||
//calculate prorata per segment
|
||||
let total_vacation_days = 0;
|
||||
|
|
@ -67,10 +68,8 @@ export class VacationService {
|
|||
|
||||
const raw_hours = payable_days * 8 * modifier;
|
||||
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