import { Injectable, NotFoundException } from "@nestjs/common"; import { EmployeePeriodOverviewDto } from "../dtos/overview-employee-period.dto"; import { PayPeriodOverviewDto } from "../dtos/overview-pay-period.dto"; import { PrismaService } from "src/prisma/prisma.service"; @Injectable() export class PayPeriodsOverviewService { constructor(private readonly prisma: PrismaService) {} //function to get a full overview of a selected period filtered by employee ID async getOverview(periodNumber: number): Promise { //fetch the period const period = await this.prisma.payPeriods.findUnique({ where: { period_number: periodNumber }, }); if(!period) { throw new NotFoundException(`Period #${periodNumber} not found`); } //fetch all included shifts for that period const shifts = await this.prisma.shifts.findMany({ where: { date: { gte: period.start_date, lte: period.end_date, }, }, include: { timesheet: { include: { employee: { include: { user: true }}, }, }, }, }); //regroup by employee const map = new Map(); for (const shift of shifts) { const employee_record = shift.timesheet.employee; const user = employee_record.user; const employee_id = employee_record.user_id; const employee_name = `${user.first_name} ${user.last_name}`; const hours = (shift.end_time.getTime() - shift.start_time.getTime() / 3600000); //check if employee had prior shifts and adds hours of found shift to the total hours if (map.has(employee_id)) { const summary = map.get(employee_id)!; summary.total_hours += hours; //keeps is_approved false as long as a single shift is left un-validated summary.is_approved = summary.is_approved && shift.timesheet.is_approved; } else { //if first shift of an employee is found, it adds a new entry map.set(employee_id, { employee_id: employee_id, employee_name: employee_name, total_hours: hours, is_approved: shift.timesheet.is_approved, }); } } return { period_number: period.period_number, start_date: period.start_date, end_date: period.end_date, label: period.label, employees_overview: Array.from(map.values()), }; } }