Skip to content
3 changes: 2 additions & 1 deletion backend/typescript/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import userResolvers from "./resolvers/userResolvers";
import userType from "./types/userType";
import reviewDashboardResolvers from "./resolvers/reviewDashboardResolvers";
import reviewDashboardType from "./types/reviewDashboardType";
import reviewedApplicantRecordResolvers from "./resolvers/reviewedApplicantRecordResolvers";
import reviewedApplicantRecordTypes from "./types/reviewedApplicantRecordTypes";
import reviewedApplicantRecordResolvers from "./resolvers/reviewedApplicantRecordResolver";
import adminCommentResolvers from "./resolvers/adminCommentsResolvers";
import adminCommentType from "./types/adminCommentsType";
import applicantRecordResolvers from "./resolvers/applicantRecordResolvers";
Expand Down Expand Up @@ -103,6 +103,7 @@ const graphQLMiddlewares = {
createAdminComment: authorizedByAdmin(),
updateAdminComment: authorizedByAdmin(),
deleteAdminCommentById: authorizedByAdmin(),
updateReviewStatus: authorizedByAllRoles(),
},
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import ReviewedApplicantRecordService from "../../services/implementations/reviewedApplicantRecordService";
import IReviewedApplicantRecordService from "../../services/interfaces/reviewedApplicantRecordService";
import {
ReviewedApplicantRecordDTO,
CreateReviewedApplicantRecordDTO,
DeleteReviewedApplicantRecordDTO,
ReviewStatus,
} from "../../types";
import { getErrorMessage } from "../../utilities/errorUtils";

const reviewedApplicantRecordService = new ReviewedApplicantRecordService();
const reviewedApplicantRecordService: IReviewedApplicantRecordService =
new ReviewedApplicantRecordService();

const reviewedApplicantRecordResolvers = {
Mutation: {
Expand Down Expand Up @@ -61,6 +64,25 @@ const reviewedApplicantRecordResolvers = {
throw new Error(getErrorMessage(error));
}
},

updateReviewStatus: async (
_parent: undefined,
{
applicantRecordId,
reviewerId,
status,
}: {
applicantRecordId: string;
reviewerId: number;
status: ReviewStatus;
},
): Promise<ReviewedApplicantRecordDTO> => {
return reviewedApplicantRecordService.updateReviewStatus(
applicantRecordId,
reviewerId,
status,
);
},
},
};

Expand Down
17 changes: 15 additions & 2 deletions backend/typescript/graphql/types/reviewedApplicantRecordTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ const reviewedApplicantRecordTypes = gql`
SENIOR
}

enum ReviewStatus {
NeedsReview
InProgress
Done
ConflictReported
}

type Review {
passionFSG: Int
teamPlayer: Int
Expand All @@ -28,7 +35,7 @@ const reviewedApplicantRecordTypes = gql`
applicantRecordId: ID!
reviewerId: Int!
review: Review
status: String
status: ReviewStatus
score: Int
reviewerHasConflict: Boolean
}
Expand All @@ -37,7 +44,7 @@ const reviewedApplicantRecordTypes = gql`
applicantRecordId: ID!
reviewerId: Int!
review: ReviewInput
status: String
status: ReviewStatus
}

input DeleteReviewedApplicantRecord {
Expand All @@ -61,6 +68,12 @@ const reviewedApplicantRecordTypes = gql`
bulkDeleteReviewedApplicantRecord(
inputs: [DeleteReviewedApplicantRecord!]!
): [ReviewedApplicantRecord!]!

updateReviewStatus(
applicantRecordId: ID!
reviewerId: Int!
status: ReviewStatus!
): ReviewedApplicantRecord!
}
`;

Expand Down
9 changes: 2 additions & 7 deletions backend/typescript/models/reviewedApplicantRecord.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ import {
BelongsTo,
} from "sequelize-typescript";
import { NonAttribute } from "sequelize";
import {
Review,
ReviewStatus,
ReviewStatusEnum,
SkillCategory,
} from "../types";
import { Review, ReviewStatus, SkillCategory } from "../types";
import ApplicantRecord from "./applicantRecord.model";
import User from "./user.model";

Expand All @@ -33,7 +28,7 @@ export default class ReviewedApplicantRecord extends Model {

@Column({
type: DataType.STRING,
defaultValue: ReviewStatusEnum.TODO,
defaultValue: "NeedsReview",
})
status!: ReviewStatus;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import {
ReviewedApplicantRecordDTO,
CreateReviewedApplicantRecordDTO,
DeleteReviewedApplicantRecordDTO,
ReviewStatus,
} from "../../types";
import { getErrorMessage } from "../../utilities/errorUtils";
import logger from "../../utilities/logger";
import IReviewApplicantRecordService from "../interfaces/IReviewedApplicantRecordService";
import IReviewedApplicantRecordService from "../interfaces/reviewedApplicantRecordService";

const Logger = logger(__filename);

class ReviewedApplicantRecordService implements IReviewApplicantRecordService {
class ReviewedApplicantRecordService
implements IReviewedApplicantRecordService
{
/* eslint-disable class-methods-use-this */

async createReviewedApplicantRecord(
dto: CreateReviewedApplicantRecordDTO,
): Promise<ReviewedApplicantRecordDTO> {
Expand Down Expand Up @@ -60,8 +64,7 @@ class ReviewedApplicantRecordService implements IReviewApplicantRecordService {
deleteReviewedApplicantRecord: DeleteReviewedApplicantRecordDTO,
): Promise<ReviewedApplicantRecordDTO> {
try {
const { applicantRecordId } = deleteReviewedApplicantRecord;
const { reviewerId } = deleteReviewedApplicantRecord;
const { applicantRecordId, reviewerId } = deleteReviewedApplicantRecord;
const record = await ReviewedApplicantRecord.findOne({
where: { applicantRecordId, reviewerId },
});
Expand Down Expand Up @@ -121,6 +124,38 @@ class ReviewedApplicantRecordService implements IReviewApplicantRecordService {
throw error;
}
}

async updateReviewStatus(
applicantRecordId: string,
reviewerId: number,
status: ReviewStatus,
): Promise<ReviewedApplicantRecordDTO> {
const applicantRecord = await ReviewedApplicantRecord.findOne({
where: { applicantRecordId, reviewerId },
});
if (!applicantRecord) {
throw new Error(
`ReviewedApplicantRecord with applicantRecordId ${applicantRecordId} and reviewerId ${reviewerId} not found.`,
);
}
try {
applicantRecord.status = status;
await applicantRecord.save();
return {
applicantRecordId: applicantRecord.applicantRecordId,
reviewerId: applicantRecord.reviewerId,
review: applicantRecord.review,
status: applicantRecord.status,
score: applicantRecord.score,
reviewerHasConflict: applicantRecord.reviewerHasConflict,
};
} catch (error: unknown) {
Logger.error(
`Failed to update review status. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
}
}

export default ReviewedApplicantRecordService;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApplicantRecordDTO } from "../../types";
import { ApplicantRecordDTO, ApplicationStatus } from "../../types";

interface IApplicantRecordService {
updateApplicantStatus(
Expand All @@ -8,7 +8,7 @@ interface IApplicantRecordService {
bulkUpdateApplicantStatus(
applicantRecordIds: string[],
status: ApplicationStatus,
): Promise<ApplicantRecordDto[]>;
): Promise<ApplicantRecordDTO[]>;
setApplicantRecordFlag(
applicantRecordId: string,
flagValue: boolean,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {
ReviewedApplicantRecordDTO,
ReviewStatus,
CreateReviewedApplicantRecordDTO,
DeleteReviewedApplicantRecordDTO,
} from "../../types";

interface IReviewApplicantRecordService {
interface IReviewedApplicantRecordService {
/**
* Creates a single reviewed applicant record entry
* @Param createReviewedApplicantRecordDTO data to create reviewed applicant record
Expand Down Expand Up @@ -37,6 +38,18 @@ interface IReviewApplicantRecordService {
bulkDeleteReviewedApplicantRecord(
deleteReviewedApplicantRecords: DeleteReviewedApplicantRecordDTO[],
): Promise<ReviewedApplicantRecordDTO[]>;

/**
* Updates the review status of a reviewed applicant record
* @Param applicantRecordId the ID of the applicant record to update
* @Param reviewerId the ID of the reviewer
* @Param status the new review status to set
*/
updateReviewStatus(
applicantRecordId: string,
reviewerId: number,
status: ReviewStatus,
): Promise<ReviewedApplicantRecordDTO>;
}

export default IReviewApplicantRecordService;
export default IReviewedApplicantRecordService;
7 changes: 6 additions & 1 deletion backend/typescript/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,19 @@ export type ProductPositionTitle = (typeof ProductPositionTitles)[number];
export type CommunityPositionTitle = (typeof CommunityPositionTitles)[number];
export type PositionTitle = (typeof PositionTitles)[number];

// Legacy, needed for migrations
export enum ReviewStatusEnum {
TODO = "Todo",
IN_PROGRESS = "In Progress",
DONE = "Done",
CONFLICT = "Conflict",
}

export type ReviewStatus = `${ReviewStatusEnum}`;
export type ReviewStatus =
| "NeedsReview"
| "InProgress"
| "Done"
| "ConflictReported";

export type Review = {
passionFSG?: number;
Expand Down
Loading