diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index 986ae34..a47cebe 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -13,7 +13,6 @@ import { ApplicationsModule } from './applications/applications.module'; imports: [ TypeOrmModule.forRoot({ type: 'postgres', - database: 'c4c-ops', host: process.env.NX_DB_HOST, port: 5432, username: process.env.NX_DB_USERNAME, diff --git a/apps/backend/src/applications/application.entity.ts b/apps/backend/src/applications/application.entity.ts index ae2cd5c..c59ceb8 100644 --- a/apps/backend/src/applications/application.entity.ts +++ b/apps/backend/src/applications/application.entity.ts @@ -17,6 +17,7 @@ import { } from './types'; import { GetApplicationResponseDTO } from './dto/get-application.response.dto'; import { Review } from '../reviews/review.entity'; +import { GetAllApplicationResponseDTO } from './dto/get-all-application.response.dto'; @Entity() export class Application { @@ -62,6 +63,23 @@ export class Application { @IsObject({ each: true }) reviews: Review[]; + toGetAllApplicationResponseDTO(): GetAllApplicationResponseDTO { + const meanRatingAllStages = 0; // TODO: calculate this + const meanRatingSingleStages = 0; // TODO: calculate this (should be an object) + + return { + userId: this.user.id, + firstName: this.user.firstName, + lastName: this.user.lastName, + stage: this.stage, + step: this.step, + position: this.position, + createdAt: this.createdAt, + meanRatingAllStages: meanRatingAllStages, + meanRatingSingleStages: meanRatingSingleStages, + }; + } + toGetApplicationResponseDTO(numApps: number): GetApplicationResponseDTO { return { id: this.id, diff --git a/apps/backend/src/applications/applications.controller.ts b/apps/backend/src/applications/applications.controller.ts index bfd8ee8..a8c894a 100644 --- a/apps/backend/src/applications/applications.controller.ts +++ b/apps/backend/src/applications/applications.controller.ts @@ -10,6 +10,7 @@ import { Body, BadRequestException, NotFoundException, + UnauthorizedException, } from '@nestjs/common'; import { Response } from './types'; import { ApplicationsService } from './applications.service'; @@ -19,6 +20,7 @@ import { GetApplicationResponseDTO } from './dto/get-application.response.dto'; import { getAppForCurrentCycle } from './utils'; import { UserStatus } from '../users/types'; import { Application } from './application.entity'; +import { GetAllApplicationResponseDTO } from './dto/get-all-application.response.dto'; @Controller('apps') @UseInterceptors(CurrentUserInterceptor) @@ -38,6 +40,25 @@ export class ApplicationsController { return await this.applicationsService.submitApp(application, user); } + @UseGuards(AuthGuard('jwt')) + @Get('/') + async getApplications( + @Request() req, + ): Promise { + if ( + !( + req.user.status === UserStatus.RECRUITER || + req.user.status === UserStatus.ADMIN + ) + ) { + throw new UnauthorizedException( + 'Calling user is not a recruiter or admin.', + ); + } + + return this.applicationsService.findAllCurrentApplications(); + } + @Get('/:userId') @UseGuards(AuthGuard('jwt')) async getApplication( diff --git a/apps/backend/src/applications/applications.service.ts b/apps/backend/src/applications/applications.service.ts index 70243c0..45868f6 100644 --- a/apps/backend/src/applications/applications.service.ts +++ b/apps/backend/src/applications/applications.service.ts @@ -7,11 +7,17 @@ import { InjectRepository } from '@nestjs/typeorm'; import { MongoRepository } from 'typeorm'; import { UsersService } from '../users/users.service'; import { Application } from './application.entity'; -import { getAppForCurrentCycle, getCurrentCycle } from './utils'; +import { + getAppForCurrentCycle, + getCurrentCycle, + getCurrentSemester, + getCurrentYear, +} from './utils'; import { Response } from './types'; import * as crypto from 'crypto'; import { User } from '../users/user.entity'; import { Position, ApplicationStage, ApplicationStep } from './types'; +import { GetAllApplicationResponseDTO } from './dto/get-all-application.response.dto'; @Injectable() export class ApplicationsService { @@ -97,6 +103,22 @@ export class ApplicationsService { return apps; } + async findAllCurrentApplications(): Promise { + const applications = await this.applicationsRepository.find({ + where: { + year: getCurrentYear(), + semester: getCurrentSemester(), + }, + relations: ['user'], + }); + + const dtos: GetAllApplicationResponseDTO[] = applications.map((app) => + app.toGetAllApplicationResponseDTO(), + ); + + return dtos; + } + async findCurrent(userId: number): Promise { const apps = await this.findAll(userId); const currentApp = getAppForCurrentCycle(apps); diff --git a/apps/backend/src/applications/dto/get-all-application.response.dto.ts b/apps/backend/src/applications/dto/get-all-application.response.dto.ts new file mode 100644 index 0000000..5ed0264 --- /dev/null +++ b/apps/backend/src/applications/dto/get-all-application.response.dto.ts @@ -0,0 +1,32 @@ +import { IsDate, IsEnum, IsPositive, IsString } from 'class-validator'; +import { ApplicationStage, ApplicationStep, Position } from '../types'; + +export class GetAllApplicationResponseDTO { + @IsPositive() + userId: number; + + @IsString() + firstName: string; + + @IsString() + lastName: string; + + @IsEnum(ApplicationStage) + stage: ApplicationStage; + + @IsEnum(ApplicationStep) + step: ApplicationStep; + + @IsEnum(Position) + position: Position; + + @IsDate() + createdAt: Date; + + @IsPositive() + meanRatingAllStages: number; + + // TODO: Should be a JSON or similar that defines scores for each stage + @IsPositive() + meanRatingSingleStages: number; +} diff --git a/apps/backend/src/applications/utils.ts b/apps/backend/src/applications/utils.ts index 6b45bf8..b24a353 100644 --- a/apps/backend/src/applications/utils.ts +++ b/apps/backend/src/applications/utils.ts @@ -2,8 +2,20 @@ import { Application } from './application.entity'; import { Cycle } from './dto/cycle'; import { Semester } from './types'; -// TODO get the current cycle's year and semester from env variables -export const getCurrentCycle = () => new Cycle(2024, Semester.SPRING); +export const getCurrentSemester = (): Semester => { + const month: number = new Date().getMonth(); + if (month >= 1 && month <= 7) { + return Semester.FALL; // We will be recruiting for the fall semester during Feb - Aug + } + return Semester.SPRING; // We will be recruiting for the spring semester during Sep - Jan +}; + +export const getCurrentYear = (): number => { + return new Date().getFullYear(); +}; + +export const getCurrentCycle = () => + new Cycle(getCurrentYear(), getCurrentSemester()); export const getAppForCurrentCycle = ( applications: Application[],