diff --git a/openedx/core/djangoapps/content/learning_sequences/migrations/0014_remove_user_partition_group_duplicates.py b/openedx/core/djangoapps/content/learning_sequences/migrations/0014_remove_user_partition_group_duplicates.py new file mode 100644 index 0000000000..0469daa6ad --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/migrations/0014_remove_user_partition_group_duplicates.py @@ -0,0 +1,47 @@ +# Generated by Django 2.2.24 on 2021-07-07 18:34 + +from django.db import migrations +from django.db.models import Count, Min + + +class Migration(migrations.Migration): + + def remove_user_partition_group_duplicates(apps, schema_editor): + UserPartitionGroup = apps.get_model('learning_sequences', 'UserPartitionGroup') + + upg_duplicates = ( + UserPartitionGroup.objects.values("partition_id", "group_id") + .annotate(first_entry_id=Min("id"), num_entries=Count("id")) + .filter(num_entries__gt=1) + ) + + for duplicate in upg_duplicates: + + # Repoint the course sections and section sequences which have the duplicate user partition + # group entries to the single remaining non-duplicate user partition group. + upg_to_keep = UserPartitionGroup.objects.filter(id=duplicate["first_entry_id"])[:1].get() + upgs_to_remove = ( + UserPartitionGroup.objects + .filter(partition_id=duplicate["partition_id"], group_id=duplicate["group_id"]) + .exclude(id=duplicate["first_entry_id"]) + ) + for one_duplicate in upgs_to_remove: + sections_to_change = one_duplicate.coursesection_set.all() + for section in sections_to_change: + section.user_partition_groups.remove(one_duplicate) + section.user_partition_groups.add(upg_to_keep) + sequences_to_change = one_duplicate.coursesectionsequence_set.all() + for sequence in sequences_to_change: + sequence.user_partition_groups.remove(one_duplicate) + sequence.user_partition_groups.add(upg_to_keep) + + # Remove the duplicate user partition groups. + upgs_to_remove.delete() + + dependencies = [ + ('learning_sequences', '0013_through_model_for_user_partition_groups_1'), + ] + + operations = [ + migrations.RunPython(code=remove_user_partition_group_duplicates, reverse_code=migrations.RunPython.noop) + ] diff --git a/openedx/core/djangoapps/content/learning_sequences/migrations/0015_add_user_partition_group_unique_constraint.py b/openedx/core/djangoapps/content/learning_sequences/migrations/0015_add_user_partition_group_unique_constraint.py new file mode 100644 index 0000000000..414105ceb2 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/migrations/0015_add_user_partition_group_unique_constraint.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.24 on 2021-07-07 19:32 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('learning_sequences', '0014_remove_user_partition_group_duplicates'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='userpartitiongroup', + unique_together={('partition_id', 'group_id')}, + ), + ] diff --git a/openedx/core/djangoapps/content/learning_sequences/models.py b/openedx/core/djangoapps/content/learning_sequences/models.py index ed7fae1f74..6674a2dcea 100644 --- a/openedx/core/djangoapps/content/learning_sequences/models.py +++ b/openedx/core/djangoapps/content/learning_sequences/models.py @@ -180,6 +180,9 @@ class UserPartitionGroup(models.Model): group_id = models.BigIntegerField(null=False) class Meta: + unique_together = [ + ['partition_id', 'group_id'], + ] indexes = [ models.Index(fields=['partition_id', 'group_id']), ]