Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use stage interview students for stage interviews #2589

Merged
merged 2 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions nestjs/src/courses/courses.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
Team,
TaskVerification,
TeamDistributionStudent,
StageInterviewStudent,
} from '@entities/index';

import { UsersModule } from 'src/users';
Expand Down Expand Up @@ -74,28 +75,29 @@ import { ConfigModule } from '../config';
imports: [
CacheModule.register(),
TypeOrmModule.forFeature([
User,
Student,
Course,
CourseEvent,
CourseTask,
CourseUser,
Mentor,
StageInterview,
StageInterviewFeedback,
Course,
CourseTask,
StageInterviewStudent,
Student,
StudentFeedback,
Task,
CourseUser,
TaskChecker,
StudentFeedback,
TaskSolutionChecker,
TaskSolutionResult,
CourseEvent,
TaskSolution,
TaskResult,
TaskInterviewResult,
TaskInterviewStudent,
TaskResult,
TaskSolution,
TaskSolutionChecker,
TaskSolutionResult,
TaskVerification,
Team,
TeamDistribution,
TeamDistributionStudent,
Team,
TaskVerification,
User,
]),
CoreModule,
UsersModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { StageInterviewStudent } from '@entities/stageInterviewStudent';
import { TaskInterviewStudent } from '@entities/taskInterviewStudent';
import { ApiProperty } from '@nestjs/swagger';

export class RegistrationInterviewDto {
constructor(taskInterviewStudent: TaskInterviewStudent) {
constructor(taskInterviewStudent: TaskInterviewStudent | StageInterviewStudent) {
this.id = taskInterviewStudent.id;
this.registrationDate = taskInterviewStudent.createdDate;
}
Expand Down
23 changes: 11 additions & 12 deletions nestjs/src/courses/interviews/interviews.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { RegistrationInterviewDto } from './dto/registration-interview.dto';
@UseGuards(DefaultGuard, CourseGuard, RoleGuard)
export class InterviewsController {
constructor(
private courseTasksService: InterviewsService,
private interviewsService: InterviewsService,
private interviewFeedbackService: InterviewFeedbackService,
) {}

Expand All @@ -58,7 +58,7 @@ export class InterviewsController {
@Query('disabled') disabled?: boolean,
@Query('types', new ParseArrayPipe({ optional: true })) types?: string[],
) {
const data = await this.courseTasksService.getAll(courseId, {
const data = await this.interviewsService.getAll(courseId, {
disabled,
types: types as TaskType[],
});
Expand All @@ -74,7 +74,7 @@ export class InterviewsController {
@ApiParam({ name: 'courseId', type: Number })
@ApiOperation({ operationId: 'getInterview' })
public async getInterview(@Param('interviewId', ParseIntPipe) interviewId: number) {
const data = await this.courseTasksService.getById(interviewId);
const data = await this.interviewsService.getById(interviewId);
if (!data) {
throw new NotFoundException(`Interview ${interviewId} doesn't exist`);
}
Expand All @@ -93,19 +93,18 @@ export class InterviewsController {
@Req() req: CurrentRequest,
) {
const { user } = req;
const interview = await this.courseTasksService.getById(interviewId);
const interview = await this.interviewsService.getById(interviewId);

if (!interview) {
throw new NotFoundException(`Interview ${interviewId} doesn't exist`);
}
if (interview.studentRegistrationStartDate && new Date() < interview.studentRegistrationStartDate) {
throw new BadRequestException('Student registration is not available yet');
}
const taskInterviewStudent = await this.courseTasksService.registerStudentToInterview(
courseId,
interviewId,
user.githubId,
);
const taskInterviewStudent =
interview.type === TaskType.StageInterview
? await this.interviewsService.registerStudentToStageInterview(courseId, user.githubId)
: await this.interviewsService.registerStudentToInterview(courseId, interviewId, user.githubId);

return new RegistrationInterviewDto(taskInterviewStudent);
}
Expand All @@ -120,17 +119,17 @@ export class InterviewsController {
@Param('courseId', ParseIntPipe) courseId: number,
@Param('interviewId', ParseIntPipe) interviewId: number,
) {
const interview = await this.courseTasksService.getById(interviewId);
const interview = await this.interviewsService.getById(interviewId);

if (!interview) {
throw new NotFoundException(`Interview ${interviewId} doesn't exist`);
}
if (interview.type === 'stage-interview') {
return this.courseTasksService.getStageInterviewAvailableStudents(courseId);
return this.interviewsService.getStageInterviewAvailableStudents(courseId);
}

if (interview.type === 'interview') {
return this.courseTasksService.getInterviewRegisteredStudents(courseId, +interviewId);
return this.interviewsService.getInterviewRegisteredStudents(courseId, +interviewId);
}

throw new BadRequestException('Invalid interview id');
Expand Down
20 changes: 20 additions & 0 deletions nestjs/src/courses/interviews/interviews.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class InterviewsService {
readonly taskInterviewStudentRepository: Repository<TaskInterviewStudent>,
@InjectRepository(Student)
readonly studentRepository: Repository<Student>,
@InjectRepository(StageInterviewStudent)
readonly stageInterviewStudentRepository: Repository<StageInterviewStudent>,
) {}

public getAll(
Expand Down Expand Up @@ -92,6 +94,9 @@ export class InterviewsService {
}));
}

/**
* TODO: rewrite it. Hard to maintain and understand
*/
public async getStageInterviewAvailableStudents(courseId: number): Promise<AvailableStudentDto[]> {
const { entities, raw } = await this.studentRepository
.createQueryBuilder('student')
Expand Down Expand Up @@ -183,6 +188,21 @@ export class InterviewsService {
return stageInterviews.some(i => i.isCompleted && i.isGoodCandidate);
}

public async registerStudentToStageInterview(courseId: number, githubId: string) {
const student = await this.studentRepository.findOneOrFail({ where: { courseId, user: { githubId } } });
if (student.isExpelled) {
throw new BadRequestException('Student is expelled');
}

const studentId = student.id;
const record = await this.stageInterviewStudentRepository.findOne({ where: { courseId, studentId } });
if (record) {
throw new BadRequestException('Student is already registered');
}
await this.stageInterviewStudentRepository.insert({ courseId, studentId });
return this.stageInterviewStudentRepository.findOneByOrFail({ courseId, studentId });
}

public async registerStudentToInterview(courseId: number, courseTaskId: number, githubId: string) {
const student = await this.studentRepository.findOneOrFail({ where: { courseId, user: { githubId } } });
if (student.isExpelled) {
Expand Down
4 changes: 2 additions & 2 deletions server/src/models/stageInterviewStudent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export class StageInterviewStudent {
@PrimaryGeneratedColumn() id: number;

@CreateDateColumn()
createdDate: number;
createdDate: string;

@UpdateDateColumn()
updatedDate: number;
updatedDate: string;

@ManyToOne(_ => Student)
student: Student;
Expand Down
2 changes: 1 addition & 1 deletion server/src/models/taskInterviewStudent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class TaskInterviewStudent {
createdDate: string;

@UpdateDateColumn()
updatedDate: number;
updatedDate: string;

@ManyToOne(_ => Student)
student: Student;
Expand Down
9 changes: 0 additions & 9 deletions server/src/repositories/stageInterview.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,6 @@ export class StageInterviewRepository extends AbstractRepository<StageInterview>
}
}

public async addStudent(courseId: number, studentId: number) {
const repository = getRepository(StageInterviewStudent);
let record = await repository.findOne({ where: { courseId, studentId } });
if (record == null) {
record = await repository.save({ courseId, studentId });
}
return { id: record.id };
}

public async findStudent(courseId: number, studentId: number) {
const repository = getRepository(StageInterviewStudent);
const record = await repository.findOne({ where: { courseId, studentId } });
Expand Down
6 changes: 0 additions & 6 deletions server/src/routes/course/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,6 @@ function addStudentApi(router: Router<any, any>, logger: ILogger) {
...validators,
stageInterview.getInterviewStudent(logger),
);
router.post(
'/student/:githubId/interview/stage',
courseGuard,
...validators,
stageInterview.createInterviewStudent(logger),
);

router.get(
'/student/:githubId/interview/:courseTaskId',
Expand Down
23 changes: 0 additions & 23 deletions server/src/routes/course/stageInterview/createInterviewStudent.ts

This file was deleted.

1 change: 0 additions & 1 deletion server/src/routes/course/stageInterview/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export { createFeedback } from './createFeedback';
export { createInterview } from './createInterview';
export { createInterviews } from './createInterviews';
export { createInterviewStudent } from './createInterviewStudent';
export { cancelInterview } from './cancelInterview';
export { getFeedback } from './getFeedback';
export { getInterviewStudent } from './getInterviewStudent';
Expand Down
2 changes: 1 addition & 1 deletion setup/cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app": "npx ts-node App.ts",
"app": "npx tsx App.ts",
"context": {
"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
"@aws-cdk/core:stackRelativeExports": true,
Expand Down
Loading
Loading