diff --git a/apps/backend/src/applications/applications.controller.ts b/apps/backend/src/applications/applications.controller.ts index a8c894a..7b5a17d 100644 --- a/apps/backend/src/applications/applications.controller.ts +++ b/apps/backend/src/applications/applications.controller.ts @@ -12,7 +12,7 @@ import { NotFoundException, UnauthorizedException, } from '@nestjs/common'; -import { Response } from './types'; +import { Decision, Response } from './types'; import { ApplicationsService } from './applications.service'; import { CurrentUserInterceptor } from '../interceptors/current-user.interceptor'; import { AuthGuard } from '@nestjs/passport'; @@ -40,6 +40,27 @@ export class ApplicationsController { return await this.applicationsService.submitApp(application, user); } + @Post('/decision/:appId') + @UseGuards(AuthGuard('jwt')) + async makeDecision( + @Param('appId', ParseIntPipe) applicantId: number, + @Body('decision') decision: Decision, + @Request() req, + ): Promise { + //Authorization check for admin and recruiters + if (![UserStatus.ADMIN, UserStatus.RECRUITER].includes(req.user.status)) { + throw new UnauthorizedException(); + } + + //Check if the string decision matches with the Decision enum + const decisionEnum: Decision = Decision[decision]; + if (!decisionEnum) { + throw new BadRequestException('Invalid decision value'); + } + + //Delegate the decision making to the service. + await this.applicationsService.processDecision(applicantId, decisionEnum); + } @UseGuards(AuthGuard('jwt')) @Get('/') async getApplications( diff --git a/apps/backend/src/applications/applications.service.ts b/apps/backend/src/applications/applications.service.ts index 45868f6..593a4ea 100644 --- a/apps/backend/src/applications/applications.service.ts +++ b/apps/backend/src/applications/applications.service.ts @@ -13,11 +13,12 @@ import { getCurrentSemester, getCurrentYear, } from './utils'; -import { Response } from './types'; +import { Decision, 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'; +import { stagesMap } from './applications.constants'; @Injectable() export class ApplicationsService { @@ -94,6 +95,37 @@ export class ApplicationsService { throw new UnauthorizedException(); } + /** + * Updates the application stage of the applicant. + * Moves the stage to either the next stage or to rejected. + * + * @param applicantId the id of the applicant. + * @param decision enum that contains either the applicant was 'ACCEPT' or 'REJECT' + * @returns { void } only updates the stage of the applicant. + */ + async processDecision( + applicantId: number, + decision: Decision, + ): Promise { + const application = await this.findCurrent(applicantId); + + let newStage: ApplicationStage; + if (decision === Decision.REJECT) { + newStage = ApplicationStage.REJECTED; + } else { + const stagesArr = stagesMap[application.position]; + const stageIndex = stagesArr.indexOf(application.stage); + if (stageIndex === -1) { + return; + } + newStage = stagesArr[stageIndex + 1]; + } + application.stage = newStage; + + //Save the updated stage + await this.applicationsRepository.save(application); + } + async findAll(userId: number): Promise { const apps = await this.applicationsRepository.find({ where: { user: { id: userId } }, diff --git a/apps/backend/src/applications/types.ts b/apps/backend/src/applications/types.ts index 3ae67ab..ebc0a69 100644 --- a/apps/backend/src/applications/types.ts +++ b/apps/backend/src/applications/types.ts @@ -30,3 +30,8 @@ export enum Position { PM = 'PRODUCT_MANAGER', DESIGNER = 'DESIGNER', } + +export enum Decision { + ACCEPT = 'ACCEPT', + REJECT = 'REJECT', +}