diff --git a/src/modules/employees/employees.module.ts b/src/modules/employees/employees.module.ts index 66a14a7..0f0be93 100644 --- a/src/modules/employees/employees.module.ts +++ b/src/modules/employees/employees.module.ts @@ -5,7 +5,8 @@ import { EmployeesArchivalService } from './services/employees-archival.service' import { SharedModule } from '../shared/shared.module'; @Module({ - controllers: [EmployeesController, SharedModule], + imports: [SharedModule], + controllers: [EmployeesController], providers: [EmployeesService, EmployeesArchivalService], exports: [EmployeesService, EmployeesArchivalService], }) diff --git a/src/modules/expenses/services/expenses-query.service.ts b/src/modules/expenses/services/expenses-query.service.ts index 18be585..9a56fa8 100644 --- a/src/modules/expenses/services/expenses-query.service.ts +++ b/src/modules/expenses/services/expenses-query.service.ts @@ -1,8 +1,8 @@ import { Injectable, NotFoundException } from "@nestjs/common"; import { PrismaService } from "src/prisma/prisma.service"; import { DayExpensesDto as ExpenseListResponseDto, ExpenseDto } from "src/modules/timesheets/dtos/timesheet-period.dto"; -import { round2, toUTCDateOnly } from "src/modules/timesheets/timesheet.helpers"; -import { EXPENSE_TYPES } from "src/modules/timesheets/timesheet.types"; +import { round2, toUTCDateOnly } from "src/modules/timesheets/utils-helpers-others/timesheet.helpers"; +import { EXPENSE_TYPES } from "src/modules/timesheets/utils-helpers-others/timesheet.types"; import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; @Injectable() diff --git a/src/modules/shared/constants/date-time.constant.ts b/src/modules/shared/constants/date-time.constant.ts new file mode 100644 index 0000000..9cf4f96 --- /dev/null +++ b/src/modules/shared/constants/date-time.constant.ts @@ -0,0 +1,2 @@ +export const MS_PER_DAY = 86_400_000; +export const MS_PER_HOUR = 3_600_000; \ No newline at end of file diff --git a/src/modules/shared/selects/employees.select.ts b/src/modules/shared/selects/employees.select.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/shared/selects/timesheets.select.ts b/src/modules/shared/selects/timesheets.select.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/timesheets/controllers/timesheets.controller.ts b/src/modules/timesheets/controllers/timesheets.controller.ts index 98350ab..4abca29 100644 --- a/src/modules/timesheets/controllers/timesheets.controller.ts +++ b/src/modules/timesheets/controllers/timesheets.controller.ts @@ -5,7 +5,8 @@ import { RolesAllowed } from "src/common/decorators/roles.decorators"; import { Roles as RoleEnum } from '.prisma/client'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { TimesheetsCommandService } from '../services/timesheets-command.service'; -import { TimesheetDto, TimesheetPeriodDto } from '../dtos/timesheet-period.dto'; +import { TimesheetMap } from '../utils-helpers-others/timesheet.types'; +import { TimesheetPeriodDto } from '../dtos/timesheet-period.dto'; @ApiTags('Timesheets') @@ -33,7 +34,7 @@ export class TimesheetsController { async getByEmail( @Param('email') email: string, @Query('offset') offset?: string, - ): Promise { + ): Promise { const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; return this.timesheetsQuery.getTimesheetByEmail(email, week_offset); } @@ -43,37 +44,8 @@ export class TimesheetsController { @Param('email') email: string, @Body() dto: CreateWeekShiftsDto, @Query('offset') offset?: string, - ): Promise { + ): Promise { const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; return this.timesheetsCommand.createWeekShiftsAndReturnOverview(email, dto.shifts, week_offset); } - - //_____________________________________________________________________________________________ - // Deprecated or unused methods - //_____________________________________________________________________________________________ - - // @Patch('approval/:id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) - // async approve(@Param('id', ParseIntPipe) id: number, @Body('is_approved', ParseBoolPipe) isApproved: boolean) { - // return this.timesheetsCommand.updateApproval(id, isApproved); - // } - - // @Get(':id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Find timesheet' }) - // @ApiResponse({ status: 201, description: 'Timesheet found', type: CreateTimesheetDto }) - // @ApiResponse({ status: 400, description: 'Timesheet not found' }) - // findOne(@Param('id', ParseIntPipe) id: number): Promise { - // return this.timesheetsQuery.findOne(id); - // } - - // @Delete(':id') - // // @RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Delete timesheet' }) - // @ApiResponse({ status: 201, description: 'Timesheet deleted', type: CreateTimesheetDto }) - // @ApiResponse({ status: 400, description: 'Timesheet not found' }) - // remove(@Param('id', ParseIntPipe) id: number): Promise { - // return this.timesheetsQuery.remove(id); - // } - } diff --git a/src/modules/timesheets/services/timesheet-archive.service.ts b/src/modules/timesheets/services/timesheet-archive.service.ts index 4988c75..c75bdc3 100644 --- a/src/modules/timesheets/services/timesheet-archive.service.ts +++ b/src/modules/timesheets/services/timesheet-archive.service.ts @@ -1,7 +1,6 @@ import { TimesheetsArchive } from "@prisma/client"; import { PrismaService } from "src/prisma/prisma.service"; - export class TimesheetArchiveService { constructor(private readonly prisma: PrismaService){} @@ -21,9 +20,7 @@ export class TimesheetArchiveService { is_approved: true, }, }); - if( oldSheets.length === 0) { - return; - } + if( oldSheets.length === 0) return; //preping data for archivation const archiveDate = oldSheets.map(sheet => ({ diff --git a/src/modules/timesheets/services/timesheets-command.service.ts b/src/modules/timesheets/services/timesheets-command.service.ts index 2db914e..045b7b5 100644 --- a/src/modules/timesheets/services/timesheets-command.service.ts +++ b/src/modules/timesheets/services/timesheets-command.service.ts @@ -1,15 +1,15 @@ import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; -import { Prisma, Timesheets } from "@prisma/client"; -import { BaseApprovalService } from "src/common/shared/base-approval.service"; -import { PrismaService } from "src/prisma/prisma.service"; -import { TimesheetsQueryService } from "./timesheets-query.service"; -import { CreateTimesheetDto } from "../dtos/create-timesheet.dto"; -import { getWeekEnd, getWeekStart } from "src/common/utils/date-utils"; -import { parseISODate, parseHHmm } from "../timesheet.helpers"; -import { TimesheetDto } from "../dtos/timesheet-period.dto"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-employee-timesheet.utils"; +import { getWeekEnd, getWeekStart } from "src/common/utils/date-utils"; +import { parseISODate, parseHHmm } from "../utils-helpers-others/timesheet.helpers"; +import { TimesheetsQueryService } from "./timesheets-query.service"; +import { BaseApprovalService } from "src/common/shared/base-approval.service"; +import { Prisma, Timesheets } from "@prisma/client"; +import { CreateTimesheetDto } from "../dtos/create-timesheet.dto"; +import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +import { PrismaService } from "src/prisma/prisma.service"; +import { TimesheetMap } from "../utils-helpers-others/timesheet.types"; @Injectable() export class TimesheetsCommandService extends BaseApprovalService{ @@ -58,7 +58,7 @@ export class TimesheetsCommandService extends BaseApprovalService{ email:string, shifts: CreateTimesheetDto[], week_offset = 0, - ): Promise { + ): Promise { //fetchs employee matchint user's email const employee_id = await this.emailResolver.findIdByEmail(email); if(!employee_id) throw new NotFoundException(`employee for ${ email } not found`); diff --git a/src/modules/timesheets/services/timesheets-query.service.ts b/src/modules/timesheets/services/timesheets-query.service.ts index 58dfd72..67149ef 100644 --- a/src/modules/timesheets/services/timesheets-query.service.ts +++ b/src/modules/timesheets/services/timesheets-query.service.ts @@ -1,14 +1,13 @@ -import { endOfDayUTC, toHHmm, toNum, toRangeFromPeriod, toUTCDateOnly } from '../timesheet.helpers'; -import { Injectable, NotFoundException } from '@nestjs/common'; -import { formatDateISO, getWeekEnd, getWeekStart } from 'src/common/utils/date-utils'; -import { PrismaService } from 'src/prisma/prisma.service'; -import { TimesheetDto, TimesheetPeriodDto } from '../dtos/timesheet-period.dto'; -import { ShiftRow, ExpenseRow } from '../timesheet.types'; -import { buildPeriod } from '../timesheet.utils'; +import { makeEmptyTimesheet, mapExpenseRow, mapShiftRow } from '../utils-helpers-others/timesheet.mappers'; +import { buildPeriod, computeWeekRange } from '../utils-helpers-others/timesheet.utils'; +import { TimesheetSelectorsService } from '../utils-helpers-others/timesheet.selectors'; +import { TimesheetPeriodDto } from '../dtos/timesheet-period.dto'; +import { toRangeFromPeriod } from '../utils-helpers-others/timesheet.helpers'; import { EmailToIdResolver } from 'src/modules/shared/utils/resolve-email-id.utils'; import { FullNameResolver } from 'src/modules/shared/utils/resolve-full-name.utils'; -import { TimesheetSelectors } from '../timesheet.selectors'; -import { mapExpenseRow, mapShiftRow } from '../timesheet.mappers'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { TimesheetMap } from '../utils-helpers-others/timesheet.types'; +import { Injectable } from '@nestjs/common'; @Injectable() @@ -17,150 +16,39 @@ export class TimesheetsQueryService { private readonly prisma: PrismaService, private readonly emailResolver: EmailToIdResolver, private readonly fullNameResolver: FullNameResolver, - private readonly selectors: TimesheetSelectors, + private readonly selectors: TimesheetSelectorsService, ) {} async findAll(year: number, period_no: number, email: string): Promise { - //finds the employee using email - const employee_id = await this.emailResolver.findIdByEmail(email); - - //finds the employee full name using employee_id - const full_name = await this.fullNameResolver.resolveFullName(employee_id); - - //finds the pay period using year and period_no - const period = await this.selectors.getPayPeriod(year, period_no); - - //finds start and end dates - const{ from, to } = toRangeFromPeriod(period); - + const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email + const full_name = await this.fullNameResolver.resolveFullName(employee_id); //finds the employee full name using employee_id + const period = await this.selectors.getPayPeriod(year, period_no);//finds the pay period using year and period_no + const{ from, to } = toRangeFromPeriod(period); //finds start and end dates //finds all shifts from selected period const [raw_shifts, raw_expenses] = await Promise.all([ this.selectors.getShifts(employee_id, from, to), this.selectors.getExpenses(employee_id, from, to), - ]); - + ]); // data mapping - const shifts = raw_shifts.map(mapShiftRow); + const shifts = raw_shifts.map(mapShiftRow); const expenses = raw_expenses.map(mapExpenseRow); return buildPeriod(period.period_start, period.period_end, shifts , expenses, full_name); } - async getTimesheetByEmail(email: string, week_offset = 0): Promise { - const employee_id = await this.emailResolver.findIdByEmail(email); - if(!employee_id) throw new NotFoundException(`Employee with email: ${email} not found`); - //sets current week Sunday -> Saturday - const base = new Date(); - const offset = new Date(base); - offset.setDate(offset.getDate() + (week_offset * 7)); - const start_date_week = getWeekStart(offset, 0); - const end_date_week = getWeekEnd(start_date_week); - const start_day = formatDateISO(start_date_week); - const end_day = formatDateISO(end_date_week); - - //build the label MM/DD/YYYY.MM/DD.YYYY - const mm_dd = (date: Date) => `${String(date.getFullYear())}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2,'0')}`; - const label = `${mm_dd(start_date_week)}.${mm_dd(end_date_week)}`; - - //fetch timesheet shifts and expenses - const timesheet = await this.prisma.timesheets.findUnique({ - where: { - employee_id_start_date: { - employee_id: employee_id, - start_date: start_date_week, - }, - }, - include: { - shift: { - include: { bank_code: true }, - orderBy: [{ date: 'asc'}, { start_time: 'asc'}], - }, - expense: { - include: { bank_code: true }, - orderBy: [{date: 'asc'}], - }, - }, - }); - - //returns an empty timesheet if not found - if(!timesheet) { - return { - is_approved: false, - start_day, - end_day, - label, - shifts:[], - expenses: [], - } as TimesheetDto; - } + async getTimesheetByEmail(email: string, week_offset = 0): Promise { + const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email + const { start, start_day, end_day, label } = computeWeekRange(week_offset); + const timesheet = await this.selectors.getTimesheetWithShiftsAndExpenses(employee_id, start); //fetch timesheet shifts and expenses + if(!timesheet) return makeEmptyTimesheet({ start_day, end_day, label}); //maps all shifts of selected timesheet - const shifts = timesheet.shift.map((shift_row) => ({ - type: shift_row.bank_code?.type ?? '', - date: formatDateISO(shift_row.date), - start_time: toHHmm(shift_row.start_time), - end_time: toHHmm(shift_row.end_time), - comment: shift_row.comment ?? '', - is_approved: shift_row.is_approved ?? false, - is_remote: shift_row.is_remote ?? false, - })); + const shifts = timesheet.shift.map(mapShiftRow); + const expenses = timesheet.expense.map(mapExpenseRow); - //maps all expenses of selected timsheet - const expenses = timesheet.expense.map((exp) => ({ - type: exp.bank_code?.type ?? '', - date: formatDateISO(exp.date), - amount: Number(exp.amount) || 0, - mileage: exp.mileage != null ? Number(exp.mileage) : 0, - comment: exp.comment ?? '', - is_approved: exp.is_approved ?? false, - supervisor_comment: exp.supervisor_comment ?? '', - })); - return { - start_day, - end_day, - label, - shifts, - expenses, - is_approved: timesheet.is_approved, - } as TimesheetDto; - } - //_____________________________________________________________________________________________ - // Deprecated or unused methods - //_____________________________________________________________________________________________ - - // async findOne(id: number): Promise { - // const timesheet = await this.prisma.timesheets.findUnique({ - // where: { id }, - // include: { - // shift: { include: { bank_code: true } }, - // expense: { include: { bank_code: true } }, - // employee: { include: { user: true } }, - // }, - // }); - // if(!timesheet) { - // throw new NotFoundException(`Timesheet #${id} not found`); - // } - - // const detailedShifts = timesheet.shift.map( s => { - // const hours = computeHours(s.start_time, s.end_time); - // const regularHours = Math.min(8, hours); - // const dailyOvertime = this.overtime.getDailyOvertimeHours(s.start_time, s.end_time); - // const payRegular = regularHours * s.bank_code.modifier; - // const payOvertime = this.overtime.calculateOvertimePay(dailyOvertime, s.bank_code.modifier); - // return { ...s, hours, payRegular, payOvertime }; - // }); - // const weeklyOvertimeHours = detailedShifts.length - // ? await this.overtime.getWeeklyOvertimeHours( - // timesheet.employee_id, - // timesheet.shift[0].date): 0; - // return { ...timesheet, shift: detailedShifts, weeklyOvertimeHours }; - // } - - // async remove(id: number): Promise { - // await this.findOne(id); - // return this.prisma.timesheets.delete({ where: { id } }); - // } + return { start_day, end_day, label, shifts, expenses, is_approved: timesheet.is_approved}; + } } diff --git a/src/modules/timesheets/timesheets.module.ts b/src/modules/timesheets/timesheets.module.ts index 7824aa4..bbffd71 100644 --- a/src/modules/timesheets/timesheets.module.ts +++ b/src/modules/timesheets/timesheets.module.ts @@ -7,11 +7,12 @@ import { ExpensesCommandService } from '../expenses/services/expenses-command. import { BusinessLogicsModule } from 'src/modules/business-logics/business-logics.module'; import { SharedModule } from '../shared/shared.module'; import { Module } from '@nestjs/common'; +import { TimesheetSelectorsService } from './utils-helpers-others/timesheet.selectors'; @Module({ imports: [ BusinessLogicsModule, - SharedModule + SharedModule, ], controllers: [TimesheetsController], providers: [ @@ -19,7 +20,8 @@ import { Module } from '@nestjs/common'; TimesheetsCommandService, ShiftsCommandService, ExpensesCommandService, - TimesheetArchiveService, + TimesheetArchiveService, + TimesheetSelectorsService, ], exports: [ TimesheetsQueryService, diff --git a/src/modules/timesheets/timesheet.helpers.ts b/src/modules/timesheets/utils-helpers-others/timesheet.helpers.ts similarity index 94% rename from src/modules/timesheets/timesheet.helpers.ts rename to src/modules/timesheets/utils-helpers-others/timesheet.helpers.ts index 249b3a0..9e0ca82 100644 --- a/src/modules/timesheets/timesheet.helpers.ts +++ b/src/modules/timesheets/utils-helpers-others/timesheet.helpers.ts @@ -1,4 +1,5 @@ -import { MS_PER_DAY, DayKey, DAY_KEYS } from "./timesheet.types"; +import { MS_PER_DAY } from "src/modules/shared/constants/date-time.constant"; +import { DAY_KEYS, DayKey } from "././timesheet.types"; export function toUTCDateOnly(date: Date | string): Date { const d = new Date(date); diff --git a/src/modules/timesheets/timesheet.mappers.ts b/src/modules/timesheets/utils-helpers-others/timesheet.mappers.ts similarity index 85% rename from src/modules/timesheets/timesheet.mappers.ts rename to src/modules/timesheets/utils-helpers-others/timesheet.mappers.ts index 5807863..6a0b928 100644 --- a/src/modules/timesheets/timesheet.mappers.ts +++ b/src/modules/timesheets/utils-helpers-others/timesheet.mappers.ts @@ -1,5 +1,5 @@ -import { DayExpensesDto, WeekDto, DetailedShifts, TimesheetPeriodDto } from "./dtos/timesheet-period.dto"; -import { ExpenseRow, ExpensesAmount, ShiftRow } from "./timesheet.types"; +import { DayExpensesDto, WeekDto, DetailedShifts, TimesheetPeriodDto } from "../dtos/timesheet-period.dto"; +import { ShiftRow, ExpenseRow, ExpensesAmount, TimesheetMap } from "./timesheet.types"; import { addDays, shortDate, toNum, upper } from "./timesheet.helpers"; import { Prisma } from "@prisma/client"; @@ -41,7 +41,6 @@ export const mapExpenseRow = (expense: { type: upper(expense.bank_code.type), }); - // Factories export function makeEmptyDayExpenses(): DayExpensesDto { return { @@ -92,4 +91,21 @@ export function makeEmptyPeriod(): TimesheetPeriodDto { export const makeAmounts = (): ExpensesAmount => ({ expense: 0, mileage: 0, -}); \ No newline at end of file +}); + +export function makeEmptyTimesheet(params: { + start_day: string; + end_day: string; + label: string; + is_approved?: boolean; +}): TimesheetMap { + const { start_day, end_day, label, is_approved = false } = params; + return { + start_day, + end_day, + label, + shifts: [], + expenses: [], + is_approved, + }; +} \ No newline at end of file diff --git a/src/modules/timesheets/timesheet.selectors.ts b/src/modules/timesheets/utils-helpers-others/timesheet.selectors.ts similarity index 57% rename from src/modules/timesheets/timesheet.selectors.ts rename to src/modules/timesheets/utils-helpers-others/timesheet.selectors.ts index 1c309d4..ec082ad 100644 --- a/src/modules/timesheets/timesheet.selectors.ts +++ b/src/modules/timesheets/utils-helpers-others/timesheet.selectors.ts @@ -1,11 +1,11 @@ +import { EXPENSE_ASC_ORDER, EXPENSE_SELECT } from "../../shared/selects/expenses.select"; import { Injectable, NotFoundException } from "@nestjs/common"; +import { SHIFT_ASC_ORDER, SHIFT_SELECT } from "../../shared/selects/shifts.select"; +import { PAY_PERIOD_SELECT } from "../../shared/selects/pay-periods.select"; import { PrismaService } from "src/prisma/prisma.service"; -import { SHIFT_ASC_ORDER, SHIFT_SELECT } from "../shared/selects/shifts.select"; -import { PAY_PERIOD_SELECT } from "../shared/selects/pay-periods.select"; -import { EXPENSE_ASC_ORDER, EXPENSE_SELECT } from "../shared/selects/expenses.select"; @Injectable() -export class TimesheetSelectors { +export class TimesheetSelectorsService { constructor(readonly prisma: PrismaService){} async getPayPeriod(pay_year: number, pay_period_no: number) { @@ -20,7 +20,7 @@ export class TimesheetSelectors { async getShifts(employee_id: number, from: Date, to: Date) { return this.prisma.shifts.findMany({ where: {timesheet: { is: { employee_id } }, date: { gte: from, lte: to } }, - select: SHIFT_SELECT, + select: SHIFT_SELECT, orderBy: SHIFT_ASC_ORDER, }); } @@ -32,4 +32,15 @@ export class TimesheetSelectors { orderBy: EXPENSE_ASC_ORDER, }); } + + async getTimesheetWithShiftsAndExpenses(employee_id: number, start_date_week: Date) { + return this.prisma.timesheets.findUnique({ + where: { employee_id_start_date: { employee_id, start_date: start_date_week } }, + select: { + is_approved: true, + shift: { select: SHIFT_SELECT, orderBy: SHIFT_ASC_ORDER }, + expense: { select: EXPENSE_SELECT, orderBy: EXPENSE_ASC_ORDER }, + }, + }); + } } \ No newline at end of file diff --git a/src/modules/timesheets/timesheet.types.ts b/src/modules/timesheets/utils-helpers-others/timesheet.types.ts similarity index 89% rename from src/modules/timesheets/timesheet.types.ts rename to src/modules/timesheets/utils-helpers-others/timesheet.types.ts index e33f86b..6fcc951 100644 --- a/src/modules/timesheets/timesheet.types.ts +++ b/src/modules/timesheets/utils-helpers-others/timesheet.types.ts @@ -17,9 +17,14 @@ export type ExpenseRow = { supervisor_comment: string; }; -//Date & Format -export const MS_PER_DAY = 86_400_000; -export const MS_PER_HOUR = 3_600_000; +export type TimesheetMap = { + start_day: string; + end_day: string; + label: string; + shifts: ShiftRow[]; + expenses: ExpenseRow[] + is_approved: boolean; +} // Types export const SHIFT_TYPES = { diff --git a/src/modules/timesheets/timesheet.utils.ts b/src/modules/timesheets/utils-helpers-others/timesheet.utils.ts similarity index 87% rename from src/modules/timesheets/timesheet.utils.ts rename to src/modules/timesheets/utils-helpers-others/timesheet.utils.ts index 3d762c1..d6e691f 100644 --- a/src/modules/timesheets/timesheet.utils.ts +++ b/src/modules/timesheets/utils-helpers-others/timesheet.utils.ts @@ -1,14 +1,31 @@ import { - DayKey, DAY_KEYS, EXPENSE_TYPES, ExpenseRow, MS_PER_HOUR, + DayKey, DAY_KEYS, EXPENSE_TYPES, ExpenseRow, SHIFT_TYPES, ShiftRow, make_hours, ShiftsHours, ExpensesAmount } from "./timesheet.types"; import { isBetweenUTC, dayKeyFromDate, toTimeString, round2, toUTCDateOnly, endOfDayUTC, addDays } from "./timesheet.helpers"; -import { WeekDto, ShiftDto, TimesheetPeriodDto, DayExpensesDto, ExpenseDto } from "./dtos/timesheet-period.dto"; +import { WeekDto, ShiftDto, TimesheetPeriodDto, DayExpensesDto, ExpenseDto } from "../dtos/timesheet-period.dto"; +import { getWeekStart, getWeekEnd, formatDateISO } from "src/common/utils/date-utils"; import { makeAmounts, makeEmptyWeek } from "./timesheet.mappers"; import { toDateString } from "src/modules/pay-periods/utils/pay-year.util"; +import { MS_PER_HOUR } from "src/modules/shared/constants/date-time.constant"; + + export function computeWeekRange(week_offset = 0){ + //sets current week Sunday -> Saturday + const base = new Date(); + const offset = new Date(base); + offset.setDate(offset.getDate() + (week_offset * 7)); + + const start = getWeekStart(offset, 0); + const end = getWeekEnd(start); + const start_day = formatDateISO(start); + const end_day = formatDateISO(end); + const label = `${(start_day)}.${(end_day)}`; + + return { start, end, start_day, end_day, label } + }; export function buildWeek( week_start: Date,