Files
edx-platform/lms/djangoapps/grades/services.py
Tyler Hallada 1ab1880337 Remove override behavior and log instead
This will break tests.
2017-08-09 17:27:58 -04:00

117 lines
4.4 KiB
Python

from datetime import datetime
import logging
import pytz
from opaque_keys.edx.keys import CourseKey, UsageKey
from track.event_transaction_utils import create_new_event_transaction_id, set_event_transaction_type
from util.date_utils import to_timestamp
from .config.waffle import waffle_flags, REJECTED_EXAM_OVERRIDES_GRADE
from .constants import ScoreDatabaseTableEnum
from .models import PersistentSubsectionGrade, PersistentSubsectionGradeOverride
from .signals.signals import SUBSECTION_OVERRIDE_CHANGED
log = logging.getLogger(__name__)
def _get_key(key_or_id, key_cls):
"""
Helper method to get a course/usage key either from a string or a key_cls,
where the key_cls (CourseKey or UsageKey) will simply be returned.
"""
return (
key_cls.from_string(key_or_id)
if isinstance(key_or_id, basestring)
else key_or_id
)
class GradesService(object):
"""
Course grade service
Provides various functions related to getting, setting, and overriding user grades.
"""
def get_subsection_grade(self, user_id, course_key_or_id, usage_key_or_id):
"""
Finds and returns the earned subsection grade for user
"""
course_key = _get_key(course_key_or_id, CourseKey)
usage_key = _get_key(usage_key_or_id, UsageKey)
return PersistentSubsectionGrade.objects.get(
user_id=user_id,
course_id=course_key,
usage_key=usage_key
)
def get_subsection_grade_override(self, user_id, course_key_or_id, usage_key_or_id):
"""
Finds the subsection grade for user and returns the override for that grade if it exists
If override does not exist, returns None. If subsection grade does not exist, will raise an exception.
"""
course_key = _get_key(course_key_or_id, CourseKey)
usage_key = _get_key(usage_key_or_id, UsageKey)
grade = self.get_subsection_grade(user_id, course_key, usage_key)
try:
return PersistentSubsectionGradeOverride.objects.get(
grade=grade
)
except PersistentSubsectionGradeOverride.DoesNotExist:
return None
def override_subsection_grade(self, user_id, course_key_or_id, usage_key_or_id, earned_all=None,
earned_graded=None):
"""
Override subsection grade (the PersistentSubsectionGrade model must already exist)
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. Will not
override earned_all or earned_graded value if they are None. Both default to None.
"""
course_key = _get_key(course_key_or_id, CourseKey)
usage_key = _get_key(usage_key_or_id, UsageKey)
log.info(
u"EDUCATOR-1127: Subsection grade override for user {user_id} on subsection {usage_key} in course "
u"{course_key} would be created with params: {params}"
.format(
user_id=unicode(user_id),
usage_key=unicode(usage_key),
course_key=unicode(course_key),
params=unicode({
'earned_all': earned_all,
'earned_graded': earned_graded,
})
)
)
def undo_override_subsection_grade(self, user_id, course_key_or_id, usage_key_or_id):
"""
Delete the override subsection grade row (the PersistentSubsectionGrade model must already exist)
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. If the
override does not exist, no error is raised, it just triggers the recalculation.
"""
course_key = _get_key(course_key_or_id, CourseKey)
usage_key = _get_key(usage_key_or_id, UsageKey)
log.info(
u"EDUCATOR-1127: Subsection grade override for user {user_id} on subsection {usage_key} in course "
u"{course_key} would be deleted"
.format(
user_id=unicode(user_id),
usage_key=unicode(usage_key),
course_key=unicode(course_key)
)
)
def should_override_grade_on_rejected_exam(self, course_key_or_id):
"""Convienence function to return the state of the CourseWaffleFlag REJECTED_EXAM_OVERRIDES_GRADE"""
course_key = _get_key(course_key_or_id, CourseKey)
return waffle_flags()[REJECTED_EXAM_OVERRIDES_GRADE].is_enabled(course_key)