targo-backend/src/modules/timesheets/services/timesheets-command.service.ts

121 lines
4.6 KiB
TypeScript

import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
import { Prisma, Timesheets } from "@prisma/client";
import { BaseApprovalService } from "src/common/shared/base-approval.service";
import { PrismaService } from "src/prisma/prisma.service";
import { TimesheetsQueryService } from "./timesheets-query.service";
import { CreateTimesheetDto } from "../dtos/create-timesheet.dto";
import { TimesheetDto } from "../dtos/overview-timesheet.dto";
import { getWeekEnd, getWeekStart } from "src/common/utils/date-utils";
import { parseISODate, parseHHmm } from "../utils/timesheet.helpers";
@Injectable()
export class TimesheetsCommandService extends BaseApprovalService<Timesheets>{
constructor(
prisma: PrismaService,
private readonly query: TimesheetsQueryService,
) {super(prisma);}
//_____________________________________________________________________________________________
// APPROVAL AND DELEGATE METHODS
//_____________________________________________________________________________________________
protected get delegate() {
return this.prisma.timesheets;
}
protected delegateFor(transaction: Prisma.TransactionClient) {
return transaction.timesheets;
}
async updateApproval(id: number, isApproved: boolean): Promise<Timesheets> {
return this.prisma.$transaction((transaction) =>
this.updateApprovalWithTransaction(transaction, id, isApproved),
);
}
async cascadeApprovalWithtx(transaction: Prisma.TransactionClient, timesheetId: number, isApproved: boolean): Promise<Timesheets> {
const timesheet = await this.updateApprovalWithTransaction(transaction, timesheetId, isApproved);
await transaction.shifts.updateMany({
where: { timesheet_id: timesheetId },
data: { is_approved: isApproved },
});
await transaction.expenses.updateManyAndReturn({
where: { timesheet_id: timesheetId },
data: { is_approved: isApproved },
});
return timesheet;
}
async createWeekShiftsAndReturnOverview(
email:string,
shifts: CreateTimesheetDto[],
week_offset = 0,
): Promise<TimesheetDto> {
//match user's email with email
const user = await this.prisma.users.findUnique({
where: { email },
select: { id: true },
});
if(!user) throw new NotFoundException(`user with email ${email} not found`);
//fetchs employee matchint user's email
const employee = await this.prisma.employees.findFirst({
where: { user_id: user?.id },
select: { id: true },
});
if(!employee) throw new NotFoundException(`employee for ${ email } not found`);
//insure that the week starts on sunday and finishes on saturday
const base = new Date();
base.setDate(base.getDate() + week_offset * 7);
const start_week = getWeekStart(base, 0);
const end_week = getWeekEnd(start_week);
const timesheet = await this.prisma.timesheets.upsert({
where: {
employee_id_start_date: {
employee_id: employee.id,
start_date: start_week,
},
},
create: {
employee_id: employee.id,
start_date: start_week,
is_approved: false,
},
update: {},
select: { id: true },
});
//validations and insertions
for(const shift of shifts) {
const date = parseISODate(shift.date);
if (date < start_week || date > end_week) throw new BadRequestException(`date ${shift.date} not in current week`);
const bank_code = await this.prisma.bankCodes.findFirst({
where: { type: shift.type },
select: { id: true },
});
if(!bank_code) throw new BadRequestException(`Invalid bank_code type: ${shift.type}`);
await this.prisma.shifts.create({
data: {
timesheet_id: timesheet.id,
bank_code_id: bank_code.id,
date: date,
start_time: parseHHmm(shift.start_time),
end_time: parseHHmm(shift.end_time),
comment: shift.comment ?? null,
is_approved: false,
is_remote: false,
},
});
}
return this.query.getTimesheetByEmail(email, week_offset);
}
}