def test_filter_criteria(self): gpa_ranges = [ 'numrange(0, 2, \'[)\')', 'numrange(2, 2.5, \'[)\')', ] group_codes = ['MFB-DB', 'MFB-DL'] levels = ['Junior'] majors = ['Environmental Economics & Policy', 'Gender and Women\'s Studies'] unit_ranges = [ 'numrange(0, 5, \'[]\')', 'numrange(30, NULL, \'[)\')', ] cohort = CohortFilter.create( uid='1022796', label='All criteria, all the time', gpa_ranges=gpa_ranges, group_codes=group_codes, in_intensive_cohort=None, levels=levels, majors=majors, unit_ranges=unit_ranges, ) cohort = CohortFilter.find_by_id(cohort.id) expected = { 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'levels': levels, 'majors': majors, 'unitRanges': unit_ranges, } def sort_and_format(filter_criteria): return json.dumps(filter_criteria, sort_keys=True, indent=2) assert sort_and_format(expected) == sort_and_format(cohort.filter_criteria)
def get_cohort(cohort_id): if is_unauthorized_search(request.args): raise ForbiddenRequestError( 'You are unauthorized to access student data managed by other departments' ) include_students = util.to_bool_or_none( util.get(request.args, 'includeStudents')) include_students = True if include_students is None else include_students order_by = util.get(request.args, 'orderBy', None) offset = util.get(request.args, 'offset', 0) limit = util.get(request.args, 'limit', 50) cohort = CohortFilter.find_by_id(int(cohort_id)) if cohort and can_view_cohort(current_user, cohort): cohort = decorate_cohort( cohort, order_by=order_by, offset=int(offset), limit=int(limit), include_alerts_for_uid=current_user.uid, include_profiles=True, include_students=include_students, ) return tolerant_jsonify(cohort) else: raise ResourceNotFoundError( f'No cohort found with identifier: {cohort_id}')
def students_with_alerts(cohort_id): benchmark = get_benchmarker(f'cohort {cohort_id} students_with_alerts') benchmark('begin') offset = get_param(request.args, 'offset', 0) limit = get_param(request.args, 'limit', 50) cohort = CohortFilter.find_by_id( cohort_id, include_alerts_for_user_id=current_user.get_id(), include_students=False, alert_offset=offset, alert_limit=limit, ) benchmark('fetched cohort') if cohort and _can_current_user_view_cohort(cohort): _decorate_cohort(cohort) students = cohort.get('alerts', []) alert_sids = [s['sid'] for s in students] alert_profiles = get_summary_student_profiles(alert_sids) benchmark('fetched student profiles') alert_profiles_by_sid = {p['sid']: p for p in alert_profiles} for student in students: student.update(alert_profiles_by_sid[student['sid']]) # The enrolled units count is the one piece of term data we want to preserve. if student.get('term'): student['term'] = { 'enrolledUnits': student['term'].get('enrolledUnits') } else: raise ResourceNotFoundError( f'No cohort found with identifier: {cohort_id}') benchmark('end') return tolerant_jsonify(students)
def test_create_and_delete_cohort(self): """Cohort_filter record to Flask-Login for recognized UID.""" owner = AuthorizedUser.find_by_uid(asc_advisor_uid).uid # Check validity of UID assert owner # Create cohort group_codes = ['MFB-DB', 'MFB-DL', 'MFB-MLB', 'MFB-OLB'] cohort = CohortFilter.create( uid=owner, name='Football, Defense', filter_criteria={ 'groupCodes': group_codes, }, ) cohort_id = cohort['id'] assert CohortFilter.find_by_id(cohort_id)['owner']['uid'] == owner assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) # Delete cohort and verify previous_owner_count = cohort_count(owner) CohortFilter.delete(cohort_id) std_commit(allow_test_environment=True) assert cohort_count(owner) == previous_owner_count - 1
def get_cohort(cohort_id): benchmark = get_benchmarker(f'cohort {cohort_id} get_cohort') benchmark('begin') filter_keys = list(request.args.keys()) order_by = get_param(request.args, 'orderBy', None) if is_unauthorized_search(filter_keys, order_by): raise ForbiddenRequestError( 'You are unauthorized to access student data managed by other departments' ) include_students = to_bool(get_param(request.args, 'includeStudents')) include_students = True if include_students is None else include_students offset = get_param(request.args, 'offset', 0) limit = get_param(request.args, 'limit', 50) benchmark('begin cohort filter query') cohort = CohortFilter.find_by_id( int(cohort_id), order_by=order_by, offset=int(offset), limit=int(limit), include_alerts_for_user_id=current_user.get_id(), include_profiles=True, include_students=include_students, ) if cohort and _can_current_user_view_cohort(cohort): _decorate_cohort(cohort) benchmark('end') return tolerant_jsonify(cohort) else: raise ResourceNotFoundError( f'No cohort found with identifier: {cohort_id}')
def test_create_and_delete_cohort(self): """Cohort_filter record to Flask-Login for recognized UID.""" owner = AuthorizedUser.find_by_uid(asc_advisor_uid).uid shared_with = AuthorizedUser.find_by_uid(coe_advisor_uid).uid # Check validity of UIDs assert owner assert shared_with # Create and share cohort group_codes = ['MFB-DB', 'MFB-DL', 'MFB-MLB', 'MFB-OLB'] cohort = CohortFilter.create( uid=owner, name='Football, Defense', filter_criteria={ 'groupCodes': group_codes, }, ) cohort_id = cohort['id'] CohortFilter.share(cohort_id, shared_with) owners = CohortFilter.find_by_id(cohort_id)['owners'] assert len(owners) == 2 assert owner, shared_with in [user['uid'] for user in owners] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) # Delete cohort and verify previous_owner_count = cohort_count(owner) previous_shared_count = cohort_count(shared_with) CohortFilter.delete(cohort_id) assert cohort_count(owner) == previous_owner_count - 1 assert cohort_count(shared_with) == previous_shared_count - 1
def test_cohort_update_filter_criteria(self, client, asc_advisor_session): label = 'Swimming, Men\'s' original_student_count = 4 cohort = CohortFilter.create( uid=asc_advisor_uid, label=label, group_codes=['MSW', 'MSW-DV', 'MSW-SW'], student_count=original_student_count, ) assert original_student_count > 0 updated_filter_criteria = { 'groupCodes': ['MSW-DV', 'MSW-SW'], } data = { 'id': cohort.id, 'filterCriteria': updated_filter_criteria, 'studentCount': original_student_count - 1, } response = client.post('/api/filtered_cohort/update', data=json.dumps(data), content_type='application/json') assert 200 == response.status_code updated_cohort = CohortFilter.find_by_id(int(response.json['id'])) assert updated_cohort.label == label assert updated_cohort.student_count == original_student_count - 1 def remove_empties(filter_criteria): return {k: v for k, v in filter_criteria.items() if v is not None} expected = remove_empties(cohort.filter_criteria) actual = remove_empties(updated_cohort.filter_criteria) assert expected == actual
def test_filter_criteria(self): gpa_ranges = [ { 'min': 0, 'max': 1.999 }, { 'min': 2, 'max': 2.499 }, ] group_codes = ['MFB-DB', 'MFB-DL'] intended_majors = ['Public Health BA'] levels = ['Junior'] majors = [ 'Environmental Economics & Policy', 'Gender and Women\'s Studies' ] minors = ['Physics UG'] unit_ranges = [ 'numrange(0, 5, \'[]\')', 'numrange(30, NULL, \'[)\')', ] cohort = CohortFilter.create( uid='1022796', name='All criteria, all the time', filter_criteria={ 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'intendedMajors': intended_majors, 'levels': levels, 'majors': majors, 'minors': minors, 'unitRanges': unit_ranges, }, ) cohort_id = cohort['id'] cohort = CohortFilter.find_by_id(cohort_id) expected = { 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'intendedMajors': intended_majors, 'levels': levels, 'majors': majors, 'minors': minors, 'unitRanges': unit_ranges, } for key, value in expected.items(): assert cohort['criteria'][key] == expected[key] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id))
def get_cohort(code): params = request.get_json() order_by = get_param(params, 'orderBy', 'member_name') if code.isdigit(): offset = get_param(params, 'offset', 0) limit = get_param(params, 'limit', 50) cohort = CohortFilter.find_by_id(int(code), order_by, offset, limit) else: cohort = TeamMember.for_code(code) load_member_profiles(cohort) # Translate requested order_by to naming convention of TeamMember sort_by = 'uid' if order_by == 'member_uid' else 'name' cohort['members'].sort(key=lambda member: member[sort_by]) return tolerant_jsonify(cohort)
def download_cohort_csv(): benchmark = get_benchmarker('cohort download_csv') benchmark('begin') params = request.get_json() cohort_id = int(get_param(params, 'cohortId')) cohort = CohortFilter.find_by_id( cohort_id, offset=0, limit=None, include_profiles=False, include_sids=True, include_students=False, ) if cohort and _can_current_user_view_cohort(cohort): fieldnames = get_param(params, 'csvColumnsSelected', []) sids = CohortFilter.get_sids(cohort['id']) return _response_with_csv_download(benchmark, cohort['domain'], fieldnames, sids) else: raise ResourceNotFoundError( f'No cohort found with identifier: {cohort_id}')
def test_create_cohort(self, authenticated_session, client): """creates custom cohort, owned by current user""" label = 'All tennis, all the time' team_codes = ['TNW', 'TNM'] custom_cohort = { 'label': label, 'team_codes': team_codes, } response = client.post('/api/cohort/create', data=json.dumps(custom_cohort), content_type='application/json') assert response.status_code == 200 cohort = json.loads(response.data) assert 'label' in cohort and cohort['label'] == label assert 'teams' in cohort and len(cohort['teams']) == 2 assert cohort['teams'][0]['code'] == team_codes[0] assert cohort['teams'][1]['code'] == team_codes[1] same_cohort = CohortFilter.find_by_id(cohort['id']) assert same_cohort['label'] == label assert 'teams' in cohort and len(cohort['teams']) == 2 assert cohort['teams'][0]['code'] == team_codes[0] assert cohort['teams'][1]['code'] == team_codes[1]
def test_ce3_filter_criteria(self): colleges = ['College of Letters and Science', 'College of Engineering'] family_dependent_ranges = [ { 'min': 0, 'max': 2 }, { 'min': 5, 'max': 5 }, ] freshman_or_transfer = ['Transfer'] has_fee_waiver = True cohort = CohortFilter.create( uid=ce3_advisor_uid, name='All my admits', filter_criteria={ 'colleges': colleges, 'familyDependentRanges': family_dependent_ranges, 'freshmanOrTransfer': freshman_or_transfer, 'hasFeeWaiver': has_fee_waiver, }, domain='admitted_students', ) cohort_id = cohort['id'] cohort = CohortFilter.find_by_id(cohort_id) expected = { 'colleges': colleges, 'familyDependentRanges': family_dependent_ranges, 'freshmanOrTransfer': freshman_or_transfer, 'hasFeeWaiver': has_fee_waiver, } for key, value in expected.items(): assert cohort['criteria'][key] == expected[key] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) assert cohort['students']
def get_cohort_events(cohort_id): cohort = CohortFilter.find_by_id(cohort_id, include_students=False) if not cohort or not _can_current_user_view_cohort(cohort): raise ResourceNotFoundError( f'No cohort found with identifier: {cohort_id}') if cohort['domain'] != 'default': raise BadRequestError( f"Cohort events are not supported in domain {cohort['domain']}") offset = get_param(request.args, 'offset', 0) limit = get_param(request.args, 'limit', 50) results = CohortFilterEvent.events_for_cohort(cohort_id, offset, limit) count = results['count'] events = results['events'] event_sids = [e.sid for e in events] event_profiles_by_sid = { e['sid']: e for e in get_summary_student_profiles(event_sids, include_historical=True) } def _event_feed(event): profile = event_profiles_by_sid.get(event.sid, {}) return { 'createdAt': event.created_at.isoformat(), 'eventType': event.event_type, 'firstName': profile.get('firstName'), 'lastName': profile.get('lastName'), 'sid': event.sid, 'uid': profile.get('uid'), } feed = { 'count': count, 'events': [_event_feed(e) for e in events], } return tolerant_jsonify(feed)
def test_no_cohort(self): assert not CohortFilter.find_by_id(99999999) assert not CohortFilter.all_owned_by('88888888')