diff --git a/src/time-and-attendance/expenses/expense.controller.ts b/src/time-and-attendance/expenses/expense.controller.ts index d5d3ada..418ce19 100644 --- a/src/time-and-attendance/expenses/expense.controller.ts +++ b/src/time-and-attendance/expenses/expense.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Post, Param, Body, Patch, Delete, Req, UnauthorizedException } from "@nestjs/common"; +import { Controller, Post, Param, Body, Patch, Delete, Req, UnauthorizedException, Query } from "@nestjs/common"; import { ExpenseUpsertService } from "src/time-and-attendance/expenses/services/expense-upsert.service"; import { ExpenseDto } from "src/time-and-attendance/expenses/expense-create.dto"; import { Result } from "src/common/errors/result-error.factory"; @@ -19,8 +19,12 @@ export class ExpenseController { @Patch('update') @ModuleAccessAllowed(ModulesEnum.timesheets) - update(@Body() dto: ExpenseDto, @Access('email') email: string): Promise> { - return this.upsert_service.updateExpense(dto, email); + update( + @Body() dto: ExpenseDto, + @Access('email') email: string, + @Query('employee_email') employee_email?: string, + ): Promise> { + return this.upsert_service.updateExpense(dto, email, employee_email); } @Delete('delete/:expense_id') 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 07ece0e..6d3d5d1 100644 --- a/src/time-and-attendance/expenses/services/expense-upsert.service.ts +++ b/src/time-and-attendance/expenses/services/expense-upsert.service.ts @@ -72,10 +72,11 @@ export class ExpenseUpsertService { //_________________________________________________________________ // UPDATE //_________________________________________________________________ - async updateExpense(dto: ExpenseDto, email: string): Promise> { + async updateExpense(dto: ExpenseDto, email: string, employee_email?: string): Promise> { try { + const account_email = employee_email ?? email; //fetch employee_id using req.user.email - const employee_id = await this.emailResolver.findIdByEmail(email); + const employee_id = await this.emailResolver.findIdByEmail(account_email); if (!employee_id.success) return { success: false, error: employee_id.error }; //normalize string , date format and parse numbers const normed_expense = await this.normalizeAndParseExpenseDto(dto); diff --git a/src/time-and-attendance/exports/csv-exports.module.ts b/src/time-and-attendance/exports/csv-exports.module.ts index 338de0b..ad60848 100644 --- a/src/time-and-attendance/exports/csv-exports.module.ts +++ b/src/time-and-attendance/exports/csv-exports.module.ts @@ -3,9 +3,17 @@ import { CsvExportController } from "./csv-exports.controller"; import { CsvExportService } from "./services/csv-exports.service"; import { CsvGeneratorService } from "src/time-and-attendance/exports/services/csv-builder.service"; import { OvertimeService } from "src/time-and-attendance/domains/services/overtime.service"; +import { HolidayService } from "src/time-and-attendance/domains/services/holiday.service"; +import { EmailToIdResolver } from "src/common/mappers/email-id.mapper"; @Module({ - providers: [CsvExportService, CsvGeneratorService, OvertimeService], + providers: [ + CsvExportService, + CsvGeneratorService, + OvertimeService, + HolidayService, + EmailToIdResolver, + ], controllers: [CsvExportController], }) export class CsvExportModule { } diff --git a/src/time-and-attendance/exports/csv-exports.utils.ts b/src/time-and-attendance/exports/csv-exports.utils.ts index ae202cc..6faab94 100644 --- a/src/time-and-attendance/exports/csv-exports.utils.ts +++ b/src/time-and-attendance/exports/csv-exports.utils.ts @@ -1,3 +1,4 @@ +import { HolidayService } from "src/time-and-attendance/domains/services/holiday.service"; import { OvertimeService } from "src/time-and-attendance/domains/services/overtime.service"; import { CsvRow, InternalCsvRow } from "src/time-and-attendance/exports/export-csv-options.dto"; @@ -20,6 +21,33 @@ export const consolidateRowHoursAndAmountByType = (rows: InternalCsvRow[]): Inte return Array.from(map.values()); } +export const applyHolidayRequalifications = async ( + rows: InternalCsvRow[], + holiday_service: HolidayService, +): Promise => { + const result: InternalCsvRow[] = []; + + for (const row of rows) { + if (row.bank_code !== 'G104') { + result.push(row); + continue; + } + if (!row.holiday_date || !row.email) { + result.push(row); + continue; + } + const calculated = await holiday_service.calculateHolidayPay(row.email, new Date(row.holiday_date), 1); + if (!calculated.success) { + result.push({ ...row, quantity_hours: 0 }); + continue; + } + + result.push({ ...row, quantity_hours: calculated.data }); + } + return result; + +} + export const applyOvertimeRequalifications = async ( consolidated_rows: InternalCsvRow[], overtime_service: OvertimeService, diff --git a/src/time-and-attendance/exports/export-csv-options.dto.ts b/src/time-and-attendance/exports/export-csv-options.dto.ts index 190be8d..939e228 100644 --- a/src/time-and-attendance/exports/export-csv-options.dto.ts +++ b/src/time-and-attendance/exports/export-csv-options.dto.ts @@ -58,7 +58,7 @@ export interface CsvRow { holiday_date?: string; } -export type InternalCsvRow = CsvRow & { timesheet_id: number; shift_date: Date; } +export type InternalCsvRow = CsvRow & { timesheet_id: number; shift_date: Date; email: string; } export type Filters = { diff --git a/src/time-and-attendance/exports/services/csv-exports.service.ts b/src/time-and-attendance/exports/services/csv-exports.service.ts index 41f25a3..de7165e 100644 --- a/src/time-and-attendance/exports/services/csv-exports.service.ts +++ b/src/time-and-attendance/exports/services/csv-exports.service.ts @@ -2,14 +2,16 @@ import { PrismaService } from "src/prisma/prisma.service"; import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; import { Filters, CsvRow, InternalCsvRow } from "src/time-and-attendance/exports/export-csv-options.dto"; import { computeHours } from "src/common/utils/date-utils"; -import { applyOvertimeRequalifications, computeWeekNumber, consolidateRowHoursAndAmountByType, formatDate, resolveCompanyCodes } from "src/time-and-attendance/exports/csv-exports.utils"; +import { applyHolidayRequalifications, applyOvertimeRequalifications, computeWeekNumber, consolidateRowHoursAndAmountByType, formatDate, resolveCompanyCodes } from "src/time-and-attendance/exports/csv-exports.utils"; import { OvertimeService } from "src/time-and-attendance/domains/services/overtime.service"; +import { HolidayService } from "src/time-and-attendance/domains/services/holiday.service"; @Injectable() export class CsvExportService { constructor( private readonly prisma: PrismaService, private readonly overtime_service: OvertimeService, + private readonly holiday_service: HolidayService, ) { } async collectTransaction( @@ -67,7 +69,7 @@ export class CsvExportService { select: { company_code: true, external_payroll_id: true, - user: { select: { first_name: true, last_name: true } }, + user: { select: { first_name: true, last_name: true, email: true } }, } }, } @@ -98,7 +100,7 @@ export class CsvExportService { select: { company_code: true, external_payroll_id: true, - user: { select: { first_name: true, last_name: true } }, + user: { select: { first_name: true, last_name: true, email: true } }, } }, } @@ -129,7 +131,7 @@ export class CsvExportService { select: { company_code: true, external_payroll_id: true, - user: { select: { first_name: true, last_name: true } }, + user: { select: { first_name: true, last_name: true, email: true } }, } }, } @@ -158,7 +160,7 @@ export class CsvExportService { select: { company_code: true, external_payroll_id: true, - user: { select: { first_name: true, last_name: true } }, + user: { select: { first_name: true, last_name: true, email: true } }, } }, } @@ -181,6 +183,7 @@ export class CsvExportService { company_code: employee.company_code, external_payroll_id: employee.external_payroll_id, timesheet_id: shift.timesheet.id, + email: '', shift_date: shift.date, full_name: `${employee.user.first_name} ${employee.user.last_name}`, bank_code: shift.bank_code?.bank_code ?? '', @@ -203,6 +206,7 @@ export class CsvExportService { company_code: employee.company_code, external_payroll_id: employee.external_payroll_id, timesheet_id: expense.timesheet.id, + email: '', full_name: `${employee.user.first_name} ${employee.user.last_name}`, bank_code: expense.bank_code?.bank_code ?? '', quantity_hours: undefined, @@ -210,7 +214,7 @@ export class CsvExportService { week_number: week, pay_date: formatDate(end), holiday_date: '', - shift_date : expense.date, + shift_date: expense.date, }) } @@ -225,9 +229,15 @@ export class CsvExportService { return 0; }); - const consolidated_rows = consolidateRowHoursAndAmountByType(rows); - const requalified_rows = await applyOvertimeRequalifications(consolidated_rows, this.overtime_service); + //groups hours by bank_code + const consolidated_rows = await consolidateRowHoursAndAmountByType(rows); + + //requalifies the real amount paid for holidays + const holiday_rows = await applyHolidayRequalifications(consolidated_rows, this.holiday_service); + + //requalifies regular hours into overtime when needed + const requalified_rows = await applyOvertimeRequalifications(holiday_rows, this.overtime_service); return requalified_rows; }