feat(presets): added a route to apply a preset to a single day

This commit is contained in:
Matthieu Haineault 2025-12-17 11:28:35 -05:00
parent 21dfe60548
commit 4f0f5ae30f
2 changed files with 75 additions and 21 deletions

View File

@ -52,6 +52,17 @@ export class SchedulePresetsController {
async applyPresetToTimesheet( async applyPresetToTimesheet(
@Access('email') email: string, @Body('timesheet_id') timesheet_id: number, @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);
} }
} }

View File

@ -1,7 +1,7 @@
import { Injectable } from "@nestjs/common"; import { Injectable } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service"; 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 { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { Result } from "src/common/errors/result-error.factory"; 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 { timesheet_select } from "src/time-and-attendance/utils/selects.utils";
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto"; import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto"; import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
import { Prisma, SchedulePresetShifts } from "@prisma/client";
@Injectable() @Injectable()
@ -21,7 +22,7 @@ export class SchedulePresetsApplyService {
private readonly typeResolver: BankCodesResolver, private readonly typeResolver: BankCodesResolver,
) { } ) { }
async ApplyPresetToTimesheet(email: string, timesheet_id: number): Promise<Result<boolean, string>> { async applyPresetToTimesheet(email: string, timesheet_id: number): Promise<Result<boolean, string>> {
const employee_id = await this.emailResolver.findIdByEmail(email); const employee_id = await this.emailResolver.findIdByEmail(email);
if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }; if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' };
@ -65,30 +66,72 @@ export class SchedulePresetsApplyService {
let created_shifts: ShiftDto[] = []; let created_shifts: ShiftDto[] = [];
for (const preset_shift of default_preset_shifts) { 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]) const date = dated_map.find(date => date.getUTCDay() === WEEKDAY_MAP[preset_shift.week_day])
if (!date) return { success: false, error: 'INVALID_PRESET_DATE' };
if (!date) return {success: false, error: 'INVALIDE_PRESET_DATE'};
if (!type.success) return { success: false, error: 'INVALID_PRESET_SHIFT' };
const shift: ShiftDto = { const shift = await this.createShiftFromPreset(preset_shift, date!, timesheet.id)
timesheet_id: timesheet.id, if (!shift.success) return { success: false, error: shift.error };
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,
};
created_shifts.push(shift); created_shifts.push(shift.data);
// await this.shiftService.createShift(employee_id.data, shift);
} }
const response = await this.shiftService.createOneOrManyShifts(email, created_shifts); const response = await this.shiftService.createOneOrManyShifts(email, created_shifts);
if (response.success) if (response.success)
return { success: true, data: true }; return { success: true, data: true };
else 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' };
} }
}
async applyPresetToDay(email: string, timesheet_id: number, week_day_index: number, date: string): Promise<Result<boolean, string>> {
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<SchedulePresetShifts>, date: Date, timesheet_id: number): Promise<Result<ShiftDto, string>> => {
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 };
}
}