diff --git a/src/time-and-attendance/time-tracker/shifts/controllers/shift.controller.ts b/src/time-and-attendance/time-tracker/shifts/controllers/shift.controller.ts index 789117f..3c796c5 100644 --- a/src/time-and-attendance/time-tracker/shifts/controllers/shift.controller.ts +++ b/src/time-and-attendance/time-tracker/shifts/controllers/shift.controller.ts @@ -22,8 +22,9 @@ export class ShiftController { } @Patch('update') - updateBatch( @Body() dtos: ShiftDto[]): Promise>{ - return this.update_delete_service.updateOneOrManyShifts(dtos); + updateBatch( @Body() dtos: ShiftDto[], @Req() req): Promise>{ + const email = req.user?.email; + return this.update_delete_service.updateOneOrManyShifts(dtos, email); } @Delete(':shift_id') diff --git a/src/time-and-attendance/time-tracker/shifts/services/shifts-update-delete.service.ts b/src/time-and-attendance/time-tracker/shifts/services/shifts-update-delete.service.ts index 726e216..d533954 100644 --- a/src/time-and-attendance/time-tracker/shifts/services/shifts-update-delete.service.ts +++ b/src/time-and-attendance/time-tracker/shifts/services/shifts-update-delete.service.ts @@ -6,21 +6,27 @@ import { Injectable } from "@nestjs/common"; import { Normalized } from "src/time-and-attendance/utils/type.utils"; import { ShiftDto } from "src/time-and-attendance/time-tracker/shifts/dtos/shift-create.dto"; import { Result } from "src/common/errors/result-error.factory"; +import { EmployeeTimesheetResolver } from "src/time-and-attendance/utils/resolve-timesheet.utils"; @Injectable() export class ShiftsUpdateDeleteService { constructor( private readonly prisma: PrismaService, private readonly typeResolver: BankCodesResolver, + private readonly timesheetResolver: EmployeeTimesheetResolver, ) { } - async updateOneOrManyShifts(shifts: ShiftDto[]): Promise> { + async updateOneOrManyShifts(shifts: ShiftDto[], email: string): Promise> { try { //verify if array is empty or not if (!Array.isArray(shifts) || shifts.length === 0) return { success: false, error: 'No data received' }; + //check for overlap inside dto objects + const overlap_check = await this.overlapChecker(shifts); + if (!overlap_check.success) return overlap_check; + //calls the update functions and await the return of successfull result or not - const results = await Promise.allSettled(shifts.map(shift => this.updateShift(shift))); + const results = await Promise.allSettled(shifts.map(shift => this.updateShift(shift, email))); //return arrays of updated shifts or errors const updated_shifts: ShiftDto[] = []; @@ -50,11 +56,14 @@ export class ShiftsUpdateDeleteService { //_________________________________________________________________ // UPDATE //_________________________________________________________________ - async updateShift(dto: ShiftDto): Promise> { + async updateShift(dto: ShiftDto, email): Promise> { try { + const timesheet = await this.timesheetResolver.findTimesheetIdByEmail(email, toDateFromString(dto.date)); + if (!timesheet.success) return { success: false, error: ' timesheet not found' } + //finds original shift const original = await this.prisma.shifts.findFirst({ - where: { id: dto.id }, + where: { id: dto.id, timesheet_id: timesheet.data.id }, select: shift_select, }); if (!original) return { success: false, error: `Shift with id: ${dto.id} not found` }; @@ -69,12 +78,10 @@ export class ShiftsUpdateDeleteService { + `end_time: ${toStringFromHHmm(normed_shift.data.end_time)},` + `date: ${toStringFromDate(normed_shift.data.date)}.` }; - const overlap_check = await this.overlapChecker(normed_shift.data); - if(!overlap_check.success) return { success: false, error: 'Invalid shift, overlaps with existing shifts'} //finds bank_code_id using the type const bank_code = await this.typeResolver.findBankCodeIDByType(dto.type); - if (!bank_code.success) return { success: false, error: 'No bank_code_id found' }; + if (!bank_code.success) return { success: false, error: bank_code.error }; //updates sent to DB const updated = await this.prisma.shifts.update({ @@ -147,28 +154,23 @@ export class ShiftsUpdateDeleteService { return { success: true, data: { date, start_time, end_time, bank_code_id: bank_code_id.data } }; } - private overlapChecker = async (dto: Normalized): Promise> => { - - const existing_shifts = await this.prisma.shifts.findMany({ - where: { date: dto.date }, - select: { id: true, date: true, start_time: true, end_time: true }, - }); - for (const existing of existing_shifts) { - const existing_start = toDateFromString(existing.start_time); - const existing_end = toDateFromString(existing.end_time); - const existing_date = toDateFromString(existing.date); - - const has_overlap = overlaps( - { start: dto.start_time, end: dto.end_time, date: dto.date }, - { start: existing_start, end: existing_end, date: existing_date }, - ); - if (has_overlap) { - return { - success: false, - error: `SHIFT_OVERLAP` - + `new shift: ${toStringFromHHmm(dto.start_time)}–${toStringFromHHmm(dto.end_time)} ` - + `existing shift: ${toStringFromHHmm(existing.start_time)}–${toStringFromHHmm(existing.end_time)} ` - + `date: ${toStringFromDate(dto.date)})`, + private overlapChecker = async (shifts: ShiftDto[]): Promise> => { + for (const shift_a of shifts) { + for(const shift_b of shifts){ + if(shift_a.date === shift_b.date){ + const has_overlap = overlaps( + { start: toHHmmFromString(shift_a.start_time), end: toHHmmFromString(shift_a.end_time) }, + { start: toDateFromString(shift_b.start_time), end: toDateFromString(shift_b.end_time) }, + ); + if (has_overlap) { + return { + success: false, + error: `SHIFT_OVERLAP` + + `new shift: ${shift_a.start_time}–${shift_a.end_time} ` + + `existing shift: ${shift_b.start_time}–${shift_b.end_time} ` + + `date: ${shift_a.date})`, + } + } } } }