refactor(schedules_employees): refactor schema relations between employees and presets

This commit is contained in:
Matthieu Haineault 2025-12-04 10:42:54 -05:00
parent 3e0e835cd8
commit d913f59eb5
19 changed files with 170 additions and 161 deletions

View File

@ -0,0 +1,20 @@
/*
Warnings:
- You are about to drop the column `employee_id` on the `schedule_presets` table. All the data in the column will be lost.
*/
-- DropForeignKey
ALTER TABLE "public"."schedule_presets" DROP CONSTRAINT "schedule_presets_employee_id_fkey";
-- DropIndex
DROP INDEX "public"."schedule_presets_employee_id_name_key";
-- AlterTable
ALTER TABLE "employees" ADD COLUMN "schedule_preset_id" INTEGER;
-- AlterTable
ALTER TABLE "schedule_presets" DROP COLUMN "employee_id";
-- AddForeignKey
ALTER TABLE "employees" ADD CONSTRAINT "employees_schedule_preset_id_fkey" FOREIGN KEY ("schedule_preset_id") REFERENCES "schedule_presets"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -47,11 +47,13 @@ model userModuleAccess {
}
model Employees {
id Int @id @default(autoincrement())
user Users @relation("UserEmployee", fields: [user_id], references: [id])
user_id String @unique @db.Uuid
supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
supervisor_id Int?
id Int @id @default(autoincrement())
user Users @relation("UserEmployee", fields: [user_id], references: [id])
user_id String @unique @db.Uuid
supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
supervisor_id Int?
schedule_preset SchedulePresets? @relation("EmployeesSchedulePreset", fields: [schedule_preset_id], references: [id])
schedule_preset_id Int?
external_payroll_id Int
company_code Int
@ -60,10 +62,9 @@ model Employees {
job_title String?
is_supervisor Boolean @default(false)
crew Employees[] @relation("EmployeeSupervisor")
timesheet Timesheets[] @relation("TimesheetEmployee")
leave_request LeaveRequests[] @relation("LeaveRequestEmployee")
schedule_presets SchedulePresets[] @relation("SchedulePreset")
crew Employees[] @relation("EmployeeSupervisor")
timesheet Timesheets[] @relation("TimesheetEmployee")
leave_request LeaveRequests[] @relation("LeaveRequestEmployee")
@@map("employees")
}
@ -149,16 +150,13 @@ model TimesheetsArchive {
}
model SchedulePresets {
id Int @id @default(autoincrement())
employee Employees @relation("SchedulePreset", fields: [employee_id], references: [id])
employee_id Int
id Int @id @default(autoincrement())
name String
is_default Boolean @default(false)
shifts SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset")
shifts SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset")
employees Employees[] @relation("EmployeesSchedulePreset")
@@unique([employee_id, name], name: "unique_preset_name_per_employee")
@@map("schedule_presets")
}

View File

@ -16,4 +16,5 @@ export class EmployeeDetailedDto {
@IsString() @IsOptional() residence?: string;
@IsInt() @IsPositive() @Type(() => Number) external_payroll_id: number;
@IsArray() @IsString({ each: true }) user_module_access: string[];
@IsInt() @IsOptional() preset_id?: number;
}

View File

@ -6,7 +6,7 @@ export class EmployeeDto {
@IsString() last_name!: string;
@IsString() @IsEmail() email!: string;
@IsString() @IsOptional() supervisor_full_name: string | '';
@IsString() company_name: number;
@IsString() company_name: string;
@IsString() @IsOptional() job_title: string;
@IsInt() @Type(()=> Number) external_payroll_id: number;
}

View File

@ -44,6 +44,7 @@ export class EmployeesCreateService {
first_work_day: dto.first_work_day,
is_supervisor: dto.is_supervisor,
supervisor_id: supervisor_id,
schedule_preset_id: dto.preset_id,
},
});
});

View File

@ -1,12 +1,14 @@
import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { PrismaService } from "src/prisma/prisma.service";
import { Modules, toStringFromBoolean } from "src/common/mappers/module-access.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { toStringFromDate } from "src/common/utils/date-utils";
import { Result } from "src/common/errors/result-error.factory";
import { toStringFromCompanyCode } from "src/identity-and-account/employees/utils/employee.utils";
import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto";
import { EmployeeDto } from "src/identity-and-account/employees/dtos/employee.dto";
import { toStringFromCompanyCode } from "src/identity-and-account/employees/utils/employee.utils";
import { PrismaService } from "src/prisma/prisma.service";
@Injectable()
export class EmployeesGetService {
@ -44,13 +46,12 @@ export class EmployeesGetService {
first_name: r.user.first_name,
last_name: r.user.last_name,
email: r.user.email,
company_name: r.company_code,
company_name: toStringFromCompanyCode(r.company_code),
job_title: r.job_title ?? '',
external_payroll_id: r.external_payroll_id,
employee_full_name: `${r.user.first_name} ${r.user.last_name}`,
supervisor_full_name: `${r.supervisor?.user.first_name} ${r.supervisor?.user.last_name}`,
})),
)
})),)
return { success: true, data: employee_list }
}
@ -148,6 +149,7 @@ export class EmployeesGetService {
last_work_day: true,
external_payroll_id: true,
is_supervisor: true,
schedule_preset_id: true,
}
});
if (!employee) return { success: false, error: `EMPLOYEE_NOT_FOUND` };

View File

@ -1,12 +1,14 @@
import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { toBooleanFromString } from "src/common/mappers/module-access.mapper";
import { toDateFromString } from "src/common/utils/date-utils";
import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto";
import { toCompanyCodeFromString } from "src/identity-and-account/employees/utils/employee.utils";
import { PrismaService } from "src/prisma/prisma.service";
import { toBooleanFromString } from "src/common/mappers/module-access.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { toDateFromString } from "src/common/utils/date-utils";
import { Result } from "src/common/errors/result-error.factory";
import { toCompanyCodeFromString } from "src/identity-and-account/employees/utils/employee.utils";
import { EmployeeDetailedDto } from "src/identity-and-account/employees/dtos/employee-detailed.dto";
@Injectable()
export class EmployeesUpdateService {
constructor(
@ -62,6 +64,8 @@ export class EmployeesUpdateService {
last_work_day: dto.last_work_day,
is_supervisor: dto.is_supervisor,
supervisor_id: supervisor_id,
schedule_preset_id: dto.preset_id,
external_payroll_id: dto.external_payroll_id,
},
});

View File

@ -1,57 +1,46 @@
import { Controller, Param, Body, Get, Post, ParseIntPipe, Delete, Patch } from "@nestjs/common";
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-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 { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
import { SchedulePresetUpdateDeleteService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update-delete.service";
import { SchedulePresetUpdateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update.service";
import { SchedulePresetDeleteService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-delete.service";
import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-get.service";
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto";
import { ModuleAccessAllowed } from "src/common/decorators/modules-guard.decorators";
import { Modules as ModulesEnum } from ".prisma/client";
import { Access } from "src/common/decorators/module-access.decorators";
@Controller('schedule-presets')
export class SchedulePresetsController {
constructor(
private readonly createService: SchedulePresetsCreateService,
private readonly getService: SchedulePresetsGetService,
private readonly applyPresetsService: SchedulePresetsApplyService,
private readonly updateDeleteService: SchedulePresetUpdateDeleteService,
private readonly createService: SchedulePresetsCreateService,
private readonly updateService: SchedulePresetUpdateService,
private readonly deleteService: SchedulePresetDeleteService,
) { }
// used to create a schedule preset
@Post('create')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async createPreset(@Access('email') email: string, @Body() dto: SchedulePresetsDto) {
return await this.createService.createPreset(email, dto);
}
//used to update an already existing schedule preset
@Patch('update/:preset_id')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async updatePreset(
@Param('preset_id', ParseIntPipe) preset_id: number, @Body() dto: SchedulePresetsDto, @Access('email') email: string) {
return await this.updateDeleteService.updatePreset(preset_id, dto, email);
}
//used to delete a schedule preset
@Delete('delete/:preset_id')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async deletePreset(
@Param('preset_id', ParseIntPipe) preset_id: number, @Access('email') email: string) {
return await this.updateDeleteService.deletePreset(preset_id, email);
}
//used to show the list of available schedule presets
@Get('find-list')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async findListById(@Access('email') email: string) {
return this.getService.getSchedulePresets(email);
async findListById() {
return this.getService.getSchedulePresets();
}
//used to apply a preset to a timesheet
@Post('apply-presets')
@ModuleAccessAllowed(ModulesEnum.timesheets)
async applyPresets(
@Body('preset') preset_id: number, @Body('start') start_date: string, @Access('email') email: string) {
return this.applyPresetsService.applyToTimesheet(email, preset_id, start_date);
@Post('create')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async createPreset(@Body() dto: SchedulePresetsDto) {
return await this.createService.createPreset(dto);
}
@Patch('update')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async updatePreset(
@Body() dto: SchedulePresetsDto) {
return await this.updateService.updatePreset(dto);
}
@Delete('delete/:id')
@ModuleAccessAllowed(ModulesEnum.employee_management)
async deletePreset(
@Param('id', ParseIntPipe) id: number) {
return await this.deleteService.deletePreset(id);
}
}

View File

@ -3,11 +3,11 @@ import { HH_MM_REGEX } from "src/common/utils/constants.utils";
import { Weekday } from "@prisma/client";
export class SchedulePresetShiftsDto {
@IsInt() preset_id!: number;
@IsInt() preset_id!: number;
@IsEnum(Weekday) week_day!: Weekday;
@IsInt() @Min(1) sort_order!: number;
@IsString() type!: string;
@IsString() type!: string;
@IsString() @Matches(HH_MM_REGEX) start_time!: string;
@IsString() @Matches(HH_MM_REGEX) end_time!: string;
@IsOptional() @IsBoolean() is_remote?: boolean;
@IsOptional() @IsBoolean() is_remote?: boolean;
}

View File

@ -1,9 +1,10 @@
import { ArrayMinSize, IsArray, IsBoolean, IsInt, IsOptional, IsString } from "class-validator";
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;
@IsBoolean() @IsOptional() is_default: boolean;
@IsArray() @ArrayMinSize(1) preset_shifts: SchedulePresetShiftsDto[];
}

View File

@ -1,25 +1,25 @@
import { Module } from "@nestjs/common";
import { SchedulePresetsController } from "src/time-and-attendance/schedule-presets/controller/schedule-presets.controller";
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-get.service";
import { SchedulePresetUpdateDeleteService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update-delete.service";
import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
import { SchedulePresetUpdateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update.service";
import { SchedulePresetDeleteService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-delete.service";
@Module({
controllers: [SchedulePresetsController],
providers: [
SchedulePresetsCreateService,
SchedulePresetUpdateDeleteService,
SchedulePresetsGetService,
SchedulePresetsApplyService,
SchedulePresetsCreateService,
SchedulePresetUpdateService,
SchedulePresetDeleteService,
],
exports: [
SchedulePresetsCreateService,
SchedulePresetUpdateDeleteService,
SchedulePresetsGetService,
SchedulePresetsApplyService,
SchedulePresetsCreateService,
SchedulePresetUpdateService,
SchedulePresetDeleteService,
],
}) export class SchedulePresetsModule { }

View File

@ -1,35 +1,30 @@
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";
import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { Result } from "src/common/errors/result-error.factory";
@Injectable()
export class SchedulePresetsCreateService {
constructor(
private readonly prisma: PrismaService,
private readonly typeResolver: BankCodesResolver,
private readonly emailResolver: EmailToIdResolver,
) { }
//_________________________________________________________________
// CREATE
//_________________________________________________________________
async createPreset(email: string, dto: SchedulePresetsDto): Promise<Result<boolean, string>> {
async createPreset(dto: SchedulePresetsDto): Promise<Result<boolean, string>> {
try {
//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 };
//validate new unique name
const existing = await this.prisma.schedulePresets.findFirst({
where: { name: dto.name, employee_id: employee_id.data },
where: { name: dto.name },
select: { name: true },
});
if (!existing) return { success: false, error: 'INVALID_SCHEDULE_PRESET' };
if (existing) return { success: false, error: 'INVALID_SCHEDULE_PRESET' };
const normalized_shifts = dto.preset_shifts.map((shift) => ({
...shift,
@ -63,14 +58,13 @@ export class SchedulePresetsCreateService {
//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 },
where: { is_default: true },
data: { is_default: false },
});
}
await tx.schedulePresets.create({
data: {
employee_id: employee_id.data,
name: dto.name,
is_default: dto.is_default ?? false,
shifts: {

View File

@ -0,0 +1,23 @@
import { Result } from "src/common/errors/result-error.factory";
import { PrismaService } from "src/prisma/prisma.service";
export class SchedulePresetDeleteService {
constructor(private readonly prisma: PrismaService) { }
//_________________________________________________________________
// DELETE
//_________________________________________________________________
async deletePreset(preset_id: number): Promise<Result<boolean, string>> {
const preset = await this.prisma.schedulePresets.findFirst({
where: { id: preset_id },
select: { id: true },
});
if (!preset) return { success: false, error: `SCHEDULE_PRESET_NOT_FOUND` };
await this.prisma.$transaction(async (tx) => {
await tx.schedulePresetShifts.deleteMany({ where: { preset_id: preset_id } });
await tx.schedulePresets.delete({ where: { id: preset_id } });
});
return { success: true, data: true };
}
}

View File

@ -1,23 +1,20 @@
import { PresetResponse, ShiftResponse } from "src/time-and-attendance/utils/type.utils";
import { PrismaService } from "src/prisma/prisma.service";
import { Injectable } from "@nestjs/common";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { PrismaService } from "src/prisma/prisma.service";
import { PresetResponse, ShiftResponse } from "src/time-and-attendance/utils/type.utils";
import { Result } from "src/common/errors/result-error.factory";
@Injectable()
export class SchedulePresetsGetService {
constructor(
private readonly prisma: PrismaService,
private readonly emailResolver: EmailToIdResolver,
) { }
async getSchedulePresets(email: string): Promise<Result<PresetResponse[], string>> {
async getSchedulePresets(): Promise<Result<PresetResponse[], string>> {
try {
const employee_id = await this.emailResolver.findIdByEmail(email);
if (!employee_id.success) return { success: false, error: employee_id.error };
const presets = await this.prisma.schedulePresets.findMany({
where: { employee_id: employee_id.data },
orderBy: [{ is_default: 'desc' }, { name: 'asc' }],
include: {
shifts: {

View File

@ -1,38 +1,32 @@
import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
import { PrismaService } from "src/prisma/prisma.service";
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto";
import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { Result } from "src/common/errors/result-error.factory";
@Injectable()
export class SchedulePresetUpdateDeleteService {
export class SchedulePresetUpdateService {
constructor(
private readonly prisma: PrismaService,
private readonly typeResolver: BankCodesResolver,
private readonly emailResolver: EmailToIdResolver,
) { }
//_________________________________________________________________
// UPDATE
//_________________________________________________________________
async updatePreset(preset_id: number, dto: SchedulePresetsDto, email: string): Promise<Result<boolean, string>> {
const employee_id = await this.emailResolver.findIdByEmail(email);
if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
//look for existing schedule_preset and return OG's data
async updatePreset(dto: SchedulePresetsDto): Promise<Result<boolean, string>> {
const existing = await this.prisma.schedulePresets.findFirst({
where: { id: preset_id, name: dto.name, employee_id: employee_id.data },
where: { id: dto.id, name: dto.name },
select: {
id: true,
is_default: true,
employee_id: true,
shifts: true,
},
});
if (!existing) return { success: false, error: `SCHEDULE_PRESET_NOT_FOUND` };
//normalized shifts start and end time to make an overlap check with other shifts
const normalized_shifts = dto.preset_shifts.map((shift) => ({
...shift,
start: toDateFromHHmm(shift.start_time),
@ -41,10 +35,8 @@ export class SchedulePresetUpdateDeleteService {
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 },
@ -52,7 +44,6 @@ export class SchedulePresetUpdateDeleteService {
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),
));
@ -61,18 +52,15 @@ export class SchedulePresetUpdateDeleteService {
}
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: existing.employee_id,
is_default: true,
NOT: { id: existing.id },
},
data: { is_default: false },
});
}
//deletes old preset shifts to make place to new ones
await tx.schedulePresetShifts.deleteMany({ where: { preset_id: existing.id } });
await tx.schedulePresets.update({
@ -82,7 +70,6 @@ export class SchedulePresetUpdateDeleteService {
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,
@ -91,7 +78,6 @@ export class SchedulePresetUpdateDeleteService {
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 },
},
}
@ -103,23 +89,4 @@ export class SchedulePresetUpdateDeleteService {
return { success: true, data: true };
}
//_________________________________________________________________
// DELETE
//_________________________________________________________________
async deletePreset(preset_id: number, email: 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 = await this.prisma.schedulePresets.findFirst({
where: { id: preset_id, employee_id: employee_id.data },
select: { id: true },
});
if (!preset) return { success: false, error: `SCHEDULE_PRESET_NOT_FOUND` };
await this.prisma.$transaction(async (tx) => {
await tx.schedulePresetShifts.deleteMany({ where: { preset_id: preset_id } });
await tx.schedulePresets.delete({ where: { id: preset_id } });
});
return { success: true, data: true };
}
}

View File

@ -19,7 +19,7 @@ export class ShiftsCreateService {
//_________________________________________________________________
// CREATE WRAPPER FUNCTION FOR ONE OR MANY INPUT
//_________________________________________________________________
async createOneOrManyShifts(email: string, shifts: ShiftDto[]): Promise<Result<ShiftDto[], string>> {
async createOneOrManyShifts(email: string, shifts: ShiftDto[]): Promise<Result<boolean, string>> {
try {
//verify if array is empty or not
if (!Array.isArray(shifts) || shifts.length === 0) return { success: false, error: 'No data received' };
@ -51,7 +51,7 @@ export class ShiftsCreateService {
if (created_shifts.length === 0) return { success: false, error: errors.join(' | ') || 'No shift created' };
// returns array of created shifts
return { success: true, data: created_shifts }
return { success: true, data: true }
} catch (error) {
return { success: false, error }
}

View File

@ -16,7 +16,7 @@ export class ShiftsUpdateDeleteService {
private readonly timesheetResolver: EmployeeTimesheetResolver,
) { }
async updateOneOrManyShifts(shifts: ShiftDto[], email: string): Promise<Result<ShiftDto[], string>> {
async updateOneOrManyShifts(shifts: ShiftDto[], email: string): Promise<Result<boolean, string>> {
try {
//verify if array is empty or not
if (!Array.isArray(shifts) || shifts.length === 0) return { success: false, error: 'No data received' };
@ -48,7 +48,7 @@ export class ShiftsUpdateDeleteService {
if (updated_shifts.length === 0) return { success: false, error: errors.join(' | ') || 'No shift updated' };
// returns array of updated shifts
return { success: true, data: updated_shifts }
return { success: true, data: true }
} catch (error) {
return { success: false, error }
}

View File

@ -1,31 +1,41 @@
import { Module } from "@nestjs/common";
import { BusinessLogicsModule } from "src/time-and-attendance/domains/business-logics.module";
import { ExpenseController } from "src/time-and-attendance/expenses/controllers/expense.controller";
import { ExpenseUpsertService } from "src/time-and-attendance/expenses/services/expense-upsert.service";
import { PayperiodsModule } from "src/time-and-attendance/pay-period/pay-periods.module";
import { ExpensesModule } from "src/time-and-attendance/expenses/expenses.module";
import { TimesheetController } from "src/time-and-attendance/timesheets/controllers/timesheet.controller";
import { TimesheetApprovalService } from "src/time-and-attendance/timesheets/services/timesheet-approval.service";
import { GetTimesheetsOverviewService } from "src/time-and-attendance/timesheets/services/timesheet-get-overview.service";
import { TimesheetsModule } from "src/time-and-attendance/timesheets/timesheets.module";
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
import { EmployeeTimesheetResolver } from "src/common/mappers/timesheet.mapper";
import { PayperiodsModule } from "src/time-and-attendance/pay-period/pay-periods.module";
import { PayPeriodsController } from "src/time-and-attendance/pay-period/controllers/pay-periods.controller";
import { ExpensesModule } from "src/time-and-attendance/expenses/expenses.module";
import { PayPeriodsQueryService } from "src/time-and-attendance/pay-period/services/pay-periods-query.service";
import { PayPeriodsCommandService } from "src/time-and-attendance/pay-period/services/pay-periods-command.service";
import { CsvExportModule } from "src/modules/exports/csv-exports.module";
import { CsvExportService } from "src/modules/exports/services/csv-exports.service";
import { CsvExportController } from "src/modules/exports/controllers/csv-exports.controller";
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 { ShiftController } from "src/time-and-attendance/shifts/controllers/shift.controller";
import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shifts-create.service";
import { ShiftsGetService } from "src/time-and-attendance/shifts/services/shifts-get.service";
import { ShiftsUpdateDeleteService } from "src/time-and-attendance/shifts/services/shifts-update-delete.service";
import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-get.service";
import { SchedulePresetsController } from "src/time-and-attendance/schedule-presets/controller/schedule-presets.controller";
import { SchedulePresetsModule } from "src/time-and-attendance/schedule-presets/schedule-presets.module";
import { SchedulePresetDeleteService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-delete.service";
import { SchedulePresetUpdateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update.service";
import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
@Module({
imports: [
BusinessLogicsModule,
@ -33,12 +43,13 @@ import { ShiftsUpdateDeleteService } from "src/time-and-attendance/shifts/servic
TimesheetsModule,
ExpensesModule,
PayperiodsModule,
CsvExportModule,
CsvExportModule,
SchedulePresetsModule,
],
controllers: [
TimesheetController,
ShiftController,
// SchedulePresetsController,
SchedulePresetsController,
ExpenseController,
PayPeriodsController,
CsvExportController,
@ -50,9 +61,10 @@ import { ShiftsUpdateDeleteService } from "src/time-and-attendance/shifts/servic
ShiftsCreateService,
ShiftsUpdateDeleteService,
ExpenseUpsertService,
// SchedulePresetsUpsertService,
SchedulePresetsGetService,
SchedulePresetsApplyService,
SchedulePresetDeleteService,
SchedulePresetUpdateService,
SchedulePresetsCreateService,
EmailToIdResolver,
BankCodesResolver,
TimesheetApprovalService,