feat(schedule-presets): added a service that applies a preset to an existing timesheet. did some cleaning in utils and dtos
This commit is contained in:
parent
74e16d7960
commit
b6132c8b35
|
|
@ -286,6 +286,30 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/schedule-presets/apply-preset": {
|
||||
"post": {
|
||||
"operationId": "SchedulePresetsController_applyPresetToTimesheet",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"SchedulePresets"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/expense/create": {
|
||||
"post": {
|
||||
"operationId": "ExpenseController_create",
|
||||
|
|
|
|||
|
|
@ -167,13 +167,12 @@ model SchedulePresetShifts {
|
|||
bank_code BankCodes @relation("SchedulePresetShiftsBankCodes", fields: [bank_code_id], references: [id])
|
||||
bank_code_id Int
|
||||
|
||||
sort_order Int
|
||||
start_time DateTime @db.Time(0)
|
||||
end_time DateTime @db.Time(0)
|
||||
is_remote Boolean @default(false)
|
||||
week_day Weekday
|
||||
|
||||
@@unique([preset_id, week_day, sort_order], name: "unique_preset_shift_per_day_order")
|
||||
@@unique([preset_id, week_day], name: "unique_preset_shift_per_day")
|
||||
@@index([preset_id, week_day])
|
||||
@@map("schedule_preset_shifts")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,29 @@
|
|||
import { Weekday } from "@prisma/client";
|
||||
import { ANCHOR_ISO, MS_PER_DAY, PERIODS_PER_YEAR, PERIOD_DAYS } from "src/common/utils/constants.utils";
|
||||
import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
|
||||
|
||||
//lenght of a shift, rouded to nearest 'x' minute
|
||||
export function computeHours(start: Date, end: Date, roundToMinutes?: number): number {
|
||||
const diffMs = end.getTime() - start.getTime();
|
||||
const totalMinutes = diffMs / 60000;
|
||||
const minutes = roundToMinutes ?
|
||||
Math.round(totalMinutes / roundToMinutes) * roundToMinutes :
|
||||
totalMinutes;
|
||||
Math.round(totalMinutes / roundToMinutes) * roundToMinutes :
|
||||
totalMinutes;
|
||||
return +(minutes / 60).toFixed(2);
|
||||
}
|
||||
|
||||
//round the amount of hours to quarter
|
||||
export function roundToQuarterHour(hours: number): number {
|
||||
return Math.round(hours *4) / 4;
|
||||
return Math.round(hours * 4) / 4;
|
||||
}
|
||||
|
||||
//fetch firts day of the week (Sunday)
|
||||
export function getWeekStart(date:Date, firstDayOfWeek = 0): Date {
|
||||
// fetch firts day of the week (Sunday)
|
||||
export function getWeekStart(date: Date, firstDayOfWeek = 0): Date {
|
||||
const d = new Date(date);
|
||||
const day = d.getDay();
|
||||
const diff = (day < firstDayOfWeek ? 7 : 0) + (day - firstDayOfWeek);
|
||||
d.setDate(d.getDate() - diff);
|
||||
d.setHours(0,0,0,0);
|
||||
d.setHours(0, 0, 0, 0);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
|
@ -28,32 +31,29 @@ export function getWeekStart(date:Date, firstDayOfWeek = 0): Date {
|
|||
export function getWeekEnd(startOfWeek: Date): Date {
|
||||
const d = new Date(startOfWeek);
|
||||
d.setDate(d.getDate() + 6);
|
||||
d.setHours(23,59,59,999);
|
||||
d.setHours(23, 59, 59, 999);
|
||||
return d;
|
||||
}
|
||||
|
||||
//returns january 1st of the selected date's year
|
||||
export function getYearStart(date:Date): Date {
|
||||
return new Date(date.getFullYear(),0,1,0,0,0,0);
|
||||
export function getYearStart(date: Date): Date {
|
||||
return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
//to be used to calculate breaks time
|
||||
export function hoursBetweenSameDay(day: Date, startTime: Date, endTime: Date): number {
|
||||
const start = new Date(day); start.setHours(startTime.getHours(),
|
||||
startTime.getMinutes(),
|
||||
startTime.getSeconds(),
|
||||
startTime.getMilliseconds());
|
||||
const end = new Date(day); end.setHours(endTime.getHours(),
|
||||
endTime.getMinutes(),
|
||||
endTime.getSeconds(),
|
||||
endTime.getMilliseconds());
|
||||
const ms = Math.max(0, end.getTime() - start.getTime());
|
||||
return ms / 3_600_000; // decimal hours
|
||||
const start = new Date(day); start.setHours(startTime.getHours(),
|
||||
startTime.getMinutes(),
|
||||
startTime.getSeconds(),
|
||||
startTime.getMilliseconds());
|
||||
const end = new Date(day); end.setHours(endTime.getHours(),
|
||||
endTime.getMinutes(),
|
||||
endTime.getSeconds(),
|
||||
endTime.getMilliseconds());
|
||||
const ms = Math.max(0, end.getTime() - start.getTime());
|
||||
return ms / 3_600_000; // decimal hours
|
||||
}
|
||||
|
||||
import { BadRequestException } from "@nestjs/common";
|
||||
import { ANCHOR_ISO, MS_PER_DAY, PERIODS_PER_YEAR, PERIOD_DAYS } from "src/common/utils/constants.utils";
|
||||
|
||||
//ensures the week starts from sunday
|
||||
export function weekStartSunday(date_local: Date): Date {
|
||||
const start_date = new Date();
|
||||
|
|
@ -140,39 +140,10 @@ export function listPayYear(pay_year: number, anchorISO = ANCHOR_ISO) {
|
|||
return Array.from({ length: PERIODS_PER_YEAR }, (_, i) => computePeriod(pay_year, i + 1, anchorISO));
|
||||
}
|
||||
|
||||
//checks for shifts overlaping one another
|
||||
export const overlaps = (a: { start: Date; end: Date, date?: Date; }, b: { start: Date; end: Date; date?: Date; }) =>
|
||||
((a.date?.getTime() === b.date?.getTime()) && !(a.end <= b.start || a.start >= b.end));
|
||||
|
||||
|
||||
export const hhmmFromLocal = (d: Date) =>
|
||||
`${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
|
||||
|
||||
export const toDateOnly = (s: string): Date => {
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(s)) {
|
||||
const y = Number(s.slice(0,4));
|
||||
const m = Number(s.slice(5,7)) - 1;
|
||||
const d = Number(s.slice(8,10));
|
||||
return new Date(y, m, d, 0, 0, 0, 0);
|
||||
}
|
||||
const dt = new Date(s);
|
||||
if (Number.isNaN(dt.getTime())) throw new BadRequestException(`Invalid date: ${s}`);
|
||||
return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate(), 0,0,0,0);
|
||||
};
|
||||
|
||||
// export const toStringFromDate = (d: Date) =>
|
||||
// `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
|
||||
|
||||
|
||||
export const toISOtoDateOnly = (iso: string): Date => {
|
||||
const date = new Date(iso);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
throw new BadRequestException(`Invalid date: ${iso}`);
|
||||
}
|
||||
date.setHours(0, 0, 0, 0);
|
||||
return date;
|
||||
};
|
||||
|
||||
export const toISODateKey = (date: Date): string => date.toISOString().slice(0, 10);
|
||||
|
||||
export const normalizeDates = (dates: string[]): string[] =>
|
||||
Array.from(new Set(dates.map((iso) => toISODateKey(toISOtoDateOnly(iso)))));
|
||||
export const is_same_week_day = (date: Date, week_day: Weekday): boolean => {
|
||||
return date.getUTCDay() !== WEEKDAY_MAP[week_day];
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import { IsBoolean, IsEnum, IsInt, IsOptional, IsString, Matches, Min } from "class-validator";
|
||||
import { HH_MM_REGEX } from "src/common/utils/constants.utils";
|
||||
import { Weekday } from "@prisma/client";
|
||||
|
||||
export class SchedulePresetShiftsDto {
|
||||
@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;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
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;
|
||||
@IsArray() @ArrayMinSize(1) preset_shifts: SchedulePresetShiftsDto[];
|
||||
}
|
||||
|
|
@ -4,10 +4,12 @@ import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-p
|
|||
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 { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/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";
|
||||
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
|
||||
|
||||
@Controller('schedule-presets')
|
||||
export class SchedulePresetsController {
|
||||
|
|
@ -16,6 +18,7 @@ export class SchedulePresetsController {
|
|||
private readonly createService: SchedulePresetsCreateService,
|
||||
private readonly updateService: SchedulePresetUpdateService,
|
||||
private readonly deleteService: SchedulePresetDeleteService,
|
||||
private readonly applyService: SchedulePresetsApplyService,
|
||||
) { }
|
||||
|
||||
@Get('find-list')
|
||||
|
|
@ -43,4 +46,12 @@ export class SchedulePresetsController {
|
|||
@Param('id', ParseIntPipe) id: number) {
|
||||
return await this.deleteService.deletePreset(id);
|
||||
}
|
||||
|
||||
@Post('apply-preset')
|
||||
@ModuleAccessAllowed(ModulesEnum.timesheets)
|
||||
async applyPresetToTimesheet(
|
||||
@Access('email') email: string, @Body() timesheet_id: number,
|
||||
) {
|
||||
return await this.applyService.ApplyPresetToTimesheet(email, timesheet_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import { Weekday } from "@prisma/client";
|
||||
import { ArrayMinSize, IsArray, IsBoolean, IsEnum, IsInt, IsOptional, IsString, Matches, Min } from "class-validator";
|
||||
import { HH_MM_REGEX } from "src/common/utils/constants.utils";
|
||||
|
||||
export class SchedulePresetsDto {
|
||||
@IsInt() id!: number;
|
||||
@IsString() name!: string;
|
||||
@IsBoolean() @IsOptional() is_default: boolean;
|
||||
@IsArray() @ArrayMinSize(1) preset_shifts: SchedulePresetShiftsDto[];
|
||||
}
|
||||
|
||||
export class SchedulePresetShiftsDto {
|
||||
@IsInt() preset_id!: number;
|
||||
@IsEnum(Weekday) week_day!: Weekday;
|
||||
@IsString() type!: string;
|
||||
@IsString() @Matches(HH_MM_REGEX) start_time!: string;
|
||||
@IsString() @Matches(HH_MM_REGEX) end_time!: string;
|
||||
@IsOptional() @IsBoolean() is_remote?: boolean;
|
||||
}
|
||||
|
||||
export const WEEKDAY_MAP: Record<Weekday, number> = {
|
||||
SUN: 0,
|
||||
MON: 1,
|
||||
TUE: 2,
|
||||
WED: 3,
|
||||
THU: 4,
|
||||
FRI: 5,
|
||||
SAT: 6,
|
||||
};
|
||||
|
|
@ -7,6 +7,9 @@ import { SchedulePresetsGetService } from "src/time-and-attendance/schedule-pres
|
|||
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";
|
||||
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
|
||||
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||
import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shifts-create.service";
|
||||
|
||||
|
||||
|
||||
|
|
@ -17,6 +20,9 @@ import { SchedulePresetDeleteService } from "src/time-and-attendance/schedule-pr
|
|||
SchedulePresetsCreateService,
|
||||
SchedulePresetUpdateService,
|
||||
SchedulePresetDeleteService,
|
||||
SchedulePresetsApplyService,
|
||||
EmailToIdResolver,
|
||||
ShiftsCreateService,
|
||||
BankCodesResolver,
|
||||
],
|
||||
exports: [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
import { Injectable } from "@nestjs/common";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
|
||||
import { is_same_week_day, sevenDaysFrom, toStringFromDate } 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";
|
||||
|
||||
import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shifts-create.service";
|
||||
import { timesheet_select } from "src/time-and-attendance/utils/selects.utils";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class SchedulePresetsApplyService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly emailResolver: EmailToIdResolver,
|
||||
private readonly shiftService: ShiftsCreateService,
|
||||
private readonly typeResolver: BankCodesResolver,
|
||||
) { }
|
||||
|
||||
async ApplyPresetToTimesheet(email: string, timesheet_id: number): Promise<Result<boolean, string>> {
|
||||
const employee_id = await this.emailResolver.findIdByEmail(email);
|
||||
if (!employee_id.success) return { success: false, error: 'EMPLOYEE_NOT_FOUND' };
|
||||
|
||||
const employee_default_schedule_preset = await this.prisma.employees.findFirst({
|
||||
where: { id: employee_id.data },
|
||||
select: {
|
||||
schedule_preset: {
|
||||
select: {
|
||||
id: true,
|
||||
is_default: true,
|
||||
shifts: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!employee_default_schedule_preset) return { success: false, error: 'EMPLOYEE_NOT_FOUND' };
|
||||
if (!employee_default_schedule_preset.schedule_preset) return { success: false, error: 'SCHEDULE_PRESET_NOT_FOUND' };
|
||||
|
||||
const default_preset_shifts = await this.prisma.schedulePresetShifts.findMany({
|
||||
where: { preset_id: employee_default_schedule_preset.schedule_preset.id },
|
||||
select: {
|
||||
bank_code_id: true,
|
||||
start_time: true,
|
||||
end_time: true,
|
||||
is_remote: true,
|
||||
week_day: true,
|
||||
},
|
||||
});
|
||||
if (default_preset_shifts.length <= 0) return { success: false, error: 'INVALID_SCHEDULE_PRESET' };
|
||||
|
||||
const timesheet = await this.prisma.timesheets.findUnique({
|
||||
where: { id: timesheet_id },
|
||||
select: timesheet_select,
|
||||
});
|
||||
if (!timesheet) return { success: false, error: 'TIMESHEET_NOT_FOUND' };
|
||||
if (timesheet.is_approved) return { success: false, error: 'INVALID_TIMESHEET' };
|
||||
if (timesheet.shift.length > 0) return { success: false, error: 'INVALID_TIMESHEET' };
|
||||
|
||||
const dated_map = await sevenDaysFrom(timesheet.start_date);
|
||||
|
||||
for (const date of dated_map) {
|
||||
for (const preset_shift of default_preset_shifts) {
|
||||
if (!is_same_week_day(date, preset_shift.week_day)) continue;
|
||||
|
||||
const type = await this.typeResolver.findTypeByBankCodeId(preset_shift.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: toStringFromDate(preset_shift.start_time),
|
||||
end_time: toStringFromDate(preset_shift.end_time),
|
||||
is_approved: false,
|
||||
is_remote: preset_shift.is_remote,
|
||||
};
|
||||
await this.shiftService.createShift(employee_id.data, shift);
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true, data: true };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import { Injectable } from "@nestjs/common";
|
|||
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
|
||||
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto";
|
||||
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
|
||||
|
||||
import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
|
||||
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
|
||||
|
|
@ -73,7 +73,6 @@ export class SchedulePresetsCreateService {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export class SchedulePresetsGetService {
|
|||
orderBy: [{ is_default: 'desc' }, { name: 'asc' }],
|
||||
include: {
|
||||
shifts: {
|
||||
orderBy: [{ week_day: 'asc' }, { sort_order: 'asc' }],
|
||||
orderBy: [{ week_day: 'asc' }],
|
||||
include: { bank_code: { select: { type: true } } },
|
||||
},
|
||||
},
|
||||
|
|
@ -31,7 +31,6 @@ export class SchedulePresetsGetService {
|
|||
is_default: preset.is_default,
|
||||
shifts: preset.shifts.map<ShiftResponse>((shift) => ({
|
||||
week_day: shift.week_day,
|
||||
sort_order: shift.sort_order,
|
||||
start_time: hhmm(shift.start_time),
|
||||
end_time: hhmm(shift.end_time),
|
||||
is_remote: shift.is_remote,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Injectable } from "@nestjs/common";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
|
||||
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/dtos/create-schedule-presets.dto";
|
||||
import { SchedulePresetsDto } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
|
||||
|
||||
import { overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
|
||||
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
|
||||
|
|
@ -73,7 +73,6 @@ export class SchedulePresetUpdateService {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
|||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
import { toStringFromHHmm, toStringFromDate, toDateFromString, overlaps, toDateFromHHmm } from "src/common/utils/date-utils";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift-create.dto";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
||||
|
||||
@Injectable()
|
||||
export class ShiftsCreateService {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Result } from "src/common/errors/result-error.factory";
|
|||
|
||||
import { shift_select } from "src/time-and-attendance/utils/selects.utils";
|
||||
import { Normalized } from "src/time-and-attendance/utils/type.utils";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift-create.dto";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
||||
|
||||
@Injectable()
|
||||
export class ShiftsUpdateService {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Body, Controller, Delete, Param, Patch, Post } from "@nestjs/common";
|
||||
import { Modules as ModulesEnum } from ".prisma/client";
|
||||
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift-create.dto";
|
||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
||||
import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shifts-create.service";
|
||||
import { ShiftsUpdateService } from "src/time-and-attendance/shifts/services/shifts-update-delete.service";
|
||||
import { ShiftsDeleteService } from "src/time-and-attendance/shifts/services/shifts-delete.service";
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
import { IsBoolean, IsInt, IsOptional, IsString, MaxLength } from "class-validator";
|
||||
|
||||
export class ShiftDto {
|
||||
@IsInt() @IsOptional() id: number;
|
||||
@IsInt() @IsOptional() id?: number;
|
||||
@IsInt() timesheet_id!: number;
|
||||
@IsString() type!: string;
|
||||
|
||||
@IsString() date!: string;
|
||||
@IsString() start_time!: string;
|
||||
@IsString() end_time!: string;
|
||||
|
||||
@IsBoolean() is_approved!: boolean;
|
||||
@IsBoolean() is_remote!: boolean;
|
||||
|
||||
@IsOptional() @IsString() @MaxLength(280) comment?: string;
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ import { SchedulePresetsModule } from "src/time-and-attendance/schedule-presets/
|
|||
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";
|
||||
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -65,6 +66,7 @@ import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-p
|
|||
ExpenseUpsertService,
|
||||
SchedulePresetsGetService,
|
||||
SchedulePresetDeleteService,
|
||||
SchedulePresetsApplyService,
|
||||
SchedulePresetUpdateService,
|
||||
SchedulePresetsCreateService,
|
||||
EmailToIdResolver,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ export type NormalizedLeaveRequest = {
|
|||
|
||||
export type ShiftResponse = {
|
||||
week_day: string;
|
||||
sort_order: number;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
is_remote: boolean;
|
||||
|
|
@ -40,8 +39,3 @@ export type PresetResponse = {
|
|||
shifts: ShiftResponse[];
|
||||
}
|
||||
|
||||
export type ApplyResult = {
|
||||
timesheet_id: number;
|
||||
created: number;
|
||||
skipped: number;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user