Skip to content

Commit

Permalink
feat: getAllApplications endpoint (#50)
Browse files Browse the repository at this point in the history
* feat: getAllAplications endpoint resolves #44

* made Cycle fields private, and created env vars for year/semester

* Application Summary DTO

* feat: completed getAllApplications endpoint

* fix: updated semester logic

* fix: updated current semester function and dto mapping

---------

Co-authored-by: Jonathan Chen <[email protected]>
Co-authored-by: Harrison Kim <[email protected]>
  • Loading branch information
3 people authored Mar 19, 2024
1 parent 85fdaad commit 756de32
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 4 deletions.
1 change: 0 additions & 1 deletion apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 18 additions & 0 deletions apps/backend/src/applications/application.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
21 changes: 21 additions & 0 deletions apps/backend/src/applications/applications.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Body,
BadRequestException,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import { Response } from './types';
import { ApplicationsService } from './applications.service';
Expand All @@ -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)
Expand All @@ -38,6 +40,25 @@ export class ApplicationsController {
return await this.applicationsService.submitApp(application, user);
}

@UseGuards(AuthGuard('jwt'))
@Get('/')
async getApplications(
@Request() req,
): Promise<GetAllApplicationResponseDTO[]> {
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(
Expand Down
24 changes: 23 additions & 1 deletion apps/backend/src/applications/applications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -97,6 +103,22 @@ export class ApplicationsService {
return apps;
}

async findAllCurrentApplications(): Promise<GetAllApplicationResponseDTO[]> {
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<Application> {
const apps = await this.findAll(userId);
const currentApp = getAppForCurrentCycle(apps);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
16 changes: 14 additions & 2 deletions apps/backend/src/applications/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[],
Expand Down

0 comments on commit 756de32

Please sign in to comment.