149 lines
6.0 KiB
TypeScript
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 } });
|
|
}
|
|
}
|