71 lines
3.2 KiB
TypeScript
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};
|
|
}
|
|
} |