feat(archival): added controllers to add a search option for archive tables for admin, hr and supervisors

This commit is contained in:
Matthieu Haineault 2025-07-30 10:07:24 -04:00
parent b7bae49ce7
commit 09a213d5dd
11 changed files with 244 additions and 10 deletions

View File

@ -5,6 +5,11 @@ import { ExpensesModule } from "../expenses/expenses.module";
import { ShiftsModule } from "../shifts/shifts.module"; import { ShiftsModule } from "../shifts/shifts.module";
import { LeaveRequestsModule } from "../leave-requests/leave-requests.module"; import { LeaveRequestsModule } from "../leave-requests/leave-requests.module";
import { ArchivalService } from "./services/archival.service"; import { ArchivalService } from "./services/archival.service";
import { EmployeesArchiveController } from "./controllers/employees-archive.controller";
import { ExpensesArchiveController } from "./controllers/expenses-archive.controller";
import { LeaveRequestsArchiveController } from "./controllers/leave-requests-archive.controller";
import { ShiftsArchiveController } from "./controllers/shifts-archive.controller";
import { TimesheetsArchiveController } from "./controllers/timesheets-archive.controller";
@Module({ @Module({
imports: [ imports: [
@ -15,6 +20,13 @@ import { ArchivalService } from "./services/archival.service";
LeaveRequestsModule, LeaveRequestsModule,
], ],
providers: [ArchivalService], providers: [ArchivalService],
controllers: [
EmployeesArchiveController,
ExpensesArchiveController,
LeaveRequestsArchiveController,
ShiftsArchiveController,
TimesheetsArchiveController,
]
}) })
export class ArchivalModule {} export class ArchivalModule {}

View File

@ -0,0 +1,34 @@
import { Controller, Get, NotFoundException, Param, ParseIntPipe, UseGuards } from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { EmployeesArchive, Roles as RoleEnum } from '@prisma/client';
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { EmployeesService } from "src/modules/employees/services/employees.service";
@ApiTags('Employee Archives')
@UseGuards(JwtAuthGuard)
@Controller('archives/employees')
export class EmployeesArchiveController {
constructor(private readonly employeesService: EmployeesService) {}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'List of archived employees'})
@ApiResponse({ status: 200, description: 'List of archived employees', isArray: true })
async findAllArchived(): Promise<EmployeesArchive[]> {
return this.employeesService.findAllArchived();
}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR,RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Fetch employee in archives with its Id'})
@ApiResponse({ status: 200, description: 'Archived employee found'})
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<EmployeesArchive> {
try{
return await this.employeesService.findOneArchived(id);
}catch {
throw new NotFoundException(`Archived employee #${id} not found`);
}
}
}

View File

@ -0,0 +1,33 @@
import { UseGuards, Controller, Get, Param, ParseIntPipe, NotFoundException } from "@nestjs/common";
import { ApiTags, ApiOperation, ApiResponse } from "@nestjs/swagger";
import { ExpensesArchive,Roles as RoleEnum } from "@prisma/client";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { ExpensesService } from "src/modules/expenses/services/expenses.service";
@ApiTags('Expense Archives')
@UseGuards(JwtAuthGuard)
@Controller('archives/expenses')
export class ExpensesArchiveController {
constructor(private readonly expensesService: ExpensesService) {}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'List of archived expenses'})
@ApiResponse({ status: 200, description: 'List of archived expenses', isArray: true })
async findAllArchived(): Promise<ExpensesArchive[]> {
return this.expensesService.findAllArchived();
}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Fetch expense in archives with its Id'})
@ApiResponse({ status: 200, description: 'Archived expense found'})
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<ExpensesArchive> {
try{
return await this.expensesService.findOneArchived(id);
}catch {
throw new NotFoundException(`Archived expense #${id} not found`);
}
}
}

View File

@ -0,0 +1,33 @@
import { Get, Param, ParseIntPipe, NotFoundException, Controller, UseGuards } from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { LeaveRequestsArchive, Roles as RoleEnum } from "@prisma/client";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { LeaveRequestsService } from "src/modules/leave-requests/services/leave-request.service";
@ApiTags('LeaveRequests Archives')
@UseGuards(JwtAuthGuard)
@Controller('archives/leaveRequests')
export class LeaveRequestsArchiveController {
constructor(private readonly leaveRequestsService: LeaveRequestsService) {}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'List of archived leaveRequests'})
@ApiResponse({ status: 200, description: 'List of archived leaveRequests', isArray: true })
async findAllArchived(): Promise<LeaveRequestsArchive[]> {
return this.leaveRequestsService.findAllArchived();
}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Fetch leaveRequest in archives with its Id'})
@ApiResponse({ status: 200, description: 'Archived leaveRequest found'})
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<LeaveRequestsArchive> {
try{
return await this.leaveRequestsService.findOneArchived(id);
}catch {
throw new NotFoundException(`Archived leaveRequest #${id} not found`);
}
}
}

View File

@ -0,0 +1,33 @@
import { Get, Param, ParseIntPipe, NotFoundException, Controller, UseGuards } from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { ShiftsArchive, Roles as RoleEnum } from "@prisma/client";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { ShiftsService } from "src/modules/shifts/services/shifts.service";
@ApiTags('Shift Archives')
@UseGuards(JwtAuthGuard)
@Controller('archives/shifts')
export class ShiftsArchiveController {
constructor(private readonly shiftsService:ShiftsService) {}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'List of archived shifts'})
@ApiResponse({ status: 200, description: 'List of archived shifts', isArray: true })
async findAllArchived(): Promise<ShiftsArchive[]> {
return this.shiftsService.findAllArchived();
}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR,RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Fetch shift in archives with its Id'})
@ApiResponse({ status: 200, description: 'Archived shift found'})
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<ShiftsArchive> {
try{
return await this.shiftsService.findOneArchived(id);
}catch {
throw new NotFoundException(`Archived shift #${id} not found`);
}
}
}

View File

@ -0,0 +1,34 @@
import { Controller, Get, NotFoundException, Param, ParseIntPipe, UseGuards } from "@nestjs/common";
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { TimesheetsArchive, Roles as RoleEnum } from '@prisma/client';
import { TimesheetsService } from "src/modules/timesheets/services/timesheets.service";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
@ApiTags('Timesheet Archives')
@UseGuards(JwtAuthGuard)
@Controller('archives/timesheets')
export class TimesheetsArchiveController {
constructor(private readonly timesheetsService: TimesheetsService) {}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'List of archived timesheets'})
@ApiResponse({ status: 200, description: 'List of archived timesheets', isArray: true })
async findAllArchived(): Promise<TimesheetsArchive[]> {
return this.timesheetsService.findAllArchived();
}
@Get()
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Fetch timesheet in archives with its Id'})
@ApiResponse({ status: 200, description: 'Archived timesheet found'})
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<TimesheetsArchive> {
try{
return await this.timesheetsService.findOneArchived(id);
}catch {
throw new NotFoundException(`Archived timesheet #${id} not found`);
}
}
}

View File

@ -2,7 +2,7 @@ import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service'; import { PrismaService } from 'src/prisma/prisma.service';
import { CreateEmployeeDto } from '../dtos/create-employee.dto'; import { CreateEmployeeDto } from '../dtos/create-employee.dto';
import { UpdateEmployeeDto } from '../dtos/update-employee.dto'; import { UpdateEmployeeDto } from '../dtos/update-employee.dto';
import { Employees, Users } from '@prisma/client'; import { Employees, EmployeesArchive, Users } from '@prisma/client';
@Injectable() @Injectable()
export class EmployeesService { export class EmployeesService {
@ -109,7 +109,8 @@ async update(
} }
//archivation function //archivation functions ******************************************************
async patchEmployee(id: number, dto: UpdateEmployeeDto): Promise<any> { async patchEmployee(id: number, dto: UpdateEmployeeDto): Promise<any> {
//fetching existing employee //fetching existing employee
const existing = await this.prisma.employees.findUnique({ const existing = await this.prisma.employees.findUnique({
@ -189,4 +190,15 @@ async update(
return restored; return restored;
}); });
} }
//fetches all archived employees
async findAllArchived(): Promise<EmployeesArchive[]> {
return this.prisma.employeesArchive.findMany();
}
//fetches an archived employee
async findOneArchived(id: number): Promise<EmployeesArchive> {
return this.prisma.employeesArchive.findUniqueOrThrow({ where: { id } });
}
} }

View File

@ -1,7 +1,7 @@
import { Injectable, NotFoundException } from "@nestjs/common"; import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service"; import { PrismaService } from "src/prisma/prisma.service";
import { CreateExpenseDto } from "../dtos/create-expense"; import { CreateExpenseDto } from "../dtos/create-expense";
import { Expenses } from "@prisma/client"; import { Expenses, ExpensesArchive } from "@prisma/client";
import { UpdateExpenseDto } from "../dtos/update-expense"; import { UpdateExpenseDto } from "../dtos/update-expense";
@Injectable() @Injectable()
@ -88,7 +88,8 @@ export class ExpensesService {
} }
//archivation function //archivation functions ******************************************************
async archiveOld(): Promise<void> { async archiveOld(): Promise<void> {
//fetches archived timesheet's Ids //fetches archived timesheet's Ids
const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({ const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({
@ -132,4 +133,14 @@ export class ExpensesService {
}) })
} }
//fetches all archived timesheets
async findAllArchived(): Promise<ExpensesArchive[]> {
return this.prisma.expensesArchive.findMany();
}
//fetches an archived timesheet
async findOneArchived(id: number): Promise<ExpensesArchive> {
return this.prisma.expensesArchive.findUniqueOrThrow({ where: { id } });
}
} }

View File

@ -1,7 +1,7 @@
import { Injectable, NotFoundException } from "@nestjs/common"; import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service"; 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 } 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";
@Injectable() @Injectable()
@ -107,7 +107,8 @@ export class LeaveRequestsService {
}); });
} }
//archivation function //archivation functions ******************************************************
async archiveExpired(): Promise<void> { async archiveExpired(): Promise<void> {
const now = new Date(); const now = new Date();
@ -136,6 +137,15 @@ export class LeaveRequestsService {
where: { id: { in: expired.map(request => request.id ) } }, where: { id: { in: expired.map(request => request.id ) } },
}); });
}); });
}
//fetches all archived employees
async findAllArchived(): Promise<LeaveRequestsArchive[]> {
return this.prisma.leaveRequestsArchive.findMany();
}
//fetches an archived employee
async findOneArchived(id: number): Promise<LeaveRequestsArchive> {
return this.prisma.leaveRequestsArchive.findUniqueOrThrow({ where: { id } });
} }
} }

View File

@ -1,7 +1,7 @@
import { Injectable, NotFoundException } from "@nestjs/common"; import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service"; import { PrismaService } from "src/prisma/prisma.service";
import { CreateShiftDto } from "../dtos/create-shifts.dto"; import { CreateShiftDto } from "../dtos/create-shifts.dto";
import { Shifts } from "@prisma/client"; import { Shifts, ShiftsArchive } from "@prisma/client";
import { UpdateShiftsDto } from "../dtos/update-shifts.dto"; import { UpdateShiftsDto } from "../dtos/update-shifts.dto";
@Injectable() @Injectable()
@ -87,7 +87,8 @@ export class ShiftsService {
return this.prisma.shifts.delete({ where: { id } }); return this.prisma.shifts.delete({ where: { id } });
} }
//archivation function //archivation functions ******************************************************
async archiveOld(): Promise<void> { async archiveOld(): Promise<void> {
//fetches archived timesheet's Ids //fetches archived timesheet's Ids
const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({ const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({
@ -130,4 +131,14 @@ export class ShiftsService {
}) })
} }
//fetches all archived timesheets
async findAllArchived(): Promise<ShiftsArchive[]> {
return this.prisma.shiftsArchive.findMany();
}
//fetches an archived timesheet
async findOneArchived(id: number): Promise<ShiftsArchive> {
return this.prisma.shiftsArchive.findUniqueOrThrow({ where: { id } });
}
} }

View File

@ -1,7 +1,7 @@
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service'; import { PrismaService } from 'src/prisma/prisma.service';
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto'; import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
import { Timesheets } from '@prisma/client'; import { Timesheets, TimesheetsArchive } from '@prisma/client';
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto'; import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
@Injectable() @Injectable()
@ -75,7 +75,8 @@ export class TimesheetsService {
} }
//Archivation function //archivation functions ******************************************************
async archiveOld(): Promise<void> { async archiveOld(): Promise<void> {
//calcul du cutoff pour archivation //calcul du cutoff pour archivation
const cutoff = new Date(); const cutoff = new Date();
@ -115,4 +116,14 @@ export class TimesheetsService {
}); });
}); });
} }
//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 } });
}
} }