diff --git a/app.py b/app.py index e37a88a..29dc98a 100644 --- a/app.py +++ b/app.py @@ -3,12 +3,14 @@ from chalicelib.api.listings import listings_api from chalicelib.api.applicants import applicants_api from chalicelib.api.announcements import announcements_api +from chalicelib.api.insights import insights_api from chalicelib.api.members import members_api app = Chalice(app_name="zap") app.register_blueprint(announcements_api) app.register_blueprint(listings_api) app.register_blueprint(applicants_api) +app.register_blueprint(insights_api) app.register_blueprint(members_api) diff --git a/chalicelib/api/insights.py b/chalicelib/api/insights.py new file mode 100644 index 0000000..bac023e --- /dev/null +++ b/chalicelib/api/insights.py @@ -0,0 +1,13 @@ +# TO BE COMPLETED: create api routes for analytics +from chalice import Blueprint +from chalicelib.services.InsightsService import insights_service +from chalicelib.handlers.error_handler import handle_exceptions +from pydantic import ValidationError + +insights_api = Blueprint(__name__) + + +@insights_api.route("/insights/listing/{listing_id}", methods=["GET"], cors=True) +def get_listing_insights(listing_id): + """Get insights from """ + return insights_service.get_insights_from_listing(listing_id) \ No newline at end of file diff --git a/chalicelib/services/InsightsService.py b/chalicelib/services/InsightsService.py new file mode 100644 index 0000000..e1e6bdb --- /dev/null +++ b/chalicelib/services/InsightsService.py @@ -0,0 +1,172 @@ +# TO BE COMPLETED: create service to perform analytics (used in API...) +from chalicelib.db import db + +class InsightsService: + def __init__(self): + pass + + def get_insights_from_listing(self, id: str): + ''' driver function of insights (returns both `dashboard` and `distribution`) ''' + + # fetch applicants from `get_applicants` endpoint in `db.py` + data = db.get_applicants(table_name="zap-applications", listing_id=id) + + # call helper functions + # NOTE: `get_dashboard_insights` updates the data object to ensure all majors/minors are Title() cased + dashboard = InsightsService._get_dashboard_insights(data) + distribution = InsightsService._get_pie_chart_insights(data) + + return dashboard, distribution + + # private method (kinda) + def _get_dashboard_insights(data): + # initialize metrics + majors = {} + grad_years = {} + num_applicants = len(data) + avg_gpa = 0 + count_gpa = 0 + + dashboard = { + "applicantCount": 0, + "avgGpa": "N/A", + "commonMajor": "N/A", + "commonGradYear": "N/A", + } + + if num_applicants < 1: + return dashboard + + # iterate over each applicant and perform analytics + for applicant in data: + # convert major/minor to title case + applicant["major"] = applicant["major"].title() + applicant["minor"] = applicant["minor"].title() + + gpa, grad_year, major = applicant["gpa"], applicant["gradYear"], applicant["major"] + + # attempt conversions (if fail, then skip) + try: + float_gpa = float(gpa) + avg_gpa += float_gpa + count_gpa += 1 + except ValueError: + print("skipping gpa: ", gpa) + pass + try: + float_grad = float(grad_year) + if float_grad in grad_years: + grad_years[float_grad] += 1 + else: + grad_years[float_grad] = 1 + except ValueError: + print("skipping gradYear: ", grad_year) + pass + + # parse majors (if non-empty) + if major: + if major in majors: + majors[major] += 1 + else: + majors[major] = 1 + + avg_gpa /= count_gpa + + # calculate most common major/gradYear + common_major, count_common_major = max(majors.items(), key=lambda x: x[1]) + common_grad_year, count_common_grad_year = max(grad_years.items(), key=lambda x: x[1]) + + + dashboard = { + "applicantCount": num_applicants, + "avgGpa": round(avg_gpa, 1), # round to 1 decimal place (e.g. 3.123 -> 3.1) + "commonMajor": common_major.title(), + # "countCommonMajor": count_common_major, # TO-DO: maybe do something with common major counts + "commonGradYear": int(common_grad_year), + # "avgResponseLength": 0 # TO-DO: maybe implement parsing for response lengths + } + + return dashboard + + + def _get_pie_chart_insights(data): + ''' helper function for pie charts (should be function, not method within InsightsService) ''' + + # initialize return object + # value (list) structure : [ {name: string, value: int, applicants: Applicant[]}, ... , ... ] + distribution = { + "colleges": [], + "gpa": [], + "gradYear": [], + "major": [], + "minor": [], + "linkedin": [], + "website": [], + } + + # list of fields we want to consider + fields = ["colleges", "gpa", "gradYear", "major", "minor", "linkedin", "website"] + + def findInsightsObject(metric, metric_val): + ''' helper to the helper lol -> checks for previously added metric_name ''' + # check if college exists in `distribution["colleges"]` + found_object = None + + for distribution_object in distribution[metric]: + if distribution_object["name"] == metric_val: + found_object = distribution_object + break + + return found_object + + for applicant in data: + # iterate over applicant dictionary + for metric, val in applicant.items(): + + # case 1: ignore irrelevant metrics + if metric not in fields: + continue + + # case 2: metric is a url + if metric in ["linkedin", "website"]: + val = 'N/A' if (not val or val == 'N/A') else 'hasURL' + + # case 3: handle other metrics with mepty val (attempt to handle some edge cases) # TO-DO: update Form.tsx in frontend to prevent bad inputs + elif metric in ['minor', 'gpa'] and (not val or val.lower() in ['na', 'n/a', 'n a', 'n / a']): + # general case + val = 'N/A' + + # case 4: colleges -> iterate over colleges object + elif metric == "colleges": + for college, status in val.items(): + # edge case: if status is false, skip (shouldn't contribute to count) + if not status: + continue + + # check if college exists in `distribution["colleges"]` + found_college = findInsightsObject(metric, college) + + if found_college: + found_college["value"] += 1 + found_college["applicants"] += [applicant] + else: + newCollege = {"name": college, "value": 1, "applicants": [applicant]} + distribution[metric] += [newCollege] + + # skip to next metric + continue + + # handle remaining fields + found_object = findInsightsObject(metric, val) + + if found_object: + found_object["value"] += 1 + found_object["applicants"] += [applicant] + else: + new_object = {"name": val, "value": 1, "applicants": [applicant]} + distribution[metric] += [new_object] + + return distribution + + +insights_service = InsightsService() diff --git a/tests/api/test_insights.py b/tests/api/test_insights.py new file mode 100644 index 0000000..c1c8b7a --- /dev/null +++ b/tests/api/test_insights.py @@ -0,0 +1,27 @@ +from chalice.app import Request +from chalice.test import Client +from unittest.mock import MagicMock, patch +import json + +from app import app + +with open('tests/fixtures/sample_dashboard.json') as f: + SAMPLE_DASHBOARD = json.load(f) + +with open('tests/fixtures/sample_distribution.json') as f: + SAMPLE_DISTRIBUTION = json.load(f) + + +def test_get_insights_from_listing(): + # Create a Chalice test client + with Client(app) as client: + # Mock applicant_service's get method + with patch( + "chalicelib.services.InsightsService.insights_service.get_insights_from_listing" + ) as mock_get_insights_from_listing: + mock_get_insights_from_listing.return_value = [SAMPLE_DASHBOARD, SAMPLE_DISTRIBUTION] + response = client.http.get(f"/insights/listing/test_listing_id") + + # Check the response status code and body + assert response.status_code == 200 + assert response.json_body == [SAMPLE_DASHBOARD, SAMPLE_DISTRIBUTION] \ No newline at end of file diff --git a/tests/fixtures/sample_applicants.json b/tests/fixtures/sample_applicants.json new file mode 100644 index 0000000..e7294aa --- /dev/null +++ b/tests/fixtures/sample_applicants.json @@ -0,0 +1,170 @@ +[ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "chAos EngInEering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } +] \ No newline at end of file diff --git a/tests/fixtures/sample_dashboard.json b/tests/fixtures/sample_dashboard.json new file mode 100644 index 0000000..7919760 --- /dev/null +++ b/tests/fixtures/sample_dashboard.json @@ -0,0 +1,6 @@ +{ + "applicantCount": 4, + "avgGpa": 3.8, + "commonMajor": "Chaos Engineering", + "commonGradYear": 2028 +} \ No newline at end of file diff --git a/tests/fixtures/sample_distribution.json b/tests/fixtures/sample_distribution.json new file mode 100644 index 0000000..b2a8f2f --- /dev/null +++ b/tests/fixtures/sample_distribution.json @@ -0,0 +1,1396 @@ +{ + "colleges": [ + { + "name": "CAS", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "Wheelock", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "Sargent", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + }, + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + }, + { + "name": "Pardee", + "value": 1, + "applicants": [ + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ], + "gpa": [ + { + "name": "N/A", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "3.99", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + }, + { + "name": "3.6", + "value": 1, + "applicants": [ + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ], + "gradYear": [ + { + "name": "2028", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + }, + { + "name": "2022", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "2026", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + } + ], + "major": [ + { + "name": "Computer Science", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + }, + { + "name": "Culinary Arts", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "Chaos Engineering", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ], + "minor": [ + { + "name": "N/A", + "value": 2, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + }, + { + "name": "Rock Climbing", + "value": 1, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + } + ] + }, + { + "name": "Biology", + "value": 1, + "applicants": [ + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ], + "linkedin": [ + { + "name": "N/A", + "value": 3, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + }, + { + "name": "hasURL", + "value": 1, + "applicants": [ + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ], + "website": [ + { + "name": "N/A", + "value": 3, + "applicants": [ + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Reynolds", + "linkedin": "", + "dateApplied": "2024-02-15T23:51:52.216457-05:00", + "email": "wderocco@bu.edu", + "firstName": "Ryan", + "applicantId": "5eae4310-b9fc-4896-9997-e614615558a9", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Reynolds_Ryan_5eae4310-b9fc-4896-9997-e614615558a9.pdf", + "major": "Computer Science", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": true, + "Wheelock": true, + "Sargent": true, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "in the Hat", + "linkedin": "", + "dateApplied": "2024-02-09T14:57:46.760096-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Rat", + "applicantId": "9d5c3489-6535-447a-8696-c35eec239c0d", + "minor": "Rock Climbing", + "events": { + "infoSession2": false, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.jpg", + "gpa": "", + "hasGpa": false, + "gradYear": "2022", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/in the Hat_Rat_9d5c3489-6535-447a-8696-c35eec239c0d.pdf", + "major": "Culinary Arts", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "Jay" + }, + { + "website": "", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": false, + "Pardee": false, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "Coast", + "linkedin": "", + "dateApplied": "2024-02-09T14:59:14.575818-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Wes", + "applicantId": "db3a4d5e-7480-4ef4-83c3-8abd1373764c", + "minor": "", + "events": { + "infoSession2": false, + "professionalPanel": false, + "infoSession1": false, + "resumeWorkshop": false, + "socialEvent": false + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.png", + "gpa": "3.99", + "hasGpa": true, + "gradYear": "2026", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/Coast_Wes_db3a4d5e-7480-4ef4-83c3-8abd1373764c.pdf", + "major": "Chaos Engineering", + "gradMonth": "January", + "phone": "2032091600", + "preferredName": "" + } + ] + }, + { + "name": "hasURL", + "value": 1, + "applicants": [ + { + "website": "https://github.com/wderocco8", + "listingId": "a6612ed3-6d48-45c4-ab39-fbd946b8cbe8", + "colleges": { + "COM": false, + "QST": false, + "CDS": false, + "CAS": false, + "Wheelock": false, + "Sargent": true, + "Pardee": true, + "SHA": false, + "CGS": false, + "ENG": false, + "CFA": false, + "Other": false + }, + "responses": [], + "lastName": "The Breaker", + "linkedin": "https://www.linkedin.com/in/william-derocco/", + "dateApplied": "2024-02-09T14:56:23.066712-05:00", + "email": "wergewretr@gmail.com", + "firstName": "Bob", + "applicantId": "e6522255-8853-484e-ba9a-d6687fbc2bce", + "minor": "Biology", + "events": { + "infoSession2": true, + "professionalPanel": true, + "infoSession1": true, + "resumeWorkshop": true, + "socialEvent": true + }, + "image": "https://whyphi-zap.s3.amazonaws.com/dev/image/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.jpg", + "gpa": "3.6", + "hasGpa": true, + "gradYear": "2028", + "resume": "https://whyphi-zap.s3.amazonaws.com/dev/resume/a6612ed3-6d48-45c4-ab39-fbd946b8cbe8/The Breaker_Bob_e6522255-8853-484e-ba9a-d6687fbc2bce.pdf", + "major": "Chaos Engineering", + "gradMonth": "May", + "phone": "2032091600", + "preferredName": "Bobert" + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/services/test_insights_service.py b/tests/services/test_insights_service.py new file mode 100644 index 0000000..35a1340 --- /dev/null +++ b/tests/services/test_insights_service.py @@ -0,0 +1,47 @@ +import pytest +from unittest.mock import MagicMock, patch +from chalicelib.services.InsightsService import InsightsService +import copy +import json + +# Load JSON data from a file +with open('tests/fixtures/sample_applicants.json') as f: + SAMPLE_APPLICANTS = json.load(f) + +with open('tests/fixtures/sample_dashboard.json') as f: + SAMPLE_DASHBOARD = json.load(f) + +with open('tests/fixtures/sample_distribution.json') as f: + SAMPLE_DISTRIBUTION = json.load(f) + +@pytest.fixture +def service(): + with patch("chalicelib.services.InsightsService.db") as mock_db: + yield InsightsService(), mock_db + + +def test_get_insights(service): + insights_service, mock_db = service + + listing_id = "1" + # whenever get_item is called on the fake db, sample_data will be returned (create a deepcopy since it is being mutated) + mock_db.get_applicants.return_value = copy.deepcopy(SAMPLE_APPLICANTS) + + result = insights_service.get_insights_from_listing(listing_id) + # confirm that database was called once with correct inputs + mock_db.get_applicants.assert_called_once_with( + table_name="zap-applications", + listing_id=listing_id + ) + + # Convert Python dictionary to JSON format for comparison + result_dash = json.dumps(result[0], sort_keys=True) + result_dist = json.dumps(result[1], sort_keys=True) + + # Convert boolean values to lowercase strings + result_dash = result_dash.replace("True", "true").replace("False", "false") + result_dist = result_dist.replace("True", "true").replace("False", "false") + + assert len(result) == 2 + assert result_dash == json.dumps(SAMPLE_DASHBOARD, sort_keys=True) + assert result_dist == json.dumps(SAMPLE_DISTRIBUTION, sort_keys=True) \ No newline at end of file