This commit is contained in:
Nic D 2026-03-13 15:21:12 -04:00
commit 4979f82e6f
2 changed files with 28 additions and 22 deletions

View File

@ -69,8 +69,8 @@ export class OvertimeService {
const day = new Date(week_start.getTime() + i * 24 * 60 * 60 * 1000); const day = new Date(week_start.getTime() + i * 24 * 60 * 60 * 1000);
days.push(day.toISOString().slice(0, 10)); days.push(day.toISOString().slice(0, 10));
} }
//allows the weekly overtime to be calculate skiping the daily overtime
const week_total_hours = [...day_totals.values()].reduce((a, b) => a + b, 0); const week_total_hours = [...day_totals.values()].reduce((a, b) => a + Math.min(b, DAILY_LIMIT_HOURS), 0);
const weekly_overtime = Math.max(0, week_total_hours - WEEKLY_LIMIT_HOURS); const weekly_overtime = Math.max(0, week_total_hours - WEEKLY_LIMIT_HOURS);
let running = 0; let running = 0;
@ -93,9 +93,10 @@ export class OvertimeService {
}); });
daily_kept_sum += daily_kept; daily_kept_sum += daily_kept;
running += day_hours; // Math.min to use only the regular hours in the weekly overtime hours calcul
running += Math.min(day_hours, DAILY_LIMIT_HOURS);
} }
const total_overtime = weekly_overtime + daily_kept_sum; const total_overtime = Math.max(0, weekly_overtime - daily_kept_sum);
return { return {
success: true, success: true,

View File

@ -2,16 +2,16 @@ import { HolidayService } from "src/time-and-attendance/domains/services/holiday
import { OvertimeService } from "src/time-and-attendance/domains/services/overtime.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"; import { CsvRow, InternalCsvRow } from "src/time-and-attendance/exports/export-csv-options.dto";
// You made a helper to pull bank codes from the db, but omitted to use it here... curious.
const REGULAR = 1; const REGULAR = 1;
const OVERTIME = 43; const OVERTIME = 43;
const VACATION = 109; const VACATION = 109;
const SICK = 105;
export const consolidateRowHoursAndAmountByType = (rows: InternalCsvRow[]): InternalCsvRow[] => { export const consolidateRowHoursAndAmountByType = (rows: InternalCsvRow[]): InternalCsvRow[] => {
const map = new Map<string, InternalCsvRow>(); const map = new Map<string, InternalCsvRow>();
for (const row of rows) { for (const row of rows) {
if (row.code === VACATION) { if (row.code === VACATION || row.code === SICK) {
map.set(`${row.code}|${row.shift_date.toString()}|${row.timesheet_id}`, row); map.set(`${row.code}|${row.shift_date.toString()}|${row.timesheet_id}`, row);
} else { } else {
const key = `${row.code}|${row.timesheet_id}`; const key = `${row.code}|${row.timesheet_id}`;
@ -62,9 +62,9 @@ export const applyOvertimeRequalifications = async (
overtime_service: OvertimeService, overtime_service: OvertimeService,
): Promise<CsvRow[]> => { ): Promise<CsvRow[]> => {
const result: InternalCsvRow[] = []; const result: InternalCsvRow[] = [];
//grouped by timesheet and week number
const grouped_rows = new Map<string, InternalCsvRow[]>();
//regroup rows by timesheet and week number
const grouped_rows = new Map<string, InternalCsvRow[]>();
for (const row of consolidated_rows) { for (const row of consolidated_rows) {
const key = `${row.timesheet_id}|${row.semaine_no}`; const key = `${row.timesheet_id}|${row.semaine_no}`;
if (!grouped_rows.has(key)) { if (!grouped_rows.has(key)) {
@ -74,35 +74,40 @@ export const applyOvertimeRequalifications = async (
} }
for (const [, rows] of grouped_rows) { for (const [, rows] of grouped_rows) {
//serves only to get the right timesheet_id and a date to find the "week_start of the getWeekOvertimeSummary" //use the 1st row to determine wich timesheet and wich week number
const representative = rows[0]; const representative = rows[0];
const summary = await overtime_service.getWeekOvertimeSummary(representative.timesheet_id, representative.shift_date); const summary = await overtime_service.getWeekOvertimeSummary(
if (!summary.success || summary.data.total_overtime <= 0) { representative.timesheet_id,
result.push(...rows); representative.shift_date
continue; );
} //if it fails, push to rows as is
if (!summary.success) { result.push(...rows); continue; };
const overtime_hours = summary.data.total_overtime; //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); const regular_hours = rows.find(r => r.code === REGULAR);
if (!regular_hours || !regular_hours.quantite_hre) { if (!regular_hours?.quantite_hre) { result.push(...rows); continue; };
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 deducted = Math.min(overtime_hours, regular_hours.quantite_hre);
const remaining = regular_hours.quantite_hre - deducted;
for (const row of rows) { for (const row of rows) {
if (row === regular_hours) { if (row === regular_hours) {
const remaining = regular_hours.quantite_hre - deducted; //pushes the regular rows with subtracted overtime hours, if enough hours available
if (remaining > 0) { if (remaining > 0) {
result.push({ ...regular_hours, quantite_hre: remaining }); result.push({ ...regular_hours, quantite_hre: remaining });
} }
} else { } else {
//other rows are left unchanged
result.push(row); result.push(row);
} }
} }
//adds a new row with overtime hours deducted from the regular hours
result.push({ result.push({
...regular_hours, ...regular_hours,
code: OVERTIME, code: OVERTIME,