From 70575e1772010615dc2a20131030b7343fde6640 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Fri, 9 Jan 2026 08:00:08 -0500 Subject: [PATCH] feat(banking_hours): added a function to add or take banked_hours --- .../domains/business-logics.module.ts | 2 +- .../services/banking-hours.service.service.ts | 64 ------- .../domains/services/banking-hours.service.ts | 70 +++++++ .../domains/services/sick-leave.service.ts | 172 +++++++++++------- .../domains/services/vacation.service.ts | 7 +- .../schedule-presets.module.ts | 4 + .../shifts/services/shifts-create.service.ts | 26 ++- .../shifts/services/shifts-delete.service.ts | 52 +++++- .../services/shifts-update-delete.service.ts | 54 +++++- .../shifts/shifts.module.ts | 3 +- .../time-and-attendance.module.ts | 2 + 11 files changed, 319 insertions(+), 137 deletions(-) delete mode 100644 src/time-and-attendance/domains/services/banking-hours.service.service.ts create mode 100644 src/time-and-attendance/domains/services/banking-hours.service.ts diff --git a/src/time-and-attendance/domains/business-logics.module.ts b/src/time-and-attendance/domains/business-logics.module.ts index 0a1190c..f0b9b56 100644 --- a/src/time-and-attendance/domains/business-logics.module.ts +++ b/src/time-and-attendance/domains/business-logics.module.ts @@ -1,4 +1,4 @@ -import { BankedHoursService } from "./services/banking-hours.service.service"; +import { BankedHoursService } from "./services/banking-hours.service"; import { SickLeaveService } from "./services/sick-leave.service"; import { OvertimeService } from "./services/overtime.service"; import { VacationService } from "./services/vacation.service"; diff --git a/src/time-and-attendance/domains/services/banking-hours.service.service.ts b/src/time-and-attendance/domains/services/banking-hours.service.service.ts deleted file mode 100644 index 48c974e..0000000 --- a/src/time-and-attendance/domains/services/banking-hours.service.service.ts +++ /dev/null @@ -1,64 +0,0 @@ -// import { Injectable } from "@nestjs/common"; -// import { Result } from "src/common/errors/result-error.factory"; -// import { PrismaService } from "src/prisma/prisma.service"; - -// @Injectable() -// export class BankedHoursService { - -// constructor(private readonly prisma: PrismaService) { } - -// //manage shifts with bank_code.type BANKING -// bankingHours = async (employee_id: number, hours: number): Promise> => { -// if (hours <= 0) return { success: false, error: 'INVALID_BANKING_HOURS' }; - -// try { -// const result = await this.prisma.$transaction(async (tx) => { -// const employee = await this.prisma.employees.findUnique({ -// where: { id: employee_id }, -// select: { -// id: true, -// paid_time_off: { -// select: { -// banked_hours: true -// }, -// }, -// }, -// }); -// if (!employee) { -// return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result -// } -// if (!employee.paid_time_off) { -// return { success: false, error: 'VACATION_HOURS_BANK_NOT_FOUND' } as Result -// } - -// const new_balance = await tx.paidTimeOff.update({ -// where: { employee_id: employee.id }, -// data: { -// banked_hours: { increment: hours }, -// }, -// select: { -// banked_hours: true, -// }, -// }); -// return { success: true, data: new_balance }; -// }); - -// return result; -// } catch (error) { -// return { success: false, error: 'INVALID_BANKING_SHIFT' }; -// } - - - - -// } - - -// //manage shifts with bank_code.type WITHDRAW_BANKED -// withdrawBankedHours = async (employee_id: number, asked_hours: number): Promise> => { -// if (asked_hours <= 0) return { success: false, error: 'INVALID_WITHDRAW_BANKED' }; - - - -// } -// } \ No newline at end of file diff --git a/src/time-and-attendance/domains/services/banking-hours.service.ts b/src/time-and-attendance/domains/services/banking-hours.service.ts new file mode 100644 index 0000000..dd600e1 --- /dev/null +++ b/src/time-and-attendance/domains/services/banking-hours.service.ts @@ -0,0 +1,70 @@ +import { Injectable } from "@nestjs/common"; +import { Result } from "src/common/errors/result-error.factory"; +import { PrismaService } from "src/prisma/prisma.service"; + +@Injectable() +export class BankedHoursService { + + constructor(private readonly prisma: PrismaService) { } + + //manage shifts with bank_code.type BANKING + manageBankingHours = async (employee_id: number, asked_hours: number, type: string): Promise> => { + if (asked_hours <= 0) return { success: false, error: 'INVALID_BANKING_HOURS' }; + + try { + const result = await this.prisma.$transaction(async (tx) => { + const employee = await this.prisma.employees.findUnique({ + where: { id: employee_id }, + select: { + id: true, + paid_time_off: { + select: { + banked_hours: true + }, + }, + }, + }); + + if (!employee) { + return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result; + } + if (!employee.paid_time_off) { + return { success: false, error: 'BANKING_HOURS_BANK_NOT_FOUND' } as Result; + } + const banked_hours = (employee.paid_time_off.banked_hours).toNumber(); + if (banked_hours <= 0) { + return { success: false, error: 'EMPTY_BANKED_HOURS' } as Result; + } + + if (type === 'BANKING') { + const new_balance = await tx.paidTimeOff.update({ + where: { employee_id: employee.id }, + data: { banked_hours: { increment: asked_hours } }, + select: { banked_hours: true }, + }); + return { success: true, data: (new_balance.banked_hours).toNumber() } as Result; + + } else if (type === 'WITHDRAW_BANKED') { + if (asked_hours > banked_hours) { + return { success: true, data: banked_hours } as Result; + } else { + + } + await tx.paidTimeOff.update({ + where: { employee_id: employee.id }, + data: { banked_hours: { decrement: asked_hours } }, + select: { banked_hours: true }, + }); + return { success: true, data: asked_hours } as Result; + } else { + return { success: false, error: 'INVALID_SHIFT_TYPE' } as Result; + } + + }); + return result; + + } catch (error) { + return { success: false, error: 'INVALID_BANKING_SHIFT' }; + } + } +} \ No newline at end of file diff --git a/src/time-and-attendance/domains/services/sick-leave.service.ts b/src/time-and-attendance/domains/services/sick-leave.service.ts index 7bf8f4c..30e3c6d 100644 --- a/src/time-and-attendance/domains/services/sick-leave.service.ts +++ b/src/time-and-attendance/domains/services/sick-leave.service.ts @@ -53,7 +53,7 @@ export class SickLeaveService { if (!updated_pto.success) return { success: updated_pto.success, error: updated_pto.error } } - + const year_difference = today.getFullYear() - (pto_details!.last_updated.getFullYear() ?? today.getFullYear()); const months_since_last_update = (today.getMonth() + year_difference * 12) - pto_details!.last_updated.getMonth(); @@ -61,7 +61,7 @@ export class SickLeaveService { const updated_pto = await this.addHoursToPTO(months_since_last_update * 8, employee.id, today); if (updated_pto.success) { - return {success: true, data: true} + return { success: true, data: true } } } @@ -111,68 +111,114 @@ export class SickLeaveService { } }; - // switch employeeId for email - async calculateSickLeavePay( - employee_id: number, - reference_date: Date, - days_requested: number, - hours_per_day: number, - modifier: number, - ): Promise> { - if (days_requested <= 0 || hours_per_day <= 0 || modifier <= 0) { - return { success: true, data: 0 }; + takeSickLeaveHours = async (employee_id: number, asked_hours: number): Promise> => { + if (asked_hours <= 0) return { success: false, error: 'INVALID_BANKING_HOURS' }; + console.log('also got here') + try { + const result = await this.prisma.$transaction(async (tx) => { + const employee = await this.prisma.employees.findUnique({ + where: { id: employee_id }, + select: { + id: true, + paid_time_off: { + select: { + banked_hours: true + }, + }, + }, + }); + + if (!employee) { + return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result; + } + if (!employee.paid_time_off) { + return { success: false, error: 'SICK_HOURS_BANK_NOT_FOUND' } as Result; + } + const sick_bank = (employee.paid_time_off.banked_hours).toNumber(); + if (sick_bank <= 0) return { success: false, error: 'EMPTY_SICK_HOURS_BANK' } as Result; + + if (asked_hours > sick_bank) { + return { success: true, data: sick_bank } as Result; + } else { + await tx.paidTimeOff.update({ + where: { employee_id: employee.id }, + data: { banked_hours: { decrement: asked_hours } }, + select: { banked_hours: true }, + }); + return { success: true, data: asked_hours } as Result; + } + }); + return result; + + } catch (error) { + return { success: false, error: 'INVALID_BANKING_SHIFT' }; } - //sets the year to jan 1st to dec 31st - const period_start = getYearStart(reference_date); - const period_end = reference_date; - - //fetches all shifts of a selected employee - const shifts = await this.prisma.shifts.findMany({ - where: { - timesheet: { employee_id: employee_id }, - date: { gte: period_start, lte: period_end }, - }, - select: { date: true }, - }); - - //count the amount of worked days - const worked_dates = new Set( - shifts.map((shift) => shift.date.toISOString().slice(0, 10)), - ); - const days_worked = worked_dates.size; - - //less than 30 worked days returns 0 - if (days_worked < 30) { - return { success: true, data: 0 }; - } - - //default 3 days allowed after 30 worked days - let acquired_days = 3; - - //identify the date of the 30th worked day - const ordered_dates = Array.from(worked_dates).sort(); - const threshold_date = new Date(ordered_dates[29]); // index 29 is the 30th day - - //calculate each completed month, starting the 1st of the next month - const first_bonus_date = new Date( - threshold_date.getFullYear(), - threshold_date.getMonth() + 1, - 1, - ); - let months = - (period_end.getFullYear() - first_bonus_date.getFullYear()) * 12 + - (period_end.getMonth() - first_bonus_date.getMonth()) + - 1; - if (months < 0) months = 0; - acquired_days += months; - - //cap of 10 days - if (acquired_days > 10) acquired_days = 10; - - const payable_days = Math.min(acquired_days, days_requested); - const raw_hours = payable_days * hours_per_day * modifier; - const rounded = roundToQuarterHour(raw_hours); - return { success: true, data: rounded }; } + + + //LEAVE REQUEST FUNCTION - DEPRECATED + // async calculateSickLeavePay( + // employee_id: number, + // reference_date: Date, + // days_requested: number, + // hours_per_day: number, + // modifier: number, + // ): Promise> { + // if (days_requested <= 0 || hours_per_day <= 0 || modifier <= 0) { + // return { success: true, data: 0 }; + // } + + // //sets the year to jan 1st to dec 31st + // const period_start = getYearStart(reference_date); + // const period_end = reference_date; + + // //fetches all shifts of a selected employee + // const shifts = await this.prisma.shifts.findMany({ + // where: { + // timesheet: { employee_id: employee_id }, + // date: { gte: period_start, lte: period_end }, + // }, + // select: { date: true }, + // }); + + // //count the amount of worked days + // const worked_dates = new Set( + // shifts.map((shift) => shift.date.toISOString().slice(0, 10)), + // ); + // const days_worked = worked_dates.size; + + // //less than 30 worked days returns 0 + // if (days_worked < 30) { + // return { success: true, data: 0 }; + // } + + // //default 3 days allowed after 30 worked days + // let acquired_days = 3; + + // //identify the date of the 30th worked day + // const ordered_dates = Array.from(worked_dates).sort(); + // const threshold_date = new Date(ordered_dates[29]); // index 29 is the 30th day + + // //calculate each completed month, starting the 1st of the next month + // const first_bonus_date = new Date( + // threshold_date.getFullYear(), + // threshold_date.getMonth() + 1, + // 1, + // ); + // let months = + // (period_end.getFullYear() - first_bonus_date.getFullYear()) * 12 + + // (period_end.getMonth() - first_bonus_date.getMonth()) + + // 1; + // if (months < 0) months = 0; + // acquired_days += months; + + // //cap of 10 days + // if (acquired_days > 10) acquired_days = 10; + + // const payable_days = Math.min(acquired_days, days_requested); + // const raw_hours = payable_days * hours_per_day * modifier; + // const rounded = roundToQuarterHour(raw_hours); + // return { success: true, data: rounded }; + // } } diff --git a/src/time-and-attendance/domains/services/vacation.service.ts b/src/time-and-attendance/domains/services/vacation.service.ts index ac1461e..b673671 100644 --- a/src/time-and-attendance/domains/services/vacation.service.ts +++ b/src/time-and-attendance/domains/services/vacation.service.ts @@ -84,16 +84,17 @@ export class VacationService { select: { paid_time_off: { select: { vacation_hours: true } } }, }); if (!employee) { - return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result + return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result; } if (!employee.paid_time_off) { - return { success: false, error: 'VACATION_HOURS_BANK_NOT_FOUND' } as Result + return { success: false, error: 'VACATION_HOURS_BANK_NOT_FOUND' } as Result; } const vacation_bank = employee.paid_time_off.vacation_hours.toNumber() + if (vacation_bank <= 0) return { success: false, error: 'EMPTY_VACATION_BANK' } as Result; //check if remaining hours are less than asked and return maximum available hours if (asked_hours > vacation_bank) { - return { success: true, data: vacation_bank } as Result + return { success: true, data: vacation_bank } as Result; } else { //update vacation_bank await tx.paidTimeOff.update({ diff --git a/src/time-and-attendance/schedule-presets/schedule-presets.module.ts b/src/time-and-attendance/schedule-presets/schedule-presets.module.ts index 9cbf8bc..56beb0a 100644 --- a/src/time-and-attendance/schedule-presets/schedule-presets.module.ts +++ b/src/time-and-attendance/schedule-presets/schedule-presets.module.ts @@ -11,6 +11,8 @@ import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-pr import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shifts-create.service"; import { VacationService } from "src/time-and-attendance/domains/services/vacation.service"; +import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service"; +import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service"; @@ -26,6 +28,8 @@ import { VacationService } from "src/time-and-attendance/domains/services/vacati ShiftsCreateService, BankCodesResolver, VacationService, + SickLeaveService, + BankedHoursService, ], exports: [ SchedulePresetsGetService, diff --git a/src/time-and-attendance/shifts/services/shifts-create.service.ts b/src/time-and-attendance/shifts/services/shifts-create.service.ts index 1dce91c..d9fa4b7 100644 --- a/src/time-and-attendance/shifts/services/shifts-create.service.ts +++ b/src/time-and-attendance/shifts/services/shifts-create.service.ts @@ -8,6 +8,8 @@ import { Result } from "src/common/errors/result-error.factory"; import { toStringFromHHmm, toStringFromDate, toDateFromString, overlaps, toDateFromHHmm, computeHours } from "src/common/utils/date-utils"; import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto"; import { VacationService } from "src/time-and-attendance/domains/services/vacation.service"; +import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service"; +import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service"; @Injectable() export class ShiftsCreateService { @@ -16,6 +18,8 @@ export class ShiftsCreateService { private readonly emailResolver: EmailToIdResolver, private readonly typeResolver: BankCodesResolver, private readonly vacationService: VacationService, + private readonly bankingService: BankedHoursService, + private readonly sickService: SickLeaveService, ) { } //_________________________________________________________________ @@ -95,15 +99,33 @@ export class ShiftsCreateService { return { success: false, error: `SHIFT_OVERLAP` }; } } + //api call to validate available hours in vacation_bank and ajust end_time accordingly if (dto.type === 'VACATION') { - const asked_hours = computeHours(toDateFromString(dto.start_time), toDateFromString(dto.end_time)); + const asked_hours = computeHours(toDateFromHHmm(dto.start_time), toDateFromHHmm(dto.end_time)); const vacation_shift = await this.vacationService.manageVacationHoursBank(employee_id, asked_hours) if (!vacation_shift.success) return { success: false, error: vacation_shift.error }; dto.end_time = this.addHourstoDateString(dto.start_time, vacation_shift.data); } - //ADD HERE THE LOGICS TO CHECK FOR AVAILABLE BANK TYPE "PAID_BANKED_HOUR" AND BANKING_HOUR + //api call to validate available hours in banked_hours and ajust end_time accordingly + const banking_types: string[] = ['BANKING', 'WITHDRAW_BANKED']; + if (banking_types.includes(dto.type)) { + const hours = computeHours(toDateFromHHmm(dto.start_time), toDateFromHHmm(dto.end_time)); + const banking_shift = await this.bankingService.manageBankingHours(employee_id, hours, dto.type); + if (!banking_shift.success) return { success: false, error: banking_shift.error }; + dto.end_time = this.addHourstoDateString(dto.start_time, banking_shift.data); + } + + //api call to validate available hours in sick_hours and ajust end_time accordingly + if (dto.type === 'SICK') { + console.log('got here') + const hours = computeHours(toDateFromHHmm(dto.start_time), toDateFromHHmm(dto.end_time)); + const sick_hours = await this.sickService.takeSickLeaveHours(employee_id, hours); + if (!sick_hours.success) return { success: false, error: sick_hours.error }; + console.log(sick_hours.data) + dto.end_time = this.addHourstoDateString(dto.start_time, sick_hours.data); + } //sends data for creation of a shift in db const created_shift = await this.prisma.shifts.create({ diff --git a/src/time-and-attendance/shifts/services/shifts-delete.service.ts b/src/time-and-attendance/shifts/services/shifts-delete.service.ts index f214407..3a32464 100644 --- a/src/time-and-attendance/shifts/services/shifts-delete.service.ts +++ b/src/time-and-attendance/shifts/services/shifts-delete.service.ts @@ -1,5 +1,6 @@ import { Injectable } from "@nestjs/common"; import { Result } from "src/common/errors/result-error.factory"; +import { computeHours } from "src/common/utils/date-utils"; import { PrismaService } from "src/prisma/prisma.service"; @Injectable() @@ -9,15 +10,64 @@ export class ShiftsDeleteService { // DELETE //_________________________________________________________________ //finds shifts using shit_ids + //ajust paid-time-off banks //blocs deletion if approved async deleteShift(shift_id: number): Promise> { try { return await this.prisma.$transaction(async (tx) => { + const paid_time_off_types: string[] = ['SICK', 'VACATION', 'BANKING', 'WITHDRAW_BANKED']; const shift = await tx.shifts.findUnique({ where: { id: shift_id }, - select: { id: true, date: true, timesheet_id: true }, + select: { + id: true, + date: true, + start_time: true, + end_time: true, + timesheet: true, + bank_code: { select: { type: true } } + }, }); if (!shift) return { success: false, error: `SHIFT_NOT_FOUND` }; + const ajusted_hours = computeHours(shift.start_time, shift.end_time); + + //manage banked types, ensures update of amount of hours in bank is ajusted when a paid_time_off shift is deleted + if (paid_time_off_types.includes(shift.bank_code.type)) { + switch (shift.bank_code.type) { + case 'SICK': + await this.prisma.paidTimeOff.update({ + where: { employee_id: shift.timesheet.employee_id }, + data: { + sick_hours: { increment: ajusted_hours }, + }, + }); + break; + case 'VACATION': + await this.prisma.paidTimeOff.update({ + where: { employee_id: shift.timesheet.employee_id }, + data: { + vacation_hours: { increment: ajusted_hours }, + }, + }); + break; + case 'WITHDRAW_BANKED': + await this.prisma.paidTimeOff.update({ + where: { employee_id: shift.timesheet.employee_id }, + data: { + banked_hours: { decrement: ajusted_hours }, + }, + }); + case 'BANKING': + await this.prisma.paidTimeOff.update({ + where: { employee_id: shift.timesheet.employee_id }, + data: { + banked_hours: { increment: ajusted_hours }, + }, + }); + break; + default: + break; + } + } await tx.shifts.delete({ where: { id: shift_id } }); return { success: true, data: shift.id }; diff --git a/src/time-and-attendance/shifts/services/shifts-update-delete.service.ts b/src/time-and-attendance/shifts/services/shifts-update-delete.service.ts index 5c9d61e..3d1e1d1 100644 --- a/src/time-and-attendance/shifts/services/shifts-update-delete.service.ts +++ b/src/time-and-attendance/shifts/services/shifts-update-delete.service.ts @@ -1,4 +1,4 @@ -import { toDateFromString, toStringFromHHmm, toStringFromDate, toDateFromHHmm, overlaps } from "src/common/utils/date-utils"; +import { toDateFromString, toStringFromHHmm, toStringFromDate, toDateFromHHmm, overlaps, computeHours } from "src/common/utils/date-utils"; import { Injectable } from "@nestjs/common"; import { PrismaService } from "src/prisma/prisma.service"; @@ -9,6 +9,7 @@ import { Result } from "src/common/errors/result-error.factory"; import { shift_select } from "src/time-and-attendance/utils/selects.utils"; import { Normalized } from "src/time-and-attendance/utils/type.utils"; import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto"; +import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; @Injectable() export class ShiftsUpdateService { @@ -16,6 +17,7 @@ export class ShiftsUpdateService { private readonly prisma: PrismaService, private readonly typeResolver: BankCodesResolver, private readonly timesheetResolver: EmployeeTimesheetResolver, + private readonly emailResolver: EmailToIdResolver, ) { } async updateOneOrManyShifts(shifts: ShiftDto[], email: string): Promise> { @@ -60,8 +62,11 @@ export class ShiftsUpdateService { //_________________________________________________________________ async updateShift(dto: ShiftDto, email: string): Promise> { try { + // const paid_time_off_types: string[] = ['SICK', 'VACATION', 'BANKING', 'WITHDRAW_BANKED']; const timesheet = await this.timesheetResolver.findTimesheetIdByEmail(email, toDateFromString(dto.date)); - if (!timesheet.success) return { success: false, error: timesheet.error } + if (!timesheet.success) return { success: false, error: timesheet.error }; + const employee = await this.emailResolver.findIdByEmail(email); + if (!employee.success) return { success: false, error: employee.error }; //finds original shift const original = await this.prisma.shifts.findFirst({ @@ -78,6 +83,51 @@ export class ShiftsUpdateService { //finds bank_code_id using the type const bank_code = await this.typeResolver.findBankCodeIDByType(dto.type); if (!bank_code.success) return { success: false, error: bank_code.error }; + // const original_hours = computeHours(original.start_time, original.end_time); + // const ajusted_hours = computeHours(toDateFromHHmm(dto.start_time), toDateFromHHmm(dto.end_time)); + + // if (paid_time_off_types.includes(dto.type)) { + // switch (dto.type) { + // case 'SICK': + // if (ajusted_hours < original_hours){ + // const diff_hours = original_hours - ajusted_hours; + // await this.prisma.paidTimeOff.update({ + // where: { employee_id: employee.data }, + // data: { + // sick_hours: { decrement: diff_hours }, + // }, + // }); + // } else { + + // } + // break; + // case 'VACATION': + // await this.prisma.paidTimeOff.update({ + // where: { employee_id: shift.timesheet.employee_id }, + // data: { + // vacation_hours: { increment: ajusted_hours }, + // }, + // }); + // break; + // case 'WITHDRAW_BANKED': + // await this.prisma.paidTimeOff.update({ + // where: { employee_id: shift.timesheet.employee_id }, + // data: { + // banked_hours: { decrement: ajusted_hours }, + // }, + // }); + // case 'BANKING': + // await this.prisma.paidTimeOff.update({ + // where: { employee_id: shift.timesheet.employee_id }, + // data: { + // banked_hours: { increment: ajusted_hours }, + // }, + // }); + // break; + // default: + // break; + // } + // } //updates sent to DB const updated = await this.prisma.shifts.update({ diff --git a/src/time-and-attendance/shifts/shifts.module.ts b/src/time-and-attendance/shifts/shifts.module.ts index f5eb148..de00220 100644 --- a/src/time-and-attendance/shifts/shifts.module.ts +++ b/src/time-and-attendance/shifts/shifts.module.ts @@ -6,10 +6,11 @@ import { ShiftsCreateService } from 'src/time-and-attendance/shifts/services/shi import { ShiftsDeleteService } from 'src/time-and-attendance/shifts/services/shifts-delete.service'; import { ShiftsUpdateService } from 'src/time-and-attendance/shifts/services/shifts-update-delete.service'; import { VacationService } from 'src/time-and-attendance/domains/services/vacation.service'; +import { BankedHoursService } from 'src/time-and-attendance/domains/services/banking-hours.service'; @Module({ controllers: [ShiftController], - providers: [ShiftsCreateService, ShiftsUpdateService, ShiftsDeleteService, VacationService], + providers: [ShiftsCreateService, ShiftsUpdateService, ShiftsDeleteService, VacationService, BankedHoursService], exports: [ShiftsCreateService, ShiftsUpdateService, ShiftsDeleteService], }) export class ShiftsModule { } diff --git a/src/time-and-attendance/time-and-attendance.module.ts b/src/time-and-attendance/time-and-attendance.module.ts index 171664c..69fb117 100644 --- a/src/time-and-attendance/time-and-attendance.module.ts +++ b/src/time-and-attendance/time-and-attendance.module.ts @@ -40,6 +40,7 @@ import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-p import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service"; import { CsvGeneratorService } from "src/time-and-attendance/exports/services/csv-builder.service"; import { VacationService } from "src/time-and-attendance/domains/services/vacation.service"; +import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service"; @Module({ imports: [ @@ -82,6 +83,7 @@ import { VacationService } from "src/time-and-attendance/domains/services/vacati CsvExportService, CsvGeneratorService, VacationService, + BankedHoursService, ], exports: [TimesheetApprovalService], }) export class TimeAndAttendanceModule { }; \ No newline at end of file