// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; // import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; // import { roundToQuarterHour } from "src/common/utils/date-utils"; // import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; // import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; // import { mapRowToView } from "../mappers/leave-requests.mapper"; // import { leaveRequestsSelect } from "../utils/leave-requests.select"; // import { HolidayLeaveRequestsService } from "./holiday-leave-requests.service"; // import { SickLeaveRequestsService } from "./sick-leave-requests.service"; // import { VacationLeaveRequestsService } from "./vacation-leave-requests.service"; // import { HolidayService } from "src/modules/business-logics/services/holiday.service"; // import { SickLeaveService } from "src/modules/business-logics/services/sick-leave.service"; // import { VacationService } from "src/modules/business-logics/services/vacation.service"; // import { PrismaService } from "src/prisma/prisma.service"; // import { LeaveRequestsUtils } from "../utils/leave-request.util"; // import { normalizeDates, toDateOnly, toISODateKey } from "src/modules/shared/helpers/date-time.helpers"; // import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; // import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; // @Injectable() // export class LeaveRequestsService { // constructor( // private readonly prisma: PrismaService, // private readonly holidayLeaveService: HolidayLeaveRequestsService, // private readonly holidayService: HolidayService, // private readonly sickLogic: SickLeaveService, // private readonly sickLeaveService: SickLeaveRequestsService, // private readonly vacationLeaveService: VacationLeaveRequestsService, // private readonly vacationLogic: VacationService, // private readonly leaveUtils: LeaveRequestsUtils, // private readonly emailResolver: EmailToIdResolver, // private readonly typeResolver: BankCodesResolver, // ) {} // //handle distribution to the right service according to the selected type and action // async handle(dto: UpsertLeaveRequestDto): Promise { // switch (dto.type) { // case LeaveTypes.HOLIDAY: // if( dto.action === 'create'){ // return this.holidayLeaveService.create(dto); // } else if (dto.action === 'update') { // return this.update(dto, LeaveTypes.HOLIDAY); // } else if (dto.action === 'delete'){ // return this.delete(dto, LeaveTypes.HOLIDAY); // } // case LeaveTypes.VACATION: // if( dto.action === 'create'){ // return this.vacationLeaveService.create(dto); // } else if (dto.action === 'update') { // return this.update(dto, LeaveTypes.VACATION); // } else if (dto.action === 'delete'){ // return this.delete(dto, LeaveTypes.VACATION); // } // case LeaveTypes.SICK: // if( dto.action === 'create'){ // return this.sickLeaveService.create(dto); // } else if (dto.action === 'update') { // return this.update(dto, LeaveTypes.SICK); // } else if (dto.action === 'delete'){ // return this.delete(dto, LeaveTypes.SICK); // } // default: // throw new BadRequestException(`Unsupported leave type: ${dto.type} or action: ${dto.action}`); // } // } // async delete(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { // const email = dto.email.trim(); // const dates = normalizeDates(dto.dates); // const employee_id = await this.emailResolver.findIdByEmail(email); // if (!dates.length) throw new BadRequestException("Dates array must not be empty"); // const rows = await this.prisma.leaveRequests.findMany({ // where: { // employee_id: employee_id, // leave_type: type, // date: { in: dates.map((d) => toDateOnly(d)) }, // }, // select: leaveRequestsSelect, // }); // if (rows.length !== dates.length) { // const missing = dates.filter((isoDate) => !rows.some((row) => toISODateKey(row.date) === isoDate)); // throw new NotFoundException(`No Leave request found for: ${missing.join(", ")}`); // } // for (const row of rows) { // if (row.approval_status === LeaveApprovalStatus.APPROVED) { // const iso = toISODateKey(row.date); // await this.leaveUtils.removeShift(email, employee_id, iso, type); // } // } // await this.prisma.leaveRequests.deleteMany({ // where: { id: { in: rows.map((row) => row.id) } }, // }); // const deleted = rows.map((row) => ({ ...mapRowToView(row), action: "delete" as const })); // return { action: "delete", leave_requests: deleted }; // } // async update(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { // const email = dto.email.trim(); // const employee_id = await this.emailResolver.findIdByEmail(email); // const bank_code = await this.typeResolver.findByType(type); // if(!bank_code) throw new NotFoundException(`bank_code not found`); // const modifier = Number(bank_code.modifier ?? 1); // const dates = normalizeDates(dto.dates); // if (!dates.length) { // throw new BadRequestException("Dates array must not be empty"); // } // const entries = await Promise.all( // dates.map(async (iso_date) => { // const date = toDateOnly(iso_date); // const existing = await this.prisma.leaveRequests.findUnique({ // where: { // leave_per_employee_date: { // employee_id: employee_id, // leave_type: type, // date, // }, // }, // select: leaveRequestsSelect, // }); // if (!existing) throw new NotFoundException(`No Leave request found for ${iso_date}`); // return { iso_date, date, existing }; // }), // ); // const updated: LeaveRequestViewDto[] = []; // if (type === LeaveTypes.SICK) { // const firstExisting = entries[0].existing; // const fallbackRequested = // firstExisting.requested_hours !== null && firstExisting.requested_hours !== undefined // ? Number(firstExisting.requested_hours) // : 8; // const requested_hours_per_day = dto.requested_hours ?? fallbackRequested; // const reference_date = entries.reduce( // (latest, entry) => (entry.date > latest ? entry.date : latest), // entries[0].date, // ); // const total_payable_hours = await this.sickLogic.calculateSickLeavePay( // employee_id, // reference_date, // entries.length, // requested_hours_per_day, // modifier, // ); // let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); // const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); // for (const { iso_date, existing } of entries) { // const previous_status = existing.approval_status; // const payable = Math.min(remaining_payable_hours, daily_payable_cap); // const payable_rounded = roundToQuarterHour(Math.max(0, payable)); // remaining_payable_hours = roundToQuarterHour( // Math.max(0, remaining_payable_hours - payable_rounded), // ); // const row = await this.prisma.leaveRequests.update({ // where: { id: existing.id }, // data: { // comment: dto.comment ?? existing.comment, // requested_hours: requested_hours_per_day, // payable_hours: payable_rounded, // bank_code_id: bank_code.id, // approval_status: dto.approval_status ?? existing.approval_status, // }, // select: leaveRequestsSelect, // }); // const was_approved = previous_status === LeaveApprovalStatus.APPROVED; // const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; // const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); // if (!was_approved && is_approved) { // await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); // } else if (was_approved && !is_approved) { // await this.leaveUtils.removeShift(email, employee_id, iso_date, type); // } else if (was_approved && is_approved) { // await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); // } // updated.push({ ...mapRowToView(row), action: "update" }); // } // return { action: "update", leave_requests: updated }; // } // for (const { iso_date, date, existing } of entries) { // const previous_status = existing.approval_status; // const fallbackRequested = // existing.requested_hours !== null && existing.requested_hours !== undefined // ? Number(existing.requested_hours) // : 8; // const requested_hours = dto.requested_hours ?? fallbackRequested; // let payable: number; // switch (type) { // case LeaveTypes.HOLIDAY: // payable = await this.holidayService.calculateHolidayPay(email, date, modifier); // break; // case LeaveTypes.VACATION: { // const days_requested = requested_hours / 8; // payable = await this.vacationLogic.calculateVacationPay( // employee_id, // date, // Math.max(0, days_requested), // modifier, // ); // break; // } // default: // payable = existing.payable_hours !== null && existing.payable_hours !== undefined // ? Number(existing.payable_hours) // : requested_hours; // } // const row = await this.prisma.leaveRequests.update({ // where: { id: existing.id }, // data: { // requested_hours, // comment: dto.comment ?? existing.comment, // payable_hours: payable, // bank_code_id: bank_code.id, // approval_status: dto.approval_status ?? existing.approval_status, // }, // select: leaveRequestsSelect, // }); // const was_approved = previous_status === LeaveApprovalStatus.APPROVED; // const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; // const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); // if (!was_approved && is_approved) { // await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); // } else if (was_approved && !is_approved) { // await this.leaveUtils.removeShift(email, employee_id, iso_date, type); // } else if (was_approved && is_approved) { // await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); // } // updated.push({ ...mapRowToView(row), action: "update" }); // } // return { action: "update", leave_requests: updated }; // } // }