From 4f0f5ae30fd124442a195372c38b229a2e898894 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Wed, 17 Dec 2025 11:28:35 -0500 Subject: [PATCH] feat(presets): added a route to apply a preset to a single day --- .../schedule-presets.controller.ts | 13 ++- .../schedule-presets-apply.service.ts | 83 ++++++++++++++----- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/time-and-attendance/schedule-presets/schedule-presets.controller.ts b/src/time-and-attendance/schedule-presets/schedule-presets.controller.ts index b78b3a6..7293438 100644 --- a/src/time-and-attendance/schedule-presets/schedule-presets.controller.ts +++ b/src/time-and-attendance/schedule-presets/schedule-presets.controller.ts @@ -52,6 +52,17 @@ export class SchedulePresetsController { async applyPresetToTimesheet( @Access('email') email: string, @Body('timesheet_id') timesheet_id: number, ) { - return await this.applyService.ApplyPresetToTimesheet(email, timesheet_id); + return await this.applyService.applyPresetToTimesheet(email, timesheet_id); + } + + @Post('apply-day-preset') + @ModuleAccessAllowed(ModulesEnum.timesheets) + async applyPresetToDay( + @Access('email') email: string, + @Body('timesheet_id') timesheet_id: number, + @Body('week_day_index') week_day_index: number, + @Body('date') date: string, + ) { + return await this.applyService.applyPresetToDay(email, timesheet_id, week_day_index, date); } } \ No newline at end of file diff --git a/src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service.ts b/src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service.ts index cb78bd4..ed471c4 100644 --- a/src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service.ts +++ b/src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service.ts @@ -1,7 +1,7 @@ import { Injectable } from "@nestjs/common"; import { PrismaService } from "src/prisma/prisma.service"; -import { is_same_week_day, sevenDaysFrom, toStringFromDate, toStringFromHHmm } from "src/common/utils/date-utils"; +import { is_same_week_day, sevenDaysFrom, toDateFromString, toStringFromDate, toStringFromHHmm } from "src/common/utils/date-utils"; import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper"; import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; import { Result } from "src/common/errors/result-error.factory"; @@ -10,6 +10,7 @@ import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shi import { timesheet_select } from "src/time-and-attendance/utils/selects.utils"; import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto"; import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto"; +import { Prisma, SchedulePresetShifts } from "@prisma/client"; @Injectable() @@ -21,7 +22,7 @@ export class SchedulePresetsApplyService { private readonly typeResolver: BankCodesResolver, ) { } - async ApplyPresetToTimesheet(email: string, timesheet_id: number): Promise> { + async applyPresetToTimesheet(email: string, timesheet_id: number): Promise> { const employee_id = await this.emailResolver.findIdByEmail(email); if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }; @@ -65,30 +66,72 @@ export class SchedulePresetsApplyService { let created_shifts: ShiftDto[] = []; for (const preset_shift of default_preset_shifts) { - const type = await this.typeResolver.findTypeByBankCodeId(preset_shift.bank_code_id); const date = dated_map.find(date => date.getUTCDay() === WEEKDAY_MAP[preset_shift.week_day]) - - if (!date) return {success: false, error: 'INVALIDE_PRESET_DATE'}; - if (!type.success) return { success: false, error: 'INVALID_PRESET_SHIFT' }; + if (!date) return { success: false, error: 'INVALID_PRESET_DATE' }; - const shift: ShiftDto = { - timesheet_id: timesheet.id, - type: type.data, - date: toStringFromDate(date), - start_time: toStringFromHHmm(preset_shift.start_time), - end_time: toStringFromHHmm(preset_shift.end_time), - is_approved: false, - is_remote: preset_shift.is_remote, - }; + const shift = await this.createShiftFromPreset(preset_shift, date!, timesheet.id) + if (!shift.success) return { success: false, error: shift.error }; - created_shifts.push(shift); - // await this.shiftService.createShift(employee_id.data, shift); + created_shifts.push(shift.data); } const response = await this.shiftService.createOneOrManyShifts(email, created_shifts); - if (response.success) + if (response.success) return { success: true, data: true }; else - return { success: false, error: 'There was an error applying presets for this week'}; + return { success: false, error: 'There was an error applying presets for this week' }; } -} \ No newline at end of file + + + async applyPresetToDay(email: string, timesheet_id: number, week_day_index: number, date: string): Promise> { + const employee_id = await this.emailResolver.findIdByEmail(email); + if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }; + + const preset_shift = await this.prisma.employees.findFirst({ + where: { id: employee_id.data, }, + select: { + schedule_preset: { + select: { + id: true, + is_default: true, + shifts: { + where: { week_day: WEEKDAY_MAP[week_day_index] }, + select: { + bank_code_id: true, + start_time: true, + end_time: true, + is_remote: true, + week_day: true, + }, + }, + }, + }, + }, + }); + if (!preset_shift) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }; + if (!preset_shift.schedule_preset) return { success: false, error: 'SCHEDULE_PRESET_NOT_FOUND' }; + + for (const shift of preset_shift.schedule_preset.shifts) { + await this.createShiftFromPreset(shift, toDateFromString(date), timesheet_id); + + } + // await this.shiftService.createShift(employee_id.data, shift); + return { success: true, data: true }; + } + + private createShiftFromPreset = async (preset: Partial, date: Date, timesheet_id: number): Promise> => { + const type = await this.typeResolver.findTypeByBankCodeId(preset.bank_code_id!); + if (!type.success) return { success: false, error: 'INVALID_PRESET_SHIFT' }; + + const shift: ShiftDto = { + timesheet_id: timesheet_id, + type: type.data, + date: toStringFromDate(date), + start_time: toStringFromHHmm(preset.start_time!), + end_time: toStringFromHHmm(preset.end_time!), + is_approved: false, + is_remote: preset.is_remote!, + }; + return { success: true, data: shift }; + } +}