Skip to content

Commit eceb651

Browse files
authored
Merge pull request #77 from uwblueprint/INTF25-fetch-application-review-page-query
[INTF25] Build fetch application review page query
2 parents ea91602 + 5582c1a commit eceb651

File tree

9 files changed

+151
-9
lines changed

9 files changed

+151
-9
lines changed

backend/typescript/graphql/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import reviewDashboardResolvers from "./resolvers/reviewDashboardResolvers";
1919
import reviewDashboardType from "./types/reviewDashboardType";
2020
import adminCommentResolvers from "./resolvers/adminCommentsResolvers";
2121
import adminCommentType from "./types/adminCommentsType";
22+
import reviewPageType from "./types/reviewPageType";
23+
import reviewPageResolvers from "./resolvers/reviewPageResolvers";
2224

2325
const query = gql`
2426
type Query {
@@ -42,6 +44,7 @@ const executableSchema = makeExecutableSchema({
4244
userType,
4345
reviewDashboardType,
4446
adminCommentType,
47+
reviewPageType,
4548
],
4649
resolvers: merge(
4750
authResolvers,
@@ -50,6 +53,7 @@ const executableSchema = makeExecutableSchema({
5053
userResolvers,
5154
reviewDashboardResolvers,
5255
adminCommentResolvers,
56+
reviewPageResolvers,
5357
),
5458
});
5559

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ApplicationDTO } from "../../types";
2+
import ReviewPageService from "../../services/implementations/reviewPageService";
3+
import { getErrorMessage } from "../../utilities/errorUtils";
4+
5+
const reviewPageService = new ReviewPageService();
6+
7+
const reviewPageResolvers = {
8+
Query: {
9+
reviewApplicantPage: async (
10+
_parent: undefined,
11+
args: { applicantRecordId: string },
12+
): Promise<ApplicationDTO> => {
13+
try {
14+
return await reviewPageService.getReviewPage(args.applicantRecordId);
15+
} catch (error) {
16+
throw new Error(getErrorMessage(error));
17+
}
18+
},
19+
},
20+
};
21+
22+
export default reviewPageResolvers;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { gql } from "apollo-server-express";
2+
3+
const reviewPageType = gql`
4+
type ApplicationDTO {
5+
id: Int!
6+
academicOrCoop: String!
7+
academicYear: String!
8+
email: String!
9+
firstChoiceRole: String!
10+
firstName: String!
11+
heardFrom: String!
12+
lastName: String!
13+
locationPreference: String!
14+
program: String!
15+
pronouns: String!
16+
pronounsSpecified: String!
17+
resumeUrl: String!
18+
roleSpecificQuestions: [String!]!
19+
secondChoiceRole: String!
20+
shortAnswerQuestions: [String!]!
21+
status: String!
22+
secondChoiceStatus: String!
23+
term: String!
24+
timesApplied: String!
25+
timestamp: Int
26+
}
27+
28+
extend type Query {
29+
reviewApplicantPage(applicantRecordId: String!): ApplicationDTO!
30+
}
31+
`;
32+
33+
export default reviewPageType;

backend/typescript/models/applicant.model.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ export default class Applicant extends Model {
5757
submittedAt!: Date;
5858

5959
@HasMany(() => ApplicantRecord, {
60-
foreignKey: "id",
61-
as: "applicant",
60+
foreignKey: "applicantId",
61+
sourceKey: "id",
62+
as: "applicantRecords",
6263
})
6364
applicantRecords?: NonAttribute<ApplicantRecord[]>;
6465
}

backend/typescript/models/applicantRecord.model.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ import ReviewedApplicantRecord from "./reviewedApplicantRecord.model";
2222
@Table({ tableName: "applicant_records" })
2323
export default class ApplicantRecord extends Model {
2424
@Column({
25-
type: DataType.INTEGER,
25+
type: DataType.STRING,
2626
primaryKey: true,
2727
unique: true,
2828
autoIncrement: true,
2929
})
30-
id!: number;
30+
id!: string;
3131

3232
@ForeignKey(() => Applicant)
33-
@Column({ type: DataType.STRING })
34-
applicantId!: string;
33+
@Column({ type: DataType.INTEGER })
34+
applicantId!: number;
3535

3636
@ForeignKey(() => Position)
3737
@Column({ type: DataType.STRING })

backend/typescript/models/reviewedApplicantRecord.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import User from "./user.model";
1717
export default class ReviewedApplicantRecord extends Model {
1818
@ForeignKey(() => ApplicantRecord)
1919
@Column({ type: DataType.STRING, primaryKey: true })
20-
applicantRecordId!: number;
20+
applicantRecordId!: string;
2121

2222
@ForeignKey(() => User)
2323
@Column({ type: DataType.INTEGER, primaryKey: true })
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { ApplicationDTO } from "../../types";
2+
import IReviewPageService from "../interfaces/IReviewPageService";
3+
import { getErrorMessage } from "../../utilities/errorUtils";
4+
import logger from "../../utilities/logger";
5+
import ApplicantRecord from "../../models/applicantRecord.model";
6+
import ReviewedApplicantRecord from "../../models/reviewedApplicantRecord.model";
7+
import Applicant from "../../models/applicant.model";
8+
9+
const Logger = logger(__filename);
10+
11+
function toDTO(model: Applicant): ApplicationDTO {
12+
const firstChoice = model.applicantRecords!.find((ar) => ar.choice === 1);
13+
const secondChoice = model.applicantRecords!.find((ar) => ar.choice === 2);
14+
15+
return {
16+
id: model.id,
17+
academicOrCoop: model.academicOrCoop,
18+
academicYear: model.academicYear,
19+
email: model.email,
20+
firstChoiceRole: firstChoice!.position,
21+
firstName: model.firstName,
22+
lastName: model.lastName,
23+
heardFrom: model.heardFrom,
24+
locationPreference: model.locationPreference,
25+
program: model.program,
26+
timesApplied: model.timesApplied.toString(),
27+
pronouns: model.pronouns,
28+
pronounsSpecified: model.pronouns,
29+
resumeUrl: model.resumeUrl,
30+
roleSpecificQuestions: firstChoice!.roleSpecificQuestions,
31+
secondChoiceRole: secondChoice ? secondChoice.position : "",
32+
shortAnswerQuestions: model.shortAnswerQuestions,
33+
status: firstChoice!.status,
34+
term: model.term,
35+
secondChoiceStatus: secondChoice ? secondChoice.status : "",
36+
/* timestamp: model.submittedAt.getSeconds(), */
37+
};
38+
}
39+
40+
class ReviewPageService implements IReviewPageService {
41+
/* eslint-disable class-methods-use-this */
42+
async getReviewPage(applicantRecordId: string): Promise<ApplicationDTO> {
43+
try {
44+
const applicantRecord: ApplicantRecord | null =
45+
await ApplicantRecord.findOne({
46+
where: { id: applicantRecordId },
47+
attributes: { exclude: ["createdAt", "updatedAt"] },
48+
});
49+
if (!applicantRecord)
50+
throw new Error(`Database integrity has been violated`);
51+
52+
const applicant: Applicant | null = await Applicant.findOne({
53+
where: { id: applicantRecord.applicantId },
54+
attributes: { exclude: ["createdAt", "updatedAt"] },
55+
include: [
56+
{
57+
attributes: { exclude: ["createdAt", "updatedAt"] },
58+
association: "applicantRecords",
59+
},
60+
],
61+
});
62+
if (!applicant) throw new Error(`Database integrity has been violated`);
63+
64+
return toDTO(applicant);
65+
} catch (error: unknown) {
66+
Logger.error(`Failed to fetch. Reason = ${getErrorMessage(error)}`);
67+
throw error;
68+
}
69+
}
70+
}
71+
72+
export default ReviewPageService;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ApplicationDTO } from "../../types";
2+
3+
interface IReviewPageService {
4+
/**
5+
* Fetch data from the Applicant and ApplicantRecord table to return an ApplicationDTO object
6+
* @Param applicantRecordId the id of the applicant record that the viewer is interested in
7+
*/
8+
getReviewPage(applicantRecordId: string): Promise<ApplicationDTO>;
9+
}
10+
11+
export default IReviewPageService;

backend/typescript/types.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export type UserDTO = {
3333
role: Role;
3434
};
3535

36-
// DEPRECATED - TO BE REMOVED AT THE END OF S25
3736
export type ApplicationDTO = {
3837
id: number;
3938
academicOrCoop: string;
@@ -55,7 +54,7 @@ export type ApplicationDTO = {
5554
secondChoiceStatus: string;
5655
term: string;
5756
timesApplied: string;
58-
timestamp: bigint;
57+
timestamp?: bigint;
5958
};
6059

6160
export type ApplicantDTO = {

0 commit comments

Comments
 (0)