refactor(leave-requests): refactor the logic of the module leave-requests and modified naming in timesheet GET function
This commit is contained in:
parent
8c816da286
commit
6936ac39fa
|
|
@ -1,82 +1,82 @@
|
|||
import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
|
||||
// import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
|
||||
|
||||
if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
|
||||
console.log('?? Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)');
|
||||
process.exit(0);
|
||||
}
|
||||
// if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
|
||||
// console.log('?? Seed leave-requests ignor<6F> (SKIP_LEAVE_REQUESTS=true)');
|
||||
// process.exit(0);
|
||||
// }
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
// const prisma = new PrismaClient();
|
||||
|
||||
function dateOn(y: number, m: number, d: number) {
|
||||
// stocke une date (@db.Date) à minuit UTC
|
||||
return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
|
||||
}
|
||||
// function dateOn(y: number, m: number, d: number) {
|
||||
// // stocke une date (@db.Date) <20> minuit UTC
|
||||
// return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
|
||||
// }
|
||||
|
||||
async function main() {
|
||||
const year = new Date().getFullYear();
|
||||
const today = new Date();
|
||||
// async function main() {
|
||||
// const year = new Date().getFullYear();
|
||||
// const today = new Date();
|
||||
|
||||
const employees = await prisma.employees.findMany({ select: { id: true } });
|
||||
const bankCodes = await prisma.bankCodes.findMany({
|
||||
where: { categorie: 'LEAVE' },
|
||||
select: { id: true, type: true },
|
||||
});
|
||||
// const employees = await prisma.employees.findMany({ select: { id: true } });
|
||||
// const bankCodes = await prisma.bankCodes.findMany({
|
||||
// where: { categorie: 'LEAVE' },
|
||||
// select: { id: true, type: true },
|
||||
// });
|
||||
|
||||
if (!employees.length || !bankCodes.length) {
|
||||
console.warn('No employees or LEAVE bank codes; aborting');
|
||||
return;
|
||||
}
|
||||
// if (!employees.length || !bankCodes.length) {
|
||||
// console.warn('No employees or LEAVE bank codes; aborting');
|
||||
// return;
|
||||
// }
|
||||
|
||||
const types: LeaveTypes[] = [
|
||||
LeaveTypes.SICK,
|
||||
LeaveTypes.VACATION,
|
||||
LeaveTypes.UNPAID,
|
||||
LeaveTypes.BEREAVEMENT,
|
||||
LeaveTypes.PARENTAL,
|
||||
LeaveTypes.LEGAL,
|
||||
LeaveTypes.WEDDING,
|
||||
];
|
||||
const statuses: LeaveApprovalStatus[] = [
|
||||
LeaveApprovalStatus.PENDING,
|
||||
LeaveApprovalStatus.APPROVED,
|
||||
LeaveApprovalStatus.DENIED,
|
||||
LeaveApprovalStatus.CANCELLED,
|
||||
LeaveApprovalStatus.ESCALATED,
|
||||
];
|
||||
// const types: LeaveTypes[] = [
|
||||
// LeaveTypes.SICK,
|
||||
// LeaveTypes.VACATION,
|
||||
// LeaveTypes.UNPAID,
|
||||
// LeaveTypes.BEREAVEMENT,
|
||||
// LeaveTypes.PARENTAL,
|
||||
// LeaveTypes.LEGAL,
|
||||
// LeaveTypes.WEDDING,
|
||||
// ];
|
||||
// const statuses: LeaveApprovalStatus[] = [
|
||||
// LeaveApprovalStatus.PENDING,
|
||||
// LeaveApprovalStatus.APPROVED,
|
||||
// LeaveApprovalStatus.DENIED,
|
||||
// LeaveApprovalStatus.CANCELLED,
|
||||
// LeaveApprovalStatus.ESCALATED,
|
||||
// ];
|
||||
|
||||
const futureMonths = [8, 9, 10, 11, 12]; // Août ? Déc. (1-based)
|
||||
// const futureMonths = [8, 9, 10, 11, 12]; // Ao<41>t ? D<>c. (1-based)
|
||||
|
||||
const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
|
||||
// const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const emp = employees[i % employees.length];
|
||||
const m = futureMonths[i % futureMonths.length];
|
||||
const date = dateOn(year, m, 5 + i); // 5..14
|
||||
if (date <= today) continue; // garantir « futur »
|
||||
// for (let i = 0; i < 10; i++) {
|
||||
// const emp = employees[i % employees.length];
|
||||
// const m = futureMonths[i % futureMonths.length];
|
||||
// const date = dateOn(year, m, 5 + i); // 5..14
|
||||
// if (date <= today) continue; // garantir <20> futur <20>
|
||||
|
||||
const type = types[i % types.length];
|
||||
const status = statuses[i % statuses.length];
|
||||
const bc = bankCodes[i % bankCodes.length];
|
||||
const requestedHours = 4 + (i % 5); // 4 ? 8 h
|
||||
const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
|
||||
// const type = types[i % types.length];
|
||||
// const status = statuses[i % statuses.length];
|
||||
// const bc = bankCodes[i % bankCodes.length];
|
||||
// const requestedHours = 4 + (i % 5); // 4 ? 8 h
|
||||
// const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
|
||||
|
||||
rows.push({
|
||||
employee_id: emp.id,
|
||||
bank_code_id: bc.id,
|
||||
leave_type: type,
|
||||
date,
|
||||
comment: `Future leave #${i + 1} (${bc.type})`,
|
||||
approval_status: status,
|
||||
requested_hours: requestedHours,
|
||||
payable_hours: payableHours,
|
||||
});
|
||||
}
|
||||
// rows.push({
|
||||
// employee_id: emp.id,
|
||||
// bank_code_id: bc.id,
|
||||
// leave_type: type,
|
||||
// date,
|
||||
// comment: `Future leave #${i + 1} (${bc.type})`,
|
||||
// approval_status: status,
|
||||
// requested_hours: requestedHours,
|
||||
// payable_hours: payableHours,
|
||||
// });
|
||||
// }
|
||||
|
||||
if (rows.length) {
|
||||
await prisma.leaveRequests.createMany({ data: rows });
|
||||
}
|
||||
// if (rows.length) {
|
||||
// await prisma.leaveRequests.createMany({ data: rows });
|
||||
// }
|
||||
|
||||
console.log(`? LeaveRequests (future): ${rows.length} rows`);
|
||||
}
|
||||
// console.log(`? LeaveRequests (future): ${rows.length} rows`);
|
||||
// }
|
||||
|
||||
main().finally(() => prisma.$disconnect());
|
||||
// main().finally(() => prisma.$disconnect());
|
||||
|
|
@ -61,7 +61,7 @@ model LeaveRequests {
|
|||
bank_code_id Int
|
||||
|
||||
comment String
|
||||
date DateTime @db.Date
|
||||
dates DateTime[] @db.Date
|
||||
payable_hours Decimal? @db.Decimal(5, 2)
|
||||
requested_hours Decimal? @db.Decimal(5, 2)
|
||||
approval_status LeaveApprovalStatus @default(PENDING)
|
||||
|
|
@ -69,8 +69,8 @@ model LeaveRequests {
|
|||
|
||||
archive LeaveRequestsArchive[] @relation("LeaveRequestToArchive")
|
||||
|
||||
@@unique([employee_id, leave_type, date], name: "leave_per_employee_date")
|
||||
@@index([employee_id, date])
|
||||
@@unique([employee_id, leave_type, dates], name: "leave_per_employee_date")
|
||||
@@index([employee_id, dates])
|
||||
@@map("leave_requests")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||
import { Prisma, PrismaClient } from "@prisma/client";
|
||||
import { LeaveTypes, Prisma, PrismaClient } from "@prisma/client";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
|
||||
|
|
@ -46,4 +46,6 @@ export class BankCodesResolver {
|
|||
|
||||
return { success: true, data: bank_code.type };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,20 +1,28 @@
|
|||
// import { Body, Controller, Post } from "@nestjs/common";
|
||||
// import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
|
||||
// import { UpsertLeaveRequestDto } from "../dtos/upsert-leave-request.dto";
|
||||
// import { LeaveRequestsService } from "../services/leave-request.service";
|
||||
import { Body, Controller, Delete, Patch, Post, Req } from "@nestjs/common";
|
||||
import { LeaveRequestDto } from "../dtos/leave-request.dto";
|
||||
import { LeaveRequestsService } from "src/time-and-attendance/leave-requests/services/leave-request.service";
|
||||
|
||||
// @ApiTags('Leave Requests')
|
||||
// @ApiBearerAuth('access-token')
|
||||
// // @UseGuards()
|
||||
// @Controller('leave-requests')
|
||||
// export class LeaveRequestController {
|
||||
// constructor(private readonly leave_service: LeaveRequestsService){}
|
||||
@Controller('leave-requests')
|
||||
export class LeaveRequestController {
|
||||
constructor(private readonly leave_service: LeaveRequestsService) { }
|
||||
|
||||
// @Post('upsert')
|
||||
// async upsertLeaveRequest(@Body() dto: UpsertLeaveRequestDto) {
|
||||
// const { action, leave_requests } = await this.leave_service.handle(dto);
|
||||
// return { action, leave_requests };
|
||||
// }
|
||||
// @Post('create')
|
||||
// async create(@Req() req, @Body() dto: LeaveRequestDto) {
|
||||
// const email = req.user?.email;
|
||||
// return await this.leave_service.create(email, dto);
|
||||
// }
|
||||
|
||||
// }
|
||||
// @Delete('delete')
|
||||
// async delete(@Req() req, @Body() leave_request_id: number) {
|
||||
// const email = req.user?.email;
|
||||
// return await this.leave_service.delete(email, leave_request_id);
|
||||
// }
|
||||
|
||||
// @Patch('update')
|
||||
// async update(@Req() req, @Body() request_id: number, approval_status: string) {
|
||||
// const email = req.user?.email;
|
||||
// return await this.leave_service.update(email, request_id, approval_status);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,12 @@
|
|||
import { IsEmail, IsArray, ArrayNotEmpty, ArrayUnique, IsISO8601, IsIn, IsOptional, IsString, IsNumber, Min, Max, IsEnum } from "class-validator";
|
||||
import { IsEmail, IsArray, ArrayNotEmpty, ArrayUnique, IsISO8601, IsOptional, IsString, IsNumber, Min, Max, IsEnum } from "class-validator";
|
||||
import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
|
||||
import { LeaveRequestViewDto } from "./leave-request-view.dto";
|
||||
import { Type } from "class-transformer";
|
||||
|
||||
//sets wich function to call
|
||||
export const UPSERT_ACTIONS = ['create', 'update', 'delete'] as const;
|
||||
export type UpsertAction = (typeof UPSERT_ACTIONS)[number];
|
||||
|
||||
//sets wich types to use
|
||||
export const REQUEST_TYPES = Object.values(LeaveTypes) as readonly LeaveTypes[];
|
||||
export type RequestTypes = (typeof REQUEST_TYPES)[number];
|
||||
|
||||
//filter requests by type and action
|
||||
export interface UpsertResult {
|
||||
action: UpsertAction;
|
||||
leave_requests: LeaveRequestViewDto[];
|
||||
}
|
||||
|
||||
export class UpsertLeaveRequestDto {
|
||||
export class LeaveRequestDto {
|
||||
@IsEmail()
|
||||
email!: string;
|
||||
|
||||
|
|
@ -27,16 +16,11 @@ export class UpsertLeaveRequestDto {
|
|||
@IsISO8601({}, { each: true })
|
||||
dates!: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(LeaveTypes)
|
||||
type!: string;
|
||||
|
||||
@IsIn(UPSERT_ACTIONS)
|
||||
action!: UpsertAction;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
comment?: string;
|
||||
comment!: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
|
|
@ -45,7 +29,6 @@ export class UpsertLeaveRequestDto {
|
|||
@Max(24)
|
||||
requested_hours?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(LeaveApprovalStatus)
|
||||
approval_status?: LeaveApprovalStatus
|
||||
}
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
|
||||
import { leave_requests_select } from "src/time-and-attendance/utils/selects.utils";
|
||||
|
||||
type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
|
||||
type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leave_requests_select}>;
|
||||
|
||||
const toNum = (value?: Prisma.Decimal | null) =>
|
||||
value !== null && value !== undefined ? Number(value) : undefined;
|
||||
|
||||
export function mapRowToView(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
const iso_date = row.date?.toISOString().slice(0, 10);
|
||||
if (!iso_date) throw new Error(`Leave request #${row.id} has no date set.`);
|
||||
// export function mapRowToView(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
// const iso_date = row.dates?.toISOString().slice(0, 10);
|
||||
// if (!iso_date) throw new Error(`Leave request #${row.id} has no date set.`);
|
||||
|
||||
return {
|
||||
id: row.id,
|
||||
leave_type: row.leave_type,
|
||||
date: iso_date,
|
||||
payable_hours: toNum(row.payable_hours),
|
||||
requested_hours: toNum(row.requested_hours),
|
||||
comment: row.comment,
|
||||
approval_status: row.approval_status,
|
||||
email: row.employee.user.email,
|
||||
employee_full_name: `${row.employee.user.first_name} ${row.employee.user.last_name}`,
|
||||
};
|
||||
}
|
||||
// return {
|
||||
// id: row.id,
|
||||
// leave_type: row.leave_type,
|
||||
// date: iso_date,
|
||||
// payable_hours: toNum(row.payable_hours),
|
||||
// requested_hours: toNum(row.requested_hours),
|
||||
// comment: row.comment,
|
||||
// approval_status: row.approval_status,
|
||||
// email: row.employee.user.email,
|
||||
// employee_full_name: `${row.employee.user.first_name} ${row.employee.user.last_name}`,
|
||||
// };
|
||||
// }
|
||||
|
|
@ -1,241 +1,186 @@
|
|||
// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
|
||||
// import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto";
|
||||
// import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
|
||||
// import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
|
||||
// import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto";
|
||||
// import { roundToQuarterHour } from "src/common/utils/date-utils";
|
||||
// import { LeaveRequestsUtils } from "src/time-and-attendance/leave-requests/utils/leave-request.util";
|
||||
// import { EmailToIdResolver } from "src/time-and-attendance/utils/resolve-email-id.utils";
|
||||
// import { BankCodesResolver } from "src/time-and-attendance/utils/resolve-bank-type-id.utils";
|
||||
// import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service";
|
||||
// import { VacationService } from "src/time-and-attendance/domains/services/vacation.service";
|
||||
// import { HolidayService } from "src/time-and-attendance/domains/services/holiday.service";
|
||||
// import { PrismaService } from "src/prisma/prisma.service";
|
||||
// import { mapRowToView } from "../mappers/leave-requests.mapper";
|
||||
// import { normalizeDates, toDateOnly, toISODateKey } from "src/time-and-attendance/utils/date-time.utils";
|
||||
// @Injectable()
|
||||
// export class LeaveRequestsService {
|
||||
import { EmployeeTimesheetResolver } from "src/common/mappers/timesheet.mapper";
|
||||
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||
import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
|
||||
import { LeaveApprovalStatus, LeaveRequests, LeaveTypes, Prisma, Shifts } from "@prisma/client";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { Result } from "src/common/errors/result-error.factory";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { LeaveRequestDto } from "src/time-and-attendance/leave-requests/dtos/leave-request.dto";
|
||||
import { leave_requests_select } from "src/time-and-attendance/utils/selects.utils";
|
||||
import { toDateFromString, toStringFromDate } from "src/common/utils/date-utils";
|
||||
import { NormalizedLeaveRequest } from "src/time-and-attendance/utils/type.utils";
|
||||
|
||||
@Injectable()
|
||||
export class LeaveRequestsService {
|
||||
// constructor(
|
||||
// private readonly prisma: PrismaService,
|
||||
// private readonly holidayService: HolidayService,
|
||||
// private readonly sickLogic: SickLeaveService,
|
||||
// private readonly vacationLogic: VacationService,
|
||||
// private readonly leaveUtils: LeaveRequestsUtils,
|
||||
// private readonly emailResolver: EmailToIdResolver,
|
||||
// private readonly typeResolver: BankCodesResolver,
|
||||
// ) {}
|
||||
// private readonly prisma: PrismaService,
|
||||
// private readonly timesheetResolver: EmployeeTimesheetResolver,
|
||||
// private readonly emailResolver: EmailToIdResolver,
|
||||
// private readonly typeResolver: BankCodesResolver,
|
||||
// ) { }
|
||||
|
||||
// // handle distribution to the right service according to the selected type and action
|
||||
// async handle(dto: UpsertLeaveRequestDto): Promise<UpsertResult> {
|
||||
// switch (dto.type) {
|
||||
// case LeaveTypes.HOLIDAY:
|
||||
// if( dto.action === 'create'){
|
||||
// // return this.holidayService.create(dto);
|
||||
// } else if (dto.action === 'update') {
|
||||
// return this.update(dto, LeaveTypes.HOLIDAY);
|
||||
// } else if (dto.action === 'delete'){
|
||||
// return this.delete(dto, LeaveTypes.HOLIDAY);
|
||||
// }
|
||||
// case LeaveTypes.VACATION:
|
||||
// if( dto.action === 'create'){
|
||||
// // return this.vacationService.create(dto);
|
||||
// } else if (dto.action === 'update') {
|
||||
// return this.update(dto, LeaveTypes.VACATION);
|
||||
// } else if (dto.action === 'delete'){
|
||||
// return this.delete(dto, LeaveTypes.VACATION);
|
||||
// }
|
||||
// case LeaveTypes.SICK:
|
||||
// if( dto.action === 'create'){
|
||||
// // return this.sickLeaveService.create(dto);
|
||||
// } else if (dto.action === 'update') {
|
||||
// return this.update(dto, LeaveTypes.SICK);
|
||||
// } else if (dto.action === 'delete'){
|
||||
// return this.delete(dto, LeaveTypes.SICK);
|
||||
// }
|
||||
// default:
|
||||
// throw new BadRequestException(`Unsupported leave type: ${dto.type} or action: ${dto.action}`);
|
||||
// }
|
||||
// }
|
||||
|
||||
// async delete(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise<UpsertResult> {
|
||||
// const email = dto.email.trim();
|
||||
// const dates = normalizeDates(dto.dates);
|
||||
// const employee_id = await this.emailResolver.findIdByEmail(email);
|
||||
// if (!dates.length) throw new BadRequestException("Dates array must not be empty");
|
||||
|
||||
// const rows = await this.prisma.leaveRequests.findMany({
|
||||
// where: {
|
||||
// employee_id: employee_id,
|
||||
// leave_type: type,
|
||||
// date: { in: dates.map((d) => toDateOnly(d)) },
|
||||
// },
|
||||
// select: leaveRequestsSelect,
|
||||
// });
|
||||
// async create(email: string, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> {
|
||||
// try {
|
||||
// //verify if array is empty or not
|
||||
// if (!Array.isArray(dto.dates) || dto.dates.length === 0) return { success: false, error: 'no data received' };
|
||||
// //verify if email is valid or not
|
||||
// const employee = await this.emailResolver.findIdByEmail(email);
|
||||
// if (!employee.success) return { success: false, error: employee.error }
|
||||
// //normalized dto datas to match DB's
|
||||
// const normed_request = await this.normalizeRequest(dto);
|
||||
// if (!normed_request.success) return { success: false, error: normed_request.error }
|
||||
|
||||
// if (rows.length !== dates.length) {
|
||||
// const missing = dates.filter((isoDate) => !rows.some((row) => toISODateKey(row.date) === isoDate));
|
||||
// throw new NotFoundException(`No Leave request found for: ${missing.join(", ")}`);
|
||||
// }
|
||||
|
||||
// for (const row of rows) {
|
||||
// if (row.approval_status === LeaveApprovalStatus.APPROVED) {
|
||||
// const iso = toISODateKey(row.date);
|
||||
// await this.leaveUtils.removeShift(email, employee_id, iso, type);
|
||||
// }
|
||||
// }
|
||||
|
||||
// await this.prisma.leaveRequests.deleteMany({
|
||||
// where: { id: { in: rows.map((row) => row.id) } },
|
||||
// });
|
||||
|
||||
// const deleted = rows.map((row) => ({ ...mapRowToView(row), action: "delete" as const }));
|
||||
// return { action: "delete", leave_requests: deleted };
|
||||
// }
|
||||
|
||||
// async update(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise<UpsertResult> {
|
||||
// const email = dto.email.trim();
|
||||
// const employee_id = await this.emailResolver.findIdByEmail(email);
|
||||
// const bank_code = await this.typeResolver.findIdAndModifierByType(type);
|
||||
// if(!bank_code) throw new NotFoundException(`bank_code not found`);
|
||||
// const modifier = Number(bank_code.modifier ?? 1);
|
||||
// const dates = normalizeDates(dto.dates);
|
||||
// if (!dates.length) {
|
||||
// throw new BadRequestException("Dates array must not be empty");
|
||||
// }
|
||||
|
||||
// const entries = await Promise.all(
|
||||
// dates.map(async (iso_date) => {
|
||||
// const date = toDateOnly(iso_date);
|
||||
// const existing = await this.prisma.leaveRequests.findUnique({
|
||||
// where: {
|
||||
// leave_per_employee_date: {
|
||||
// employee_id: employee_id,
|
||||
// leave_type: type,
|
||||
// date,
|
||||
// },
|
||||
// },
|
||||
// select: leaveRequestsSelect,
|
||||
// });
|
||||
// if (!existing) throw new NotFoundException(`No Leave request found for ${iso_date}`);
|
||||
// return { iso_date, date, existing };
|
||||
// }),
|
||||
// );
|
||||
|
||||
// const updated: LeaveRequestViewDto[] = [];
|
||||
|
||||
// if (type === LeaveTypes.SICK) {
|
||||
// const firstExisting = entries[0].existing;
|
||||
// const fallbackRequested =
|
||||
// firstExisting.requested_hours !== null && firstExisting.requested_hours !== undefined
|
||||
// ? Number(firstExisting.requested_hours)
|
||||
// : 8;
|
||||
// const requested_hours_per_day = dto.requested_hours ?? fallbackRequested;
|
||||
// const reference_date = entries.reduce(
|
||||
// (latest, entry) => (entry.date > latest ? entry.date : latest),
|
||||
// entries[0].date,
|
||||
// );
|
||||
// const total_payable_hours = await this.sickLogic.calculateSickLeavePay(
|
||||
// employee_id,
|
||||
// reference_date,
|
||||
// entries.length,
|
||||
// requested_hours_per_day,
|
||||
// modifier,
|
||||
// );
|
||||
// let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours));
|
||||
// const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier);
|
||||
|
||||
// for (const { iso_date, existing } of entries) {
|
||||
// const previous_status = existing.approval_status;
|
||||
// const payable = Math.min(remaining_payable_hours, daily_payable_cap);
|
||||
// const payable_rounded = roundToQuarterHour(Math.max(0, payable));
|
||||
// remaining_payable_hours = roundToQuarterHour(
|
||||
// Math.max(0, remaining_payable_hours - payable_rounded),
|
||||
// );
|
||||
|
||||
// const row = await this.prisma.leaveRequests.update({
|
||||
// where: { id: existing.id },
|
||||
// data: {
|
||||
// comment: dto.comment ?? existing.comment,
|
||||
// requested_hours: requested_hours_per_day,
|
||||
// payable_hours: payable_rounded,
|
||||
// bank_code_id: bank_code.id,
|
||||
// approval_status: dto.approval_status ?? existing.approval_status,
|
||||
// },
|
||||
// select: leaveRequestsSelect,
|
||||
// });
|
||||
|
||||
// const was_approved = previous_status === LeaveApprovalStatus.APPROVED;
|
||||
// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED;
|
||||
// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0);
|
||||
|
||||
// if (!was_approved && is_approved) {
|
||||
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
|
||||
// } else if (was_approved && !is_approved) {
|
||||
// await this.leaveUtils.removeShift(email, employee_id, iso_date, type);
|
||||
// } else if (was_approved && is_approved) {
|
||||
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
|
||||
// }
|
||||
// updated.push({ ...mapRowToView(row), action: "update" });
|
||||
// }
|
||||
// return { action: "update", leave_requests: updated };
|
||||
// }
|
||||
|
||||
// for (const { iso_date, date, existing } of entries) {
|
||||
// const previous_status = existing.approval_status;
|
||||
// const fallbackRequested =
|
||||
// existing.requested_hours !== null && existing.requested_hours !== undefined
|
||||
// ? Number(existing.requested_hours)
|
||||
// : 8;
|
||||
// const requested_hours = dto.requested_hours ?? fallbackRequested;
|
||||
|
||||
// let payable: number;
|
||||
// switch (type) {
|
||||
// case LeaveTypes.HOLIDAY:
|
||||
// payable = await this.holidayService.calculateHolidayPay(email, date, modifier);
|
||||
// break;
|
||||
// case LeaveTypes.VACATION: {
|
||||
// const days_requested = requested_hours / 8;
|
||||
// payable = await this.vacationLogic.calculateVacationPay(
|
||||
// employee_id,
|
||||
// date,
|
||||
// Math.max(0, days_requested),
|
||||
// modifier,
|
||||
// );
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// payable = existing.payable_hours !== null && existing.payable_hours !== undefined
|
||||
// ? Number(existing.payable_hours)
|
||||
// : requested_hours;
|
||||
// }
|
||||
|
||||
// const row = await this.prisma.leaveRequests.update({
|
||||
// where: { id: existing.id },
|
||||
// //creates the requests
|
||||
// const request_day = await this.prisma.leaveRequests.create({
|
||||
// data: {
|
||||
// requested_hours,
|
||||
// comment: dto.comment ?? existing.comment,
|
||||
// payable_hours: payable,
|
||||
// bank_code_id: bank_code.id,
|
||||
// approval_status: dto.approval_status ?? existing.approval_status,
|
||||
// employee_id: employee.data,
|
||||
// bank_code_id: normed_request.data.bank_code_id,
|
||||
// comment: normed_request.data.comment,
|
||||
// dates: normed_request.data.dates,
|
||||
// approval_status: dto.approval_status,
|
||||
// requested_hours: dto.requested_hours,
|
||||
// leave_type: normed_request.data.leave_type,
|
||||
// },
|
||||
// select: leaveRequestsSelect,
|
||||
// select: leave_requests_select,
|
||||
// });
|
||||
// if (!request_day) return { success: false, error: 'An error occured during creation. Leave-Request is invalid' }
|
||||
|
||||
// const was_approved = previous_status === LeaveApprovalStatus.APPROVED;
|
||||
// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED;
|
||||
// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0);
|
||||
// const created_request: LeaveRequestDto = {
|
||||
// email: dto.email,
|
||||
// type: request_day.leave_type.toString(),
|
||||
// dates: dto.dates,
|
||||
// comment: normed_request.data.comment,
|
||||
// approval_status: 'PENDING',
|
||||
// requested_hours: dto.requested_hours,
|
||||
// };
|
||||
|
||||
// if (!was_approved && is_approved) {
|
||||
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
|
||||
// } else if (was_approved && !is_approved) {
|
||||
// await this.leaveUtils.removeShift(email, employee_id, iso_date, type);
|
||||
// } else if (was_approved && is_approved) {
|
||||
// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment);
|
||||
// }
|
||||
// updated.push({ ...mapRowToView(row), action: "update" });
|
||||
// return { success: true, data: created_request };
|
||||
// } catch (error) {
|
||||
// return { success: false, error: `An error occured during creation, invalid data` }
|
||||
// }
|
||||
// return { action: "update", leave_requests: updated };
|
||||
// }
|
||||
// }
|
||||
|
||||
// async update(email: string, request_id: number, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> {
|
||||
// try {
|
||||
// const employee = await this.emailResolver.findIdByEmail(email);
|
||||
// if (!employee.success) return { success: false, error: employee.error }
|
||||
|
||||
// switch (dto.approval_status) {
|
||||
// case 'APPROVED': //creation of shifts and returns void
|
||||
// break;
|
||||
// case 'DENIED': //simple update and returns void
|
||||
// break;
|
||||
// case 'CANCELLED': //CANCELLED, simple update and returns void
|
||||
// break;
|
||||
// case 'PENDING': this.updatePendingRequest(dto)
|
||||
// break;
|
||||
// default: return { success: false, error: `invalid approval_status` };
|
||||
// }
|
||||
|
||||
// // const updated_request: LeaveRequestDto = {
|
||||
// // email: dto.email,
|
||||
// // type: request_day.leave_type.toString(),
|
||||
// // dates: dto.dates,
|
||||
// // comment: normed_request.data.comment,
|
||||
// // approval_status: dto.approval_status,
|
||||
// // requested_hours: dto.requested_hours,
|
||||
// // }
|
||||
|
||||
// } catch (error) {
|
||||
// return { success: false, error: ' An error occured during update, Invalid Leave-Request data' }
|
||||
// }
|
||||
// return { success: true, data: updated_request };
|
||||
// }
|
||||
|
||||
// async delete(email: string, request_id: number): Promise<Result<number, string>> {
|
||||
// try {
|
||||
// const employee = await this.emailResolver.findIdByEmail(email);
|
||||
// if (!employee.success) return { success: false, error: employee.error }
|
||||
|
||||
// const deleted = await this.prisma.leaveRequests.findUnique({
|
||||
// where: { id: request_id, employee_id: employee.data },
|
||||
// select: { id: true, dates: true },
|
||||
// });
|
||||
// if (!deleted) return { success: false, error: `Leave Request with id ${request_id} not found ` };
|
||||
// return { success: true, data: deleted.id };
|
||||
|
||||
// } catch (error) {
|
||||
// return { success: false, error: `INVALID_REQUEST, leave-request with id ${request_id} not found` }
|
||||
// }
|
||||
// }
|
||||
|
||||
// private normalizeRequest = async (dto: LeaveRequestDto): Promise<Result<NormalizedLeaveRequest, string>> => {
|
||||
// const bank_code = await this.typeResolver.findBankCodeIDByType(dto.type);
|
||||
// if (!bank_code.success) return { success: false, error: bank_code.error };
|
||||
// const comment = this.truncate280(dto.comment);
|
||||
// //maps enum, check if dto.type is include in the list and return a valid type
|
||||
// const leave_type_list = Object.values(LeaveTypes);
|
||||
// const leave_type = leave_type_list.includes(dto.type.toUpperCase() as LeaveTypes);
|
||||
// if (!leave_type) return { success: false, error: `Leave Request of type ${dto.type} is invalid` }
|
||||
// const valid_leave_type = dto.type.toUpperCase() as LeaveTypes;
|
||||
|
||||
// //map of all dates in string format
|
||||
// const dates = dto.dates.map(toDateFromString);
|
||||
// if (!dates) return { success: false, error: 'Bad date' }
|
||||
|
||||
// return { success: true, data: { comment, dates, leave_type: valid_leave_type, bank_code_id: bank_code.data } };
|
||||
// }
|
||||
|
||||
// //makes sure that a string cannot exceed 280 chars
|
||||
// private truncate280 = (input: string): string => {
|
||||
// return input.length > 280 ? input.slice(0, 280) : input;
|
||||
// }
|
||||
|
||||
// private updatePendingRequest = async (request_id: number, dto: LeaveRequestDto): Promise<Result<LeaveRequestDto, string>> => {
|
||||
// const normed_dto = await this.normalizeRequest(dto);
|
||||
// if (!normed_dto.success) return { success: false, error: normed_dto.error }
|
||||
|
||||
// const leave_request = await this.prisma.leaveRequests.findUnique({
|
||||
// where: { id: request_id },
|
||||
// select: leave_requests_select,
|
||||
// });
|
||||
// if (!leave_request) return { success: false, error: `Leave Request with id: ${request_id} not found` }
|
||||
|
||||
// const update = await this.prisma.leaveRequests.update({
|
||||
// where: { id: request_id },
|
||||
// data: {
|
||||
// bank_code_id: normed_dto.data.bank_code_id,
|
||||
// leave_type: normed_dto.data.leave_type,
|
||||
// comment: normed_dto.data.comment,
|
||||
// dates: normed_dto.data.dates,
|
||||
// requested_hours: dto.requested_hours ?? 0,
|
||||
// }
|
||||
// })
|
||||
// // (alias) class LeaveRequestDto {
|
||||
// // email: string;
|
||||
// // dates: string[];
|
||||
// // type: string;
|
||||
// // comment: string;
|
||||
// // requested_hours?: number | undefined;
|
||||
// // approval_status?: $Enums.LeaveApprovalStatus | undefined;
|
||||
// // }
|
||||
// // const dates_string = update.dates.map(toStringFromDate);
|
||||
// // const updated_request: LeaveRequestDto = {
|
||||
// // email: leave_request,
|
||||
// // type: update.leave_type,
|
||||
|
||||
// // }
|
||||
|
||||
// return { success: true, data: updated_request }
|
||||
// }
|
||||
}
|
||||
|
||||
type leaveRequests = {
|
||||
id: number;
|
||||
bank_code_id: number;
|
||||
comment: string;
|
||||
dates: Date[];
|
||||
payable_hours: Prisma.Decimal | null;
|
||||
requested_hours: Prisma.Decimal | null;
|
||||
approval_status: LeaveApprovalStatus;
|
||||
leave_type: LeaveTypes;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import { Prisma } from "@prisma/client";
|
||||
import { LeaveRequestViewDto } from "src/time-and-attendance/leave-requests/dtos/leave-request-view.dto";
|
||||
import { mapArchiveRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests-archive.mapper";
|
||||
import { mapRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests.mapper";
|
||||
// import { mapRowToView } from "src/time-and-attendance/leave-requests/mappers/leave-requests.mapper";
|
||||
import { LeaveRequestArchiveRow } from "src/time-and-attendance/leave-requests/utils/leave-requests-archive.select";
|
||||
import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
|
||||
// import { leaveRequestsSelect } from "src/time-and-attendance/utils/selects.utils";
|
||||
|
||||
export type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
|
||||
// export type LeaveRequestRow = Prisma.LeaveRequestsGetPayload<{ select: typeof leaveRequestsSelect}>;
|
||||
|
||||
/** Active (table leave_requests) : proxy to base mapper */
|
||||
export function mapRowToViewWithDays(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
return mapRowToView(row);
|
||||
}
|
||||
// /** Active (table leave_requests) : proxy to base mapper */
|
||||
// export function mapRowToViewWithDays(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
// return mapRowToView(row);
|
||||
// }
|
||||
|
||||
/** Archive (table leave_requests_archive) : proxy to base mapper */
|
||||
export function mapArchiveRowToViewWithDays(
|
||||
row: LeaveRequestArchiveRow,
|
||||
email: string,
|
||||
employee_full_name?: string,
|
||||
): LeaveRequestViewDto {
|
||||
return mapArchiveRowToView(row, email, employee_full_name!);
|
||||
}
|
||||
// /** Archive (table leave_requests_archive) : proxy to base mapper */
|
||||
// export function mapArchiveRowToViewWithDays(
|
||||
// row: LeaveRequestArchiveRow,
|
||||
// email: string,
|
||||
// employee_full_name?: string,
|
||||
// ): LeaveRequestViewDto {
|
||||
// return mapArchiveRowToView(row, email, employee_full_name!);
|
||||
// }
|
||||
|
|
@ -7,15 +7,16 @@ import { toDateFromString, toStringFromDate } from "src/common/utils/date-utils"
|
|||
export class LeaveRequestsUtils {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
){}
|
||||
) { }
|
||||
|
||||
|
||||
async syncShift(
|
||||
email: string,
|
||||
email: string,
|
||||
employee_id: number,
|
||||
date: string,
|
||||
hours: number,
|
||||
type: LeaveTypes,
|
||||
comment?: string,
|
||||
date: string,
|
||||
hours: number,
|
||||
type: LeaveTypes,
|
||||
comment?: string,
|
||||
) {
|
||||
if (hours <= 0) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ export class Expense {
|
|||
amount?: number;
|
||||
mileage?: number;
|
||||
attachment?: string;
|
||||
expense_id?: number | null;
|
||||
id?: number | null;
|
||||
supervisor_comment?: string | null;
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ export class GetTimesheetsOverviewService {
|
|||
date: toStringFromDate(expense.date),
|
||||
amount: expense.amount != null ? Number(expense.amount) : undefined,
|
||||
mileage: expense.mileage != null ? Number(expense.mileage) : undefined,
|
||||
expense_id: expense.id ?? null,
|
||||
id: expense.id ?? null,
|
||||
attachment: expense.attachment_record ? String(expense.attachment_record.id) : undefined,
|
||||
is_approved: expense.is_approved ?? false,
|
||||
comment: expense.comment ?? '',
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ export const shift_select = {
|
|||
comment: true,
|
||||
} satisfies Prisma.ShiftsSelect;
|
||||
|
||||
export const leaveRequestsSelect = {
|
||||
export const leave_requests_select = {
|
||||
id: true,
|
||||
bank_code_id: true,
|
||||
leave_type: true,
|
||||
date: true,
|
||||
dates: true,
|
||||
payable_hours: true,
|
||||
requested_hours: true,
|
||||
comment: true,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Prisma } from "@prisma/client";
|
||||
import { LeaveTypes, Prisma } from "@prisma/client";
|
||||
|
||||
export type Normalized = {
|
||||
date: Date;
|
||||
|
|
@ -16,6 +16,13 @@ export type NormalizedExpense = {
|
|||
parsed_attachment?: number;
|
||||
};
|
||||
|
||||
export type NormalizedLeaveRequest = {
|
||||
comment: string;
|
||||
dates: Date[];
|
||||
bank_code_id: number;
|
||||
leave_type: LeaveTypes;
|
||||
}
|
||||
|
||||
export type ShiftResponse = {
|
||||
week_day: string;
|
||||
sort_order: number;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user