feat(business-logic): holiday implementation for leave Requests
This commit is contained in:
parent
c6ff3139f2
commit
2e6bafeb18
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { Injectable, Logger } from "@nestjs/common";
|
||||||
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class HolidayService {
|
||||||
|
private readonly logger = new Logger(HolidayService.name);
|
||||||
|
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
//return the sunday of the current week that includes the holiday
|
||||||
|
private getWeekStart(date: Date): Date {
|
||||||
|
const day = new Date(date);
|
||||||
|
const offset = day.getDay();
|
||||||
|
day.setDate(day.getDate() - offset);
|
||||||
|
day.setHours(0,0,0,0);
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
//rounds minutes to 5s
|
||||||
|
private computeHours(start: Date, end: Date): number {
|
||||||
|
const durationMS = end.getTime() - start.getTime();
|
||||||
|
const totalMinutes = durationMS / 60000;
|
||||||
|
const rounded = Math.round(totalMinutes / 5) * 5;
|
||||||
|
return rounded / 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async computeHoursPrevious4Weeks(employeeId: number, holidayDate: Date): Promise<number> {
|
||||||
|
//sets the end of the window to 1ms before the week with the holiday
|
||||||
|
const holidayWeekStart = this.getWeekStart(holidayDate);
|
||||||
|
const windowEnd = new Date(holidayWeekStart.getTime() - 1);
|
||||||
|
//sets the start of the window to 28 days ( 4 completed weeks ) before the week with the holiday
|
||||||
|
const windowStart = new Date(windowEnd.getTime() - 28 * 24 * 60 * 60000 + 1 )
|
||||||
|
|
||||||
|
const validCodes = ['G1', 'G45', 'G56', 'G104', 'G105', 'G700'];
|
||||||
|
//fetches all shift of the employee in said window ( 4 completed weeks )
|
||||||
|
const shifts = await this.prisma.shifts.findMany({
|
||||||
|
where: { timesheet: { employee_id: employeeId } ,
|
||||||
|
date: { gte: windowStart, lte: windowEnd },
|
||||||
|
bank_code: { bank_code: { in: validCodes } },
|
||||||
|
},
|
||||||
|
select: { date: true, start_time: true, end_time: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalHours = shifts.map(s => this.computeHours(s.start_time, s.end_time)).reduce((sum, h)=> sum + h, 0);
|
||||||
|
const dailyHours = totalHours / 20;
|
||||||
|
|
||||||
|
return dailyHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculateHolidayPay( employeeId: number, holidayDate: Date, modifier: number): Promise<number> {
|
||||||
|
const hours = await this. computeHoursPrevious4Weeks(employeeId, holidayDate);
|
||||||
|
const dailyRate = Math.min(hours, 8);
|
||||||
|
this.logger.debug(`Holiday pay calculation: hours=${hours.toFixed(2)}`);
|
||||||
|
return dailyRate * modifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,15 @@ import { PrismaService } from "src/prisma/prisma.service";
|
||||||
import { LeaveRequestController } from "./controllers/leave-requests.controller";
|
import { LeaveRequestController } from "./controllers/leave-requests.controller";
|
||||||
import { LeaveRequestsService } from "./services/leave-requests.service";
|
import { LeaveRequestsService } from "./services/leave-requests.service";
|
||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
import { HolidayService } from "src/business-logic/holiday.service";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [LeaveRequestController],
|
controllers: [LeaveRequestController],
|
||||||
providers: [ LeaveRequestsService, PrismaService],
|
providers: [
|
||||||
|
LeaveRequestsService,
|
||||||
|
PrismaService,
|
||||||
|
HolidayService,
|
||||||
|
],
|
||||||
exports: [ LeaveRequestsService],
|
exports: [ LeaveRequestsService],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,87 +3,78 @@ import { PrismaService } from "src/prisma/prisma.service";
|
||||||
import { CreateLeaveRequestsDto } from "../dtos/create-leave-requests.dto";
|
import { CreateLeaveRequestsDto } from "../dtos/create-leave-requests.dto";
|
||||||
import { LeaveRequests, LeaveRequestsArchive } from "@prisma/client";
|
import { LeaveRequests, LeaveRequestsArchive } from "@prisma/client";
|
||||||
import { UpdateLeaveRequestsDto } from "../dtos/update-leave-requests.dto";
|
import { UpdateLeaveRequestsDto } from "../dtos/update-leave-requests.dto";
|
||||||
|
import { HolidayService } from "src/business-logic/holiday.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LeaveRequestsService {
|
export class LeaveRequestsService {
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly holidayService: HolidayService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async create(dto: CreateLeaveRequestsDto): Promise<LeaveRequests> {
|
async create(dto: CreateLeaveRequestsDto): Promise<LeaveRequests> {
|
||||||
const {
|
const { employee_id, bank_code_id, leave_type, start_date_time,
|
||||||
employee_id,
|
end_date_time, comment, approval_status } = dto;
|
||||||
bank_code_id,
|
|
||||||
leave_type,
|
|
||||||
start_date_time,
|
|
||||||
end_date_time,
|
|
||||||
comment,
|
|
||||||
approval_status,
|
|
||||||
} = dto;
|
|
||||||
|
|
||||||
return this.prisma.leaveRequests.create({
|
return this.prisma.leaveRequests.create({
|
||||||
data: {
|
data: { employee_id, bank_code_id, leave_type, start_date_time,
|
||||||
employee_id,
|
end_date_time, comment, approval_status: approval_status ?? undefined
|
||||||
bank_code_id,
|
|
||||||
leave_type,
|
|
||||||
start_date_time,
|
|
||||||
end_date_time,
|
|
||||||
comment,
|
|
||||||
approval_status: approval_status ?? undefined,
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
employee: {
|
|
||||||
include: {
|
|
||||||
user: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
include: { employee: { include: { user: true } } },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
findAll(): Promise<LeaveRequests[]> {
|
async findAll(): Promise<any[]> {
|
||||||
return this.prisma.leaveRequests.findMany({
|
const list = await this.prisma.leaveRequests.findMany({
|
||||||
include: {
|
include: { employee: { include: { user: true } },
|
||||||
employee: {
|
bank_code: true,
|
||||||
include: {
|
|
||||||
user: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
bank_code: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
list.map(async request => {
|
||||||
|
if(request.bank_code?.type === 'holiday') {
|
||||||
|
const cost = await this.holidayService.calculateHolidayPay(
|
||||||
|
request.employee_id,
|
||||||
|
request.start_date_time,
|
||||||
|
request.bank_code.modifier
|
||||||
|
);
|
||||||
|
return { ...request, cost };
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(id:number): Promise<LeaveRequests> {
|
async findOne(id:number): Promise<any> {
|
||||||
const req = await this.prisma.leaveRequests.findUnique({
|
const request = await this.prisma.leaveRequests.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: { employee: { include: { user: true } },
|
||||||
employee: {
|
bank_code: true,
|
||||||
include: {
|
|
||||||
user: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
bank_code: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if(!req) {
|
if(!request) {
|
||||||
throw new NotFoundException(`LeaveRequest #${id} not found`);
|
throw new NotFoundException(`LeaveRequest #${id} not found`);
|
||||||
}
|
}
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//search for leave type. if holiday
|
||||||
|
if (request.bank_code?.type === 'holiday') {
|
||||||
|
const cost = await this.holidayService.calculateHolidayPay(
|
||||||
|
request.employee_id,
|
||||||
|
request.start_date_time,
|
||||||
|
request.bank_code.modifier,
|
||||||
|
);
|
||||||
|
return { ...request, cost };
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
async update(
|
async update(
|
||||||
id: number,
|
id: number,
|
||||||
dto: UpdateLeaveRequestsDto,
|
dto: UpdateLeaveRequestsDto,
|
||||||
): Promise<LeaveRequests> {
|
): Promise<LeaveRequests> {
|
||||||
await this.findOne(id);
|
await this.findOne(id);
|
||||||
const {
|
const { employee_id, leave_type, start_date_time, end_date_time, comment, approval_status } = dto;
|
||||||
employee_id,
|
|
||||||
leave_type,
|
|
||||||
start_date_time,
|
|
||||||
end_date_time,
|
|
||||||
comment,
|
|
||||||
approval_status,
|
|
||||||
} = dto;
|
|
||||||
return this.prisma.leaveRequests.update({
|
return this.prisma.leaveRequests.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -94,13 +85,7 @@ export class LeaveRequestsService {
|
||||||
...(comment !== undefined && { comment }),
|
...(comment !== undefined && { comment }),
|
||||||
...(approval_status == undefined && { approval_status }),
|
...(approval_status == undefined && { approval_status }),
|
||||||
},
|
},
|
||||||
include: {
|
include: { employee: { include: { user:true } } },
|
||||||
employee: {
|
|
||||||
include: {
|
|
||||||
user:true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user