From a914faf11c0070056405b51a7d2d4ceed65dda0e Mon Sep 17 00:00:00 2001 From: atesker Date: Thu, 6 Jun 2019 09:45:45 -0400 Subject: [PATCH 1/2] Adding simple history to track grade changes. Educator-4347 added migration Adding simple history to track grade changes. Educator-4347 Adding migration file Adding simple history to track grade changes. Educator-4347 Adding migration file Adding simple history to track grade changes. Educator-4347 Adding migration file Re-adding lms.djangoapps reference to see if it will fix the build issues Re-adding lms.djangoapps reference to see if it will fix the build issues --- cms/envs/common.py | 3 ++ ...oricalpersistentsubsectiongradeoverride.py | 43 +++++++++++++++++++ lms/djangoapps/grades/models.py | 5 ++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lms/djangoapps/grades/migrations/0015_historicalpersistentsubsectiongradeoverride.py diff --git a/cms/envs/common.py b/cms/envs/common.py index 215f18d4a4..65e5436113 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1127,6 +1127,8 @@ INSTALLED_APPS = [ 'survey.apps.SurveyConfig', 'lms.djangoapps.verify_student.apps.VerifyStudentConfig', 'completion', + # Reference we couldn't get simple_history dependencies working in any other way. Leaving it + 'lms.djangoapps.grades.apps.GradesConfig', # Microsite configuration application 'microsite_configuration', @@ -1178,6 +1180,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..07e45126d7 100644 --- a/lms/djangoapps/grades/models.py +++ b/lms/djangoapps/grades/models.py @@ -25,7 +25,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__) @@ -652,6 +653,7 @@ class PersistentSubsectionGradeOverride(models.Model): possible_graded_override = models.FloatField(null=True, blank=True) _CACHE_NAMESPACE = u"grades.models.PersistentSubsectionGradeOverride" + history = HistoricalRecords() def __unicode__(self): return u', '.join([ @@ -703,6 +705,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 From 23ab20a6fd1863c02bf1197ff8f0d3a288288d32 Mon Sep 17 00:00:00 2001 From: "Dave St.Germain" Date: Mon, 10 Jun 2019 10:49:06 -0400 Subject: [PATCH 2/2] Prevent import failure on CMS --- cms/envs/common.py | 2 -- lms/djangoapps/grades/models.py | 8 +++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index 65e5436113..33be61f1af 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1127,8 +1127,6 @@ INSTALLED_APPS = [ 'survey.apps.SurveyConfig', 'lms.djangoapps.verify_student.apps.VerifyStudentConfig', 'completion', - # Reference we couldn't get simple_history dependencies working in any other way. Leaving it - 'lms.djangoapps.grades.apps.GradesConfig', # Microsite configuration application 'microsite_configuration', diff --git a/lms/djangoapps/grades/models.py b/lms/djangoapps/grades/models.py index 07e45126d7..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 @@ -653,7 +654,12 @@ class PersistentSubsectionGradeOverride(models.Model): possible_graded_override = models.FloatField(null=True, blank=True) _CACHE_NAMESPACE = u"grades.models.PersistentSubsectionGradeOverride" - history = HistoricalRecords() + + # 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([