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{ 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 { return this.prisma.$transaction((transaction) => this.updateApprovalWithTransaction(transaction, id, isApproved), ); } async cascadeApprovalWithtx(transaction: Prisma.TransactionClient, timesheetId: number, isApproved: boolean): Promise { 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 { //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); } }