diff --git a/aleksis/apps/chronos/model_extensions.py b/aleksis/apps/chronos/model_extensions.py
index 31bdbab5eb0400b70ebb94fab1f7f86801b21866..afad135f17191cfc6a329c439572619729d61de1 100644
--- a/aleksis/apps/chronos/model_extensions.py
+++ b/aleksis/apps/chronos/model_extensions.py
@@ -5,7 +5,7 @@ from jsonstore import BooleanField
 
 from aleksis.core.models import Person, Group, Announcement
 
-from .models import Lesson, LessonPeriod
+from .models import Lesson, LessonPeriod, TimetableType
 
 
 @Person.property
@@ -16,13 +16,13 @@ def is_teacher(self):
 
 
 @Person.property
-def timetable_type(self) -> Optional[str]:
+def timetable_type(self) -> Optional[TimetableType]:
     """ Return which type of timetable this user has """
 
     if self.is_teacher:
-        return "teacher"
+        return TimetableType.TEACHER
     elif self.primary_group:
-        return "group"
+        return TimetableType.GROUP
     else:
         return None
 
@@ -33,9 +33,9 @@ def timetable_object(self) -> Optional[Union[Group, Person]]:
 
     type_ = self.timetable_type
 
-    if type_ == "teacher":
+    if type_ == TimetableType.TEACHER:
         return self
-    elif type_ == "group":
+    elif type_ == TimetableType.GROUP:
         return self.primary_group
     else:
         return None
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index d2dc9fa1b3097d50b38cfa24dcc77895e96480e9..dc84b5cf90d3c0a424d8415200a35f82a348c3d9 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 from collections import OrderedDict
 from datetime import date, datetime, timedelta, time
+from enum import Enum
 from typing import Dict, Optional, Tuple, Union
 
 from constance import config
@@ -31,6 +32,16 @@ from aleksis.apps.chronos.util.date import week_weekday_from_date
 from aleksis.core.util.core_helpers import has_person
 
 
+class TimetableType(Enum):
+    GROUP = "group"
+    TEACHER = "teacher"
+    ROOM = "room"
+
+    @classmethod
+    def from_string(cls, s: Optional[str]):
+        return cls.__members__.get(s.upper())
+
+
 class LessonPeriodManager(models.Manager):
     """ Manager adding specific methods to lesson periods. """
 
@@ -208,12 +219,12 @@ class LessonPeriodQuerySet(LessonDataQuerySet):
         if query_data.get("room", None):
             return self.filter_room(int(query_data["room"]))
 
-    def filter_from_type(self, type_: str, pk: int) -> Optional[models.QuerySet]:
-        if type_ == "group":
+    def filter_from_type(self, type_: TimetableType, pk: int) -> Optional[models.QuerySet]:
+        if type_ == TimetableType.GROUP:
             return self.filter_group(pk)
-        elif type_ == "teacher":
+        elif type_ == TimetableType.TEACHER:
             return self.filter_teacher(pk)
-        elif type_ == "room":
+        elif type_ == TimetableType.ROOM:
             return self.filter_room(pk)
         else:
             return None
@@ -221,12 +232,12 @@ class LessonPeriodQuerySet(LessonDataQuerySet):
     def filter_from_person(self, person: Person) -> Optional[models.QuerySet]:
         type_ = person.timetable_type
 
-        if type_ == "teacher":
+        if type_ == TimetableType.TEACHER:
             # Teacher
 
             return self.filter_teacher(person)
 
-        elif type_ == "group":
+        elif type_ == TimetableType.GROUP:
             # Student
 
             return self.filter(lesson__groups__members=person)
@@ -509,15 +520,6 @@ class LessonSubstitution(ExtensibleModel):
         if self.subject and self.cancelled:
             raise ValidationError(_("Lessons can only be either substituted or cancelled."))
 
-    @property
-    def type_(self):
-        if self.cancelled:
-            return "cancellation"
-        elif self.cancelled_for_teachers:
-            return "cancellation_for_teachers"
-        else:
-            return "substitution"
-
     @property
     def date(self):
         week = CalendarWeek(week=self.week)
@@ -989,12 +991,12 @@ class TimetableQuerySet(models.QuerySet):
         else:
             return self.filter(room=room)
 
-    def filter_from_type(self, type_: str, pk: int) -> Optional[models.QuerySet]:
-        if type_ == "group":
+    def filter_from_type(self, type_: TimetableType, pk: int) -> Optional[models.QuerySet]:
+        if type_ == TimetableType.GROUP:
             return self.filter_group(pk)
-        elif type_ == "teacher":
+        elif type_ == TimetableType.TEACHER:
             return self.filter_teacher(pk)
-        elif type_ == "room":
+        elif type_ == TimetableType.ROOM:
             return self.filter_room(pk)
         else:
             return None
@@ -1002,12 +1004,12 @@ class TimetableQuerySet(models.QuerySet):
     def filter_from_person(self, person: Person) -> Optional[models.QuerySet]:
         type_ = person.timetable_type
 
-        if type_ == "teacher":
+        if type_ == TimetableType.TEACHER:
             # Teacher
 
             return self.filter_teacher(person)
 
-        elif type_ == "group":
+        elif type_ == TimetableType.GROUP:
             # Student
 
             return self.filter_participant(person)
diff --git a/aleksis/apps/chronos/templates/chronos/my_timetable.html b/aleksis/apps/chronos/templates/chronos/my_timetable.html
index cc9b03c973e664b89001ed8932f278da16493f58..ed55cc19014b061b0a2f956ae8dabfd55d5083e4 100644
--- a/aleksis/apps/chronos/templates/chronos/my_timetable.html
+++ b/aleksis/apps/chronos/templates/chronos/my_timetable.html
@@ -18,7 +18,7 @@
         {% trans "My timetable" %} <i>{{ el }}</i>
         <span class="badge new primary-color ">{% trans "SMART PLAN" %}</span>
       </h4>
-      <a class="btn-flat waves-effect waves-light" href="{% url "timetable" super.type super.el.pk %}">
+      <a class="btn-flat waves-effect waves-light" href="{% url "timetable" super.type.value super.el.pk %}">
         {% trans "Show week timetable for" %} {{ super.el.short_name }}
       </a>
     </div>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/event.html b/aleksis/apps/chronos/templates/chronos/partials/event.html
index 3ca850407977fd5a75a5e1b824086002c26943fc..3aa6b797639598c0e24051053f040fcd3f1aead4 100644
--- a/aleksis/apps/chronos/templates/chronos/partials/event.html
+++ b/aleksis/apps/chronos/templates/chronos/partials/event.html
@@ -1,27 +1,27 @@
 <div class="lesson-with-event">
   <p>
     {# Teacher or room > Display groups #}
-    {% if type == "teacher" or type == "room" %}
+    {% if type.value == "teacher" or type.value == "room" %}
       {% include "chronos/partials/groups.html" with groups=event.groups.all %}
     {% endif %}
 
     {# Class or room > Display teachers #}
-    {% if type == "room" or type == "group" %}
+    {% if type.value == "room" or type.value == "group" %}
       {% include "chronos/partials/teachers.html" with teachers=event.teachers.all %}
     {% endif %}
 
     {# Teacher or class > Display rooms #}
-    {% if type == "teacher" or type == "group" %}
+    {% if type.value == "teacher" or type.value == "group" %}
       {% for room in event.rooms.all %}
         {% include "chronos/partials/room.html" with room=room %}{% if not forloop.last %},{% endif %}
       {% endfor %}
     {% endif %}
 
-    {% if type == "teacher" and not event.groups.all and not event.rooms.all and event.title %}
+    {% if type.value == "teacher" and not event.groups.all and not event.rooms.all and event.title %}
       <em>{{ event.title }}</em>
-    {% elif type == "group" and not event.teachers.all and not event.groups.all and event.title %}
+    {% elif type.value == "group" and not event.teachers.all and not event.groups.all and event.title %}
       <em>{{ event.title }}</em>
-    {% elif type == "room" and not event.teachers.all and not event.groups.all and event.title %}
+    {% elif type.value == "room" and not event.teachers.all and not event.groups.all and event.title %}
       <em>{{ event.title }}</em>
     {% elif event.title %}
       <br/>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/extra_lesson.html b/aleksis/apps/chronos/templates/chronos/partials/extra_lesson.html
index 167fdab44694c078a63aa3657215f00ba511ffb1..1113f011f0164be5a92f1dbe7ef3b32e8db07ed5 100644
--- a/aleksis/apps/chronos/templates/chronos/partials/extra_lesson.html
+++ b/aleksis/apps/chronos/templates/chronos/partials/extra_lesson.html
@@ -2,19 +2,19 @@
      style="{% include "chronos/partials/subject_colour.html" with subject=extra_lesson.subject %}">
   <p>
     {# Teacher or room > Display groups #}
-    {% if type == "teacher" or type == "room" %}
+    {% if type.value == "teacher" or type.value == "room" %}
       {% include "chronos/partials/groups.html" with groups=extra_lesson.groups.all %}
     {% endif %}
 
     {# Class or room > Display teachers #}
-    {% if type == "room" or type == "group" %}
+    {% if type.value == "room" or type.value == "group" %}
       {% include "chronos/partials/teachers.html" with teachers=extra_lesson.teachers.all %}
     {% endif %}
 
     {% include "chronos/partials/subject.html" with subject=extra_lesson.subject %}
 
     {# Teacher or class > Display rooms #}
-    {% if type == "teacher" or type == "group" %}
+    {% if type.value == "teacher" or type.value == "group" %}
       {% include "chronos/partials/room.html" with room=extra_lesson.room %}
     {% endif %}
 
diff --git a/aleksis/apps/chronos/templates/chronos/partials/lesson.html b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
index dd0ac1c30cfa47909ef0636a0f7339a1b97361a7..5230c94536125ed3d20f0757b63df90c297cfd53 100644
--- a/aleksis/apps/chronos/templates/chronos/partials/lesson.html
+++ b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
@@ -3,7 +3,7 @@
 <div style="
         {# Display background color only if lesson is not cancelled and it is not the old room #}
         {% if not lesson_period.get_substitution.cancelled and not lesson_period.get_substitution.cancelled_for_teachers %}
-          {% if not type == "room" or lesson_period.room == lesson_period.get_room or lesson_period.get_room == el %}
+          {% if not type.value == "room" or lesson_period.room == lesson_period.get_room or lesson_period.get_room == el %}
             {% include "chronos/partials/subject_colour.html" with subject=lesson_period.lesson.subject %}
           {% endif %}
         {% endif %}
@@ -17,14 +17,14 @@
     {% elif lesson_period.get_substitution and smart %}
       {% with sub=lesson_period.get_substitution %}
         {# SUBSTITUTION #}
-        {% if type == "room" and lesson_period.room != lesson_period.get_room and lesson_period.get_room != el %}
+        {% if type.value == "room" and lesson_period.room != lesson_period.get_room and lesson_period.get_room != el %}
           {# When it's the old room, let it empty #}
 
         {% elif sub.cancelled or sub.cancelled_for_teachers %}
           {# When a badge (cancellation, etc.) exists, then display it with the teacher#}
 
           {# Class or room > Display teacher #}
-          {% if type == "group" or type == "room" and lesson_period.lesson.teachers.all %}
+          {% if type.value == "group" or type.value == "room" and lesson_period.lesson.teachers.all %}
             {% include "chronos/partials/teachers.html" with teachers=lesson_period.lesson.teachers.all %}<br/>
           {% endif %}
 
@@ -35,7 +35,7 @@
           {# Display sub #}
 
           {# Teacher or room > display classes #}
-          {% if type == "teacher" or type == "room" %}
+          {% if type.value == "teacher" or type.value == "room" %}
             {% include "chronos/partials/groups.html" with groups=lesson_period.lesson.groups.all %}
           {% endif %}
 
@@ -46,7 +46,7 @@
           {% include "chronos/partials/subs/subject.html" with type="substitution" el=sub %}
 
           {# Teacher or class > display room #}
-          {% if type == "teacher" or type == "group" %}
+          {% if type.value == "teacher" or type.value == "group" %}
             {% include "chronos/partials/subs/room.html" with type="substitution" el=sub %}
           {% endif %}
         {% endif %}
@@ -66,7 +66,7 @@
       {# Normal plan #}
 
       {# Teacher or room > Display classes #}
-      {% if type == "teacher" or type == "room" %}
+      {% if type.value == "teacher" or type.value == "room" %}
         {#                            {{ element_container.element.classes }}#}
         {% if lesson_period.lesson.groups %}
           {% include "chronos/partials/groups.html" with groups=lesson_period.lesson.groups.all %}
@@ -74,7 +74,7 @@
       {% endif %}
 
       {# Class or room > Display teacher #}
-      {% if type == "room" or type == "group" %}
+      {% if type.value == "room" or type.value == "group" %}
         {% include "chronos/partials/teachers.html" with teachers=lesson_period.lesson.teachers.all %}
       {% endif %}
 
@@ -82,7 +82,7 @@
       {% include "chronos/partials/subject.html" with subject=lesson_period.lesson.subject %}
 
       {# Teacher or class > Display room #}
-      {% if type == "teacher" or type == "group" %}
+      {% if type.value == "teacher" or type.value == "group" %}
         {% if lesson_period.room %}
           {% include "chronos/partials/room.html" with room=lesson_period.room %}
         {% endif %}
diff --git a/aleksis/apps/chronos/templates/chronos/timetable.html b/aleksis/apps/chronos/templates/chronos/timetable.html
index 88b02be677b238d9b05d71e52104f19a12de47bb..341d35c32e00feddf9cbcbb9b2aaabf881aab410 100644
--- a/aleksis/apps/chronos/templates/chronos/timetable.html
+++ b/aleksis/apps/chronos/templates/chronos/timetable.html
@@ -24,7 +24,7 @@
       </h4>
 
       {# Show class teacher and deputy class teacher #}
-      {% if type == "group" and el.owners.all %}
+      {% if type.value == "group" and el.owners.all %}
         <h5>{% trans "Group teachers:" %}
           {% for teacher in el.owners.all %}
             <span data-position="bottom" class="tooltipped"
@@ -50,7 +50,7 @@
         <span class="badge new primary-color left smart-plan-badge">{% trans "SMART PLAN" %}</span>
 
         <a class="waves-effect waves-light btn-flat no-print"
-           href="{% url "timetable_regular" type pk "regular" %}">
+           href="{% url "timetable_regular" type.value pk "regular" %}">
           <i class="material-icons left">slideshow</i>
           {% trans "Show regular timetable" %}
         </a>
@@ -62,7 +62,7 @@
     {% else %}
       {# Show if regular #}
       <a class="waves-effect waves-light btn-flat no-print"
-         href="{% url "timetable" type pk %}">
+         href="{% url "timetable" type.value pk %}">
         <i class="material-icons left">slideshow</i>
         {% trans "Show SMART PLAN" %}
       </a>
diff --git a/aleksis/apps/chronos/util/build.py b/aleksis/apps/chronos/util/build.py
index 6b3668cb1689d2081c1b0a362c2136f1ed829976..47f6dc319d5b18ad84354f00607cdf8b943ad38e 100644
--- a/aleksis/apps/chronos/util/build.py
+++ b/aleksis/apps/chronos/util/build.py
@@ -6,6 +6,7 @@ from calendarweek import CalendarWeek
 from django.apps import apps
 from django.db.models import QuerySet
 
+from aleksis.apps.chronos.models import TimetableType
 from aleksis.core.models import Person
 
 LessonPeriod = apps.get_model("chronos", "LessonPeriod")
@@ -39,7 +40,7 @@ def group_by_periods(objs: QuerySet, is_person: bool =False) -> dict:
 
 
 def build_timetable(
-    type_: str, obj: Union[int, Person], date_ref: Union[CalendarWeek, date]
+    type_: Union[TimetableType, str], obj: Union[int, Person], date_ref: Union[CalendarWeek, date]
 ):
     needed_breaks = []
 
@@ -138,7 +139,7 @@ def build_timetable(
                 else:
                     events_per_period[period][weekday].append(event)
 
-    if type_ == "teacher":
+    if type_ == TimetableType.TEACHER:
         # Get matching supervisions
         if is_person:
             week = CalendarWeek.from_date(date_ref)
@@ -175,7 +176,7 @@ def build_timetable(
     rows = []
     for period, break_ in breaks.items():  # period is period after break
         # Break
-        if type_ == "teacher" and period in needed_breaks:
+        if type_ == TimetableType.TEACHER and period in needed_breaks:
             row = {
                 "type": "break",
                 "after_period": break_.after_period_number,
diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py
index fe335b48e1e66743f2c725541017233691ef57fc..9ebe7de9b927262a372ec68c581c9eef45eb693b 100644
--- a/aleksis/apps/chronos/views.py
+++ b/aleksis/apps/chronos/views.py
@@ -16,7 +16,7 @@ from aleksis.core.decorators import admin_required
 from aleksis.core.models import Person, Group, Announcement
 from aleksis.core.util import messages
 from .forms import LessonSubstitutionForm
-from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room, Holiday, Absence
+from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room, Holiday, Absence, TimetableType
 from .tables import LessonsTable
 from .util.build import build_timetable, build_substitutions_list, build_weekdays
 from .util.js import date_unix
@@ -108,15 +108,17 @@ def timetable(
 
     is_smart = regular != "regular"
 
-    if type_ == "group":
+    if type_ == TimetableType.GROUP.value:
         el = get_object_or_404(Group, pk=pk)
-    elif type_ == "teacher":
+    elif type_ == TimetableType.TEACHER.value:
         el = get_object_or_404(Person, pk=pk)
-    elif type_ == "room":
+    elif type_ == TimetableType.ROOM.value:
         el = get_object_or_404(Room, pk=pk)
     else:
         return HttpResponseNotFound()
 
+    type_ = TimetableType.from_string(type_)
+
     if year and week:
         wanted_week = CalendarWeek(year=year, week=week)
     else: