refactor(leave-requests): refactor the logic of the module leave-requests and modified naming in timesheet GET function

This commit is contained in:
Matthieu Haineault 2025-11-17 14:13:38 -05:00
parent 8c816da286
commit 6936ac39fa
13 changed files with 323 additions and 377 deletions

View File

@ -1,82 +1,82 @@
import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
// import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
console.log('?? Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)');
process.exit(0);
}
// if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
// console.log('?? Seed leave-requests ignor<6F> (SKIP_LEAVE_REQUESTS=true)');
// process.exit(0);
// }
const prisma = new PrismaClient();
// const prisma = new PrismaClient();
function dateOn(y: number, m: number, d: number) {
// stocke une date (@db.Date) à minuit UTC
return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
}
// function dateOn(y: number, m: number, d: number) {
// // stocke une date (@db.Date) <20> minuit UTC
// return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
// }
async function main() {
const year = new Date().getFullYear();
const today = new Date();
// async function main() {
// const year = new Date().getFullYear();
// const today = new Date();
const employees = await prisma.employees.findMany({ select: { id: true } });
const bankCodes = await prisma.bankCodes.findMany({
where: { categorie: 'LEAVE' },
select: { id: true, type: true },
});
// const employees = await prisma.employees.findMany({ select: { id: true } });
// const bankCodes = await prisma.bankCodes.findMany({
// where: { categorie: 'LEAVE' },
// select: { id: true, type: true },
// });
if (!employees.length || !bankCodes.length) {
console.warn('No employees or LEAVE bank codes; aborting');
return;
}
// if (!employees.length || !bankCodes.length) {
// console.warn('No employees or LEAVE bank codes; aborting');
// return;
// }
const types: LeaveTypes[] = [
LeaveTypes.SICK,
LeaveTypes.VACATION,
LeaveTypes.UNPAID,
LeaveTypes.BEREAVEMENT,
LeaveTypes.PARENTAL,
LeaveTypes.LEGAL,
LeaveTypes.WEDDING,
];
const statuses: LeaveApprovalStatus[] = [
LeaveApprovalStatus.PENDING,
LeaveApprovalStatus.APPROVED,
LeaveApprovalStatus.DENIED,
LeaveApprovalStatus.CANCELLED,
LeaveApprovalStatus.ESCALATED,
];
// const types: LeaveTypes[] = [
// LeaveTypes.SICK,
// LeaveTypes.VACATION,
// LeaveTypes.UNPAID,
// LeaveTypes.BEREAVEMENT,
// LeaveTypes.PARENTAL,
// LeaveTypes.LEGAL,
// LeaveTypes.WEDDING,
// ];
// const statuses: LeaveApprovalStatus[] = [
// LeaveApprovalStatus.PENDING,
// LeaveApprovalStatus.APPROVED,
// LeaveApprovalStatus.DENIED,
// LeaveApprovalStatus.CANCELLED,
// LeaveApprovalStatus.ESCALATED,
// ];
const futureMonths = [8, 9, 10, 11, 12]; // Août ? Déc. (1-based)
// const futureMonths = [8, 9, 10, 11, 12]; // Ao<41>t ? D<>c. (1-based)
const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
// const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
for (let i = 0; i < 10; i++) {
const emp = employees[i % employees.length];
const m = futureMonths[i % futureMonths.length];
const date = dateOn(year, m, 5 + i); // 5..14
if (date <= today) continue; // garantir « futur »
// for (let i = 0; i < 10; i++) {
// const emp = employees[i % employees.length];
// const m = futureMonths[i % futureMonths.length];
// const date = dateOn(year, m, 5 + i); // 5..14
// if (date <= today) continue; // garantir <20> futur <20>
const type = types[i % types.length];
const status = statuses[i % statuses.length];
const bc = bankCodes[i % bankCodes.length];
const requestedHours = 4 + (i % 5); // 4 ? 8 h
const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
// const type = types[i % types.length];
// const status = statuses[i % statuses.length];
// const bc = bankCodes[i % bankCodes.length];
// const requestedHours = 4 + (i % 5); // 4 ? 8 h
// const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
rows.push({
employee_id: emp.id,
bank_code_id: bc.id,
leave_type: type,
date,
comment: `Future leave #${i + 1} (${bc.type})`,
approval_status: status,
requested_hours: requestedHours,
payable_hours: payableHours,
});
}
// rows.push({
// employee_id: emp.id,
// bank_code_id: bc.id,
// leave_type: type,
// date,
// comment: `Future leave #${i + 1} (${bc.type})`,
// approval_status: status,
// requested_hours: requestedHours,
// payable_hours: payableHours,
// });
// }
if (rows.length) {
await prisma.leaveRequests.createMany({ data: rows });
}
// if (rows.length) {
// await prisma.leaveRequests.createMany({ data: rows });
// }
console.log(`? LeaveRequests (future): ${rows.length} rows`);
}
// console.log(`? LeaveRequests (future): ${rows.length} rows`);
// }
main().finally(() => prisma.$disconnect());
// main().finally(() => prisma.$disconnect());

View File

@ -61,7 +61,7 @@ model LeaveRequests {
bank_code_id Int
comment String
date DateTime @db.Date
dates DateTime[] @db.Date
payable_hours Decimal? @db.Decimal(5, 2)
requested_hours Decimal? @db.Decimal(5, 2)
approval_status LeaveApprovalStatus @default(PENDING)
@ -69,8 +69,8 @@ model LeaveRequests {
archive LeaveRequestsArchive[] @relation("LeaveRequestToArchive")
@@unique([employee_id, leave_type, date], name: "leave_per_employee_date")
@@index([employee_id, date])
@@unique([employee_id, leave_type, dates], name: "leave_per_employee_date")
@@index([employee_id, dates])
@@map("leave_requests")
}

View File

@ -1,5 +1,5 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { Prisma, PrismaClient } from "@prisma/client";
import { LeaveTypes, Prisma, PrismaClient } from "@prisma/client";
import { Result } from "src/common/errors/result-error.factory";
import { PrismaService } from "src/prisma/prisma.service";
@ -46,4 +46,6 @@ export class BankCodesResolver {
return { success: true, data: bank_code.type };
}
}

View File

@ -1,20 +1,28 @@
// import { Body, Controller, Post } from "@nestjs/common";
// import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
// import { UpsertLeaveRequestDto } from "../dtos/upsert-leave-request.dto";
// import { LeaveRequestsService } from "../services/leave-request.service";
import { Body, Controller, Delete, Patch, Post, Req } from "@nestjs/common";
import { LeaveRequestDto } from "../dtos/leave-request.dto";
import { LeaveRequestsService } from "src/time-and-attendance/leave-requests/services/leave-request.service";
// @ApiTags('Leave Requests')
// @ApiBearerAuth('access-token')
// // @UseGuards()
// @Controller('leave-requests')
// export class LeaveRequestController {
// constructor(private readonly leave_service: LeaveRequestsService){}
@Controller('leave-requests')
export class LeaveRequestController {
constructor(private readonly leave_service: LeaveRequestsService) { }
// @Post('upsert')
// async upsertLeaveRequest(@Body() dto: UpsertLeaveRequestDto) {
// const { action, leave_requests } = await this.leave_service.handle(dto);
// return { action, leave_requests };
// }
// @Post('create')
// async create(@Req() req, @Body() dto: LeaveRequestDto) {
// const email = req.user?.email;
// return await this.leave_service.create(email, dto);
// }
// }
// @Delete('delete')
// async delete(@Req() req, @Body() leave_request_id: number) {
// const email = req.user?.email;
// return await this.leave_service.delete(email, leave_request_id);
// }
// @Patch('update')
// async update(@Req() req, @Body() request_id: number, approval_status: string) {
// const email = req.user?.email;
// return await this.leave_service.update(email, request_id, approval_status);
// }
}

View File

@ -1,23 +1,12 @@
import { IsEmail, IsArray, ArrayNotEmpty, ArrayUnique, IsISO8601, IsIn, IsOptional, IsString, IsNumber, Min, Max, IsEnum } from "class-validator";
import { IsEmail, IsArray, ArrayNotEmpty, ArrayUnique, IsISO8601, IsOptional, IsString, IsNumber, Min, Max, IsEnum } from "class-validator";
import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
import { LeaveRequestViewDto } from "./leave-request-view.dto";
import { Type } from "class-transformer";
//sets wich function to call
export const UPSERT_ACTIONS = ['create', 'update', 'delete'] as const;
export type UpsertAction = (typeof UPSERT_ACTIONS)[number];
//sets wich types to use
export const REQUEST_TYPES = Object.values(LeaveTypes) as readonly LeaveTypes[];
export type RequestTypes = (typeof REQUEST_TYPES)[number];
//filter requests by type and action
export interface UpsertResult {
action: UpsertAction;
leave_requests: LeaveRequestViewDto[];
}
export class UpsertLeaveRequestDto {
export class LeaveRequestDto {
@IsEmail()
email!: string;
@ -27,16 +16,11 @@ export class UpsertLeaveRequestDto {
@IsISO8601({}, { each: true })
dates!: string[];
@IsOptional()
@IsEnum(LeaveTypes)
type!: string;
@IsIn(UPSERT_ACTIONS)
action!: UpsertAction;
@IsOptional()
@IsString()
comment?: string;
comment!: string;
@IsOptional()
@Type(() => Number)
@ -45,7 +29,6 @@ export class UpsertLeaveRequestDto {
@Max(24)
requested_hours?: number;
@IsOptional()
@IsEnum(LeaveApprovalStatus)
approval_status?: LeaveApprovalStatus
}

View File

@ -1,25 +1,25 @@
import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto";
import { Prisma } from "@prisma/client";
import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
import { leave_requests_select } from "src/time-and-attendance/utils/selects.utils";
type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leave_requests_select}>;
const toNum = (value?: Prisma.Decimal | null) =>
value !== null && value !== undefined ? Number(value) : undefined;
export function mapRowToView(row: LeaveRequestRow): LeaveRequestViewDto {
const iso_date = row.date?.toISOString().slice(0, 10);
if (!iso_date) throw new Error(`Leave request #${row.id} has no date set.`);
// export function mapRowToView(row: LeaveRequestRow): LeaveRequestViewDto {
// const iso_date = row.dates?.toISOString().slice(0, 10);
// if (!iso_date) throw new Error(`Leave request #${row.id} has no date set.`);
return {
id: row.id,
leave_type: row.leave_type,
date: iso_date,
payable_hours: toNum(row.payable_hours),
requested_hours: toNum(row.requested_hours),
comment: row.comment,
approval_status: row.approval_status,
email: row.employee.user.email,
employee_full_name: `${row.employee.user.first_name} ${row.employee.user.last_name}`,
};
}
// return {
// id: row.id,
// leave_type: row.leave_type,
// date: iso_date,
// payable_hours: toNum(row.payable_hours),
// requested_hours: toNum(row.requested_hours),
// comment: row.comment,
// approval_status: row.approval_status,
// email: row.employee.user.email,
// employee_full_name: `${row.employee.user.first_name} ${row.employee.user.last_name}`,
// };
// }

View File

@ -1,241 +1,186 @@
// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
// import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto";
// import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
// import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
// import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto";
// import { roundToQuarterHour } from "src/common/utils/date-utils";
// import { LeaveRequestsUtils } from "src/time-and-attendance/leave-requests/utils/leave-request.util";
// import { EmailToIdResolver } from "src/time-and-attendance/utils/resolve-email-id.utils";
// import { BankCodesResolver } from "src/time-and-attendance/utils/resolve-bank-type-id.utils";
// import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service";
// import { VacationService } from "src/time-and-attendance/domains/services/vacation.service";
// import { HolidayService } from "src/time-and-attendance/domains/services/holiday.service";
// import { PrismaService } from "src/prisma/prisma.service";
// import { mapRowToView } from "../mappers/leave-requests.mapper";
// import { normalizeDates, toDateOnly, toISODateKey } from "src/time-and-attendance/utils/date-time.utils";
// @Injectable()
// export class LeaveRequestsService {
import { EmployeeTimesheetResolver } from "src/common/mappers/timesheet.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { LeaveApprovalStatus, LeaveRequests, LeaveTypes, Prisma, Shifts } from "@prisma/client";
import { PrismaService } from "src/prisma/prisma.service";
import { Result } from "src/common/errors/result-error.factory";
import { Injectable } from "@nestjs/common";
import { LeaveRequestDto } from "src/time-and-attendance/leave-requests/dtos/leave-request.dto";
import { leave_requests_select } from "src/time-and-attendance/utils/selects.utils";
import { toDateFromString, toStringFromDate } from "src/common/utils/date-utils";
import { NormalizedLeaveRequest } from "src/time-and-attendance/utils/type.utils";
@Injectable()
export class LeaveRequestsService {
// constructor(
// private readonly prisma: PrismaService,
// private readonly holidayService: HolidayService,
// private readonly sickLogic: SickLeaveService,
// private readonly vacationLogic: VacationService,
// private readonly leaveUtils: LeaveRequestsUtils,
// private readonly emailResolver: EmailToIdResolver,
// private readonly typeResolver: BankCodesResolver,
// ) {}
// private readonly prisma: PrismaService,
// private readonly timesheetResolver: EmployeeTimesheetResolver,
// private readonly emailResolver: EmailToIdResolver,
// private readonly typeResolver: BankCodesResolver,
// ) { }
// // handle distribution to the right service according to the selected type and action
// async handle(dto: UpsertLeaveRequestDto): Promise<UpsertResult> {
// switch (dto.type) {
// case LeaveTypes.HOLIDAY:
// if( dto.action === 'create'){
// // return this.holidayService.create(dto);
// } else if (dto.action === 'update') {
// return this.update(dto, LeaveTypes.HOLIDAY);
// } else if (dto.action === 'delete'){
// return this.delete(dto, LeaveTypes.HOLIDAY);
// }
// case LeaveTypes.VACATION:
// if( dto.action === 'create'){
// // return this.vacationService.create(dto);
// } else if (dto.action === 'update') {
// return this.update(dto, LeaveTypes.VACATION);
// } else if (dto.action === 'delete'){
// return this.delete(dto, LeaveTypes.VACATION);
// }
// case LeaveTypes.SICK:
// if( dto.action === 'create'){
// // return this.sickLeaveService.create(dto);
// } else if (dto.action === 'update') {
// return this.update(dto, LeaveTypes.SICK);
// } else if (dto.action === 'delete'){
// return this.delete(dto, LeaveTypes.SICK);
// }
// default:
// throw new BadRequestException(`Unsupported leave type: ${dto.type} or action: ${dto.action}`);
// }
// }
// async delete(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise<UpsertResult> {
// const email = dto.email.trim();
// const dates = normalizeDates(dto.dates);
// const employee_id = await this.emailResolver.findIdByEmail(email);
// if (!dates.length) throw new BadRequestException("Dates array must not be empty");
// const rows = await this.prisma.leaveRequests.findMany({
// where: {
// employee_id: employee_id,
// leave_type: type,
// date: { in: dates.map((d) => toDateOnly(d)) },
// },
// select: leaveRequestsSelect,
// });
// async create(email: string, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> {
// try {
// //verify if array is empty or not
// if (!Array.isArray(dto.dates) || dto.dates.length === 0) return { success: false, error: 'no data received' };
// //verify if email is valid or not
// const employee = await this.emailResolver.findIdByEmail(email);
// if (!employee.success) return { success: false, error: employee.error }
// //normalized dto datas to match DB's
// const normed_request = await this.normalizeRequest(dto);
// if (!normed_request.success) return { success: false, error: normed_request.error }
// if (rows.length !== dates.length) {
// const missing = dates.filter((isoDate) => !rows.some((row) => toISODateKey(row.date) === isoDate));
// throw new NotFoundException(`No Leave request found for: ${missing.join(", ")}`);
// }
// for (const row of rows) {
// if (row.approval_status === LeaveApprovalStatus.APPROVED) {
// const iso = toISODateKey(row.date);
// await this.leaveUtils.removeShift(email, employee_id, iso, type);
// }
// }
// await this.prisma.leaveRequests.deleteMany({
// where: { id: { in: rows.map((row) => row.id) } },
// });
// const deleted = rows.map((row) => ({ ...mapRowToView(row), action: "delete" as const }));
// return { action: "delete", leave_requests: deleted };
// }
// async update(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise<UpsertResult> {
// const email = dto.email.trim();
// const employee_id = await this.emailResolver.findIdByEmail(email);
// const bank_code = await this.typeResolver.findIdAndModifierByType(type);
// if(!bank_code) throw new NotFoundException(`bank_code not found`);
// const modifier = Number(bank_code.modifier ?? 1);
// const dates = normalizeDates(dto.dates);
// if (!dates.length) {
// throw new BadRequestException("Dates array must not be empty");
// }
// const entries = await Promise.all(
// dates.map(async (iso_date) => {
// const date = toDateOnly(iso_date);
// const existing = await this.prisma.leaveRequests.findUnique({
// where: {
// leave_per_employee_date: {
// employee_id: employee_id,
// leave_type: type,
// date,
// },
// },
// select: leaveRequestsSelect,
// });
// if (!existing) throw new NotFoundException(`No Leave request found for ${iso_date}`);
// return { iso_date, date, existing };
// }),
// );
// const updated: LeaveRequestViewDto[] = [];
// if (type === LeaveTypes.SICK) {
// const firstExisting = entries[0].existing;
// const fallbackRequested =
// firstExisting.requested_hours !== null && firstExisting.requested_hours !== undefined
// ? Number(firstExisting.requested_hours)
// : 8;
// const requested_hours_per_day = dto.requested_hours ?? fallbackRequested;
// const reference_date = entries.reduce(
// (latest, entry) => (entry.date > latest ? entry.date : latest),
// entries[0].date,
// );
// const total_payable_hours = await this.sickLogic.calculateSickLeavePay(
// employee_id,
// reference_date,
// entries.length,
// requested_hours_per_day,
// modifier,
// );
// let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours));
// const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier);
// for (const { iso_date, existing } of entries) {
// const previous_status = existing.approval_status;
// const payable = Math.min(remaining_payable_hours, daily_payable_cap);
// const payable_rounded = roundToQuarterHour(Math.max(0, payable));
// remaining_payable_hours = roundToQuarterHour(
// Math.max(0, remaining_payable_hours - payable_rounded),
// );
// const row = await this.prisma.leaveRequests.update({
// where: { id: existing.id },
// data: {
// comment: dto.comment ?? existing.comment,
// requested_hours: requested_hours_per_day,
// payable_hours: payable_rounded,
// bank_code_id: bank_code.id,
// approval_status: dto.approval_status ?? existing.approval_status,
// },
// select: leaveRequestsSelect,
// });
// const was_approved = previous_status === LeaveApprovalStatus.APPROVED;
// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED;
// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0);
// if (!was_approved && is_approved) {
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
// } else if (was_approved && !is_approved) {
// await this.leaveUtils.removeShift(email, employee_id, iso_date, type);
// } else if (was_approved && is_approved) {
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
// }
// updated.push({ ...mapRowToView(row), action: "update" });
// }
// return { action: "update", leave_requests: updated };
// }
// for (const { iso_date, date, existing } of entries) {
// const previous_status = existing.approval_status;
// const fallbackRequested =
// existing.requested_hours !== null && existing.requested_hours !== undefined
// ? Number(existing.requested_hours)
// : 8;
// const requested_hours = dto.requested_hours ?? fallbackRequested;
// let payable: number;
// switch (type) {
// case LeaveTypes.HOLIDAY:
// payable = await this.holidayService.calculateHolidayPay(email, date, modifier);
// break;
// case LeaveTypes.VACATION: {
// const days_requested = requested_hours / 8;
// payable = await this.vacationLogic.calculateVacationPay(
// employee_id,
// date,
// Math.max(0, days_requested),
// modifier,
// );
// break;
// }
// default:
// payable = existing.payable_hours !== null && existing.payable_hours !== undefined
// ? Number(existing.payable_hours)
// : requested_hours;
// }
// const row = await this.prisma.leaveRequests.update({
// where: { id: existing.id },
// //creates the requests
// const request_day = await this.prisma.leaveRequests.create({
// data: {
// requested_hours,
// comment: dto.comment ?? existing.comment,
// payable_hours: payable,
// bank_code_id: bank_code.id,
// approval_status: dto.approval_status ?? existing.approval_status,
// employee_id: employee.data,
// bank_code_id: normed_request.data.bank_code_id,
// comment: normed_request.data.comment,
// dates: normed_request.data.dates,
// approval_status: dto.approval_status,
// requested_hours: dto.requested_hours,
// leave_type: normed_request.data.leave_type,
// },
// select: leaveRequestsSelect,
// select: leave_requests_select,
// });
// if (!request_day) return { success: false, error: 'An error occured during creation. Leave-Request is invalid' }
// const was_approved = previous_status === LeaveApprovalStatus.APPROVED;
// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED;
// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0);
// const created_request: LeaveRequestDto = {
// email: dto.email,
// type: request_day.leave_type.toString(),
// dates: dto.dates,
// comment: normed_request.data.comment,
// approval_status: 'PENDING',
// requested_hours: dto.requested_hours,
// };
// if (!was_approved && is_approved) {
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
// } else if (was_approved && !is_approved) {
// await this.leaveUtils.removeShift(email, employee_id, iso_date, type);
// } else if (was_approved && is_approved) {
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
// }
// updated.push({ ...mapRowToView(row), action: "update" });
// return { success: true, data: created_request };
// } catch (error) {
// return { success: false, error: `An error occured during creation, invalid data` }
// }
// return { action: "update", leave_requests: updated };
// }
// }
// async update(email: string, request_id: number, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> {
// try {
// const employee = await this.emailResolver.findIdByEmail(email);
// if (!employee.success) return { success: false, error: employee.error }
// switch (dto.approval_status) {
// case 'APPROVED': //creation of shifts and returns void
// break;
// case 'DENIED': //simple update and returns void
// break;
// case 'CANCELLED': //CANCELLED, simple update and returns void
// break;
// case 'PENDING': this.updatePendingRequest(dto)
// break;
// default: return { success: false, error: `invalid approval_status` };
// }
// // const updated_request: LeaveRequestDto = {
// // email: dto.email,
// // type: request_day.leave_type.toString(),
// // dates: dto.dates,
// // comment: normed_request.data.comment,
// // approval_status: dto.approval_status,
// // requested_hours: dto.requested_hours,
// // }
// } catch (error) {
// return { success: false, error: ' An error occured during update, Invalid Leave-Request data' }
// }
// return { success: true, data: updated_request };
// }
// async delete(email: string, request_id: number): Promise<Result<number, string>> {
// try {
// const employee = await this.emailResolver.findIdByEmail(email);
// if (!employee.success) return { success: false, error: employee.error }
// const deleted = await this.prisma.leaveRequests.findUnique({
// where: { id: request_id, employee_id: employee.data },
// select: { id: true, dates: true },
// });
// if (!deleted) return { success: false, error: `Leave Request with id ${request_id} not found ` };
// return { success: true, data: deleted.id };
// } catch (error) {
// return { success: false, error: `INVALID_REQUEST, leave-request with id ${request_id} not found` }
// }
// }
// private normalizeRequest = async (dto: LeaveRequestDto): Promise<Result<NormalizedLeaveRequest, string>> => {
// const bank_code = await this.typeResolver.findBankCodeIDByType(dto.type);
// if (!bank_code.success) return { success: false, error: bank_code.error };
// const comment = this.truncate280(dto.comment);
// //maps enum, check if dto.type is include in the list and return a valid type
// const leave_type_list = Object.values(LeaveTypes);
// const leave_type = leave_type_list.includes(dto.type.toUpperCase() as LeaveTypes);
// if (!leave_type) return { success: false, error: `Leave Request of type ${dto.type} is invalid` }
// const valid_leave_type = dto.type.toUpperCase() as LeaveTypes;
// //map of all dates in string format
// const dates = dto.dates.map(toDateFromString);
// if (!dates) return { success: false, error: 'Bad date' }
// return { success: true, data: { comment, dates, leave_type: valid_leave_type, bank_code_id: bank_code.data } };
// }
// //makes sure that a string cannot exceed 280 chars
// private truncate280 = (input: string): string => {
// return input.length > 280 ? input.slice(0, 280) : input;
// }
// private updatePendingRequest = async (request_id: number, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> => {
// const normed_dto = await this.normalizeRequest(dto);
// if (!normed_dto.success) return { success: false, error: normed_dto.error }
// const leave_request = await this.prisma.leaveRequests.findUnique({
// where: { id: request_id },
// select: leave_requests_select,
// });
// if (!leave_request) return { success: false, error: `Leave Request with id: ${request_id} not found` }
// const update = await this.prisma.leaveRequests.update({
// where: { id: request_id },
// data: {
// bank_code_id: normed_dto.data.bank_code_id,
// leave_type: normed_dto.data.leave_type,
// comment: normed_dto.data.comment,
// dates: normed_dto.data.dates,
// requested_hours: dto.requested_hours ?? 0,
// }
// })
// // (alias) class LeaveRequestDto {
// // email: string;
// // dates: string[];
// // type: string;
// // comment: string;
// // requested_hours?: number | undefined;
// // approval_status?: $Enums.LeaveApprovalStatus | undefined;
// // }
// // const dates_string = update.dates.map(toStringFromDate);
// // const updated_request: LeaveRequestDto = {
// // email: leave_request,
// // type: update.leave_type,
// // }
// return { success: true, data: updated_request }
// }
}
type leaveRequests = {
id: number;
bank_code_id: number;
comment: string;
dates: Date[];
payable_hours: Prisma.Decimal | null;
requested_hours: Prisma.Decimal | null;
approval_status: LeaveApprovalStatus;
leave_type: LeaveTypes;
}

View File

@ -1,22 +1,22 @@
import { Prisma } from "@prisma/client";
import { LeaveRequestViewDto } from "src/time-and-attendance/leave-requests/dtos/leave-request-view.dto";
import { mapArchiveRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests-archive.mapper";
import { mapRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests.mapper";
// import { mapRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests.mapper";
import { LeaveRequestArchiveRow } from "src/time-and-attendance/leave-requests/utils/leave-requests-archive.select";
import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
// import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
export type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
// export type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
/** Active (table leave_requests) : proxy to base mapper */
export function mapRowToViewWithDays(row: LeaveRequestRow): LeaveRequestViewDto {
return mapRowToView(row);
}
// /** Active (table leave_requests) : proxy to base mapper */
// export function mapRowToViewWithDays(row: LeaveRequestRow): LeaveRequestViewDto {
// return mapRowToView(row);
// }
/** Archive (table leave_requests_archive) : proxy to base mapper */
export function mapArchiveRowToViewWithDays(
row: LeaveRequestArchiveRow,
email: string,
employee_full_name?: string,
): LeaveRequestViewDto {
return mapArchiveRowToView(row, email, employee_full_name!);
}
// /** Archive (table leave_requests_archive) : proxy to base mapper */
// export function mapArchiveRowToViewWithDays(
// row: LeaveRequestArchiveRow,
// email: string,
// employee_full_name?: string,
// ): LeaveRequestViewDto {
// return mapArchiveRowToView(row, email, employee_full_name!);
// }

View File

@ -7,15 +7,16 @@ import { toDateFromString, toStringFromDate } from "src/common/utils/date-utils"
export class LeaveRequestsUtils {
constructor(
private readonly prisma: PrismaService,
){}
) { }
async syncShift(
email: string,
email: string,
employee_id: number,
date: string,
hours: number,
type: LeaveTypes,
comment?: string,
date: string,
hours: number,
type: LeaveTypes,
comment?: string,
) {
if (hours <= 0) return;

View File

@ -62,6 +62,6 @@ export class Expense {
amount?: number;
mileage?: number;
attachment?: string;
expense_id?: number | null;
id?: number | null;
supervisor_comment?: string | null;
}

View File

@ -159,7 +159,7 @@ export class GetTimesheetsOverviewService {
date: toStringFromDate(expense.date),
amount: expense.amount != null ? Number(expense.amount) : undefined,
mileage: expense.mileage != null ? Number(expense.mileage) : undefined,
expense_id: expense.id ?? null,
id: expense.id ?? null,
attachment: expense.attachment_record ? String(expense.attachment_record.id) : undefined,
is_approved: expense.is_approved ?? false,
comment: expense.comment ?? '',

View File

@ -28,11 +28,11 @@ export const shift_select = {
comment: true,
} satisfies Prisma.ShiftsSelect;
export const leaveRequestsSelect = {
export const leave_requests_select = {
id: true,
bank_code_id: true,
leave_type: true,
date: true,
dates: true,
payable_hours: true,
requested_hours: true,
comment: true,

View File

@ -1,4 +1,4 @@
import { Prisma } from "@prisma/client";
import { LeaveTypes, Prisma } from "@prisma/client";
export type Normalized = {
date: Date;
@ -16,6 +16,13 @@ export type NormalizedExpense = {
parsed_attachment?: number;
};
export type NormalizedLeaveRequest = {
comment: string;
dates: Date[];
bank_code_id: number;
leave_type: LeaveTypes;
}
export type ShiftResponse = {
week_day: string;
sort_order: number;