diff --git a/cms/envs/common.py b/cms/envs/common.py index 215f18d4a4..33be61f1af 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1178,6 +1178,7 @@ INSTALLED_APPS = [ 'openedx.features.course_duration_limits', 'openedx.features.content_type_gating', 'experiments', + ] diff --git a/lms/djangoapps/grades/migrations/0015_historicalpersistentsubsectiongradeoverride.py b/lms/djangoapps/grades/migrations/0015_historicalpersistentsubsectiongradeoverride.py new file mode 100644 index 0000000000..dc8f179cc8 --- /dev/null +++ b/lms/djangoapps/grades/migrations/0015_historicalpersistentsubsectiongradeoverride.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-05 13:59 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import simple_history.models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('grades', '0014_persistentsubsectiongradeoverridehistory'), + ] + + operations = [ + migrations.CreateModel( + name='HistoricalPersistentSubsectionGradeOverride', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('created', models.DateTimeField(blank=True, db_index=True, editable=False)), + ('modified', models.DateTimeField(blank=True, db_index=True, editable=False)), + ('earned_all_override', models.FloatField(blank=True, null=True)), + ('possible_all_override', models.FloatField(blank=True, null=True)), + ('earned_graded_override', models.FloatField(blank=True, null=True)), + ('possible_graded_override', models.FloatField(blank=True, null=True)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField()), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('grade', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='grades.PersistentSubsectionGrade')), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': 'history_date', + 'verbose_name': 'historical persistent subsection grade override', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/lms/djangoapps/grades/models.py b/lms/djangoapps/grades/models.py index 1b1b2fe16e..b43826e5b0 100644 --- a/lms/djangoapps/grades/models.py +++ b/lms/djangoapps/grades/models.py @@ -14,6 +14,7 @@ from base64 import b64encode from collections import defaultdict, namedtuple from hashlib import sha1 +from django.apps import apps from django.contrib.auth.models import User from django.db import models from django.utils.timezone import now @@ -25,7 +26,8 @@ from opaque_keys.edx.keys import CourseKey, UsageKey from coursewarehistoryextended.fields import UnsignedBigIntAutoField, UnsignedBigIntOneToOneField from lms.djangoapps.grades import events, constants from openedx.core.lib.cache_utils import get_cache - +from simple_history.models import HistoricalRecords +from simple_history.utils import update_change_reason log = logging.getLogger(__name__) @@ -653,6 +655,12 @@ class PersistentSubsectionGradeOverride(models.Model): _CACHE_NAMESPACE = u"grades.models.PersistentSubsectionGradeOverride" + # This is necessary because CMS does not install the grades app, but it + # imports this models code. Simple History will attempt to connect to the installed + # model in the grades app, which will fail. + if 'grades' in apps.app_configs: + history = HistoricalRecords() + def __unicode__(self): return u', '.join([ u"{}".format(type(self).__name__), @@ -703,6 +711,7 @@ class PersistentSubsectionGradeOverride(models.Model): grade=subsection_grade_model, defaults=cls._prepare_override_params(subsection_grade_model, override_data), ) + update_change_reason(override, feature) action = action or PersistentSubsectionGradeOverrideHistory.CREATE_OR_UPDATE