Repository: learningequality/kolibri
Issue: Update Lesson and Exam model infer_dataset method to use the collection rather than assigned_by foreign key

When Lesson and Exam models were first created, their `infer_dataset` method referred to the user that it was assigned by using the `assigned_by` ForeignKey.

In a scenario where only a limited subset of a facility's data is synchronized to a device, such as in a single learner syncing scenario, this would cause Lessons and Quizzes to remain forever serialized in the Morango store, as the data for the assigning user would be absent, as outside the partition of data that would be synced for a single user.

In order to ensure that Lesson and Exam models can be properly deserialized, their `infer_dataset` method should instead rely on the `collection` ForeignKey, as the full Collection hierarchy of the Facility will be shared during a single user sync.

Changed files:
kolibri/core/auth/test/test_datasets.py, kolibri/core/exams/models.py, kolibri/core/lessons/models.py

diff --git a/kolibri/core/auth/test/test_datasets.py b/kolibri/core/auth/test/test_datasets.py
index fc143cb0b0..54aca29886 100644
--- a/kolibri/core/auth/test/test_datasets.py
+++ b/kolibri/core/auth/test/test_datasets.py
@@ -10,6 +10,8 @@ from ..models import Facility
 from ..models import FacilityDataset
 from ..models import FacilityUser
 from ..models import LearnerGroup
+from kolibri.core.exams.models import Exam
+from kolibri.core.lessons.models import Lesson
 
 
 class FacilityDatasetTestCase(TestCase):
@@ -19,6 +21,15 @@ class FacilityDatasetTestCase(TestCase):
         cls.facility_2 = Facility.objects.create()
         cls.classroom = Classroom.objects.create(parent=cls.facility)
         cls.learner_group = LearnerGroup.objects.create(parent=cls.classroom)
+        cls.user = FacilityUser.objects.create(
+            username="user", password="password", facility=cls.facility
+        )
+        cls.exam = Exam.objects.create(
+            title="", question_count=1, collection=cls.facility, creator=cls.user
+        )
+        cls.lesson = Lesson.objects.create(
+            created_by=cls.user, title="lesson", collection=cls.facility
+        )
 
     def setUp(self):
         self.facility_user = FacilityUser.objects.create(
@@ -73,6 +84,31 @@ class FacilityDatasetTestCase(TestCase):
         new_dataset = FacilityDataset.objects.create()
         self.assertEqual(str(new_dataset), "FacilityDataset (no associated Facility)")
 
+    def test_exam_lesson_dataset(self):
+        self.assertTrue(self.facility.dataset is not None)
+        self.assertEqual(self.exam.infer_dataset(), self.lesson.infer_dataset())
+
+        # Check current implementation of infer_dataset on Lesson and Exam
+        self.assertEqual(
+            self.exam.infer_dataset(),
+            self.exam.cached_related_dataset_lookup("collection"),
+        )
+        self.assertEqual(
+            self.lesson.infer_dataset(),
+            self.lesson.cached_related_dataset_lookup("collection"),
+        )
+
+        # Check if the current implementation is equivalent to the previous implementation
+        self.assertEqual(
+            self.exam.infer_dataset(),
+            self.exam.cached_related_dataset_lookup("creator"),
+        )
+        self.assertEqual(
+            self.lesson.infer_dataset(),
+            self.lesson.cached_related_dataset_lookup("created_by"),
+        )
+        self.assertEqual(self.exam.infer_dataset(), self.facility.dataset.id)
+
     def test_dataset_incompatible_setting(self):
         with self.assertRaises(IncompatibleDeviceSettingError):
             FacilityDataset.objects.create(
diff --git a/kolibri/core/exams/models.py b/kolibri/core/exams/models.py
index fc451e861e..f38c9e4993 100644
--- a/kolibri/core/exams/models.py
+++ b/kolibri/core/exams/models.py
@@ -141,7 +141,7 @@ class Exam(AbstractFacilityDataModel):
     data_model_version = models.SmallIntegerField(default=2)
 
     def infer_dataset(self, *args, **kwargs):
-        return self.cached_related_dataset_lookup("creator")
+        return self.cached_related_dataset_lookup("collection")
 
     def calculate_partition(self):
         return self.dataset_id
diff --git a/kolibri/core/lessons/models.py b/kolibri/core/lessons/models.py
index b132e0ab64..9da2db742e 100644
--- a/kolibri/core/lessons/models.py
+++ b/kolibri/core/lessons/models.py
@@ -75,7 +75,7 @@ class Lesson(AbstractFacilityDataModel):
     morango_model_name = "lesson"
 
     def infer_dataset(self, *args, **kwargs):
-        return self.cached_related_dataset_lookup("created_by")
+        return self.cached_related_dataset_lookup("collection")
 
     def calculate_partition(self):
         return self.dataset_id