diff --git a/aleksis/apps/alsijil/migrations/0007_personal_note_lesson_documentation_year.py b/aleksis/apps/alsijil/migrations/0007_personal_note_lesson_documentation_year.py
new file mode 100644
index 0000000000000000000000000000000000000000..4cf8743b0ba5a2e16e0e1dcb491fe49b72dbb9c4
--- /dev/null
+++ b/aleksis/apps/alsijil/migrations/0007_personal_note_lesson_documentation_year.py
@@ -0,0 +1,55 @@
+# Generated by Django 3.0.9 on 2020-08-15 09:39
+
+from django.db import migrations, models
+
+import aleksis.apps.chronos.util.date
+
+
+def migrate_data(apps, schema_editor):
+    PersonalNote = apps.get_model("alsijil", "PersonalNote")
+    LessonDocumentation = apps.get_model("alsijil", "LessonDocumentation")
+
+    db_alias = schema_editor.connection.alias
+
+    for note in PersonalNote.objects.using(db_alias).all():
+        year = note.lesson_period.lesson.validity.date_start.year
+        if note.week < int(
+            note.lesson_period.lesson.validity.date_start.strftime("%V")
+        ):
+            year += 1
+        note.year = year
+        note.save()
+
+    for doc in LessonDocumentation.objects.using(db_alias).all():
+        year = doc.lesson_period.lesson.validity.date_start.year
+        if doc.week < int(doc.lesson_period.lesson.validity.date_start.strftime("%V")):
+            year += 1
+        doc.year = year
+        doc.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("alsijil", "0006_delete_personal_notes_filter"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="lessondocumentation",
+            name="year",
+            field=models.IntegerField(
+                default=aleksis.apps.chronos.util.date.get_current_year,
+                verbose_name="Year",
+            ),
+        ),
+        migrations.AddField(
+            model_name="personalnote",
+            name="year",
+            field=models.IntegerField(
+                default=aleksis.apps.chronos.util.date.get_current_year,
+                verbose_name="Year",
+            ),
+        ),
+        migrations.RunPython(migrate_data),
+    ]
diff --git a/aleksis/apps/alsijil/model_extensions.py b/aleksis/apps/alsijil/model_extensions.py
index 9e758d682d3f7f1ffc68df14b46cf92b6d0a6b3f..1a10bec3bc80df4511604f83f18e35320517a109 100644
--- a/aleksis/apps/alsijil/model_extensions.py
+++ b/aleksis/apps/alsijil/model_extensions.py
@@ -45,6 +45,7 @@ def mark_absent(
             person=self,
             lesson_period=lesson_period,
             week=wanted_week.week,
+            year=wanted_week.year,
             defaults={"absent": absent, "excused": excused, "excuse_type": excuse_type},
         )
         personal_note.groups_of_person.set(self.member_of.all())
@@ -74,7 +75,10 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
     missing_persons = Person.objects.annotate(
         no_personal_notes=~Exists(
             PersonalNote.objects.filter(
-                week=wanted_week.week, lesson_period=self, person__pk=OuterRef("pk")
+                week=wanted_week.week,
+                year=wanted_week.year,
+                lesson_period=self,
+                person__pk=OuterRef("pk"),
             )
         )
     ).filter(
@@ -85,7 +89,12 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
 
     # Create all missing personal notes
     new_personal_notes = [
-        PersonalNote(person=person, lesson_period=self, week=wanted_week.week)
+        PersonalNote(
+            person=person,
+            lesson_period=self,
+            week=wanted_week.week,
+            year=wanted_week.year,
+        )
         for person in missing_persons
     ]
     PersonalNote.objects.bulk_create(new_personal_notes)
@@ -94,7 +103,7 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
         personal_note.groups_of_person.set(personal_note.person.member_of.all())
 
     return PersonalNote.objects.select_related("person").filter(
-        lesson_period=self, week=wanted_week.week
+        lesson_period=self, week=wanted_week.week, year=wanted_week.year
     )
 
 
@@ -106,7 +115,9 @@ def get_lesson_documentation(
     if not week:
         week = self.week
     try:
-        return LessonDocumentation.objects.get(lesson_period=self, week=week.week)
+        return LessonDocumentation.objects.get(
+            lesson_period=self, week=week.week, year=week.year
+        )
     except LessonDocumentation.DoesNotExist:
         return None
 
@@ -119,7 +130,7 @@ def get_or_create_lesson_documentation(
     if not week:
         week = self.week
     lesson_documentation, created = LessonDocumentation.objects.get_or_create(
-        lesson_period=self, week=week.week
+        lesson_period=self, week=week.week, year=week.year
     )
     return lesson_documentation
 
@@ -129,7 +140,7 @@ def get_absences(self, week: Optional[CalendarWeek] = None) -> QuerySet:
     """Get all personal notes of absent persons for this lesson."""
     if not week:
         week = self.week
-    return self.personal_notes.filter(week=week.week, absent=True)
+    return self.personal_notes.filter(week=week.week, year=week.year, absent=True)
 
 
 @LessonPeriod.method
@@ -137,7 +148,9 @@ def get_excused_absences(self, week: Optional[CalendarWeek] = None) -> QuerySet:
     """Get all personal notes of excused absent persons for this lesson."""
     if not week:
         week = self.week
-    return self.personal_notes.filter(week=week.week, absent=True, excused=True)
+    return self.personal_notes.filter(
+        week=week.week, year=week.year, absent=True, excused=True
+    )
 
 
 @LessonPeriod.method
@@ -145,7 +158,9 @@ def get_unexcused_absences(self, week: Optional[CalendarWeek] = None) -> QuerySe
     """Get all personal notes of unexcused absent persons for this lesson."""
     if not week:
         week = self.week
-    return self.personal_notes.filter(week=week.week, absent=True, excused=False)
+    return self.personal_notes.filter(
+        week=week.week, year=week.year, absent=True, excused=False
+    )
 
 
 @LessonPeriod.method
@@ -153,7 +168,7 @@ def get_tardinesses(self, week: Optional[CalendarWeek] = None) -> QuerySet:
     """Get all personal notes of late persons for this lesson."""
     if not week:
         week = self.week
-    return self.personal_notes.filter(week=week.week, late__gt=0)
+    return self.personal_notes.filter(week=week.week, year=week.year, late__gt=0)
 
 
 @LessonPeriod.method
@@ -166,7 +181,9 @@ def get_extra_marks(
 
     stats = {}
     for extra_mark in ExtraMark.objects.all():
-        qs = self.personal_notes.filter(week=week.week, extra_marks=extra_mark)
+        qs = self.personal_notes.filter(
+            week=week.week, year=week.year, extra_marks=extra_mark
+        )
         if qs:
             stats[extra_mark] = qs
 
diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py
index c21c138bdd337cba114e473b79675ac1a4e0ff7a..721648bc4f52ddb4728de84f21319635ee9a014f 100644
--- a/aleksis/apps/alsijil/models.py
+++ b/aleksis/apps/alsijil/models.py
@@ -1,7 +1,13 @@
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
+from calendarweek import CalendarWeek
+
+from aleksis.apps.chronos.mixins import WeekRelatedMixin
+from aleksis.apps.chronos.models import LessonPeriod
+from aleksis.apps.chronos.util.date import get_current_year
 from aleksis.core.mixins import ExtensibleModel
+from aleksis.core.util.core_helpers import get_site_preferences
 
 
 def isidentifier(value: str) -> bool:
@@ -32,7 +38,7 @@ class ExcuseType(ExtensibleModel):
         verbose_name_plural = _("Excuse types")
 
 
-class PersonalNote(ExtensibleModel):
+class PersonalNote(ExtensibleModel, WeekRelatedMixin):
     """A personal note about a single person.
 
     Used in the class register to note absences, excuses
@@ -45,6 +51,8 @@ class PersonalNote(ExtensibleModel):
     groups_of_person = models.ManyToManyField("core.Group", related_name="+")
 
     week = models.IntegerField()
+    year = models.IntegerField(verbose_name=_("Year"), default=get_current_year)
+
     lesson_period = models.ForeignKey(
         "chronos.LessonPeriod", models.CASCADE, related_name="personal_notes"
     )
@@ -79,7 +87,7 @@ class PersonalNote(ExtensibleModel):
         verbose_name_plural = _("Personal notes")
         unique_together = [["lesson_period", "week", "person"]]
         ordering = [
-            "lesson_period__lesson__validity__date_start",
+            "year",
             "week",
             "lesson_period__period__weekday",
             "lesson_period__period__period",
@@ -88,13 +96,15 @@ class PersonalNote(ExtensibleModel):
         ]
 
 
-class LessonDocumentation(ExtensibleModel):
+class LessonDocumentation(ExtensibleModel, WeekRelatedMixin):
     """A documentation on a single lesson period.
 
     Non-personal, includes the topic and homework of the lesson.
     """
 
     week = models.IntegerField()
+    year = models.IntegerField(verbose_name=_("Year"), default=get_current_year)
+
     lesson_period = models.ForeignKey(
         "chronos.LessonPeriod", models.CASCADE, related_name="documentations"
     )
@@ -105,12 +115,51 @@ class LessonDocumentation(ExtensibleModel):
         verbose_name=_("Group note"), max_length=200, blank=True
     )
 
+    def _carry_over_data(self):
+        """Carry over data to directly adjacent periods in this lesson if data is not already set.
+
+        Can be deactivated using site preference ``alsijil__carry_over``.
+        """
+        following_periods = LessonPeriod.objects.filter(
+            lesson=self.lesson_period.lesson,
+            period__weekday=self.lesson_period.period.weekday,
+            period__period__gt=self.lesson_period.period.period,
+        )
+        for period in following_periods:
+            lesson_documentation = period.get_or_create_lesson_documentation(
+                CalendarWeek(week=self.week, year=self.year)
+            )
+
+            changed = False
+
+            if not lesson_documentation.topic:
+                lesson_documentation.topic = self.topic
+                changed = True
+
+            if not lesson_documentation.homework:
+                lesson_documentation.homework = self.homework
+                changed = True
+
+            if not lesson_documentation.group_note:
+                lesson_documentation.group_note = self.group_note
+                changed = True
+
+            if changed:
+                lesson_documentation.save()
+
+    def save(self, *args, **kwargs):
+        if get_site_preferences()["alsijil__carry_over"] and (
+            self.topic or self.homework or self.group_note
+        ):
+            self._carry_over_data()
+        super().save(*args, **kwargs)
+
     class Meta:
         verbose_name = _("Lesson documentation")
         verbose_name_plural = _("Lesson documentations")
         unique_together = [["lesson_period", "week"]]
         ordering = [
-            "lesson_period__lesson__validity__date_start",
+            "year",
             "week",
             "lesson_period__period__weekday",
             "lesson_period__period__period",
diff --git a/aleksis/apps/alsijil/preferences.py b/aleksis/apps/alsijil/preferences.py
index e2a55de885f3e415d9b4e461ab3192f899af2398..e9d3d2d2c0eaca9c2d7838ab79594f860f4dc1c0 100644
--- a/aleksis/apps/alsijil/preferences.py
+++ b/aleksis/apps/alsijil/preferences.py
@@ -14,3 +14,16 @@ class BlockPersonalNotesForCancelled(BooleanPreference):
     name = "block_personal_notes_for_cancelled"
     default = True
     verbose_name = _("Block adding personal notes for cancelled lessons")
+
+
+@site_preferences_registry.register
+class CarryOverDataToNextPeriods(BooleanPreference):
+    section = alsijil
+    name = "carry_over"
+    default = True
+    verbose_name = _(
+        "Carry over data from first lesson period to the following lesson periods in lessons over multiple periods"
+    )
+    help_text = _(
+        "This will carry over data only if the data in the following periods are empty."
+    )
diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py
index 5a471b20a91fdb3fff5cfaa43ad43d69f53e9c94..8c3a6b2a7bbe4021e7274b93c70b68c09f586464 100644
--- a/aleksis/apps/alsijil/views.py
+++ b/aleksis/apps/alsijil/views.py
@@ -164,7 +164,10 @@ def week_view(
     lesson_periods = LessonPeriod.objects.annotate(
         has_documentation=Exists(
             LessonDocumentation.objects.filter(
-                ~Q(topic__exact=""), lesson_period=OuterRef("pk"), week=wanted_week.week
+                ~Q(topic__exact=""),
+                lesson_period=OuterRef("pk"),
+                week=wanted_week.week,
+                year=wanted_week.year,
             )
         )
     ).in_week(wanted_week)
@@ -234,6 +237,7 @@ def week_view(
                     filter=Q(
                         personal_notes__lesson_period__in=lesson_periods_pk,
                         personal_notes__week=wanted_week.week,
+                        personal_notes__year=wanted_week.year,
                         personal_notes__absent=True,
                     ),
                     distinct=True,
@@ -243,6 +247,7 @@ def week_view(
                     filter=Q(
                         personal_notes__lesson_period__in=lesson_periods_pk,
                         personal_notes__week=wanted_week.week,
+                        personal_notes__year=wanted_week.year,
                         personal_notes__absent=True,
                         personal_notes__excused=False,
                     ),
@@ -253,6 +258,7 @@ def week_view(
                         pk=OuterRef("pk"),
                         personal_notes__lesson_period__in=lesson_periods_pk,
                         personal_notes__week=wanted_week.week,
+                        personal_notes__year=wanted_week.year,
                     )
                     .distinct()
                     .annotate(tardiness_sum=Sum("personal_notes__late"))
@@ -269,6 +275,7 @@ def week_view(
                         filter=Q(
                             personal_notes__lesson_period__in=lesson_periods_pk,
                             personal_notes__week=wanted_week.week,
+                            personal_notes__year=wanted_week.year,
                             personal_notes__extra_marks=extra_mark,
                         ),
                         distinct=True,
@@ -282,7 +289,9 @@ def week_view(
                 {
                     "person": person,
                     "personal_notes": person.personal_notes.filter(
-                        week=wanted_week.week, lesson_period__in=lesson_periods_pk
+                        week=wanted_week.week,
+                        year=wanted_week.year,
+                        lesson_period__in=lesson_periods_pk,
                     ),
                 }
             )
@@ -358,17 +367,17 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
             ):
                 documentations = list(
                     filter(
-                        lambda d: d.week == week.week,
+                        lambda d: d.week == week.week and d.year == week.year,
                         lesson_period.documentations.all(),
                     )
                 )
                 notes = list(
                     filter(
-                        lambda d: d.week == week.week,
+                        lambda d: d.week == week.week and d.year == week.year,
                         lesson_period.personal_notes.all(),
                     )
                 )
-                substitution = lesson_period.get_substitution(week.week)
+                substitution = lesson_period.get_substitution(week)
 
                 periods_by_day.setdefault(day, []).append(
                     (lesson_period, documentations, notes, substitution)