Пример #1
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}')
Пример #2
0
def search_students():
    params = request.get_json()
    if is_unauthorized_search(params):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    if not len(search_phrase):
        raise BadRequestError('Invalid or empty search input')
    results = search_for_students(
        include_profiles=True,
        search_phrase=search_phrase.replace(',', ' '),
        is_active_asc=_convert_asc_inactive_arg(
            util.get(params, 'isInactiveAsc')),
        order_by=util.get(params, 'orderBy', None),
        offset=util.get(params, 'offset', 0),
        limit=util.get(params, 'limit', 50),
    )
    alert_counts = Alert.current_alert_counts_for_viewer(current_user.id)
    students = results['students']
    add_alert_counts(alert_counts, students)
    return tolerant_jsonify({
        'students': students,
        'totalStudentCount': results['totalStudentCount'],
    })
Пример #3
0
def search():
    params = util.remove_none_values(request.get_json())
    order_by = util.get(params, 'orderBy', None)
    if is_unauthorized_search(list(params.keys()), order_by):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    domain = {
        'students': util.get(params, 'students'),
        'courses': util.get(params, 'courses'),
        'notes': util.get(params, 'notes'),
    }
    if not domain['students'] and not domain['courses'] and not domain['notes']:
        raise BadRequestError('No search domain specified')
    if not len(search_phrase) and not domain['notes']:
        raise BadRequestError('Invalid or empty search input')

    feed = {}

    if len(search_phrase) and domain['students']:
        feed.update(_student_search(search_phrase, params, order_by))

    if len(search_phrase) and domain['courses']:
        feed.update(_course_search(search_phrase, params, order_by))

    if domain['notes']:
        feed.update(_notes_search(search_phrase, params))

    return tolerant_jsonify(feed)
Пример #4
0
def _appointments_search(search_phrase, params):
    appointment_options = util.get(params, 'appointmentOptions', {})
    advisor_uid = appointment_options.get('advisorUid')
    advisor_csid = appointment_options.get('advisorCsid')
    student_csid = appointment_options.get('studentCsid')
    topic = appointment_options.get('topic')
    limit = int(util.get(appointment_options, 'limit', 20))
    offset = int(util.get(appointment_options, 'offset', 0))

    date_from = appointment_options.get('dateFrom')
    date_to = appointment_options.get('dateTo')

    if not len(search_phrase) and not (advisor_uid or advisor_csid
                                       or student_csid or topic or date_from
                                       or date_to):
        raise BadRequestError('Invalid or empty search input')

    if advisor_csid and not advisor_uid:
        advisor_uid = get_uid_for_csid(app, advisor_csid)

    if date_from:
        try:
            datetime_from = util.localized_timestamp_to_utc(
                f'{date_from}T00:00:00')
        except ValueError:
            raise BadRequestError('Invalid dateFrom value')
    else:
        datetime_from = None

    if date_to:
        try:
            datetime_to = util.localized_timestamp_to_utc(
                f'{date_to}T00:00:00') + timedelta(days=1)
        except ValueError:
            raise BadRequestError('Invalid dateTo value')
    else:
        datetime_to = None

    if datetime_from and datetime_to and datetime_to <= datetime_from:
        raise BadRequestError('dateFrom must be less than dateTo')

    appointment_results = search_advising_appointments(
        search_phrase=search_phrase,
        advisor_uid=advisor_uid,
        student_csid=student_csid,
        topic=topic,
        datetime_from=datetime_from,
        datetime_to=datetime_to,
        offset=offset,
        limit=limit,
    )
    return {
        'appointments': appointment_results,
    }
Пример #5
0
def search_admits():
    params = request.get_json()
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    if not len(search_phrase):
        raise BadRequestError('Invalid or empty search input')
    order_by = util.get(params, 'orderBy', None)
    admit_results = search_for_admitted_students(
        search_phrase=search_phrase.replace(',', ' '),
        order_by=order_by,
    )
    return tolerant_jsonify(admit_results)
Пример #6
0
def _notes_search(search_phrase, params):
    note_options = util.get(params, 'noteOptions', {})
    author_csid = note_options.get('authorCsid')
    student_csid = note_options.get('studentCsid')
    topic = note_options.get('topic')
    limit = util.get(note_options, 'limit', 100)
    offset = util.get(note_options, 'offset', 0)

    date_from = note_options.get('dateFrom')
    date_to = note_options.get('dateTo')

    if not len(search_phrase) and not (author_csid or student_csid or topic
                                       or date_from or date_to):
        raise BadRequestError('Invalid or empty search input')

    if date_from:
        try:
            datetime_from = util.localized_timestamp_to_utc(
                f'{date_from}T00:00:00')
        except ValueError:
            raise BadRequestError('Invalid dateFrom value')
    else:
        datetime_from = None

    if date_to:
        try:
            datetime_to = util.localized_timestamp_to_utc(
                f'{date_to}T00:00:00') + timedelta(days=1)
        except ValueError:
            raise BadRequestError('Invalid dateTo value')
    else:
        datetime_to = None

    if datetime_from and datetime_to and datetime_to <= datetime_from:
        raise BadRequestError('dateFrom must be less than dateTo')

    notes_results = search_advising_notes(
        search_phrase=search_phrase,
        author_csid=author_csid,
        student_csid=student_csid,
        topic=topic,
        datetime_from=datetime_from,
        datetime_to=datetime_to,
        offset=int(offset),
        limit=int(limit),
    )

    return {
        'notes': notes_results,
    }
Пример #7
0
def get_section(term_id, section_id):
    offset = util.get(request.args, 'offset', None)
    if offset:
        offset = int(offset)
    limit = util.get(request.args, 'limit', None)
    if limit:
        limit = int(limit)
    section = get_sis_section(term_id, section_id)
    if not section:
        raise ResourceNotFoundError(f'No section {section_id} in term {term_id}')
    student_profiles = get_course_student_profiles(term_id, section_id, offset=offset, limit=limit)
    section.update(student_profiles)
    Alert.include_alert_counts_for_students(viewer_uid=current_user.uid, cohort=student_profiles)
    return tolerant_jsonify(section)
Пример #8
0
def create_or_update_user_profile():
    params = request.get_json()
    profile = params.get('profile', None)
    memberships = params.get('memberships', None)
    delete_action = to_bool_or_none(util.get(params, 'deleteAction'))

    if not profile or not profile.get('uid') or memberships is None:
        raise errors.BadRequestError('Required parameters are missing')

    authorized_user = _update_or_create_authorized_user(memberships,
                                                        profile,
                                                        include_deleted=True)
    _delete_existing_memberships(authorized_user)
    _create_department_memberships(authorized_user, memberships)

    if delete_action is True and not authorized_user.deleted_at:
        AuthorizedUser.delete(authorized_user.uid)
    elif delete_action is False and authorized_user.deleted_at:
        AuthorizedUser.un_delete(authorized_user.uid)

    user_id = authorized_user.id
    UserSession.flush_cache_for_id(user_id)

    updated_user = AuthorizedUser.find_by_id(user_id, include_deleted=True)
    users_json = authorized_users_api_feed([updated_user])
    return tolerant_jsonify(users_json and users_json[0])
Пример #9
0
def get_admin_users():
    params = request.get_json()
    ignore_deleted = to_bool_or_none(util.get(params, 'ignoreDeleted'))
    users = AuthorizedUser.get_admin_users(
        ignore_deleted=True if ignore_deleted is None else ignore_deleted)
    return tolerant_jsonify({
        'users':
        authorized_users_api_feed(
            users,
            sort_by=util.get(params, 'sortBy'),
            sort_descending=to_bool_or_none(util.get(params,
                                                     'sortDescending')),
        ),
        'totalUserCount':
        len(users),
    })
Пример #10
0
def _student_search(search_phrase, params, order_by):
    student_results = search_for_students(
        search_phrase=search_phrase.replace(',', ' '),
        order_by=order_by,
        offset=util.get(params, 'offset', 0),
        limit=util.get(params, 'limit', 50),
    )
    students = student_results['students']
    sids = [s['sid'] for s in students]
    alert_counts = Alert.current_alert_counts_for_sids(current_user.get_id(),
                                                       sids)
    add_alert_counts(alert_counts, students)
    return {
        'students': students,
        'totalStudentCount': student_results['totalStudentCount'],
    }
Пример #11
0
def user_by_uid(uid):
    ignore_deleted = to_bool_or_none(util.get(request.args, 'ignoreDeleted'))
    user = _find_user_by_uid(uid, ignore_deleted)
    if user:
        users_feed = authorized_users_api_feed([user])
        return tolerant_jsonify(users_feed[0])
    else:
        raise errors.ResourceNotFoundError('User not found')
Пример #12
0
def get_section(term_id, section_id):
    if not current_user.can_access_canvas_data:
        raise ForbiddenRequestError('Unauthorized to view course data')
    offset = util.get(request.args, 'offset', None)
    if offset:
        offset = int(offset)
    limit = util.get(request.args, 'limit', None)
    if limit:
        limit = int(limit)
    featured = util.get(request.args, 'featured', None)
    section = get_sis_section(term_id, section_id)
    if not section:
        raise ResourceNotFoundError(f'No section {section_id} in term {term_id}')
    student_profiles = get_course_student_profiles(term_id, section_id, offset=offset, limit=limit, featured=featured)
    section.update(student_profiles)
    Alert.include_alert_counts_for_students(viewer_user_id=current_user.get_id(), group=student_profiles)
    return tolerant_jsonify(section)
Пример #13
0
def get_departments():
    exclude_empty = to_bool_or_none(
        util.get(request.args, 'excludeEmpty', None))
    api_json = []
    for d in UniversityDept.get_all(exclude_empty=exclude_empty):
        api_json.append({
            'id': d.id,
            'code': d.dept_code,
            'name': d.dept_name,
        })
    return tolerant_jsonify(api_json)
Пример #14
0
def all_users():
    params = request.get_json()
    users, total_user_count = AuthorizedUser.get_users(
        blocked=to_bool_or_none(util.get(params, 'blocked')),
        deleted=to_bool_or_none(util.get(params, 'deleted')),
        dept_code=util.get(params, 'deptCode', None),
        role=util.get(params, 'role', None) or None,
    )
    return tolerant_jsonify({
        'users':
        authorized_users_api_feed(
            users,
            sort_by=util.get(params, 'sortBy', 'lastName'),
            sort_descending=to_bool_or_none(
                util.get(params, 'sortDescending', False)),
        ),
        'totalUserCount':
        total_user_count,
    })
Пример #15
0
def search():
    params = util.remove_none_values(request.get_json())
    order_by = util.get(params, 'orderBy', None)
    if is_unauthorized_search(list(params.keys()), order_by):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    domain = {
        'appointments': util.get(params, 'appointments'),
        'students': util.get(params, 'students'),
        'courses': util.get(params, 'courses'),
        'notes': util.get(params, 'notes'),
    }
    if not domain['students'] and not domain['courses'] and not (
            domain['notes'] or domain['appointments']):
        raise BadRequestError('No search domain specified')
    if not len(search_phrase) and not (domain['notes']
                                       or domain['appointments']):
        raise BadRequestError('Invalid or empty search input')
    if domain['courses'] and not current_user.can_access_canvas_data:
        raise ForbiddenRequestError('Unauthorized to search courses')

    feed = {}

    if domain['appointments'] and app.config[
            'FEATURE_FLAG_ADVISOR_APPOINTMENTS']:
        feed.update(_appointments_search(search_phrase, params))

    if len(search_phrase) and domain['students']:
        feed.update(_student_search(search_phrase, params, order_by))

    if len(search_phrase) and domain['courses']:
        feed.update(_course_search(search_phrase, params, order_by))

    if domain['notes']:
        feed.update(_notes_search(search_phrase, params))

    return tolerant_jsonify(feed)
Пример #16
0
def get_students():
    params = request.get_json()
    if is_unauthorized_search(params):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    results = query_students(
        advisor_ldap_uids=util.get(params, 'advisorLdapUids'),
        coe_prep_statuses=util.get(params, 'coePrepStatuses'),
        ethnicities=util.get(params, 'ethnicities'),
        genders=util.get(params, 'genders'),
        gpa_ranges=util.get(params, 'gpaRanges'),
        group_codes=util.get(params, 'groupCodes'),
        include_profiles=True,
        is_active_asc=_convert_asc_inactive_arg(
            util.get(params, 'isInactiveAsc')),
        in_intensive_cohort=util.to_bool_or_none(
            util.get(params, 'inIntensiveCohort')),
        last_name_range=_get_name_range_boundaries(
            util.get(params, 'lastNameRange')),
        levels=util.get(params, 'levels'),
        limit=util.get(params, 'limit', 50),
        majors=util.get(params, 'majors'),
        offset=util.get(params, 'offset', 0),
        order_by=util.get(params, 'orderBy', None),
        underrepresented=util.get(params, 'underrepresented'),
        unit_ranges=util.get(params, 'unitRanges'),
    )
    if results is None:
        raise BadRequestError('Invalid search criteria')
    alert_counts = Alert.current_alert_counts_for_viewer(current_user.id)
    students = results['students'] if results else []
    add_alert_counts(alert_counts, students)
    return tolerant_jsonify({
        'students':
        students,
        'totalStudentCount':
        results['totalStudentCount'] if results else 0,
    })
Пример #17
0
    def to_api_json(
        self,
        order_by=None,
        offset=0,
        limit=50,
        alert_offset=None,
        alert_limit=None,
        include_sids=False,
        include_students=True,
        include_profiles=False,
        include_alerts_for_user_id=None,
    ):
        benchmark = get_benchmarker(f'CohortFilter {self.id} to_api_json')
        benchmark('begin')
        c = self.filter_criteria
        c = c if isinstance(c, dict) else json.loads(c)
        coe_advisor_ldap_uids = util.get(c, 'coeAdvisorLdapUids')
        if not isinstance(coe_advisor_ldap_uids, list):
            coe_advisor_ldap_uids = [coe_advisor_ldap_uids
                                     ] if coe_advisor_ldap_uids else None
        cohort_name = self.name
        cohort_json = {
            'id': self.id,
            'code': self.id,
            'name': cohort_name,
            'owners': [],
            'alertCount': self.alert_count,
        }
        for owner in self.owners:
            cohort_json['owners'].append({
                'uid':
                owner.uid,
                'deptCodes': [
                    m.university_dept.dept_code
                    for m in owner.department_memberships
                ],
            })
        coe_ethnicities = c.get('coeEthnicities')
        coe_genders = c.get('coeGenders')
        coe_prep_statuses = c.get('coePrepStatuses')
        coe_probation = util.to_bool_or_none(c.get('coeProbation'))
        coe_underrepresented = util.to_bool_or_none(
            c.get('coeUnderrepresented'))
        cohort_owner_academic_plans = util.get(c, 'cohortOwnerAcademicPlans')
        entering_terms = c.get('enteringTerms')
        ethnicities = c.get('ethnicities')
        expected_grad_terms = c.get('expectedGradTerms')
        genders = c.get('genders')
        gpa_ranges = c.get('gpaRanges')
        group_codes = c.get('groupCodes')
        in_intensive_cohort = util.to_bool_or_none(c.get('inIntensiveCohort'))
        is_inactive_asc = util.to_bool_or_none(c.get('isInactiveAsc'))
        is_inactive_coe = util.to_bool_or_none(c.get('isInactiveCoe'))
        last_name_ranges = c.get('lastNameRanges')
        last_term_gpa_ranges = c.get('lastTermGpaRanges')
        levels = c.get('levels')
        majors = c.get('majors')
        midpoint_deficient_grade = util.to_bool_or_none(
            c.get('midpointDeficient'))
        team_groups = athletics.get_team_groups(
            group_codes) if group_codes else []
        transfer = util.to_bool_or_none(c.get('transfer'))
        underrepresented = util.to_bool_or_none(c.get('underrepresented'))
        unit_ranges = c.get('unitRanges')
        cohort_json.update({
            'criteria': {
                'coeAdvisorLdapUids': coe_advisor_ldap_uids,
                'coeEthnicities': coe_ethnicities,
                'coeGenders': coe_genders,
                'coePrepStatuses': coe_prep_statuses,
                'coeProbation': coe_probation,
                'coeUnderrepresented': coe_underrepresented,
                'cohortOwnerAcademicPlans': cohort_owner_academic_plans,
                'enteringTerms': entering_terms,
                'ethnicities': ethnicities,
                'expectedGradTerms': expected_grad_terms,
                'genders': genders,
                'gpaRanges': gpa_ranges,
                'groupCodes': group_codes,
                'inIntensiveCohort': in_intensive_cohort,
                'isInactiveAsc': is_inactive_asc,
                'isInactiveCoe': is_inactive_coe,
                'lastNameRanges': last_name_ranges,
                'lastTermGpaRanges': last_term_gpa_ranges,
                'levels': levels,
                'majors': majors,
                'midpointDeficient': midpoint_deficient_grade,
                'transfer': transfer,
                'unitRanges': unit_ranges,
                'underrepresented': underrepresented,
            },
            'teamGroups': team_groups,
        })
        if not include_students and not include_alerts_for_user_id and self.student_count is not None:
            # No need for a students query; return the database-stashed student count.
            cohort_json.update({
                'totalStudentCount': self.student_count,
            })
            benchmark('end')
            return cohort_json

        benchmark('begin students query')
        sids_only = not include_students

        # Translate the "My Students" filter, if present, into queryable criteria. Although our database relationships allow
        # for multiple cohort owners, we assume a single owner here since the "My Students" filter makes no sense
        # in any other scenario.
        if cohort_owner_academic_plans:
            if self.owners:
                owner_sid = get_csid_for_uid(app, self.owners[0].uid)
            else:
                owner_sid = current_user.get_csid()
            advisor_plan_mappings = [{
                'advisor_sid': owner_sid,
                'academic_plan_code': plan
            } for plan in cohort_owner_academic_plans]
        else:
            advisor_plan_mappings = None

        results = query_students(
            advisor_plan_mappings=advisor_plan_mappings,
            coe_advisor_ldap_uids=coe_advisor_ldap_uids,
            coe_ethnicities=coe_ethnicities,
            coe_genders=coe_genders,
            coe_prep_statuses=coe_prep_statuses,
            coe_probation=coe_probation,
            coe_underrepresented=coe_underrepresented,
            entering_terms=entering_terms,
            ethnicities=ethnicities,
            expected_grad_terms=expected_grad_terms,
            genders=genders,
            gpa_ranges=gpa_ranges,
            group_codes=group_codes,
            in_intensive_cohort=in_intensive_cohort,
            include_profiles=(include_students and include_profiles),
            is_active_asc=None
            if is_inactive_asc is None else not is_inactive_asc,
            is_active_coe=None
            if is_inactive_coe is None else not is_inactive_coe,
            last_name_ranges=last_name_ranges,
            last_term_gpa_ranges=last_term_gpa_ranges,
            levels=levels,
            limit=limit,
            majors=majors,
            midpoint_deficient_grade=midpoint_deficient_grade,
            offset=offset,
            order_by=order_by,
            sids_only=sids_only,
            transfer=transfer,
            underrepresented=underrepresented,
            unit_ranges=unit_ranges,
        )
        benchmark('end students query')

        if results:
            # Cohort might have tens of thousands of SIDs.
            if include_sids:
                cohort_json['sids'] = results['sids']
            cohort_json.update({
                'totalStudentCount':
                results['totalStudentCount'],
            })
            # If the cohort is new or cache refresh is underway then store student_count and sids in the db.
            if self.student_count is None:
                self.update_sids_and_student_count(
                    results['sids'], results['totalStudentCount'])
            if include_students:
                cohort_json.update({
                    'students': results['students'],
                })
            if include_alerts_for_user_id:
                benchmark('begin alerts query')
                alert_count_per_sid = Alert.include_alert_counts_for_students(
                    viewer_user_id=include_alerts_for_user_id,
                    group=results,
                    offset=alert_offset,
                    limit=alert_limit,
                )
                benchmark('end alerts query')
                cohort_json.update({
                    'alerts': alert_count_per_sid,
                })
                if self.alert_count is None:
                    alert_count = sum(student['alertCount']
                                      for student in alert_count_per_sid)
                    self.update_alert_count(alert_count)
                    cohort_json.update({
                        'alertCount': alert_count,
                    })
        benchmark('end')
        return cohort_json
Пример #18
0
    def to_api_json(
        self,
        order_by=None,
        offset=0,
        limit=50,
        include_students=True,
        include_profiles=False,
        include_alerts_for_uid=None,
    ):
        c = self.filter_criteria
        c = c if isinstance(c, dict) else json.loads(c)
        advisor_ldap_uids = util.get(c, 'advisorLdapUids')
        if not isinstance(advisor_ldap_uids, list):
            advisor_ldap_uids = [advisor_ldap_uids
                                 ] if advisor_ldap_uids else None
        cohort_name = self.label
        cohort_json = {
            'id': self.id,
            'code': self.id,
            'label': cohort_name,
            'name': cohort_name,
            'owners': [user.uid for user in self.owners],
        }
        coe_prep_statuses = c.get('coePrepStatuses')
        ethnicities = c.get('ethnicities')
        genders = c.get('genders')
        gpa_ranges = c.get('gpaRanges')
        group_codes = c.get('groupCodes')
        in_intensive_cohort = util.to_bool_or_none(c.get('inIntensiveCohort'))
        is_inactive_asc = util.to_bool_or_none(c.get('isInactiveAsc'))
        last_name_range = c.get('lastNameRange')
        levels = c.get('levels')
        majors = c.get('majors')
        team_groups = athletics.get_team_groups(
            group_codes) if group_codes else []
        underrepresented = util.to_bool_or_none(c.get('underrepresented'))
        unit_ranges = c.get('unitRanges')
        cohort_json.update({
            'filterCriteria': {
                'advisorLdapUids': advisor_ldap_uids,
                'coePrepStatuses': coe_prep_statuses,
                'ethnicities': ethnicities,
                'genders': genders,
                'gpaRanges': gpa_ranges,
                'groupCodes': group_codes,
                'inIntensiveCohort': in_intensive_cohort,
                'isInactiveAsc': is_inactive_asc,
                'lastNameRange': last_name_range,
                'levels': levels,
                'majors': majors,
                'unitRanges': unit_ranges,
                'underrepresented': underrepresented,
            },
            'teamGroups': team_groups,
        })

        if not include_students and not include_alerts_for_uid and self.student_count is not None:
            # No need for a students query; return the database-stashed student count.
            cohort_json.update({
                'totalStudentCount': self.student_count,
            })
            return cohort_json
        owner = self.owners[0] if len(self.owners) else None
        if owner and 'UWASC' in get_dept_codes(owner):
            is_active_asc = not is_inactive_asc
        else:
            is_active_asc = None if is_inactive_asc is None else not is_inactive_asc
        sids_only = not include_students
        results = query_students(
            advisor_ldap_uids=advisor_ldap_uids,
            coe_prep_statuses=coe_prep_statuses,
            ethnicities=ethnicities,
            genders=genders,
            gpa_ranges=gpa_ranges,
            group_codes=group_codes,
            in_intensive_cohort=in_intensive_cohort,
            include_profiles=(include_students and include_profiles),
            is_active_asc=is_active_asc,
            last_name_range=last_name_range,
            levels=levels,
            limit=limit,
            majors=majors,
            offset=offset,
            order_by=order_by,
            sids_only=sids_only,
            underrepresented=underrepresented,
            unit_ranges=unit_ranges,
        )
        if results:
            # If the cohort is newly created or a cache refresh is underway, store the student count in the database
            # to save future queries.
            if self.student_count is None:
                self.update_student_count(results['totalStudentCount'])
            cohort_json.update({
                'totalStudentCount':
                results['totalStudentCount'],
            })
            if include_students:
                cohort_json.update({
                    'students': results['students'],
                })
            if include_alerts_for_uid:
                alert_counts = Alert.include_alert_counts_for_students(
                    viewer_uid=include_alerts_for_uid, cohort=results)
                cohort_json.update({
                    'alerts': alert_counts,
                })
        return cohort_json
Пример #19
0
def _query_students(
    benchmark,
    criteria,
    include_profiles,
    limit,
    offset,
    order_by,
    owner,
    sids_only,
    term_id,
):
    benchmark('begin students query')
    # Translate the "My Students" filter, if present, into queryable criteria.
    plans = criteria.get('cohortOwnerAcademicPlans')
    if plans:
        if owner:
            owner_sid = get_csid_for_uid(app, owner.uid)
        else:
            owner_sid = current_user.get_csid()
        advisor_plan_mappings = [{
            'advisor_sid': owner_sid,
            'academic_plan_code': plan
        } for plan in plans]
    else:
        advisor_plan_mappings = None
    coe_advisor_ldap_uids = util.get(criteria, 'coeAdvisorLdapUids')
    if not isinstance(coe_advisor_ldap_uids, list):
        coe_advisor_ldap_uids = [coe_advisor_ldap_uids
                                 ] if coe_advisor_ldap_uids else None
    results = query_students(
        academic_standings=criteria.get('academicStandings'),
        advisor_plan_mappings=advisor_plan_mappings,
        coe_advisor_ldap_uids=coe_advisor_ldap_uids,
        coe_ethnicities=criteria.get('coeEthnicities'),
        coe_genders=criteria.get('coeGenders'),
        coe_prep_statuses=criteria.get('coePrepStatuses'),
        coe_probation=criteria.get('coeProbation'),
        coe_underrepresented=criteria.get('coeUnderrepresented'),
        colleges=criteria.get('colleges'),
        curated_group_ids=criteria.get('curatedGroupIds'),
        entering_terms=criteria.get('enteringTerms'),
        epn_cpn_grading_terms=criteria.get('epnCpnGradingTerms'),
        ethnicities=criteria.get('ethnicities'),
        expected_grad_terms=criteria.get('expectedGradTerms'),
        genders=criteria.get('genders'),
        gpa_ranges=criteria.get('gpaRanges'),
        group_codes=criteria.get('groupCodes'),
        in_intensive_cohort=criteria.get('inIntensiveCohort'),
        include_profiles=include_profiles,
        intended_majors=criteria.get('intendedMajors'),
        is_active_asc=None if criteria.get('isInactiveAsc') is None else
        not criteria.get('isInactiveAsc'),
        is_active_coe=None if criteria.get('isInactiveCoe') is None else
        not criteria.get('isInactiveCoe'),
        last_name_ranges=criteria.get('lastNameRanges'),
        last_term_gpa_ranges=criteria.get('lastTermGpaRanges'),
        levels=criteria.get('levels'),
        limit=limit,
        majors=criteria.get('majors'),
        midpoint_deficient_grade=criteria.get('midpointDeficient'),
        minors=criteria.get('minors'),
        offset=offset,
        order_by=order_by,
        sids_only=sids_only,
        term_id=term_id,
        transfer=criteria.get('transfer'),
        underrepresented=criteria.get('underrepresented'),
        unit_ranges=criteria.get('unitRanges'),
        visa_types=criteria.get('visaTypes'),
        student_holds=criteria.get('studentHolds'),
    )
    benchmark('end students query')
    return results
Пример #20
0
def authorized_user_groups():
    sort_users_by = util.get(request.args, 'sortUsersBy', None)
    return tolerant_jsonify(_get_boa_user_groups(sort_users_by))
Пример #21
0
def all_users():
    sort_users_by = util.get(request.args, 'sortUsersBy', None)
    return tolerant_jsonify(_get_boa_users(sort_users_by))
Пример #22
0
def create_cohort():
    params = request.get_json()
    if is_unauthorized_search(params):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    label = util.get(params, 'label', None)
    if not label:
        raise BadRequestError('Cohort creation requires \'label\'')
    cohort = CohortFilter.create(
        advisor_ldap_uids=util.get(params, 'advisorLdapUids'),
        coe_prep_statuses=util.get(params, 'coePrepStatuses'),
        ethnicities=util.get(params, 'ethnicities'),
        genders=util.get(params, 'genders'),
        gpa_ranges=util.get(params, 'gpaRanges'),
        group_codes=util.get(params, 'groupCodes'),
        in_intensive_cohort=util.to_bool_or_none(
            params.get('inIntensiveCohort')),
        is_inactive_asc=util.to_bool_or_none(params.get('isInactiveAsc')),
        label=label,
        last_name_range=util.get(params, 'lastNameRange'),
        levels=util.get(params, 'levels'),
        majors=util.get(params, 'majors'),
        uid=current_user.get_id(),
        underrepresented=util.get(params, 'underrepresented'),
        unit_ranges=util.get(params, 'unitRanges'),
    )
    return tolerant_jsonify(decorate_cohort(cohort))