diff --git a/src/time-and-attendance/expenses/services/expense-upsert.service.ts b/src/time-and-attendance/expenses/services/expense-upsert.service.ts index 19be304..a47900e 100644 --- a/src/time-and-attendance/expenses/services/expense-upsert.service.ts +++ b/src/time-and-attendance/expenses/services/expense-upsert.service.ts @@ -1,6 +1,5 @@ import { toDateFromString, toStringFromDate, weekStartSunday } from "src/time-and-attendance/utils/date-time.utils"; import { EmailToIdResolver } from "src/time-and-attendance/utils/resolve-email-id.utils"; -// import { NormalizedExpense } from "src/time-and-attendance/utils/type.utils"; import { expense_select } from "src/time-and-attendance/utils/selects.utils"; import { PrismaService } from "src/prisma/prisma.service"; import { GetExpenseDto } from "src/time-and-attendance/expenses/dtos/expense-get.dto"; diff --git a/src/time-and-attendance/time-tracker/shifts/dtos/shift-entity.dto.ts b/src/time-and-attendance/time-tracker/shifts/dtos/shift-entity.dto.ts index f5993c5..863668e 100644 --- a/src/time-and-attendance/time-tracker/shifts/dtos/shift-entity.dto.ts +++ b/src/time-and-attendance/time-tracker/shifts/dtos/shift-entity.dto.ts @@ -1,5 +1,3 @@ -import { BankCodeEntity } from "src/modules/bank-codes/dtos/bank-code-entity"; - export class ShiftEntity { id: number; timesheet_id: number; @@ -10,5 +8,4 @@ export class ShiftEntity { is_remote: boolean; is_approved: boolean; comment?: string | null ; - bank_code?: BankCodeEntity; } diff --git a/src/time-and-attendance/time-tracker/timesheets/services/timesheet-get-overview.service.ts b/src/time-and-attendance/time-tracker/timesheets/services/timesheet-get-overview.service.ts index 085c0ad..b7aa38a 100644 --- a/src/time-and-attendance/time-tracker/timesheets/services/timesheet-get-overview.service.ts +++ b/src/time-and-attendance/time-tracker/timesheets/services/timesheet-get-overview.service.ts @@ -5,7 +5,7 @@ import { PrismaService } from "src/prisma/prisma.service"; import { EmailToIdResolver } from "src/time-and-attendance/utils/resolve-email-id.utils"; import { Timesheet, TimesheetEntity, Timesheets } from "src/time-and-attendance/time-tracker/timesheets/dtos/timesheet.dto"; import { Result } from "src/common/errors/result-error.factory"; -import { Users } from "@prisma/client"; +import { Prisma, Users } from "@prisma/client"; import { ShiftEntity } from "src/time-and-attendance/time-tracker/shifts/dtos/shift-entity.dto"; import { ExpenseEntity } from "src/time-and-attendance/expenses/dtos/expense-entity.dto"; @@ -77,11 +77,11 @@ export class GetTimesheetsOverviewService { //builds employee full name const user = employee.user; const employee_fullname = `${user.first_name} ${user.last_name}`.trim(); - + //maps all timesheet's infos const timesheets = await Promise.all(rows.map((timesheet) => this.mapOneTimesheet(timesheet))); - if(!timesheets) return { success: false, error: 'an error occured during the mapping of a timesheet'} + if (!timesheets) return { success: false, error: 'an error occured during the mapping of a timesheet' } return { success: true, data: { employee_fullname, timesheets } }; } catch (error) { @@ -105,112 +105,118 @@ export class GetTimesheetsOverviewService { }); } - private async mapOneTimesheet(timesheet: TimesheetResult): Promise { - //converts string to UTC date format - const start = toDateFromString(timesheet.start_date); - const day_dates = sevenDaysFrom(start); + private async mapOneTimesheet(timesheet: Prisma.TimesheetsGetPayload<{ + include: { + employee: { include: { user } }, + shift: { include: { bank_code } }, + expense: { include: { bank_code } }, + } + }>): Promise { + //converts string to UTC date format + const start = toDateFromString(timesheet.start_date); + const day_dates = sevenDaysFrom(start); - //map of shifts by days - const shifts_by_date = new Map(); - for (const shift of timesheet.shift) { - const date_string = toStringFromDate(shift.date); - const arr = shifts_by_date.get(date_string) ?? []; - arr.push(shift); - shifts_by_date.set(date_string, arr); + //map of shifts by days + const shifts_by_date = new Map(); + for (const shift of timesheet.shift) { + const date_string = toStringFromDate(shift.date); + const arr = shifts_by_date.get(date_string) ?? []; + arr.push(shift); + shifts_by_date.set(date_string, arr); + } + //map of expenses by days + const expenses_by_date = new Map(); + for (const expense of timesheet.expense) { + const date_string = toStringFromDate(expense.date); + const arr = expenses_by_date.get(date_string) ?? []; + arr.push(expense); + expenses_by_date.set(date_string, arr); + } + //weekly totals + const weekly_hours: TotalHours[] = [emptyHours()]; + const weekly_expenses: TotalExpenses[] = [emptyExpenses()]; + + //map of days + const days = day_dates.map((date) => { + const date_iso = toStringFromDate(date); + const shifts_source = shifts_by_date.get(date_iso) ?? []; + const expenses_source = expenses_by_date.get(date_iso) ?? []; + + //inner map of shifts + const shifts = shifts_source.map((shift) => ({ + timesheet_id: shift.timesheet_id, + date: toStringFromDate(shift.date), + start_time: toHHmmFromDate(shift.start_time), + end_time: toHHmmFromDate(shift.end_time), + type: shift.bank_code?.type ?? '', + is_remote: shift.is_remote ?? false, + is_approved: shift.is_approved ?? false, + id: shift.id ?? null, + comment: shift.comment ?? null, + })); + + //inner map of expenses + const expenses = expenses_source.map((expense) => ({ + date: toStringFromDate(expense.date), + amount: expense.amount != null ? Number(expense.amount) : undefined, + mileage: expense.mileage != null ? Number(expense.mileage) : undefined, + expense_id: expense.id ?? null, + attachment: expense.attachment_record ? String(expense.attachment_record.id) : undefined, + is_approved: expense.is_approved ?? false, + comment: expense.comment ?? '', + supervisor_comment: expense.supervisor_comment, + type: expense.type, + })); + + //daily totals + const daily_hours = [emptyHours()]; + const daily_expenses = [emptyExpenses()]; + + //totals by shift types + for (const shift of shifts_source) { + const hours = diffOfHours(shift.start_time, shift.end_time); + const subgroup = hoursSubGroupFromBankCode(shift.bank_code); + daily_hours[0][subgroup] += hours; + weekly_hours[0][subgroup] += hours; } - //map of expenses by days - const expenses_by_date = new Map(); - for (const expense of timesheet.expense) { - const date_string = toStringFromDate(expense.date); - const arr = expenses_by_date.get(date_string) ?? []; - arr.push(expense); - expenses_by_date.set(date_string, arr); + + //totals by expense types + for (const expense of expenses_source) { + const subgroup = expenseSubgroupFromBankCode(expense.bank_code); + if (subgroup === 'mileage') { + const mileage = num(expense.mileage); + daily_expenses[0].mileage += mileage; + weekly_expenses[0].mileage += mileage; + } else if (subgroup === 'per_diem') { + const amount = num(expense.amount); + daily_expenses[0].per_diem += amount; + weekly_expenses[0].per_diem += amount; + } else if (subgroup === 'on_call') { + const amount = num(expense.amount); + daily_expenses[0].on_call += amount; + weekly_expenses[0].on_call += amount; + } else { + const amount = num(expense.amount); + daily_expenses[0].expenses += amount; + weekly_expenses[0].expenses += amount; + } } - //weekly totals - const weekly_hours: TotalHours[] = [emptyHours()]; - const weekly_expenses: TotalExpenses[] = [emptyExpenses()]; - - //map of days - const days = day_dates.map((date) => { - const date_iso = toStringFromDate(date); - const shifts_source = shifts_by_date.get(date_iso) ?? []; - const expenses_source = expenses_by_date.get(date_iso) ?? []; - - //inner map of shifts - const shifts = shifts_source.map((shift) => ({ - timesheet_id: shift.timesheet_id, - date: toStringFromDate(shift.date), - start_time: toHHmmFromDate(shift.start_time), - end_time: toHHmmFromDate(shift.end_time), - type: shift.bank_code?.type ?? '', - is_remote: shift.is_remote ?? false, - is_approved: shift.is_approved ?? false, - id: shift.id ?? null, - comment: shift.comment ?? null, - })); - - //inner map of expenses - const expenses = expenses_source.map((expense) => ({ - date: toStringFromDate(expense.date), - amount: expense.amount != null ? Number(expense.amount) : undefined, - mileage: expense.mileage != null ? Number(expense.mileage) : undefined, - expense_id: expense.id ?? null, - attachment: expense.attachment_record ? String(expense.attachment_record.id) : undefined, - is_approved: expense.is_approved ?? false, - comment: expense.comment ?? '', - supervisor_comment: expense.supervisor_comment, - type: expense.type, - })); - - //daily totals - const daily_hours = [emptyHours()]; - const daily_expenses = [emptyExpenses()]; - - //totals by shift types - for (const shift of shifts_source) { - const hours = diffOfHours(shift.start_time, shift.end_time); - const subgroup = hoursSubGroupFromBankCode(shift.bank_code); - daily_hours[0][subgroup] += hours; - weekly_hours[0][subgroup] += hours; - } - - //totals by expense types - for (const expense of expenses_source) { - const subgroup = expenseSubgroupFromBankCode(expense.bank_code); - if (subgroup === 'mileage') { - const mileage = num(expense.mileage); - daily_expenses[0].mileage += mileage; - weekly_expenses[0].mileage += mileage; - } else if (subgroup === 'per_diem') { - const amount = num(expense.amount); - daily_expenses[0].per_diem += amount; - weekly_expenses[0].per_diem += amount; - } else if (subgroup === 'on_call') { - const amount = num(expense.amount); - daily_expenses[0].on_call += amount; - weekly_expenses[0].on_call += amount; - } else { - const amount = num(expense.amount); - daily_expenses[0].expenses += amount; - weekly_expenses[0].expenses += amount; - } - } - return { - date: date_iso, - shifts, - expenses, - daily_hours, - daily_expenses, - }; - }); - return { - timesheet_id: timesheet.id, - is_approved: timesheet.is_approved ?? false, - days, - weekly_hours, - weekly_expenses, + date: date_iso, + shifts, + expenses, + daily_hours, + daily_expenses, }; + }); + + return { + timesheet_id: timesheet.id, + is_approved: timesheet.is_approved ?? false, + days, + weekly_hours, + weekly_expenses, + }; } private ensureTimesheet = async (employee_id: number, start_date: Date | string) => { @@ -246,14 +252,6 @@ export class GetTimesheetsOverviewService { } } -interface TimesheetResult extends TimesheetEntity { - employee: { - user: Users - }, - shift: ShiftEntity[], - expense: ExpenseEntity[], -} - //filled array with default values const emptyHours = (): TotalHours => { return { regular: 0, evening: 0, emergency: 0, overtime: 0, vacation: 0, holiday: 0, sick: 0 } }; const emptyExpenses = (): TotalExpenses => { return { expenses: 0, per_diem: 0, on_call: 0, mileage: 0 } };