128 lines
4.6 KiB
TypeScript
128 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";
|
|
|
|
@Injectable()
|
|
export class TimesheetsCommandService extends BaseApprovalService<Timesheets>{
|
|
constructor(
|
|
prisma: PrismaService,
|
|
private readonly query: TimesheetsQueryService,
|
|
) {super(prisma);}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
//create shifts within timesheet's week - employee overview functions
|
|
private parseISODate(iso: string): Date {
|
|
const [ y, m, d ] = iso.split('-').map(Number);
|
|
return new Date(y, (m ?? 1) - 1, d ?? 1);
|
|
}
|
|
|
|
private parseHHmm(t: string): Date {
|
|
const [ hh, mm ] = t.split(':').map(Number);
|
|
return new Date(1970, 0, 1, hh || 0, mm || 0, 0, 0);
|
|
}
|
|
|
|
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 = this.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: this.parseHHmm(shift.start_time),
|
|
end_time: this.parseHHmm(shift.end_time),
|
|
comment: shift.comment ?? null,
|
|
is_approved: false,
|
|
is_remote: false,
|
|
},
|
|
});
|
|
}
|
|
return this.query.getTimesheetByEmail(email, week_offset);
|
|
}
|
|
} |