targo-backend/src/modules/pay-periods/services/pay-periods-command.service.ts

71 lines
3.2 KiB
TypeScript

import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common";
import { TimesheetsCommandService } from "src/modules/timesheets/~misc_deprecated-files/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<string, {period_start: Date, period_end: Date}>();
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};
}
}