import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; import { TimesheetsCommandService } from "src/modules/timesheets/services/timesheets-command.service"; import { PrismaService } from "src/prisma/prisma.service"; import { BulkCrewApprovalDto } from "../dtos/bulk-crew-approval.dto"; import { PayPeriodsQueryService } from "./pay-periods-query.service"; @Injectable() export class PayPeriodsCommandService { constructor( private readonly prisma: PrismaService, private readonly timesheets_approval: TimesheetsCommandService, private readonly query: PayPeriodsQueryService, ) {} //function to approve pay-periods according to selected crew members async bulkApproveCrew(dto:BulkCrewApprovalDto): Promise<{updated: number}> { const { supervisor_email, include_subtree, items } = dto; if(!items?.length) throw new BadRequestException('no items to process'); //fetch and validate supervisor status const supervisor = await this.query.getSupervisor(supervisor_email); if(!supervisor) throw new NotFoundException('No employee record linked to current user'); if(!supervisor.is_supervisor) throw new ForbiddenException('Employee is not a supervisor'); //fetches emails of crew members linked to supervisor const crew_emails = await this.query.resolveCrewEmails(supervisor.id, include_subtree); for(const item of items) { if(!crew_emails.has(item.employee_email)) { throw new ForbiddenException(`Employee ${item.employee_email} not in supervisor crew`); } } const period_cache = new Map(); const getPeriod = async (y:number, no: number) => { const key = `${y}-${no}`; if(!period_cache.has(key)) return period_cache.get(key)!; const period = await this.query.getPeriodWindow(y,no); if(!period) throw new NotFoundException(`Pay period ${y}-${no} not found`); period_cache.set(key, period); return period; }; let updated = 0; await this.prisma.$transaction(async (transaction) => { for(const item of items) { const { period_start, period_end } = await getPeriod(item.pay_year, item.period_no); const t_sheets = await transaction.timesheets.findMany({ where: { employee: { user: { email: item.employee_email } }, OR: [ {shift : { some: { date: { gte: period_start, lte: period_end } } } }, {expense: { some: { date: { gte: period_start, lte: period_end } } } }, ], }, select: { id: true }, }); for(const { id } of t_sheets) { await this.timesheets_approval.updateApprovalWithTransaction(transaction, id, item.approve); updated++; } } }); return {updated}; } }