def extract(self, date_for=None, **kwargs): ''' We get the count from the User model since there can be registered users who have not enrolled. TODO: Exclude non-students from the user count ''' if not date_for: date_for = prev_day( datetime.datetime.utcnow().replace(tzinfo=utc).date()) data = dict() user_count = get_user_model().objects.filter( date_joined__lt=as_datetime(next_day(date_for))).count() course_count = CourseOverview.objects.filter( created__lt=as_datetime(next_day(date_for))).count() todays_active_user_count = get_active_user_count_for_date(date_for) data['todays_active_user_count'] = todays_active_user_count data[ 'cumulative_active_user_count'] = get_previous_cumulative_active_user_count( date_for) + todays_active_user_count data['total_user_count'] = user_count data['course_count'] = course_count data['total_enrollment_count'] = get_total_enrollment_count(date_for) return data
def extract(self, site, date_for=None, **kwargs): # pylint: disable=unused-argument ''' We get the count from the User model since there can be registered users who have not enrolled. TODO: Exclude non-students from the user count ''' if not date_for: date_for = prev_day( datetime.datetime.utcnow().replace(tzinfo=utc).date()) data = dict() site_users = get_users_for_site(site) user_count = site_users.filter( date_joined__lt=as_datetime(next_day(date_for))).count() site_courses = get_courses_for_site(site) course_count = site_courses.filter( created__lt=as_datetime(next_day(date_for))).count() todays_active_users = get_site_active_users_for_date(site, date_for) todays_active_user_count = todays_active_users.count() mau = site_mau_1g_for_month_as_of_day(site, date_for) data['todays_active_user_count'] = todays_active_user_count data[ 'cumulative_active_user_count'] = get_previous_cumulative_active_user_count( site, date_for) + todays_active_user_count data['total_user_count'] = user_count data['course_count'] = course_count data['total_enrollment_count'] = get_total_enrollment_count( site, date_for) data['mau'] = mau.count() return data
def calc_from_user_model(): filter_args = dict( date_joined__gt=as_datetime(prev_day(start_date)), date_joined__lt=as_datetime(next_day(end_date)), ) users = figures.sites.get_users_for_site(site) return users.filter(**filter_args).values('id').distinct().count()
def calc_from_course_enrollments(): filter_args = dict( created__gt=prev_day(start_date), created__lt=next_day(end_date), ) return CourseEnrollment.objects.filter( **filter_args).values('course_id').distinct().count()
def calc_from_user_model(): filter_args = dict( date_joined__gt=prev_day(start_date), date_joined__lt=next_day(end_date), ) return get_user_model().objects.filter( **filter_args).values('id').distinct().count()
def get_active_users_for_time_period(site, start_date, end_date, course_ids=None): """ Returns the number of users active in the time period. This is determined by finding the unique user ids for StudentModule records modified in a time period We don't do this only because it raises timezone warnings modified__range=(as_date(start_date), as_date(end_date)), """ # Get list of learners for the site user_ids = figures.sites.get_user_ids_for_site(site) filter_args = dict( modified__gt=as_datetime(prev_day(start_date)), modified__lt=as_datetime(next_day(end_date)), student_id__in=user_ids, ) if course_ids: filter_args['course_ids__in'] = course_ids return StudentModule.objects.filter( **filter_args).values('student__id').distinct().count()
def get_course_enrollments(course_id, date_for): """Convenience method to get a filterd queryset of CourseEnrollment objects """ return CourseEnrollment.objects.filter( course_id=as_course_key(course_id), created__lt=as_datetime(next_day(date_for)), )
def calc_from_site_daily_metrics(): filter_args = dict(date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date)) qs = SiteDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(maxval=Max('total_user_count'))['maxval'] else: return 0
def calc_from_course_enrollments(): filter_args = dict( created__gt=prev_day(start_date), created__lt=next_day(end_date), ) # First get all the course enrollments for the site ce = figures.sites.get_course_enrollments_for_site(site) # Then filter on the time period return ce.filter(**filter_args).values('course_id').distinct().count()
def test_get_course_enrollments_for_course(self): course_id = self.course_overviews[0].id expected_ce = CourseEnrollment.objects.filter( course_id=course_id, created__lt=as_datetime(next_day( self.today))).values_list('id', flat=True) results_ce = pipeline_cdm.get_course_enrollments( course_id=course_id, date_for=self.today).values_list('id', flat=True) assert set(results_ce) == set(expected_ce)
def calc_from_course_daily_metrics(): filter_args = dict( date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), ) qs = CourseDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(maxval=Max('num_learners_completed'))['maxval'] else: return 0
def get_course_average_progress_for_time_period(start_date, end_date, course_id): filter_args = dict(date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), course_id=course_id) qs = CourseDailyMetrics.objects.filter(**filter_args) if qs: value = qs.aggregate(average=Avg('average_progress'))['average'] return float(Decimal(value).quantize(Decimal('.00'))) else: return 0.0
def get_course_enrolled_users_for_time_period(start_date, end_date, course_id): """ """ filter_args = dict(date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), course_id=course_id) qs = CourseDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(maxval=Max('enrollment_count'))['maxval'] else: return 0
def get_num_learners_completed(course_id, date_for): """ Get the total number of certificates generated for the course up to the 'date_for' date We will need to relabel this to "certificates" We may want to get the number of certificates granted in the given day """ certificates = GeneratedCertificate.objects.filter( course_id=as_course_key(course_id), created_date__lt=as_datetime(next_day(date_for))) return certificates.count()
def get_course_average_days_to_complete_for_time_period( start_date, end_date, course_id): filter_args = dict(date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), course_id=course_id) qs = CourseDailyMetrics.objects.filter(**filter_args) if qs: return int( math.ceil( qs.aggregate( average=Avg('average_days_to_complete'))['average'])) else: return 0
def get_course_num_learners_completed_for_time_period(start_date, end_date, course_id): """ We're duplicating some code. """ filter_args = dict(date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), course_id=course_id) qs = CourseDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(max=Max('num_learners_completed'))['max'] else: return 0
def get_total_enrollments_for_time_period(site, start_date, end_date, course_ids=None): # pylint: disable=unused-argument """Returns the maximum number of enrollments This returns the count of unique enrollments, not unique learners """ filter_args = dict( site=site, date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date), ) qs = SiteDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(maxval=Max('total_enrollment_count'))['maxval'] else: return 0
def get_active_users_for_time_period(start_date, end_date, site=None, course_ids=None): """ Returns the number of users active in the time period. This is determined by finding the unique user ids for StudentModule records modified in a time period """ filter_args = dict(created__gt=as_datetime(prev_day(start_date)), modified__lt=as_datetime(next_day(end_date))) if course_ids: filter_args['course_ids__in'] = course_ids return StudentModule.objects.filter( **filter_args).values('student__id').distinct().count()
def missing_course_daily_metrics(date_for): ''' Return a list of course ids for any courses missing from the set of CourseDailyMetrics for the given date (and site after we implement multi- tenancy) We use this to make sure that we are not missing course data when we populat the SiteDailyMetrics instance for the given date ''' cdm_course_keys = [ as_course_key(cdm.course_id) for cdm in CourseDailyMetrics.objects.filter(date_for=date_for) ] course_overviews = CourseOverview.objects.filter( created__lt=next_day(date_for)).exclude(id__in=cdm_course_keys) return set(course_overviews.values_list('id', flat=True))
def get_num_enrolled_in_exclude_admins(course_id, date_for): """ Copied over from CourseEnrollmentManager.num_enrolled_in_exclude_admins method and modified to filter on date LT """ course_locator = course_id if getattr(course_id, 'ccx', None): course_locator = course_id.to_course_locator() staff = CourseStaffRole(course_locator).users_with_role() admins = CourseInstructorRole(course_locator).users_with_role() coaches = CourseCcxCoachRole(course_locator).users_with_role() return CourseEnrollment.objects.filter( course_id=course_id, is_active=1, created__lt=as_datetime(next_day(date_for)), ).exclude(user__in=staff).exclude(user__in=admins).exclude( user__in=coaches).count()
def get_total_site_users_for_time_period(site, start_date, end_date, **_kwargs): """ Returns the maximum number of users who joined before or on the end date Even though we don't need the start_date, we follow the method signature for the other metrics functions so we can use the same handler method, ``get_monthly_history_metric`` TODO: Consider first trying to get the data from the SiteDailyMetrics model. If there are no records, then get the data from the User model """ filter_args = dict(site=site, date_for__gt=prev_day(start_date), date_for__lt=next_day(end_date)) qs = SiteDailyMetrics.objects.filter(**filter_args) if qs: return qs.aggregate(maxval=Max('total_user_count'))['maxval'] else: return 0
def missing_course_daily_metrics(site, date_for): ''' Return a list of course ids for any courses missing from the set of CourseDailyMetrics for the given date (and site after we implement multi- tenancy) The type returned is CourseLocator We use this to make sure that we are not missing course data when we populat the SiteDailyMetrics instance for the given date ''' cdm_course_keys = [ as_course_key(cdm.course_id) for cdm in CourseDailyMetrics.objects.filter(site=site, date_for=date_for) ] site_course_overviews = figures.sites.get_courses_for_site(site) course_overviews = site_course_overviews.filter( created__lt=as_datetime(next_day(date_for))).exclude(id__in=cdm_course_keys) return set(course_overviews.values_list('id', flat=True))
def get_enrolled_in_exclude_admins(course_id, date_for=None): """ Copied over from CourseEnrollmentManager.num_enrolled_in_exclude_admins method and modified to filter on date LT If no date is provided then the date is not used as a filter """ course_locator = as_course_key(course_id) if getattr(course_id, 'ccx', None): course_locator = course_id.to_course_locator() staff = CourseStaffRole(course_locator).users_with_role() admins = CourseInstructorRole(course_locator).users_with_role() coaches = CourseCcxCoachRole(course_locator).users_with_role() filter_args = dict(course_id=course_id, is_active=1) if date_for: filter_args.update(dict(created__lt=as_datetime(next_day(date_for)))) return CourseEnrollment.objects.filter(**filter_args).exclude( user__in=staff).exclude(user__in=admins).exclude(user__in=coaches)
def calc_from_user_model(): filter_args = dict(date_joined__lt=next_day(end_date), ) return get_user_model().objects.filter(**filter_args).count()
def test_next_day(self): expected = self.now + datetime.timedelta(days=1) assert next_day(self.now) == expected assert next_day(self.now.date()) == expected.date()
def get_num_learners_completed(course_id, date_for): certificates = GeneratedCertificate.objects.filter( course_id=as_course_key(course_id), created_date__lt=as_datetime(next_day(date_for))) return certificates.count()
def calc_from_user_model(): filter_args = dict(date_joined__lt=as_datetime(next_day(end_date)), ) users = figures.sites.get_users_for_site(site) return users.filter(**filter_args).count()