fix(csv): fixed a situation where phantom overtime hours were added to the csv. the problem originated from a mix between consolidated rows and the DB data.

This commit is contained in:
Matthieu Haineault 2026-03-16 14:19:22 -04:00
parent 99df3f8a15
commit 69abbe54b5
2 changed files with 17 additions and 26 deletions

View File

@ -1,5 +1,5 @@
import { WEEKLY_LIMIT_HOURS } from "src/common/utils/constants.utils";
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";
const REGULAR = 1;
@ -57,10 +57,9 @@ export const applyHolidayRequalifications = async (
return result;
}
export const applyOvertimeRequalifications = async (
export const applyOvertimeRequalifications = (
consolidated_rows: InternalCsvRow[],
overtime_service: OvertimeService,
): Promise<CsvRow[]> => {
): CsvRow[] => {
const result: InternalCsvRow[] = [];
//regroup rows by timesheet and week number
@ -74,36 +73,29 @@ export const applyOvertimeRequalifications = async (
}
for (const [, rows] of grouped_rows) {
//use the 1st row to determine wich timesheet and wich week number
const representative = rows[0];
const summary = await overtime_service.getWeekOvertimeSummary(
representative.timesheet_id,
representative.shift_date
);
//if it fails, push to rows as is
if (!summary.success) { result.push(...rows); continue; };
//combine daily and weekly overtime hours
const overtime_hours = summary.data.total_overtime + summary.data.daily_overtime_kept;
//if no overtime, push as is
if (overtime_hours <= 0) { result.push(...rows); continue; };
//search for regular hour rows and deduct overtime hours from it
const regular_hours = rows.find(r => r.code === REGULAR);
if (!regular_hours?.quantite_hre) { result.push(...rows); continue; };
//ensures that its not possible to deduct more hours than the amount of regular hours
// if no regular hours row, push as is
if (!regular_hours?.quantite_hre) { result.push(...rows); continue; }
// calculate overtime directly from consolidated regular hours
const overtime_hours = Math.max(0, regular_hours.quantite_hre - WEEKLY_LIMIT_HOURS);
// if no overtime, push as is
if (overtime_hours <= 0) { result.push(...rows); continue; }
// ensures that its not possible to deduct more hours than the amount of regular hours
const deducted = Math.min(overtime_hours, regular_hours.quantite_hre);
const remaining = regular_hours.quantite_hre - deducted;
for (const row of rows) {
if (row === regular_hours) {
//pushes the regular rows with subtracted overtime hours, if enough hours available
// pushes the regular row with subtracted overtime hours, if enough hours remaining
if (remaining > 0) {
result.push({ ...regular_hours, quantite_hre: remaining });
}
} else {
//other rows are left unchanged
// other rows are left unchanged
result.push(row);
}
}

View File

@ -3,7 +3,6 @@ import { BadRequestException, Injectable, NotFoundException } from "@nestjs/comm
import { Filters, CsvRow, InternalCsvRow } from "src/time-and-attendance/exports/export-csv-options.dto";
import { computeHours } from "src/common/utils/date-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";
import { select_csv_expense_lines, select_csv_shift_lines } from "src/time-and-attendance/utils/selects.utils";
import { BillableShiftType } from "src/time-and-attendance/shifts/shift.dto";
@ -13,7 +12,6 @@ import { BillableShiftType } from "src/time-and-attendance/shifts/shift.dto";
export class CsvExportService {
constructor(
private readonly prisma: PrismaPostgresService,
private readonly overtime_service: OvertimeService,
private readonly holiday_service: HolidayService,
) { }
@ -118,6 +116,7 @@ export class CsvExportService {
const type_transaction = expense.bank_code.bank_code.charAt(0);
const code = Number(expense.bank_code.bank_code.slice(1,))
const week = computeWeekNumber(start, expense.date);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const amount = expense.bank_code.bank_code === 'G503' ? expense.mileage : expense.amount;
const adjustedAmount = Number(amount) * expense.bank_code.modifier;
@ -153,7 +152,7 @@ export class CsvExportService {
const holiday_rows = await applyHolidayRequalifications(rows, this.holiday_service, HOLIDAY_SHIFT_CODE[0]);
const consolidated_rows = consolidateRowHoursAndAmountByType(holiday_rows);
//requalifies regular hours into overtime when needed
const requalified_rows = await applyOvertimeRequalifications(consolidated_rows, this.overtime_service);
const requalified_rows = applyOvertimeRequalifications(consolidated_rows);
return requalified_rows;
}