-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: controller, Service, Entity, Module, for interview
- Loading branch information
none
authored and
none
committed
Dec 15, 2023
1 parent
4dc60a1
commit a9eb49f
Showing
9 changed files
with
307 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Interview } from '@hkrecruitment/shared'; | ||
import { User } from '../users/user.entity' | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
|
||
|
||
export class CreateInterviewDto implements Partial<Interview> { | ||
@ApiProperty() | ||
notes: string; | ||
|
||
@ApiProperty() | ||
created_at: Date; | ||
|
||
@ApiProperty() | ||
id_timeslot: number; | ||
|
||
@ApiProperty() | ||
interviewer_1: User; | ||
|
||
@ApiProperty() | ||
interviewer_2: User; | ||
|
||
@ApiProperty({ required: false }) | ||
optional_interviewer?: User; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { | ||
Get, | ||
Param, | ||
ForbiddenException, | ||
NotFoundException, | ||
Controller, | ||
Patch, | ||
Body, | ||
Post, | ||
Req, | ||
Delete | ||
} from '@nestjs/common'; | ||
import { Interview } from './interview.entity'; | ||
import { InterviewService } from './interview.Service'; | ||
import { CreateInterviewDto } from './create-interview.dto'; | ||
import { UpdateInterviewDto } from './update-interview.dto'; | ||
import { | ||
Action, | ||
AppAbility, | ||
checkAbility, | ||
createInterviewSchema, | ||
updateInterviewSchema, | ||
} from '@hkrecruitment/shared'; | ||
import { JoiValidate } from 'src/joi-validation/joi-validate.decorator'; | ||
import { | ||
ApiBadRequestResponse, | ||
ApiBearerAuth, | ||
ApiNotFoundResponse, | ||
ApiTags, | ||
} from '@nestjs/swagger'; | ||
import { AuthenticatedRequest } from 'src/authorization/authenticated-request.types'; | ||
import * as Joi from 'joi'; | ||
import { CheckPolicies } from 'src/authorization/check-policies.decorator'; | ||
import { Ability } from 'src/authorization/ability.decorator'; | ||
|
||
@ApiBearerAuth() | ||
@ApiTags('interview') | ||
@Controller('interview') | ||
|
||
export class InterviewController { | ||
constructor(private readonly interviewService: InterviewService) {} | ||
|
||
@ApiNotFoundResponse() | ||
@ApiBadRequestResponse() | ||
@Get(':Id') | ||
@JoiValidate({ | ||
param: Joi.number().required(), | ||
}) | ||
@CheckPolicies((ability) => ability.can(Action.Read, 'Interview')) | ||
async findById( | ||
@Param('Id') Id: number, | ||
@Ability() ability: AppAbility, | ||
): Promise<Interview> { | ||
const interview = await this.interviewService.findById(Id); | ||
if (interview === null) { | ||
throw new NotFoundException(); | ||
} | ||
if (!checkAbility(ability, Action.Read, interview, 'Interview')) { | ||
throw new ForbiddenException(); | ||
} | ||
return interview; | ||
} | ||
|
||
@ApiNotFoundResponse() | ||
@ApiBadRequestResponse() | ||
@Delete(':Id') | ||
@JoiValidate({ | ||
param: Joi.number().required(), | ||
}) | ||
@CheckPolicies((ability) => ability.can(Action.Delete, 'Interview')) | ||
async delete( | ||
@Param('Id') Id: number, | ||
@Ability() ability: AppAbility, | ||
): Promise<Interview> { | ||
const interview = await this.interviewService.findById(Id); | ||
if (interview === null) { | ||
throw new NotFoundException(); | ||
} | ||
return this.interviewService.delete(interview); | ||
} | ||
|
||
@ApiNotFoundResponse() | ||
@ApiBadRequestResponse() | ||
@Patch(':Id') | ||
@JoiValidate({ | ||
body: updateInterviewSchema, | ||
param: Joi.number().required(), | ||
}) | ||
@CheckPolicies((ability) => ability.can(Action.Update, 'Interview')) | ||
async update( | ||
@Param('Id') Id: number, | ||
@Body() updateInterview: UpdateInterviewDto, | ||
@Ability() ability: AppAbility, | ||
@Req() req: AuthenticatedRequest, | ||
): Promise<Interview> { | ||
const interview = await this.interviewService.findById(Id); | ||
if (interview === null) { | ||
throw new NotFoundException(); | ||
} | ||
return this.interviewService.update({ | ||
...interview, | ||
...updateInterview, | ||
}); | ||
} | ||
|
||
@ApiNotFoundResponse() | ||
@ApiBadRequestResponse() | ||
@Post() | ||
@JoiValidate({ | ||
body: createInterviewSchema, | ||
}) | ||
async create( | ||
@Body() interview: CreateInterviewDto, | ||
@Ability() ability: AppAbility, | ||
@Req() req: AuthenticatedRequest, | ||
): Promise<Interview> { | ||
if (!checkAbility(ability, Action.Create, interview, 'Interview')){ | ||
throw new ForbiddenException()}; | ||
return this.interviewService.create({ | ||
|
||
}); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; | ||
import {Interview as InterviewSlot} from '@hkrecruitment/shared'; | ||
import {User} from '../users/user.entity'; | ||
import { TimeSlot } from '../timeslots/timeslot.entity'; | ||
import { Application } from '../application/application.entity'; | ||
|
||
@Entity() | ||
export class Interview implements InterviewSlot { | ||
@PrimaryGeneratedColumn('increment') | ||
id: number; | ||
|
||
@Column() | ||
notes: string; | ||
|
||
@Column() | ||
created_at: Date; | ||
|
||
@Column() | ||
timeslot: TimeSlot; | ||
|
||
@Column() | ||
application: Application; | ||
|
||
@Column() | ||
interviewer_1: User; | ||
|
||
@Column() | ||
interviewer_2: User; | ||
|
||
@Column({nullable: true}) | ||
optional_interviewer?: User; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { InterviewService } from './interview.service'; | ||
import { InterviewController } from './interview.controller'; | ||
import { TypeOrmModule } from '@nestjs/typeorm'; | ||
import { Interview } from './interview.entity'; | ||
|
||
@Module({ | ||
imports: [TypeOrmModule.forFeature([Interview])], | ||
providers: [InterviewService], | ||
controllers: [InterviewController], | ||
exports: [InterviewService], | ||
}) | ||
export class InterviewModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Interview } from "./interview.entity" | ||
import { Application } from "../application/application.entity"; | ||
import { TimeSlot } from "../timeslots/timeslot.entity"; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { Repository } from 'typeorm'; | ||
import { CreateInterviewDto } from "./create-interview.dto"; | ||
|
||
@Injectable() | ||
export class InterviewService { | ||
constructor( | ||
@InjectRepository(Interview) | ||
private readonly interviewRepository: Repository<Interview>, | ||
) {} | ||
|
||
async findById(id: number): Promise<Interview | null> { | ||
return this.interviewRepository.findOne({ where: { id } }); | ||
} | ||
|
||
async delete(interview: Interview): Promise<Interview> { | ||
return await this.interviewRepository.remove(interview); | ||
} | ||
|
||
async create(interview: CreateInterviewDto, application: Application, timeslot: TimeSlot): Promise<Interview> { | ||
return await this.interviewRepository.save(interview); | ||
} | ||
|
||
async update(interview: Interview): Promise<Interview> { | ||
return await this.interviewRepository.save(interview); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { ApiProperty, PartialType } from '@nestjs/swagger'; | ||
import { Interview } from '@hkrecruitment/shared'; | ||
import { User } from '../users/user.entity' | ||
import { TimeSlot } from '../timeslots/timeslot.entity'; | ||
import { Application } from '../application/application.entity'; | ||
|
||
export class UpdateInterviewDto implements Partial<Interview>{ | ||
@ApiProperty({required: false}) | ||
notes: string; | ||
|
||
@ApiProperty({required: false}) | ||
created_at: Date; | ||
|
||
@ApiProperty({required: false}) | ||
timeslot: TimeSlot; | ||
|
||
@ApiProperty({required: false}) | ||
application: Application; | ||
|
||
@ApiProperty({required: false}) | ||
interviewer_1: User; | ||
|
||
@ApiProperty({required: false}) | ||
interviewer_2: User; | ||
|
||
@ApiProperty({ required: false }) | ||
optional_interviewer?: User; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Person, createUserSchema, updateUserSchema, Role } from "./person"; | ||
import { TimeSlot, createTimeSlotSchema } from "timeslot"; | ||
import { Application, createApplicationSchema, updateApplicationSchema } from "application"; | ||
import { Action, ApplyAbilities } from "./abilities"; | ||
import * as Joi from "joi"; | ||
|
||
export interface Interview { | ||
id: number; | ||
notes: string; | ||
created_at: Date; | ||
timeslot: TimeSlot; | ||
application: Application; | ||
interviewer_1: Person; | ||
interviewer_2: Person; | ||
optional_interviewer?: Person; | ||
}; | ||
|
||
export const createInterviewSchema = Joi.object<Interview>({ | ||
notes: Joi.string().required(), | ||
created_at: Joi.date().required(), | ||
interviewer_1: createUserSchema.required(), | ||
interviewer_2: createUserSchema.required(), | ||
optional_interviewer: createUserSchema.optional(), | ||
}); | ||
|
||
export const updateInterviewSchema = Joi.object<Interview>({ | ||
notes: Joi.string().optional(), | ||
created_at: Joi.date().optional(), | ||
timeslot: createTimeSlotSchema.optional(), | ||
application: updateApplicationSchema.optional(), | ||
interviewer_1: updateUserSchema.optional(), | ||
interviewer_2: updateUserSchema.optional(), | ||
optional_interviewer: updateUserSchema.optional() | ||
}); | ||
|
||
export const applyAbilitiesOnInterview: ApplyAbilities = ( | ||
user, | ||
{ can, cannot } | ||
) => { | ||
if (user.role === Role.Admin || user.role === Role.Supervisor) { | ||
can(Action.Manage, "Interview"); | ||
} | ||
else{ | ||
cannot(Action.Manage, "Interview") | ||
} | ||
}; | ||
|