62 lines
2.6 KiB
TypeScript
62 lines
2.6 KiB
TypeScript
import { Injectable, Logger } from "@nestjs/common";
|
|
import { PrismaService } from "../../../prisma/prisma.service";
|
|
import { getYearStart, roundToQuarterHour } from "src/common/utils/date-utils";
|
|
|
|
@Injectable()
|
|
export class SickLeaveService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
private readonly logger = new Logger(SickLeaveService.name);
|
|
|
|
async calculateSickLeavePay(employeeId: number, referenceDate: Date, daysRequested: number, modifier: number): Promise<number> {
|
|
//sets the year to jan 1st to dec 31st
|
|
const periodStart = getYearStart(referenceDate);
|
|
const periodEnd = referenceDate;
|
|
|
|
//fetches all shifts of a selected employee
|
|
const shifts = await this.prisma.shifts.findMany({
|
|
where: {
|
|
timesheet: { employee_id: employeeId },
|
|
date: { gte: periodStart, lte: periodEnd},
|
|
},
|
|
select: { date: true },
|
|
});
|
|
|
|
//count the amount of worked days
|
|
const workedDates = new Set(
|
|
shifts.map(shift => shift.date.toISOString().slice(0,10))
|
|
);
|
|
const daysWorked = workedDates.size;
|
|
this.logger.debug(`Sick leave: days worked= ${daysWorked} in ${periodStart.toDateString()} -> ${periodEnd.toDateString()}`);
|
|
|
|
//less than 30 worked days returns 0
|
|
if (daysWorked < 30) {
|
|
return 0;
|
|
}
|
|
|
|
//default 3 days allowed after 30 worked days
|
|
let acquiredDays = 3;
|
|
|
|
//identify the date of the 30th worked day
|
|
const orderedDates = Array.from(workedDates).sort();
|
|
const thresholdDate = new Date(orderedDates[29]); // index 29 is the 30th day
|
|
|
|
//calculate each completed month, starting the 1st of the next month
|
|
const firstBonusDate = new Date(thresholdDate.getFullYear(), thresholdDate.getMonth() +1, 1);
|
|
let months = (periodEnd.getFullYear() - firstBonusDate.getFullYear()) * 12 +
|
|
(periodEnd.getMonth() - firstBonusDate.getMonth()) + 1;
|
|
if(months < 0) months = 0;
|
|
acquiredDays += months;
|
|
|
|
//cap of 10 days
|
|
if (acquiredDays > 10) acquiredDays = 10;
|
|
|
|
this.logger.debug(`Sick leave: threshold Date = ${thresholdDate.toDateString()}, bonusMonths = ${months}, acquired Days = ${acquiredDays}`);
|
|
|
|
const payableDays = Math.min(acquiredDays, daysRequested);
|
|
const rawHours = payableDays * 8 * modifier;
|
|
const rounded = roundToQuarterHour(rawHours)
|
|
this.logger.debug(`Sick leave pay: days= ${payableDays}, modifier= ${modifier}, hours= ${rounded}`);
|
|
return rounded;
|
|
}
|
|
} |