Exemplo n.º 1
0
Arquivo: user.py Projeto: imclab/rmc
    def get_current_term_exams(self, current_term_course_ids=None):
        if not current_term_course_ids:
            ucs = (self.get_user_courses().filter(
                term_id=util.get_current_term_id()).only('course_id'))
            current_term_course_ids = [uc.course_id for uc in ucs]

        return _exam.Exam.objects(course_id__in=current_term_course_ids)
Exemplo n.º 2
0
def render_template(*args, **kwargs):
    redis = view_helpers.get_redis_instance()

    current_user = view_helpers.get_current_user()
    should_renew_fb_token = False
    if (current_user and current_user.fbid and not current_user.is_demo_account
            and not hasattr(flask.request, 'as_user_override')):
        should_renew_fb_token = current_user.should_renew_fb_token

    kwargs.update({
        'env':
        app.config['ENV'],
        'VERSION':
        VERSION,
        'NUM_KITTENS':
        len(KITTEN_DATA),
        'js_dir':
        app.config['JS_DIR'],
        'ga_property_id':
        app.config['GA_PROPERTY_ID'],
        'total_points':
        int(redis.get('total_points') or 0),
        'current_user':
        current_user,
        'should_renew_fb_token':
        should_renew_fb_token,
        'current_term_id':
        util.get_current_term_id(),
        'user_agent':
        flask.request.headers['User-Agent']
        if 'User-Agent' in flask.request.headers else 'No Info',
    })
    return flask_render_template(*args, **kwargs)
Exemplo n.º 3
0
    def get_current_term_exams(self, current_term_course_ids=None):
        if not current_term_course_ids:
            ucs = (self.get_user_courses()
                    .filter(term_id=util.get_current_term_id())
                    .only('course_id'))
            current_term_course_ids = [uc.course_id for uc in ucs]

        return _exam.Exam.objects(course_id__in=current_term_course_ids)
Exemplo n.º 4
0
def unsafe_clear_schedule(user, term_id=_util.get_current_term_id()):
    for usi in m.UserScheduleItem.objects(user_id=user.id, term_id=term_id):
        usi.delete()

    for uc in m.UserCourse.objects(user_id=user.id, term_id=term_id):
        try:
            user.course_history.remove(uc.id)
        except ValueError:
            print "Weird problem: UC (%s) doesn't exist" % (uc.id)
        uc.delete()

    user.schedules_imported = 0
    user.save()
Exemplo n.º 5
0
def unsafe_clear_schedule(user, term_id=_util.get_current_term_id()):
    for usi in m.UserScheduleItem.objects(user_id=user.id, term_id=term_id):
        usi.delete()

    for uc in m.UserCourse.objects(user_id=user.id, term_id=term_id):
        try:
            user.course_history.remove(uc.id)
        except ValueError:
            print "Weird problem: UC (%s) doesn't exist" % (uc.id)
        uc.delete()

    user.schedules_imported = 0
    user.save()
Exemplo n.º 6
0
 def to_schedule_obj(self, term_id=None):
     """Converts to a UserScheduleItem."""
     return _user_schedule_item.UserScheduleItem(
         id=self.id,
         class_num='',
         building=self.location,
         room='',
         section_type='EXAM',  # TODO(david): Make this a constant
         section_num=self.sections,
         start_date=self.start_date,
         end_date=self.end_date,
         course_id=self.course_id,
         term_id=term_id or util.get_current_term_id(),
     )
Exemplo n.º 7
0
    def get_latest_program_year_id(self):
        latest_term_uc = None
        for uc_dict in self.get_user_courses():

            # Ignore untaken courses or shortlisted courses
            if uc_dict['term_id'] > util.get_current_term_id():
                continue

            if not latest_term_uc:
                latest_term_uc = uc_dict
            elif uc_dict['term_id'] > latest_term_uc['term_id']:
                latest_term_uc = uc_dict

        if latest_term_uc:
            return latest_term_uc['program_year_id']

        return None
Exemplo n.º 8
0
Arquivo: user.py Projeto: imclab/rmc
    def get_latest_program_year_id(self):
        latest_term_uc = None
        for uc_dict in self.get_user_courses():

            # Ignore untaken courses or shortlisted courses
            if uc_dict['term_id'] > util.get_current_term_id():
                continue

            if not latest_term_uc:
                latest_term_uc = uc_dict
            elif uc_dict['term_id'] > latest_term_uc['term_id']:
                latest_term_uc = uc_dict

        if latest_term_uc:
            return latest_term_uc['program_year_id']

        return None
Exemplo n.º 9
0
def render_template(*args, **kwargs):
    redis = view_helpers.get_redis_instance()

    current_user = view_helpers.get_current_user()
    should_renew_fb_token = False
    if (current_user and
        not current_user.is_demo_account and
        not hasattr(flask.request, 'as_user_override')):
        should_renew_fb_token = current_user.should_renew_fb_token

    kwargs.update({
        'env': app.config['ENV'],
        'VERSION': VERSION,
        'NUM_KITTENS': len(KITTEN_DATA),
        'js_dir': app.config['JS_DIR'],
        'ga_property_id': app.config['GA_PROPERTY_ID'],
        'total_points': int(redis.get('total_points') or 0),
        'current_user': current_user,
        'should_renew_fb_token': should_renew_fb_token,
        'current_term_id': util.get_current_term_id(),
    })
    return flask_render_template(*args, **kwargs)
Exemplo n.º 10
0
def render_profile_page(profile_user_id, current_user=None):
    # TODO(mack): for dict maps, use .update() rather than overwriting to
    # avoid subtle overwrites by data that has fields filled out

    LAST_TERM_ID = util.get_current_term_id()

    # PART ONE - VALIDATION

    current_user = current_user or view_helpers.get_current_user()

    try:
        if profile_user_id:
            profile_user_id = bson.ObjectId(profile_user_id)
    except:
        logging.warn('Invalid profile_user_id (%s)' % profile_user_id)
        return view_helpers.redirect_to_profile(current_user)

    if not profile_user_id:
        return view_helpers.redirect_to_profile(current_user)

    if profile_user_id == current_user.id:
        own_profile = True
        profile_user = current_user
    else:
        own_profile = False

        # Allow only friends to view profile
        if not (profile_user_id in current_user.friend_ids or
                (current_user.is_admin and flask.request.values.get('admin'))):
            logging.info("User (%s) tried to access non-friend profile (%s)" %
                         (current_user.id, profile_user_id))
            return view_helpers.redirect_to_profile(current_user)

        profile_user = m.User.objects.with_id(profile_user_id)
        # Technically we don't need this check due to above (under normal
        # operation). Though have this anyway as a failsafe
        if profile_user is None:
            logging.warn('profile_user is None')
            return view_helpers.redirect_to_profile(current_user)

    if own_profile:
        profile_user_secret_id = profile_user.get_secret_id()
    else:
        profile_user_secret_id = None

    show_import_schedule = False
    # Redirect the user appropriately... to /onboarding if they have no course
    # history, and to wherever they logged in from if they just logged in
    # TODO(david): Should have frontend decide whether to take us to /profile
    #     or /onboarding and not redirect in one of these two places
    if own_profile:
        redirect_url = flask.request.values.get('next')

        show_onboarding = False
        if not current_user.has_course_history:
            if not current_user.last_show_onboarding:
                show_onboarding = True
            else:
                time_delta = datetime.now() - current_user.last_show_onboarding
                # If they haven't imported any courses yet and the last time
                # the user was on the onboarding page is more than 5 days ago,
                # show the onboarding page again
                if time_delta.days > RESHOW_ONBOARDING_DELAY_DAYS:
                    show_onboarding = True

        # See https://uwflow.uservoice.com/admin/tickets/62
        if profile_user_id == '50b8ce2cd89d62310645ca78':
            show_onboarding = False

        if show_onboarding:
            onboarding_url = '/onboarding'
            if flask.request.query_string:
                onboarding_url = '%s?%s' % (onboarding_url,
                                            flask.request.query_string)
            return flask.make_response(flask.redirect(onboarding_url))
        else:
            redirect_url = flask.request.values.get('next')
            if redirect_url:
                return flask.make_response(flask.redirect(redirect_url))

        # Show the import schedule view if it's been long enough
        if not current_user.has_schedule:
            if current_user.last_show_import_schedule:
                time_delta = (datetime.now() -
                              current_user.last_show_import_schedule)
                # User didn't import schedule yet, reshow every few days
                if time_delta.days > RESHOW_SCHEDULE_DELAY_DAYS:
                    show_import_schedule = True
            else:
                show_import_schedule = True

            if show_import_schedule:
                # TODO(Sandy): Do this on modal dismiss instead
                current_user.last_show_import_schedule = datetime.now()
                current_user.save()

    # PART TWO - DATA FETCHING

    # Get the mutual course ids of friends of profile user
    mutual_course_ids_by_friend = {}
    if own_profile:
        mutual_course_ids_by_friend = profile_user.get_mutual_course_ids(
            view_helpers.get_redis_instance())

    def get_friend_course_ids_in_term(friend_ids, term_id):
        user_courses = m.UserCourse.objects(term_id=term_id,
                                            user_id__in=friend_ids).only(
                                                'user_id', 'course_id')

        last_term_course_ids_by_friend = {}
        for uc in user_courses:
            last_term_course_ids_by_friend.setdefault(uc.user_id,
                                                      []).append(uc.course_id)
        return last_term_course_ids_by_friend

    # Get the course ids of last term courses of friends of profile user
    last_term_course_ids_by_friend = get_friend_course_ids_in_term(
        profile_user.friend_ids, LAST_TERM_ID)

    # Get the course ids of courses profile user has taken
    profile_course_ids = set(profile_user.course_ids)

    # Fetch courses for transcript, which need more detailed information
    # than other courses (such as mutual and last term courses for friends)
    transcript_courses = list(m.Course.objects(id__in=profile_course_ids))

    # Fetch remainining courses that need less data. This will be mutual
    # and last term courses for profile user's friends
    friend_course_ids = set()
    friend_courses = []
    if own_profile:
        for course_ids in mutual_course_ids_by_friend.values():
            friend_course_ids = friend_course_ids.union(course_ids)
        for course_ids in last_term_course_ids_by_friend.values():
            friend_course_ids = friend_course_ids.union(course_ids)
        friend_course_ids = friend_course_ids - profile_course_ids
        friend_courses = m.Course.objects(id__in=friend_course_ids).only(
            'id', 'name')

    # Fetch simplified information for friends of profile user
    # (for friend sidebar)
    friends = profile_user.get_friends()

    # Fetch all professors for all courses
    professor_objs = m.Professor.get_reduced_professors_for_courses(
        transcript_courses)

    # PART THREE - TRANSFORM DATA TO DICTS

    # Convert professors to dicts
    professor_dicts = {}
    for professor_obj in professor_objs:
        professor_dicts[professor_obj['id']] = professor_obj

    # Convert courses to dicts
    course_dict_list, user_course_dict_list, user_course_list = (
        m.Course.get_course_and_user_course_dicts(transcript_courses,
                                                  current_user,
                                                  include_friends=own_profile))
    course_dicts = {}
    for course_dict in course_dict_list:
        course_dicts[course_dict['id']] = course_dict
    user_course_dicts = {}
    for user_course_dict in user_course_dict_list:
        user_course_dicts[user_course_dict['id']] = user_course_dict

    profile_uc_dict_list = []

    # We only need to fetch usercourses for profile user if it is not the
    # current user since m.Course.get_course_and_user_course_dicts() will
    # have already fetched usercourses for the current user
    if not own_profile:
        # Get the user courses of profile user
        profile_uc_dict_list = [
            uc.to_dict() for uc in profile_user.get_user_courses()
        ]
        # Get a mapping from course id to user_course for profile user
        profile_user_course_by_course = {}
        for uc_dict in profile_uc_dict_list:
            profile_user_course_by_course[uc_dict['course_id']] = uc_dict

    # Fill in with information about profile user
    for course in transcript_courses:
        course_dict = course_dicts[course.id]

        if not own_profile:
            # This has already been done for current user
            profile_uc_dict = profile_user_course_by_course.get(course.id)
            profile_user_course_id = profile_uc_dict['id']
            user_course_dicts[profile_user_course_id] = profile_uc_dict

            # Since we only fetched the user courses of the logged in user in
            # m.Course.get_course_and_user_course_dicts() above, gotta also
            # add the user courses of the profile user here
            user_course_dict_list.append(profile_uc_dict)
        else:
            profile_user_course_id = course_dict.get('user_course_id')
            if profile_user_course_id:
                profile_uc_dict_list.append(
                    user_course_dicts[profile_user_course_id])

        course_dict['profile_user_course_id'] = profile_user_course_id

    for course in friend_courses:
        course_dicts[course.id] = course.to_dict()

    def filter_course_ids(course_ids):
        return [
            course_id for course_id in course_ids if course_id in course_dicts
        ]

    # Convert friend users to dicts
    user_dicts = {}
    # TODO(mack): should really be named current_term
    last_term = m.Term(id=LAST_TERM_ID)
    for friend in friends:
        user_dict = friend.to_dict(extended=False)

        if own_profile:
            user_dict.update({
                'last_term_name':
                last_term.name,
                'last_term_course_ids':
                filter_course_ids(
                    last_term_course_ids_by_friend.get(friend.id, [])),
                'mutual_course_ids':
                filter_course_ids(
                    mutual_course_ids_by_friend.get(friend.id, [])),
            })

        user_dicts[friend.id] = user_dict

    # Convert profile user to dict
    # TODO(mack): This must be after friend user dicts since it can override
    # data in it. Remove this restriction
    profile_dict = profile_user.to_dict(include_course_ids=True)
    profile_dict.update({
        'last_program_year_id':
        profile_user.get_latest_program_year_id(),
    })
    user_dicts.setdefault(profile_user.id, {}).update(profile_dict)

    # Convert current user to dict
    # TODO(mack): This must be after friend user dicts since it can override
    # data in it. Remove this restriction
    if not own_profile:
        user_dicts.setdefault(current_user.id, {}).update(
            current_user.to_dict(include_course_ids=True))

    def get_ordered_transcript(profile_uc_dict_list):
        transcript_by_term = {}

        for uc_dict in profile_uc_dict_list:
            (transcript_by_term.setdefault(uc_dict['term_id'],
                                           []).append(uc_dict))

        ordered_transcript = []
        for term_id, uc_dicts in sorted(transcript_by_term.items(),
                                        reverse=True):
            curr_term = m.Term(id=term_id)
            term_dict = {
                'id':
                curr_term.id,
                'name':
                curr_term.name,
                'program_year_id':
                uc_dicts[0].get('program_year_id'),
                'course_ids': [
                    uc_dict['course_id'] for uc_dict in uc_dicts
                    if uc_dict['course_id'] in course_dicts
                ],
            }
            ordered_transcript.append(term_dict)

        return ordered_transcript, transcript_by_term

    # Store courses by term as transcript using the current user's friends
    ordered_transcript, transcript_by_term = get_ordered_transcript(
        profile_uc_dict_list)

    # Fetch exam schedules and schedule items
    current_term_id = util.get_current_term_id()

    current_term_courses = transcript_by_term.get(current_term_id, [])
    current_course_ids = [c['course_id'] for c in current_term_courses]

    exam_objs = profile_user.get_current_term_exams(current_course_ids)
    exam_dicts = [e.to_dict() for e in exam_objs]
    exam_updated_date = None
    if exam_objs:
        exam_updated_date = exam_objs[0].id.generation_time

    # Set the course to prompt the user to review if it's time
    course_id_to_review = None
    if own_profile and profile_user.should_prompt_review():
        profile_user_courses = filter(lambda uc: uc.user_id == profile_user.id,
                                      user_course_list)
        uc_to_review = m.UserCourse.select_course_to_review(
            profile_user_courses)
        course_id_to_review = uc_to_review and uc_to_review.course_id

        if uc_to_review:
            uc_to_review.select_for_review(current_user)

    # NOTE: This implictly requires that the courses on the schedule are on the
    # transcript, since these course objects are needed by the schedule  on the
    # frontend. This should be the case since when we add a schedule item, a
    # corresponding item is added to the transcript.
    schedule_item_dicts = profile_user.get_schedule_item_dicts(exam_objs)
    failed_schedule_item_dicts = profile_user.get_failed_schedule_item_dicts()

    referrals = m.User.objects(referrer_id=current_user.id)
    referral_objs = [referral.to_dict() for referral in referrals]

    rmclogger.log_event(
        rmclogger.LOG_CATEGORY_IMPRESSION,
        rmclogger.LOG_EVENT_PROFILE,
        {
            'current_user': current_user.id,
            'profile_user': profile_user.id,
        },
    )

    schedule_screenshot.update_screenshot_async(profile_user)

    scholarships_dict = []

    if profile_user.id == current_user.id:
        scholarships = m.Scholarship.objects()
        # Filter scholarships based on program
        closed_scholarship_ids_set = set(profile_user.closed_scholarship_ids)
        scholarships = [
            s for s in scholarships
            if profile_user.short_program_name in s.programs
            and s.id not in closed_scholarship_ids_set
        ]
        scholarships_dict = [s.to_dict() for s in scholarships]

    recommendation_dict = []
    recommended_course_ids = []
    if profile_user.id == current_user.id:
        recommended_course_ids = current_user.recommended_courses
        recommendation_dict = [
            m.Course.objects(id=course_id).first().to_dict()
            for course_id in recommended_course_ids
        ]

    return flask.render_template(
        'profile_page.html',
        page_script='profile_page.js',
        transcript_obj=ordered_transcript,
        user_objs=user_dicts.values(),
        referral_objs=referral_objs,
        user_course_objs=user_course_dicts.values(),
        course_objs=course_dicts.values(),
        professor_objs=professor_dicts.values(),
        # TODO(mack): currently needed by jinja to do server-side rendering
        # figure out a cleaner way to do this w/o passing another param
        profile_obj=profile_dict,
        profile_user_id=profile_user.id,
        current_user_id=current_user.id,
        profile_user_secret_id=profile_user_secret_id,
        own_profile=own_profile,
        has_courses=profile_user.has_course_history,
        exam_objs=exam_dicts,
        exam_updated_date=exam_updated_date,
        schedule_item_objs=schedule_item_dicts,
        failed_schedule_item_objs=failed_schedule_item_dicts,
        has_shortlisted=profile_user.has_shortlisted,
        show_import_schedule=show_import_schedule,
        show_import_schedule_button=own_profile
        and (not profile_user.has_schedule),
        course_id_to_review=course_id_to_review,
        scholarship_objs=scholarships_dict,
        recommended_objs=recommendation_dict,
    )
Exemplo n.º 11
0
def render_profile_page(profile_user_id, current_user=None):
    # TODO(mack): for dict maps, use .update() rather than overwriting to
    # avoid subtle overwrites by data that has fields filled out

    LAST_TERM_ID = util.get_current_term_id()

    # PART ONE - VALIDATION

    current_user = current_user or view_helpers.get_current_user()

    try:
        if profile_user_id:
            profile_user_id = bson.ObjectId(profile_user_id)
    except:
        logging.warn('Invalid profile_user_id (%s)' % profile_user_id)
        return view_helpers.redirect_to_profile(current_user)

    if not profile_user_id:
        return view_helpers.redirect_to_profile(current_user)

    if profile_user_id == current_user.id:
        own_profile = True
        profile_user = current_user
    else:
        own_profile = False

        # Allow only friends to view profile
        if not (profile_user_id in current_user.friend_ids or (
                current_user.is_admin and flask.request.values.get('admin'))):
            logging.info("User (%s) tried to access non-friend profile (%s)"
                    % (current_user.id, profile_user_id))
            return view_helpers.redirect_to_profile(current_user)

        profile_user = m.User.objects.with_id(profile_user_id)
        # Technically we don't need this check due to above (under normal
        # operation). Though have this anyway as a failsafe
        if profile_user is None:
            logging.warn('profile_user is None')
            return view_helpers.redirect_to_profile(current_user)

    if own_profile:
        profile_user_secret_id = profile_user.get_secret_id()
    else:
        profile_user_secret_id = None

    show_import_schedule = False
    # Redirect the user appropriately... to /onboarding if they have no course
    # history, and to wherever they logged in from if they just logged in
    # TODO(david): Should have frontend decide whether to take us to /profile
    #     or /onboarding and not redirect in one of these two places
    if own_profile:
        redirect_url = flask.request.values.get('next')

        show_onboarding = False
        if not current_user.has_course_history:
            if not current_user.last_show_onboarding:
                show_onboarding = True
            else:
                time_delta = datetime.now() - current_user.last_show_onboarding
                # If they haven't imported any courses yet and the last time
                # the user was on the onboarding page is more than 5 days ago,
                # show the onboarding page again
                if time_delta.days > RESHOW_ONBOARDING_DELAY_DAYS:
                    show_onboarding = True

        # See https://uwflow.uservoice.com/admin/tickets/62
        if profile_user_id == '50b8ce2cd89d62310645ca78':
            show_onboarding = False

        if show_onboarding:
            onboarding_url = '/onboarding'
            if flask.request.query_string:
                onboarding_url = '%s?%s' % (
                        onboarding_url, flask.request.query_string)
            return flask.make_response(flask.redirect(onboarding_url))
        else:
            redirect_url = flask.request.values.get('next')
            if redirect_url:
                return flask.make_response(flask.redirect(redirect_url))

        # Show the import schedule view if it's been long enough
        if not current_user.has_schedule:
            if current_user.last_show_import_schedule:
                time_delta = (datetime.now() -
                              current_user.last_show_import_schedule)
                # User didn't import schedule yet, reshow every few days
                if time_delta.days > RESHOW_SCHEDULE_DELAY_DAYS:
                    show_import_schedule = True
            else:
                show_import_schedule = True

            if show_import_schedule:
                # TODO(Sandy): Do this on modal dismiss instead
                current_user.last_show_import_schedule = datetime.now()
                current_user.save()

    # PART TWO - DATA FETCHING

    # Get the mutual course ids of friends of profile user
    mutual_course_ids_by_friend = {}
    if own_profile:
        mutual_course_ids_by_friend = profile_user.get_mutual_course_ids(
            view_helpers.get_redis_instance())

    def get_friend_course_ids_in_term(friend_ids, term_id):
        user_courses = m.UserCourse.objects(
                term_id=term_id, user_id__in=friend_ids).only(
                    'user_id', 'course_id')

        last_term_course_ids_by_friend = {}
        for uc in user_courses:
            last_term_course_ids_by_friend.setdefault(
                    uc.user_id, []).append(uc.course_id)
        return last_term_course_ids_by_friend

    # Get the course ids of last term courses of friends of profile user
    last_term_course_ids_by_friend = get_friend_course_ids_in_term(
            profile_user.friend_ids, LAST_TERM_ID)

    # Get the course ids of courses profile user has taken
    profile_course_ids = set(profile_user.course_ids)

    # Fetch courses for transcript, which need more detailed information
    # than other courses (such as mutual and last term courses for friends)
    transcript_courses = list(m.Course.objects(id__in=profile_course_ids))

    # Fetch remainining courses that need less data. This will be mutual
    # and last term courses for profile user's friends
    friend_course_ids = set()
    friend_courses = []
    if own_profile:
        for course_ids in mutual_course_ids_by_friend.values():
            friend_course_ids = friend_course_ids.union(course_ids)
        for course_ids in last_term_course_ids_by_friend.values():
            friend_course_ids = friend_course_ids.union(course_ids)
        friend_course_ids = friend_course_ids - profile_course_ids
        friend_courses = m.Course.objects(
                id__in=friend_course_ids).only('id', 'name')

    # Fetch simplified information for friends of profile user
    # (for friend sidebar)
    friends = profile_user.get_friends()

    # Fetch all professors for all courses
    professor_objs = m.Professor.get_reduced_professors_for_courses(
            transcript_courses)

    # PART THREE - TRANSFORM DATA TO DICTS

    # Convert professors to dicts
    professor_dicts = {}
    for professor_obj in professor_objs:
        professor_dicts[professor_obj['id']] = professor_obj

    # Convert courses to dicts
    course_dict_list, user_course_dict_list, user_course_list = (
            m.Course.get_course_and_user_course_dicts(
                transcript_courses, current_user, include_friends=own_profile))
    course_dicts = {}
    for course_dict in course_dict_list:
        course_dicts[course_dict['id']] = course_dict
    user_course_dicts = {}
    for user_course_dict in user_course_dict_list:
        user_course_dicts[user_course_dict['id']] = user_course_dict

    profile_uc_dict_list = []

    # We only need to fetch usercourses for profile user if it is not the
    # current user since m.Course.get_course_and_user_course_dicts() will
    # have already fetched usercourses for the current user
    if not own_profile:
        # Get the user courses of profile user
        profile_uc_dict_list = [
                uc.to_dict() for uc in profile_user.get_user_courses()]
        # Get a mapping from course id to user_course for profile user
        profile_user_course_by_course = {}
        for uc_dict in profile_uc_dict_list:
            profile_user_course_by_course[uc_dict['course_id']] = uc_dict

    # Fill in with information about profile user
    for course in transcript_courses:
        course_dict = course_dicts[course.id]

        if not own_profile:
            # This has already been done for current user
            profile_uc_dict = profile_user_course_by_course.get(course.id)
            profile_user_course_id = profile_uc_dict['id']
            user_course_dicts[profile_user_course_id] = profile_uc_dict

            # Since we only fetched the user courses of the logged in user in
            # m.Course.get_course_and_user_course_dicts() above, gotta also
            # add the user courses of the profile user here
            user_course_dict_list.append(profile_uc_dict)
        else:
            profile_user_course_id = course_dict.get('user_course_id')
            if profile_user_course_id:
                profile_uc_dict_list.append(
                        user_course_dicts[profile_user_course_id])

        course_dict['profile_user_course_id'] = profile_user_course_id

    for course in friend_courses:
        course_dicts[course.id] = course.to_dict()

    def filter_course_ids(course_ids):
        return [course_id for course_id in course_ids
                if course_id in course_dicts]

    # Convert friend users to dicts
    user_dicts = {}
    # TODO(mack): should really be named current_term
    last_term = m.Term(id=LAST_TERM_ID)
    for friend in friends:
        user_dict = friend.to_dict(extended=False)

        if own_profile:
            user_dict.update({
                'last_term_name': last_term.name,
                'last_term_course_ids': filter_course_ids(
                    last_term_course_ids_by_friend.get(friend.id, [])),
                'mutual_course_ids': filter_course_ids(
                    mutual_course_ids_by_friend.get(friend.id, [])),
            })

        user_dicts[friend.id] = user_dict

    # Convert profile user to dict
    # TODO(mack): This must be after friend user dicts since it can override
    # data in it. Remove this restriction
    profile_dict = profile_user.to_dict(include_course_ids=True)
    profile_dict.update({
        'last_program_year_id': profile_user.get_latest_program_year_id(),
    })
    user_dicts.setdefault(profile_user.id, {}).update(profile_dict)

    # Convert current user to dict
    # TODO(mack): This must be after friend user dicts since it can override
    # data in it. Remove this restriction
    if not own_profile:
        user_dicts.setdefault(current_user.id, {}).update(
                current_user.to_dict(include_course_ids=True))

    def get_ordered_transcript(profile_uc_dict_list):
        transcript_by_term = {}

        for uc_dict in profile_uc_dict_list:
            (transcript_by_term.setdefault(uc_dict['term_id'], [])
                               .append(uc_dict))

        ordered_transcript = []
        for term_id, uc_dicts in sorted(transcript_by_term.items(),
                                        reverse=True):
            curr_term = m.Term(id=term_id)
            term_dict = {
                'id': curr_term.id,
                'name': curr_term.name,
                'program_year_id': uc_dicts[0].get('program_year_id'),
                'course_ids': [uc_dict['course_id'] for uc_dict in uc_dicts
                    if uc_dict['course_id'] in course_dicts],
            }
            ordered_transcript.append(term_dict)

        return ordered_transcript, transcript_by_term

    # Store courses by term as transcript using the current user's friends
    ordered_transcript, transcript_by_term = get_ordered_transcript(
            profile_uc_dict_list)

    # Fetch exam schedules and schedule items
    current_term_id = util.get_current_term_id()

    current_term_courses = transcript_by_term.get(current_term_id, [])
    current_course_ids = [c['course_id'] for c in current_term_courses]

    exam_objs = profile_user.get_current_term_exams(current_course_ids)
    exam_dicts = [e.to_dict() for e in exam_objs]
    exam_updated_date = None
    if exam_objs:
        exam_updated_date = exam_objs[0].id.generation_time

    # Set the course to prompt the user to review if it's time
    course_id_to_review = None
    if own_profile and profile_user.should_prompt_review():
        profile_user_courses = filter(lambda uc: uc.user_id == profile_user.id,
                user_course_list)
        uc_to_review = m.UserCourse.select_course_to_review(
                profile_user_courses)
        course_id_to_review = uc_to_review and uc_to_review.course_id

        if uc_to_review:
            uc_to_review.select_for_review(current_user)

    # NOTE: This implictly requires that the courses on the schedule are on the
    # transcript, since these course objects are needed by the schedule  on the
    # frontend. This should be the case since when we add a schedule item, a
    # corresponding item is added to the transcript.
    schedule_item_dicts = profile_user.get_schedule_item_dicts(exam_objs)
    failed_schedule_item_dicts = profile_user.get_failed_schedule_item_dicts()

    referrals = m.User.objects(referrer_id=current_user.id)
    referral_objs = [referral.to_dict() for referral in referrals]

    rmclogger.log_event(
        rmclogger.LOG_CATEGORY_IMPRESSION,
        rmclogger.LOG_EVENT_PROFILE, {
            'current_user': current_user.id,
            'profile_user': profile_user.id,
        },
    )

    schedule_screenshot.update_screenshot_async(profile_user)

    scholarships_dict = []

    if profile_user.id == current_user.id:
        scholarships = m.Scholarship.objects()
        # Filter scholarships based on program
        closed_scholarship_ids_set = set(profile_user.closed_scholarship_ids)
        scholarships = [s for s in scholarships if
                profile_user.short_program_name in s.programs and
                s.id not in closed_scholarship_ids_set]
        scholarships_dict = [s.to_dict() for s in scholarships]

    recommendation_dict = []
    recommended_course_ids = []
    if profile_user.id == current_user.id:
        recommended_course_ids = current_user.recommended_courses
        recommendation_dict = [m.Course.objects(id=course_id).first().to_dict()
                               for course_id in recommended_course_ids]

    return flask.render_template('profile_page.html',
        page_script='profile_page.js',
        transcript_obj=ordered_transcript,
        user_objs=user_dicts.values(),
        referral_objs=referral_objs,
        user_course_objs=user_course_dicts.values(),
        course_objs=course_dicts.values(),
        professor_objs=professor_dicts.values(),
        # TODO(mack): currently needed by jinja to do server-side rendering
        # figure out a cleaner way to do this w/o passing another param
        profile_obj=profile_dict,
        profile_user_id=profile_user.id,
        current_user_id=current_user.id,
        profile_user_secret_id=profile_user_secret_id,
        own_profile=own_profile,
        has_courses=profile_user.has_course_history,
        exam_objs=exam_dicts,
        exam_updated_date=exam_updated_date,
        schedule_item_objs=schedule_item_dicts,
        failed_schedule_item_objs=failed_schedule_item_dicts,
        has_shortlisted=profile_user.has_shortlisted,
        show_import_schedule=show_import_schedule,
        show_import_schedule_button=own_profile and (not
                profile_user.has_schedule),
        course_id_to_review=course_id_to_review,
        scholarship_objs=scholarships_dict,
        recommended_objs=recommendation_dict,
    )
Exemplo n.º 12
0
 def assert_term_equals(expected_term_id, year, month, day):
     the_date = datetime.datetime(year=year, month=month, day=day)
     with freezegun.freeze_time(the_date.strftime("%c")):
         self.assertEqual(expected_term_id, util.get_current_term_id())
Exemplo n.º 13
0
 def can_review(term_id):
     return (not term.Term.is_shortlist_term(term_id)
             and term_id <= util.get_current_term_id())
Exemplo n.º 14
0
 def get_current_term_id():
     return util.get_current_term_id()
Exemplo n.º 15
0
 def can_review(term_id):
     return (not term.Term.is_shortlist_term(term_id) and
             term_id <= util.get_current_term_id())
Exemplo n.º 16
0
Arquivo: term.py Projeto: nullcat/rmc
 def get_current_term_id():
     return util.get_current_term_id()