Skip to content

Commit 83b1a51

Browse files
authored
Merge pull request #62 from uwblueprint/jesse/seeded-data
INTS25: seeded data script
2 parents 802f8f4 + fa337c4 commit 83b1a51

9 files changed

+5910
-130
lines changed

backend/typescript/migrations/2025.06.21T15.30.15.create-applicant-record.ts

Lines changed: 0 additions & 74 deletions
This file was deleted.

backend/typescript/migrations/2025.06.21T07.02.40.create-applicants.ts renamed to backend/typescript/migrations/2025.07.21T07.02.41.create-applicants.ts

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,66 @@
11
import { DataType } from "sequelize-typescript";
2-
32
import { Migration } from "../umzug";
3+
import applicants from "./processedApplicants.json";
44

55
const TABLE_NAME = "applicants";
66

7-
// const SEEDED_DATA = [
8-
// {
9-
// id: "123",
10-
// academicOrCoop: "Academic",
11-
// academicYear: "2024",
12-
// email: "jj2huang@uwaterloo.ca",
13-
// firstName: "Jesse",
14-
// lastName: "Huang",
15-
// heardFrom: "LinkedIn",
16-
// locationPreference: "Waterloo",
17-
// program: "Computer Science",
18-
// pronouns: "he/him",
19-
// resumeUrl:
20-
// "https://www.youtube.com/watch?v=xvFZjo5PgG0&list=RDxvFZjo5PgG0&start_radio=1",
21-
// timesApplied: 1,
22-
// shortAnswerQuestions: ["hi", "bye"],
23-
// term: "S25",
24-
// submittedAt: "2025-06-21T07:02:40.000Z",
25-
// createdAt: new Date(),
26-
// updatedAt: new Date(),
27-
// },
28-
// ];
29-
307
export const up: Migration = async ({ context: sequelize }) => {
318
await sequelize.getQueryInterface().createTable(TABLE_NAME, {
329
id: {
33-
type: DataType.STRING,
10+
type: DataType.STRING(4000),
3411
allowNull: false,
3512
primaryKey: true,
3613
},
3714
academicOrCoop: {
38-
type: DataType.STRING,
15+
type: DataType.STRING(4000),
3916
allowNull: false,
4017
},
4118
academicYear: {
42-
type: DataType.STRING,
19+
type: DataType.STRING(4000),
4320
allowNull: false,
4421
},
4522
email: {
46-
type: DataType.STRING,
23+
type: DataType.STRING(4000),
4724
allowNull: false,
4825
},
4926
firstName: {
50-
type: DataType.STRING,
27+
type: DataType.STRING(4000),
5128
allowNull: false,
5229
},
5330
lastName: {
54-
type: DataType.STRING,
31+
type: DataType.STRING(4000),
5532
allowNull: false,
5633
},
5734
heardFrom: {
58-
type: DataType.STRING,
35+
type: DataType.STRING(4000),
5936
allowNull: false,
6037
},
6138
locationPreference: {
62-
type: DataType.STRING,
39+
type: DataType.STRING(4000),
6340
allowNull: false,
6441
},
6542
program: {
66-
type: DataType.STRING,
43+
type: DataType.STRING(4000),
6744
allowNull: false,
6845
},
6946
pronouns: {
70-
type: DataType.STRING,
47+
type: DataType.STRING(4000),
7148
allowNull: false,
7249
},
7350
resumeUrl: {
74-
type: DataType.STRING,
51+
type: DataType.STRING(4000),
7552
allowNull: true,
7653
},
7754
timesApplied: {
7855
type: DataType.INTEGER,
7956
allowNull: false,
8057
},
8158
shortAnswerQuestions: {
82-
type: DataType.ARRAY(DataType.STRING),
59+
type: DataType.ARRAY(DataType.STRING(4000)),
8360
allowNull: true,
8461
},
8562
term: {
86-
type: DataType.STRING,
63+
type: DataType.STRING(4000),
8764
allowNull: false,
8865
},
8966
submittedAt: {
@@ -99,6 +76,7 @@ export const up: Migration = async ({ context: sequelize }) => {
9976
allowNull: false,
10077
},
10178
});
79+
await sequelize.getQueryInterface().bulkInsert(TABLE_NAME, applicants);
10280
};
10381

10482
export const down: Migration = async ({ context: sequelize }) => {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { DataType } from "sequelize-typescript";
2+
import { Migration } from "../umzug";
3+
import {
4+
Department,
5+
PositionTitles,
6+
EngineeringPositionTitles,
7+
DesignPositionTitles,
8+
ProductPositionTitles,
9+
CommunityPositionTitles,
10+
} from "../types";
11+
12+
const TABLE_NAME = "positions";
13+
14+
const SEEDED_DATA = [
15+
...EngineeringPositionTitles.map((title) => ({
16+
title,
17+
department: Department.Engineering,
18+
})),
19+
20+
...DesignPositionTitles.map((title) => ({
21+
title,
22+
department: Department.Design,
23+
})),
24+
25+
...ProductPositionTitles.map((title) => ({
26+
title,
27+
department: Department.Product,
28+
})),
29+
30+
...CommunityPositionTitles.map((title) => ({
31+
title,
32+
department: Department.Community,
33+
})),
34+
];
35+
36+
export const up: Migration = async ({ context: sequelize }) => {
37+
await sequelize.getQueryInterface().createTable(TABLE_NAME, {
38+
title: {
39+
type: DataType.ENUM(...PositionTitles),
40+
allowNull: false,
41+
primaryKey: true,
42+
},
43+
department: {
44+
type: DataType.ENUM(...Object.values(Department)),
45+
allowNull: false,
46+
},
47+
});
48+
49+
await sequelize.query("DELETE FROM positions");
50+
51+
await sequelize.getQueryInterface().bulkInsert(TABLE_NAME, SEEDED_DATA);
52+
};
53+
54+
export const down: Migration = async ({ context: sequelize }) => {
55+
await sequelize.getQueryInterface().dropTable(TABLE_NAME);
56+
};
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import { DataType } from "sequelize-typescript";
2+
import { v4 as uuidv4 } from "uuid";
3+
import { Migration } from "../umzug";
4+
5+
import allApplications from "./applicationlist.json";
6+
import applicants from "./processedApplicants.json";
7+
import {
8+
ApplicationStatus,
9+
SkillCategory,
10+
EngineeringPositionTitles,
11+
DesignPositionTitles,
12+
ProductPositionTitles,
13+
CommunityPositionTitles,
14+
} from "../types";
15+
16+
const ALL_POSITION_TITLES = [
17+
...EngineeringPositionTitles,
18+
...DesignPositionTitles,
19+
...ProductPositionTitles,
20+
...CommunityPositionTitles,
21+
];
22+
23+
const MAX_SHORT_ANSWER_LENGTH = 255;
24+
25+
function normalizeApplicantRole(role: string): string {
26+
if (!role) return "President";
27+
const trimmed = role.trim();
28+
if (trimmed.toLowerCase() === "project developer") return "Developer";
29+
// Capitalize each word for comparison
30+
const formatted = trimmed.replace(/\b\w/g, (c) => c.toUpperCase());
31+
if (ALL_POSITION_TITLES.includes(formatted as any)) return formatted;
32+
return "President";
33+
}
34+
35+
type ApplicantRecord = {
36+
id: string;
37+
applicantId: string;
38+
position: string;
39+
roleSpecificQuestions: string[] | null;
40+
choice: number;
41+
status: ApplicationStatus;
42+
skillCategory: SkillCategory | null;
43+
extraInfo: string | null;
44+
};
45+
46+
const applicantRecords: ApplicantRecord[] = [];
47+
allApplications.forEach((app, idx) => {
48+
const applicantId = applicants[idx].id;
49+
50+
// First choice
51+
if (app.firstChoiceRole) {
52+
const roleSpecificQs =
53+
app.roleSpecificQuestions
54+
?.filter((q) => q.role === app.firstChoiceRole)
55+
?.flatMap(
56+
(q) =>
57+
q.questions?.map((question) =>
58+
JSON.stringify(question).slice(0, MAX_SHORT_ANSWER_LENGTH),
59+
) || [],
60+
) || [];
61+
applicantRecords.push({
62+
id: uuidv4(),
63+
applicantId,
64+
position: normalizeApplicantRole(app.firstChoiceRole),
65+
roleSpecificQuestions: roleSpecificQs.length > 0 ? roleSpecificQs : null,
66+
choice: 1,
67+
status: (app.status as ApplicationStatus) || "Applied",
68+
skillCategory: null,
69+
extraInfo: JSON.stringify({ adminReview: "seeded_admin_review" }),
70+
});
71+
}
72+
73+
// Second choice
74+
if (app.secondChoiceRole) {
75+
const roleSpecificQs =
76+
app.roleSpecificQuestions
77+
?.filter((q) => q.role === app.secondChoiceRole)
78+
?.flatMap(
79+
(q) =>
80+
q.questions?.map((question) =>
81+
JSON.stringify(question).slice(0, MAX_SHORT_ANSWER_LENGTH),
82+
) || [],
83+
) || [];
84+
applicantRecords.push({
85+
id: uuidv4(),
86+
applicantId,
87+
position: normalizeApplicantRole(app.secondChoiceRole),
88+
roleSpecificQuestions: roleSpecificQs.length > 0 ? roleSpecificQs : null,
89+
choice: 2,
90+
status: (app.status as ApplicationStatus) || "Applied",
91+
skillCategory: null,
92+
extraInfo: JSON.stringify({ adminReview: "seeded_admin_review" }),
93+
});
94+
}
95+
});
96+
97+
const TABLE_NAME = "applicant_records";
98+
99+
export const up: Migration = async ({ context: sequelize }) => {
100+
await sequelize.getQueryInterface().createTable(TABLE_NAME, {
101+
id: {
102+
type: DataType.STRING,
103+
allowNull: false,
104+
primaryKey: true,
105+
},
106+
applicantId: {
107+
type: DataType.STRING,
108+
allowNull: false,
109+
references: {
110+
model: "applicants",
111+
key: "id",
112+
},
113+
},
114+
position: {
115+
type: DataType.ENUM(...ALL_POSITION_TITLES),
116+
allowNull: true,
117+
references: {
118+
model: "positions",
119+
key: "title",
120+
},
121+
},
122+
roleSpecificQuestions: {
123+
type: DataType.ARRAY(DataType.STRING),
124+
allowNull: true,
125+
},
126+
choice: {
127+
type: DataType.INTEGER,
128+
allowNull: false,
129+
},
130+
status: {
131+
type: DataType.STRING,
132+
allowNull: false,
133+
},
134+
skillCategory: {
135+
type: DataType.STRING,
136+
allowNull: true,
137+
},
138+
extraInfo: {
139+
type: DataType.JSONB,
140+
allowNull: true,
141+
},
142+
});
143+
await sequelize.getQueryInterface().bulkInsert(TABLE_NAME, applicantRecords);
144+
};
145+
146+
export const down: Migration = async ({ context: sequelize }) => {
147+
await sequelize.getQueryInterface().dropTable(TABLE_NAME);
148+
};

backend/typescript/migrations/2025.06.24T18.20.15.create-reviewed-application.ts renamed to backend/typescript/migrations/2025.07.24T18.20.15.create-reviewed-application.ts

File renamed without changes.

0 commit comments

Comments
 (0)