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

149 lines
6.0 KiB
TypeScript

import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
import { Timesheets, TimesheetsArchive } from '@prisma/client';
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
import { OvertimeService } from 'src/business-logic/overtime.service';
@Injectable()
export class TimesheetsService {
constructor(
private readonly prisma: PrismaService,
private readonly overtime: OvertimeService,
) {}
async create(dto : CreateTimesheetDto): Promise<Timesheets> {
const { employee_id, is_approved } = dto;
return this.prisma.timesheets.create({
data: { employee_id, is_approved: is_approved ?? false },
include: {
employee: { include: { user: true }
},
},
});
}
async findAll(): Promise<any[]> {
const list = await this.prisma.timesheets.findMany({
include: {
shift: { include: { bank_code: true } },
expense: { include: { bank_code: true } },
employee: { include: { user : true } },
},
});
return Promise.all(
list.map(async timesheet => {
const detailedShifts = timesheet.shift.map(s => {
const hours = this.overtime.computedHours(s.start_time, s.end_time);
const regularHours = Math.min(8, hours);
const dailyOvertime = this.overtime.getDailyOvertimeHours(s.start_time, s.end_time);
const payRegular = regularHours * s.bank_code.modifier;
const payOvertime = this.overtime.calculateOvertimePay(dailyOvertime, s.bank_code.modifier);
return { ...s, hours, payRegular, payOvertime };
});
const weeklyOvertimeHours = detailedShifts.length
? await this.overtime.getWeeklyOvertimeHours(
timesheet.employee_id,
timesheet.shift[0].date): 0;
return { ...timesheet, shift: detailedShifts, weeklyOvertimeHours };
})
);
}
async findOne(id: number): Promise<any> {
const timesheet = await this.prisma.timesheets.findUnique({
where: { id },
include: {
shift: { include: { bank_code: true } },
expense: { include: { bank_code: true } },
employee: { include: { user: true } },
},
});
if(!timesheet) {
throw new NotFoundException(`Timesheet #${id} not found`);
}
const detailedShifts = timesheet.shift.map( s => {
const hours = this.overtime.computedHours(s.start_time, s.end_time);
const regularHours = Math.min(8, hours);
const dailyOvertime = this.overtime.getDailyOvertimeHours(s.start_time, s.end_time);
const payRegular = regularHours * s.bank_code.modifier;
const payOvertime = this.overtime.calculateOvertimePay(dailyOvertime, s.bank_code.modifier);
return { ...s, hours, payRegular, payOvertime };
});
const weeklyOvertimeHours = detailedShifts.length
? await this.overtime.getWeeklyOvertimeHours(
timesheet.employee_id,
timesheet.shift[0].date): 0;
return { ...timesheet, shift: detailedShifts, weeklyOvertimeHours };
}
async update(id: number, dto:UpdateTimesheetDto): Promise<Timesheets> {
await this.findOne(id);
const { employee_id, is_approved } = dto;
return this.prisma.timesheets.update({
where: { id },
data: {
...(employee_id !== undefined && { employee_id }),
...(is_approved !== undefined && { is_approved }),
},
include: { employee: { include: { user: true } },
},
});
}
async remove(id: number): Promise<Timesheets> {
await this.findOne(id);
return this.prisma.timesheets.delete({ where: { id } });
}
//archivation functions ******************************************************
async archiveOld(): Promise<void> {
//calcul du cutoff pour archivation
const cutoff = new Date();
cutoff.setMonth(cutoff.getMonth() - 6)
await this.prisma.$transaction(async transaction => {
//fetches all timesheets to cutoff
const oldSheets = await transaction.timesheets.findMany({
where: { shift: { every: { date: { lt: cutoff } } },
},
select: {
id: true,
employee_id: true,
is_approved: true,
},
});
if( oldSheets.length === 0) {
return;
}
//preping data for archivation
const archiveDate = oldSheets.map(sheet => ({
timesheet_id: sheet.id,
employee_id: sheet.employee_id,
is_approved: sheet.is_approved,
}));
//copying data from timesheets table to archive table
await transaction.timesheetsArchive.createMany({ data: archiveDate });
//removing data from timesheets table
await transaction.timesheets.deleteMany({ where: { id: { in: oldSheets.map(s => s.id) } } });
});
}
//fetches all archived timesheets
async findAllArchived(): Promise<TimesheetsArchive[]> {
return this.prisma.timesheetsArchive.findMany();
}
//fetches an archived timesheet
async findOneArchived(id: number): Promise<TimesheetsArchive> {
return this.prisma.timesheetsArchive.findUniqueOrThrow({ where: { id } });
}
}