Skip to content

Commit 55e0c86

Browse files
committed
Merge branch 'main' of https://github.com/uwblueprint/website-bp-be into INTF25-resolve-conflict-mutator
2 parents 1fefa5a + c5ef398 commit 55e0c86

File tree

7 files changed

+140
-33
lines changed

7 files changed

+140
-33
lines changed

backend/typescript/graphql/resolvers/applicantRecordResolvers.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,41 @@
11
import ApplicantRecordService from "../../services/implementations/applicantRecordService";
22
import IApplicantRecordService from "../../services/interfaces/applicantRecordService";
3-
import { ApplicantRecordDTO } from "../../types";
3+
import { ApplicantRecordDTO, ApplicationStatus } from "../../types";
44
import { getErrorMessage } from "../../utilities/errorUtils";
55

66
const applicantRecordService: IApplicantRecordService =
77
new ApplicantRecordService();
88

99
const applicantRecordResolvers = {
1010
Mutation: {
11+
updateApplicantStatus: async (
12+
_parent: undefined,
13+
{
14+
applicantRecordId,
15+
status,
16+
}: { applicantRecordId: string; status: ApplicationStatus },
17+
): Promise<ApplicantRecordDTO> => {
18+
const applicantRecord =
19+
await applicantRecordService.updateApplicantStatus(
20+
applicantRecordId,
21+
status,
22+
);
23+
return applicantRecord;
24+
},
25+
bulkUpdateApplicantStatus: async (
26+
_parent: undefined,
27+
{
28+
applicantRecordIds,
29+
status,
30+
}: { applicantRecordIds: string[]; status: ApplicationStatus },
31+
): Promise<ApplicantRecordDTO[]> => {
32+
const applicantRecords =
33+
await applicantRecordService.bulkUpdateApplicantStatus(
34+
applicantRecordIds,
35+
status,
36+
);
37+
return applicantRecords;
38+
},
1139
setApplicantRecordFlag: async (
1240
_parent: undefined,
1341
{

backend/typescript/graphql/types/applicantRecordType.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
11
import { gql } from "apollo-server-express";
22

33
const applicantRecordType = gql`
4+
enum ApplicationStatus {
5+
Applied
6+
InReview
7+
Reviewed
8+
Selected
9+
Interviewed
10+
Offer
11+
Rejected
12+
}
13+
414
type ApplicantRecordDTO {
515
id: String!
616
applicantId: String!
717
position: String!
818
roleSpecificQuestions: [String!]!
919
choice: Int!
10-
status: String!
20+
status: ApplicationStatus!
1121
skillCategory: String
1222
combined_score: Int
1323
isApplicantFlagged: Boolean!
1424
}
1525
1626
extend type Mutation {
27+
updateApplicantStatus(
28+
applicantRecordId: String!
29+
status: ApplicationStatus!
30+
): ApplicantRecordDTO!
31+
bulkUpdateApplicantStatus(
32+
applicantRecordIds: [String!]!
33+
status: ApplicationStatus!
34+
): [ApplicantRecordDTO!]!
1735
setApplicantRecordFlag(
1836
applicantRecordId: String!
1937
flagValue: Boolean!

backend/typescript/graphql/types/reviewDashboardType.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ const reviewDashboardType = gql`
1717
totalScore: Int
1818
}
1919
20-
type Review {
21-
passionFSG: Int
22-
teamPlayer: Int
23-
desireToLearn: Int
24-
skill: Int
25-
skillCategory: String
26-
comments: String
27-
}
28-
2920
type ReviewDetails {
3021
reviewerFirstName: String!
3122
reviewerLastName: String!

backend/typescript/graphql/types/reviewedApplicantRecordTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const reviewedApplicantRecordTypes = gql`
1313
desireToLearn: Int
1414
skill: Int
1515
skillCategory: SkillCategory
16+
comments: String
1617
}
1718
1819
input ReviewInput {

backend/typescript/services/implementations/applicantRecordService.ts

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,98 @@
1-
import { ApplicantRecordDTO, PositionTitle } from "../../types";
1+
import {
2+
ApplicantRecordDTO,
3+
PositionTitle,
4+
ApplicationStatus,
5+
} from "../../types";
26
import { getErrorMessage } from "../../utilities/errorUtils";
37
import logger from "../../utilities/logger";
48
import ApplicantRecord from "../../models/applicantRecord.model";
59
import IApplicantRecordService from "../interfaces/applicantRecordService";
10+
import { sequelize } from "../../models";
611

712
const Logger = logger(__filename);
813

14+
function toDTO(applicantRecord: ApplicantRecord): ApplicantRecordDTO {
15+
return {
16+
id: String(applicantRecord.id),
17+
applicantId: String(applicantRecord.applicantId),
18+
position: applicantRecord.position as PositionTitle,
19+
roleSpecificQuestions: applicantRecord.roleSpecificQuestions,
20+
choice: applicantRecord.choice,
21+
status: applicantRecord.status,
22+
skillCategory: applicantRecord.skillCategory,
23+
combined_score: applicantRecord.combined_score,
24+
isApplicantFlagged: applicantRecord.isApplicantFlagged,
25+
};
26+
}
27+
28+
export const getApplicantRecord = async (
29+
applicantRecordId: string,
30+
): Promise<ApplicantRecord> => {
31+
const applicantRecord = await ApplicantRecord.findByPk(applicantRecordId);
32+
if (!applicantRecord) {
33+
throw new Error(`ApplicantRecord with id ${applicantRecordId} not found.`);
34+
}
35+
return applicantRecord;
36+
};
37+
938
class ApplicantRecordService implements IApplicantRecordService {
1039
/* eslint-disable class-methods-use-this */
40+
41+
async updateApplicantStatus(
42+
applicantRecordId: string,
43+
status: ApplicationStatus,
44+
): Promise<ApplicantRecordDTO> {
45+
try {
46+
const applicantRecord = await getApplicantRecord(applicantRecordId);
47+
applicantRecord.status = status;
48+
await applicantRecord.save();
49+
return toDTO(applicantRecord);
50+
} catch (error: unknown) {
51+
Logger.error(
52+
`Failed to update applicant record status. Reason = ${getErrorMessage(
53+
error,
54+
)}`,
55+
);
56+
throw error;
57+
}
58+
}
59+
60+
async bulkUpdateApplicantStatus(
61+
applicantRecordIds: string[],
62+
status: ApplicationStatus,
63+
): Promise<ApplicantRecordDTO[]> {
64+
const transaction = await sequelize.transaction();
65+
try {
66+
const updatedRecords = await Promise.all(
67+
applicantRecordIds.map(async (id) => {
68+
const applicantRecord = await getApplicantRecord(id);
69+
applicantRecord.status = status;
70+
await applicantRecord.save({ transaction });
71+
return toDTO(applicantRecord);
72+
}),
73+
);
74+
await transaction.commit();
75+
return updatedRecords;
76+
} catch (error: unknown) {
77+
await transaction.rollback();
78+
Logger.error(
79+
`Failed to update applicant record statuses. Reason = ${getErrorMessage(
80+
error,
81+
)}`,
82+
);
83+
throw error;
84+
}
85+
}
86+
1187
async setApplicantRecordFlag(
1288
applicantRecordId: string,
1389
flagValue: boolean,
1490
): Promise<ApplicantRecordDTO> {
1591
try {
16-
const applicantRecord = await ApplicantRecord.findByPk(applicantRecordId);
17-
if (!applicantRecord) {
18-
throw new Error(
19-
`ApplicantRecord with id ${applicantRecordId} not found.`,
20-
);
21-
}
92+
const applicantRecord = await getApplicantRecord(applicantRecordId);
2293
applicantRecord.isApplicantFlagged = flagValue;
2394
await applicantRecord.save();
24-
return {
25-
id: String(applicantRecord.id),
26-
applicantId: String(applicantRecord.applicantId),
27-
position: applicantRecord.position as PositionTitle,
28-
roleSpecificQuestions: applicantRecord.roleSpecificQuestions,
29-
choice: applicantRecord.choice,
30-
status: applicantRecord.status,
31-
skillCategory: applicantRecord.skillCategory,
32-
combined_score: applicantRecord.combined_score,
33-
isApplicantFlagged: applicantRecord.isApplicantFlagged,
34-
};
95+
return toDTO(applicantRecord);
3596
} catch (error: unknown) {
3697
Logger.error(
3798
`Failed to set applicant record flag. Reason = ${getErrorMessage(

backend/typescript/services/interfaces/applicantRecordService.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { ApplicantRecordDTO } from "../../types";
22

33
interface IApplicantRecordService {
4+
updateApplicantStatus(
5+
applicantRecordId: string,
6+
status: ApplicationStatus,
7+
): Promise<ApplicantRecordDTO>;
8+
bulkUpdateApplicantStatus(
9+
applicantRecordIds: string[],
10+
status: ApplicationStatus,
11+
): Promise<ApplicantRecordDto[]>;
412
setApplicantRecordFlag(
513
applicantRecordId: string,
614
flagValue: boolean,

backend/typescript/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ export type ApplicantRecordDTO = {
9090

9191
export type ApplicationStatus =
9292
| "Applied"
93-
| "In Review"
93+
| "InReview"
9494
| "Reviewed"
95-
| "Interview"
96-
| "Interview Complete"
95+
| "Selected"
96+
| "Interviewed"
9797
| "Offer"
98-
| "Not Considered";
98+
| "Rejected";
9999

100100
export type SkillCategory = "Junior" | "Intermediate" | "Senior";
101101

0 commit comments

Comments
 (0)