targo-backend/src/time-and-attendance/paid-time-off/paid-time-off.service.ts

109 lines
4.4 KiB
TypeScript

import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { computeHours } from "src/common/utils/date-utils";
import { PrismaService } from "src/prisma/prisma.service";
import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service";
import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service";
import { VacationService } from "src/time-and-attendance/domains/services/vacation.service";
import { paid_time_off_mapping, paid_time_off_types } from "src/time-and-attendance/paid-time-off/paid-time-off.dto";
@Injectable()
export class PaidTimeOFfBankHoursService {
constructor(
private readonly prisma: PrismaService,
private readonly bankingService: BankedHoursService,
private readonly vacationService: VacationService,
private readonly sickLeaveService: SickLeaveService,
) { }
//called during update function of Shifts Module
updatePaidTimeOffBankHoursWhenShiftUpdate = async (
start_time: Date,
end_time: Date,
type: string,
employee_id: number,
og_start: Date,
og_end: Date
): Promise<Result<boolean, string>> => {
let original_hours = computeHours(og_start, og_end);
let ajusted_hours = computeHours(start_time, end_time);
if (type === 'BANKING') {
original_hours = original_hours * 1.5;
ajusted_hours = ajusted_hours * 1.5;
}
const diff_hours = Math.abs(ajusted_hours - original_hours);
if (diff_hours === 0) return { success: true, data: true };
if (!paid_time_off_types.includes(type)) return { success: false, error: 'INVALID_SHIFT_TYPE' };
if (ajusted_hours > original_hours) {
const validation = await this.validateAndDeductPaidTimeOff(employee_id, type, diff_hours);
if (!validation.success) return { success: false, error: validation.error };
} else {
const restoration = await this.restorePaidTimeOffHours(employee_id, type, diff_hours);
if (!restoration.success) return { success: false, error: restoration.error };
}
return { success: true, data: true };
}
validateAndDeductPaidTimeOff = async (employee_id: number, type: string, hours: number): Promise<Result<number, string>> => {
const banking_types: string[] = ['BANKING', 'WITHDRAW_BANKED'];
if (banking_types.includes(type)) {
return await this.bankingService.manageBankingHours(employee_id, hours, type);
}
switch (type) {
case 'VACATION': {
return await this.vacationService.manageVacationHoursBank(employee_id, hours);
}
case 'SICK': {
return await this.sickLeaveService.takeSickLeaveHours(employee_id, hours);
}
default:
return { success: false, error: 'INVALID_PAID_TIME_OFF_TYPE' };
}
}
restorePaidTimeOffHours = async (employee_id: number, type: string, hours: number): Promise<Result<boolean, string>> => {
try {
const config = paid_time_off_mapping[type];
if (!config) return { success: false, error: 'INVALID_PAID_TIME_OFF_TYPE' }
const operation = config.invert_logic ? 'decrement' : 'increment';
await this.prisma.paidTimeOff.update({
where: { employee_id },
data: {
[config.field]: { [operation]: hours },
last_updated: new Date(),
},
});
return { success: true, data: true };
} catch (error) {
return { success: false, error: 'PAID_TIME_OFF_NOT_FOUND' };
}
};
//called during delete function of Shifts Module
updatePaidTimeoffBankHoursWhenShiftDelete = async (start: Date, end: Date, type: string, employee_id: number) => {
let ajusted_hours = computeHours(start, end);
if (!paid_time_off_types.includes(type)) return;
if (type === 'BANKING') {
ajusted_hours = ajusted_hours * 1.5;
}
const config = paid_time_off_mapping[type];
await this.prisma.paidTimeOff.update({
where: { employee_id },
data: {
[config.field]: { [config.operation]: ajusted_hours },
last_updated: new Date(),
},
});
}
}