Files
edx-platform/openedx/core/djangoapps/schedules/utils.py
Michael Terry 656ec5def9 fix: avoid resetting a learner schedule to before a course starts
If a learner changes modes (like upgrades to a verified learner),
we will reset their schedule for them. But if they did this before
the course started, we would accidentally set their schedule to
the current time. So when the course did start, they would already
appear to be behind schedule.

That's silly. So now we always look at course start time when
resetting the learner's schedule.

AA-426
2022-01-28 14:58:36 -05:00

69 lines
2.3 KiB
Python

# lint-amnesty, pylint: disable=missing-module-docstring
import datetime
import logging
import pytz
from django.db import transaction
from openedx.core.djangoapps.schedules.models import Schedule
LOG = logging.getLogger(__name__)
# TODO: consider using a LoggerAdapter instead of this mixin:
# https://docs.python.org/2/library/logging.html#logging.LoggerAdapter
class PrefixedDebugLoggerMixin: # lint-amnesty, pylint: disable=missing-class-docstring
log_prefix = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.log_prefix is None:
self.log_prefix = self.__class__.__name__
def log_debug(self, message, *args, **kwargs):
"""
Wrapper around LOG.debug that prefixes the message.
"""
LOG.debug(self.log_prefix + ': ' + message, *args, **kwargs)
def log_info(self, message, *args, **kwargs):
"""
Wrapper around LOG.info that prefixes the message.
"""
LOG.info(self.log_prefix + ': ' + message, *args, **kwargs)
def reset_self_paced_schedule(user, course_key, use_enrollment_date=False):
"""
Reset the user's schedule if self-paced.
It does not create a new schedule, just resets an existing one.
This is used, for example, when a user requests it or when an enrollment mode changes.
Arguments:
user (User)
course_key (CourseKey or str)
use_enrollment_date (bool): if False, reset to now, else reset to original enrollment creation date
"""
with transaction.atomic(savepoint=False):
try:
schedule = Schedule.objects.select_related('enrollment', 'enrollment__course').get(
enrollment__user=user,
enrollment__course__id=course_key,
enrollment__course__self_paced=True,
)
except Schedule.DoesNotExist:
return
if use_enrollment_date:
new_start_date = schedule.enrollment.created
else:
new_start_date = datetime.datetime.now(pytz.utc)
# Make sure we don't start the clock on the learner's schedule before the course even starts
new_start_date = max(new_start_date, schedule.enrollment.course.start)
schedule.start_date = new_start_date
schedule.save()