예제 #1
0
    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)
예제 #2
0
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}')
예제 #3
0
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)
예제 #4
0
    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
예제 #5
0
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}')
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
 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))
예제 #9
0
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)
예제 #10
0
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}')
예제 #11
0
    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]
예제 #12
0
 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']
예제 #13
0
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)
예제 #14
0
 def test_no_cohort(self):
     assert not CohortFilter.find_by_id(99999999)
     assert not CohortFilter.all_owned_by('88888888')