From c5c96cce22995fd2acece2fc7269b5cf091bdb2c Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Tue, 25 Nov 2025 16:32:20 -0500 Subject: [PATCH] feat(schedulePresets): ajusted the create function. added validation of the name and overlaps checking --- .../controller/schedule-presets.controller.ts | 114 ++--- .../dtos/create-schedule-preset-shifts.dto.ts | 31 +- .../dtos/create-schedule-presets.dto.ts | 18 +- .../schedule-presets-apply.service.ts | 5 +- .../schedule-presets-upsert.service.ts | 423 +++++++++--------- 5 files changed, 291 insertions(+), 300 deletions(-) diff --git a/src/time-and-attendance/schedule-presets/controller/schedule-presets.controller.ts b/src/time-and-attendance/schedule-presets/controller/schedule-presets.controller.ts index 1bc6630..3207f18 100644 --- a/src/time-and-attendance/schedule-presets/controller/schedule-presets.controller.ts +++ b/src/time-and-attendance/schedule-presets/controller/schedule-presets.controller.ts @@ -1,64 +1,66 @@ -// import { Controller, Param, Query, Body, Get, Post, ParseIntPipe, Delete, Patch, Req } from "@nestjs/common"; -// import { RolesAllowed } from "src/common/decorators/roles.decorators"; -// import { GLOBAL_CONTROLLER_ROLES, MANAGER_ROLES } from "src/common/shared/role-groupes"; -// import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto"; +import { Controller, Param, Query, Body, Get, Post, ParseIntPipe, Delete, Patch, Req } from "@nestjs/common"; +import { RolesAllowed } from "src/common/decorators/roles.decorators"; +import { GLOBAL_CONTROLLER_ROLES, MANAGER_ROLES } from "src/common/shared/role-groupes"; +import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto"; // import { SchedulePresetsUpdateDto } from "src/time-and-attendance/schedule-presets/dtos/update-schedule-presets.dto"; -// import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service"; -// import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-get.service"; -// import { SchedulePresetsUpsertService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service"; +import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service"; +import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-get.service"; +import { SchedulePresetsUpsertService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service"; -// @Controller('schedule-presets') -// @RolesAllowed(...GLOBAL_CONTROLLER_ROLES) -// export class SchedulePresetsController { -// constructor( -// private readonly upsertService: SchedulePresetsUpsertService, -// private readonly getService: SchedulePresetsGetService, -// private readonly applyPresetsService: SchedulePresetsApplyService, -// ) { } +@Controller('schedule-presets') +@RolesAllowed(...GLOBAL_CONTROLLER_ROLES) +export class SchedulePresetsController { + constructor( + private readonly upsertService: SchedulePresetsUpsertService, + private readonly getService: SchedulePresetsGetService, + private readonly applyPresetsService: SchedulePresetsApplyService, + ) { } -// //used to create a schedule preset -// @Post('create') -// @RolesAllowed(...MANAGER_ROLES) -// async createPreset(@Req() req, @Body() dto: SchedulePresetsDto) { -// const email = req.user?.email; -// return await this.upsertService.createPreset(email, dto); -// } + // used to create a schedule preset + @Post('create') + @RolesAllowed(...MANAGER_ROLES) + async createPreset(@Req() req, @Body() dto: SchedulePresetsDto) { + const email = req.user?.email; + return await this.upsertService.createPreset(email, dto); + } -// // //used to update an already existing schedule preset -// // @Patch('update/:preset_id') -// // @RolesAllowed(...MANAGER_ROLES) -// // async updatePreset( -// // @Param('preset_id', ParseIntPipe) preset_id: number, -// // @Body() dto: SchedulePresetsUpdateDto -// // ) { -// // return await this.upsertService.updatePreset(preset_id, dto); -// // } + // //used to update an already existing schedule preset + // @Patch('update/:preset_id') + // @RolesAllowed(...MANAGER_ROLES) + // async updatePreset( + // @Param('preset_id', ParseIntPipe) preset_id: number, + // @Body() dto: SchedulePresetsUpdateDto + // ) { + // return await this.upsertService.updatePreset(preset_id, dto); + // } -// //used to delete a schedule preset -// @Delete('delete/:preset_id') -// @RolesAllowed(...MANAGER_ROLES) -// async deletePreset( -// @Param('preset_id', ParseIntPipe) preset_id: number) { -// return await this.upsertService.deletePreset(preset_id); -// } + //used to delete a schedule preset + // @Delete('delete/:preset_id') + // @RolesAllowed(...MANAGER_ROLES) + // async deletePreset( + // @Param('preset_id', ParseIntPipe) preset_id: number) { + // return await this.upsertService.deletePreset(preset_id); + // } -// //used to show the list of available schedule presets -// @Get('find-list') -// @RolesAllowed(...MANAGER_ROLES) -// async findListById(@Req() req) { -// const email = req.user?.email; -// return this.getService.getSchedulePresets(email); -// } + //used to show the list of available schedule presets + @Get('find-list') + @RolesAllowed(...MANAGER_ROLES) + async findListById( + @Req() req + ) { + const email = req.user?.email; + return this.getService.getSchedulePresets(email); + } -// //used to apply a preset to a timesheet -// @Post('apply-presets') -// async applyPresets( -// @Req() req, -// @Body('preset') preset_id: number, -// @Body('start') start_date: string -// ) { -// const email = req.user?.email; -// return this.applyPresetsService.applyToTimesheet(email, preset_id, start_date); -// } -// } \ No newline at end of file + //used to apply a preset to a timesheet + @Post('apply-presets') + async applyPresets( + @Req() req, + @Body('preset') preset_id: number, + @Body('start') start_date: string + ) { + const email = req.user?.email; + return this.applyPresetsService.applyToTimesheet(email, preset_id, start_date); + } +} \ No newline at end of file diff --git a/src/time-and-attendance/schedule-presets/dtos/create-schedule-preset-shifts.dto.ts b/src/time-and-attendance/schedule-presets/dtos/create-schedule-preset-shifts.dto.ts index 34787da..117e331 100644 --- a/src/time-and-attendance/schedule-presets/dtos/create-schedule-preset-shifts.dto.ts +++ b/src/time-and-attendance/schedule-presets/dtos/create-schedule-preset-shifts.dto.ts @@ -3,28 +3,11 @@ import { HH_MM_REGEX } from "src/common/utils/constants.utils"; import { Weekday } from "@prisma/client"; export class SchedulePresetShiftsDto { - @IsEnum(Weekday) - week_day!: Weekday; - - @IsInt() - preset_id!: number; - - @IsInt() - @Min(1) - sort_order!: number; - - @IsString() - type!: string; - - @IsString() - @Matches(HH_MM_REGEX) - start_time!: string; - - @IsString() - @Matches(HH_MM_REGEX) - end_time!: string; - - @IsOptional() - @IsBoolean() - is_remote?: boolean; + @IsInt() preset_id!: number; + @IsEnum(Weekday) week_day!: Weekday; + @IsInt() @Min(1) sort_order!: number; + @IsString() type!: string; + @IsString() @Matches(HH_MM_REGEX) start_time!: string; + @IsString() @Matches(HH_MM_REGEX) end_time!: string; + @IsOptional() @IsBoolean() is_remote?: boolean; } \ No newline at end of file diff --git a/src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto.ts b/src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto.ts index 7064ee4..7c41ff0 100644 --- a/src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto.ts +++ b/src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto.ts @@ -2,18 +2,8 @@ import { ArrayMinSize, IsArray, IsBoolean, IsInt, IsOptional, IsString } from "c import { SchedulePresetShiftsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-preset-shifts.dto"; export class SchedulePresetsDto { - - @IsInt() - id!: number; - - @IsString() - name!: string; - - @IsBoolean() - @IsOptional() - is_default: boolean; - - @IsArray() - @ArrayMinSize(1) - preset_shifts: SchedulePresetShiftsDto[]; + @IsInt() id!: number; + @IsString() name!: string; + @IsBoolean() @IsOptional() is_default: boolean; + @IsArray() @ArrayMinSize(1) preset_shifts: SchedulePresetShiftsDto[]; } \ 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 bc9a51e..a6b17c0 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 @@ -9,7 +9,10 @@ import { Result } from "src/common/errors/result-error.factory"; @Injectable() export class SchedulePresetsApplyService { - constructor(private readonly prisma: PrismaService, private readonly emailResolver: EmailToIdResolver) { } + constructor( + private readonly prisma: PrismaService, + private readonly emailResolver: EmailToIdResolver + ) { } async applyToTimesheet(email: string, id: number, start_date_iso: string): Promise> { if (!DATE_ISO_FORMAT.test(start_date_iso)) return { success: false, error: 'start_date must be of format :YYYY-MM-DD' }; diff --git a/src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service.ts b/src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service.ts index 7644f90..21b5c14 100644 --- a/src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service.ts +++ b/src/time-and-attendance/schedule-presets/services/schedule-presets-upsert.service.ts @@ -1,227 +1,240 @@ -// import { Injectable, BadRequestException, NotFoundException, ConflictException } from "@nestjs/common"; -// import { Prisma, Weekday } from "@prisma/client"; -// import { PrismaService } from "src/prisma/prisma.service"; -// 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"; -// import { toHHmmFromDate, toDateFromString } from "src/common/utils/date-utils"; -// import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto"; +import { Injectable } from "@nestjs/common"; +import { Weekday } from "@prisma/client"; +import { PrismaService } from "src/prisma/prisma.service"; +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"; +import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils"; +import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto"; -// @Injectable() -// export class SchedulePresetsUpsertService { -// constructor( -// private readonly prisma: PrismaService, -// private readonly typeResolver: BankCodesResolver, -// private readonly emailResolver: EmailToIdResolver, -// ) { } -// //_________________________________________________________________ -// // CREATE -// //_________________________________________________________________ -// async createPreset(email: string, dto: SchedulePresetsDto): Promise> { -// try { -// const shifts_data = await this.normalizePresetShifts(dto); -// if (!shifts_data.success) return { success: false, error: `Employee with email: ${email} or dto not found` }; +@Injectable() +export class SchedulePresetsUpsertService { + constructor( + private readonly prisma: PrismaService, + private readonly typeResolver: BankCodesResolver, + private readonly emailResolver: EmailToIdResolver, + ) { } + //_________________________________________________________________ + // CREATE + //_________________________________________________________________ + async createPreset(email: string, dto: SchedulePresetsDto): Promise> { + //validate email and fetch employee_id + const employee_id = await this.emailResolver.findIdByEmail(email); + if (!employee_id.success) return { success: false, error: employee_id.error }; -// const employee_id = await this.emailResolver.findIdByEmail(email); -// if (!employee_id.success) return { success: false, error: employee_id.error }; + //validate new unique name + const existing = await this.prisma.schedulePresets.findFirst({ + where: { name: dto.name, employee_id: employee_id.data }, + select: { name: true }, + }); + if (!existing) return { success: false, error: 'INVALID_SCHEDULE_PRESET' }; -// const created = await this.prisma.$transaction(async (tx) => { -// if (dto.is_default) { -// await tx.schedulePresets.updateMany({ -// where: { is_default: true, employee_id: employee_id.data }, -// data: { is_default: false }, -// }); -// await tx.schedulePresets.create({ -// data: { -// id: dto.id, -// employee_id: employee_id.data, -// name: dto.name, -// is_default: !!dto.is_default, -// shifts: { create: shifts_data.data }, -// }, -// }); -// return { success: true, data: created } -// } -// }); -// return { success: true, data: created } -// } catch (error) { -// return { success: false, error: ' An error occured during create. Invalid Schedule data' }; -// } -// } + const normalized_shifts = dto.preset_shifts.map((shift) => ({ + ...shift, + start: toDateFromHHmm(shift.start_time), + end: toDateFromHHmm(shift.end_time), + })); -// //_________________________________________________________________ -// // UPDATE -// //_________________________________________________________________ -// async updatePreset(preset_id: number, dto: SchedulePresetsDto): Promise> { -// try { -// const existing = await this.prisma.schedulePresets.findFirst({ -// where: { id: preset_id }, -// select: { -// id: true, -// is_default: true, -// employee_id: true, -// }, -// }); -// if (!existing) return { success: false, error: `Preset "${dto.name}" not found` }; + for (const preset_shifts of normalized_shifts) { + for (const other_shifts of normalized_shifts) { + //skip if same object or id week_day is not the same + if (preset_shifts === other_shifts) continue; + if (preset_shifts.week_day !== other_shifts.week_day) continue; + //check overlaping possibilities + const has_overlap = overlaps( + { start: preset_shifts.start, end: preset_shifts.end }, + { start: other_shifts.start, end: other_shifts.end }, + ) + if (has_overlap) return { success: false, error: 'SCHEDULE_PRESET_OVERLAP' }; + } + } + //validate bank_code_id/type and map them + const bank_code_results = await Promise.all(dto.preset_shifts.map((shift) => + this.typeResolver.findBankCodeIDByType(shift.type), + )); + for (const result of bank_code_results) { + if (!result.success) return { success: false, error: 'INVALID_SCHEDULE_PRESET' } + } -// const shifts_data = await this.normalizePresetShifts(dto); -// if (!shifts_data.success) return { success: false, error: 'An error occured during normalization' } + await this.prisma.$transaction(async (tx) => { + //check if employee chose this preset has a default preset and ensure all others are false + if (dto.is_default) { + await tx.schedulePresets.updateMany({ + where: { employee_id: employee_id.data, is_default: true }, + data: { is_default: false }, + }); + } -// await this.prisma.$transaction(async (tx) => { -// if (typeof dto.is_default === 'boolean') { -// if (dto.is_default) { -// await tx.schedulePresets.updateMany({ -// where: { -// employee_id: existing.employee_id, -// is_default: true, -// NOT: { id: existing.id }, -// }, -// data: { is_default: false }, -// }); -// } -// await tx.schedulePresets.update({ -// where: { id: existing.id }, -// data: { -// is_default: dto.is_default, -// name: dto.name, -// }, -// }); -// } -// if (shifts_data.data.length <= 0) return { success: false, error: 'Preset shifts to update not found' }; + await tx.schedulePresets.create({ + data: { + employee_id: employee_id.data, + name: dto.name, + is_default: dto.is_default ?? false, + shifts: { + create: dto.preset_shifts.map((shift, index) => { + //validated bank_codes sent as a Result Array to access its data + const result = bank_code_results[index] as { success: true, data: number }; + return { + week_day: shift.week_day, + sort_order: shift.sort_order, + start_time: toDateFromHHmm(shift.start_time), + end_time: toDateFromHHmm(shift.end_time), + is_remote: shift.is_remote ?? false, + bank_code: { + //connect uses the FK links to set the bank_code_id + connect: { id: result.data }, + }, + } + }), + }, + }, + }); + }); + return { success: true, data: true } + } -// await tx.schedulePresetShifts.deleteMany({ where: { preset_id: existing.id } }); + // //_________________________________________________________________ + // // UPDATE + // //_________________________________________________________________ + // async updatePreset(preset_id: number, dto: SchedulePresetsDto): Promise> { + // try { + // const existing = await this.prisma.schedulePresets.findFirst({ + // where: { id: preset_id }, + // select: { + // id: true, + // is_default: true, + // employee_id: true, + // }, + // }); + // if (!existing) return { success: false, error: `Preset "${dto.name}" not found` }; -// try { -// const create_many_data: Result = -// shifts_data.data.map((shift) => { -// if (!shift.bank_code || !('connect' in shift.bank_code) || typeof shift.bank_code.connect?.id !== 'number') { -// return { success: false, error: `Bank code is required for updates( ${shift.week_day}, ${shift.sort_order})`} -// } -// const bank_code_id = shift.bank_code.connect.id; -// return { -// preset_id: existing.id, -// week_day: shift.week_day, -// sort_order: shift.sort_order, -// start_time: shift.start_time, -// end_time: shift.end_time, -// is_remote: shift.is_remote ?? false, -// bank_code_id: bank_code_id, -// }; -// }); -// if(!create_many_data.success) return { success: false, error: 'Invalid data'} -// await tx.schedulePresetShifts.createMany({ data: create_many_data.data }); + // const shifts_data = await this.normalizePresetShifts(dto); + // if (!shifts_data.success) return { success: false, error: 'An error occured during normalization' } -// return { success: true, data: create_many_data } -// } catch (error) { -// return { success: false, error: 'An error occured. Invalid data detected. ' }; -// } -// }); + // await this.prisma.$transaction(async (tx) => { + // if (typeof dto.is_default === 'boolean') { + // if (dto.is_default) { + // await tx.schedulePresets.updateMany({ + // where: { + // employee_id: existing.employee_id, + // is_default: true, + // NOT: { id: existing.id }, + // }, + // data: { is_default: false }, + // }); + // } + // await tx.schedulePresets.update({ + // where: { id: existing.id }, + // data: { + // is_default: dto.is_default, + // name: dto.name, + // }, + // }); + // } + // if (shifts_data.data.length <= 0) return { success: false, error: 'Preset shifts to update not found' }; -// const saved = await this.prisma.schedulePresets.findUnique({ -// where: { id: existing.id }, -// include: { -// shifts: { -// orderBy: [{ week_day: 'asc' }, { sort_order: 'asc' }], -// include: { bank_code: { select: { type: true } } }, -// } -// }, -// }); -// if (!saved) return { success: false, error: `Preset with id: ${existing.id} not found` }; + // await tx.schedulePresetShifts.deleteMany({ where: { preset_id: existing.id } }); -// const response_dto: SchedulePresetsDto = { -// id: saved.id, -// name: saved.name, -// is_default: saved.is_default, -// preset_shifts: saved.shifts.map((shift) => ({ -// preset_id: shift.preset_id, -// week_day: shift.week_day, -// sort_order: shift.sort_order, -// type: shift.bank_code.type, -// start_time: toHHmmFromDate(shift.start_time), -// end_time: toHHmmFromDate(shift.end_time), -// is_remote: shift.is_remote, -// })), -// }; + // try { + // const create_many_data: Result = + // shifts_data.data.map((shift) => { + // if (!shift.bank_code || !('connect' in shift.bank_code) || typeof shift.bank_code.connect?.id !== 'number') { + // return { success: false, error: `Bank code is required for updates( ${shift.week_day}, ${shift.sort_order})`} + // } + // const bank_code_id = shift.bank_code.connect.id; + // return { + // preset_id: existing.id, + // week_day: shift.week_day, + // sort_order: shift.sort_order, + // start_time: shift.start_time, + // end_time: shift.end_time, + // is_remote: shift.is_remote ?? false, + // bank_code_id: bank_code_id, + // }; + // }); + // if(!create_many_data.success) return { success: false, error: 'Invalid data'} + // await tx.schedulePresetShifts.createMany({ data: create_many_data.data }); -// return { success: true, data: response_dto }; -// } catch (error) { -// return { success: false, error: 'An error occured during update. Invalid data' } -// } -// } + // return { success: true, data: create_many_data } + // } catch (error) { + // return { success: false, error: 'An error occured. Invalid data detected. ' }; + // } + // }); -// //_________________________________________________________________ -// // DELETE -// //_________________________________________________________________ -// async deletePreset(preset_id: number): Promise> { -// try { -// await this.prisma.$transaction(async (tx) => { -// const preset = await tx.schedulePresets.findFirst({ -// where: { id: preset_id }, -// select: { id: true }, -// }); -// if (!preset) return { success: false, error: `Preset with id ${preset_id} not found` }; -// await tx.schedulePresets.delete({ where: { id: preset_id } }); + // const saved = await this.prisma.schedulePresets.findUnique({ + // where: { id: existing.id }, + // include: { + // shifts: { + // orderBy: [{ week_day: 'asc' }, { sort_order: 'asc' }], + // include: { bank_code: { select: { type: true } } }, + // } + // }, + // }); + // if (!saved) return { success: false, error: `Preset with id: ${existing.id} not found` }; -// return { success: true }; -// }); -// return { success: true, data: preset_id }; + // const response_dto: SchedulePresetsDto = { + // id: saved.id, + // name: saved.name, + // is_default: saved.is_default, + // preset_shifts: saved.shifts.map((shift) => ({ + // preset_id: shift.preset_id, + // week_day: shift.week_day, + // sort_order: shift.sort_order, + // type: shift.bank_code.type, + // start_time: toHHmmFromDate(shift.start_time), + // end_time: toHHmmFromDate(shift.end_time), + // is_remote: shift.is_remote, + // })), + // }; -// } catch (error) { -// return { success: false, error: `Preset schedule with id ${preset_id} not found` }; -// } -// } + // return { success: true, data: response_dto }; + // } catch (error) { + // return { success: false, error: 'An error occured during update. Invalid data' } + // } + // } -// //PRIVATE HELPERS + // //_________________________________________________________________ + // // DELETE + // //_________________________________________________________________ + // async deletePreset(preset_id: number): Promise> { + // try { + // await this.prisma.$transaction(async (tx) => { + // const preset = await tx.schedulePresets.findFirst({ + // where: { id: preset_id }, + // select: { id: true }, + // }); + // if (!preset) return { success: false, error: `Preset with id ${preset_id} not found` }; + // await tx.schedulePresets.delete({ where: { id: preset_id } }); -// //resolve bank_code_id using type and convert hours to TIME and valid shifts end/start -// private async normalizePresetShifts( -// dto: SchedulePresetsDto -// ): Promise> { -// if (!dto.preset_shifts?.length) return { success: false, error: `Empty or preset shifts not found` } + // return { success: true }; + // }); + // return { success: true, data: preset_id }; -// const types = Array.from(new Set(dto.preset_shifts.map((shift) => shift.type))); -// const bank_code_set = new Map(); + // } catch (error) { + // return { success: false, error: `Preset schedule with id ${preset_id} not found` }; + // } + // } -// for (const type of types) { -// const bank_code = await this.typeResolver.findIdAndModifierByType(type); -// if (!bank_code.success) return { success: false, error: 'Bank_code not found' } -// bank_code_set.set(type, bank_code.data.id); -// } + // //PRIVATE HELPERS -// const pair_set = new Set(); -// for (const shift of dto.preset_shifts) { -// const key = `${shift.week_day}:${shift.sort_order}`; -// if (pair_set.has(key)) { -// return { success: false, error: `Duplicate shift for day/order (${shift.week_day}, ${shift.sort_order})` } -// } -// pair_set.add(key); -// } + //resolve bank_code_id using type and convert hours to TIME and valid shifts end/start + // private async normalizePresetShifts(preset_shift: SchedulePresetShiftsDto, schedul_preset: SchedulePresetsDto): Promise> { -// const items = await dto.preset_shifts.map((shift) => { -// try { -// const bank_code_id = bank_code_set.get(shift.type); -// if (!bank_code_id) return { success: false, error: `Bank code not found for type ${shift.type}` } -// if (!shift.start_time || !shift.end_time) { -// return { success: false, error: `start_time and end_time are required for (${shift.week_day}, ${shift.sort_order})` } -// } -// const start = toDateFromString(shift.start_time); -// const end = toDateFromString(shift.end_time); -// if (end.getTime() <= start.getTime()) { -// return { success: false, error: `end_time must be > start_time ( day: ${shift.week_day}, order: ${shift.sort_order})` } -// } -// return { -// sort_order: shift.sort_order, -// start_time: start, -// end_time: end, -// is_remote: !!shift.is_remote, -// week_day: shift.week_day as Weekday, -// bank_code: { connect: { id: bank_code_id } }, -// } + // const bank_code = await this.typeResolver.findIdAndModifierByType(preset_shift.type); + // if (!bank_code.success) return { success: false, error: 'INVALID_SCHEDULE_PRESET_SHIFT' }; -// } catch (error) { -// return { success: false, error: '' } -// } -// }); -// return { success: true, data: items}; -// } -// } + // const start = await toDateFromHHmm(preset_shift.start_time); + // const end = await toDateFromHHmm(preset_shift.end_time); + + // //TODO: add a way to fetch + + + // const normalized_preset_shift:Normalized = { + // date: , + // start_time : start, + // end_time: end, + // bank_code_id: bank_code.data.id, + // } + // return { success: true data: normalized_preset_shift } + // } +}