diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0012f7ae6f2e8f418c0a4b50af0fedd385db87b5..8b55fc8dd21619cd55817143df53fd08627e9fe0 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,11 +9,28 @@ and this project adheres to `Semantic Versioning`_.
 Unreleased
 ----------
 
+Added
+~~~~~
+
+* Add fuzzy matching mode for searching course groups: If no 100 % match is found,
+  the importer will search a match by a subset of parent groups.
+
 Changed
 ~~~~~~~
 
 * Let untis_import_mysql management command default to ``current`` instead of all
   to prevent accidental imports of old plans
+* Use new change tracker from Chronos to trigger notifications
+
+Fixed
+~~~~~
+
+* Search course groups not only by parent groups and subject, but also take
+  the teachers (group owners) into account
+* Don't recreate lesson periods if they change, but just update them.
+
+`2.1.3`_ - 2022-02-06
+---------------------
 
 Fixed
 ~~~~~
@@ -182,3 +199,4 @@ Fixed
 .. _2.1: https://edugit.org/Teckids/AlekSIS/AlekSIS-App-Untis/-/tags/2.1
 .. _2.1.1: https://edugit.org/Teckids/AlekSIS/AlekSIS-App-Untis/-/tags/2.1.1
 .. _2.1.2: https://edugit.org/Teckids/AlekSIS/AlekSIS-App-Untis/-/tags/2.1.2
+.. _2.1.3: https://edugit.org/Teckids/AlekSIS/AlekSIS-App-Untis/-/tags/2.1.3
diff --git a/aleksis/apps/untis/preferences.py b/aleksis/apps/untis/preferences.py
index 99d9eeae4f6c3fbbaf135fa8a4edc8aa2ab505a3..d95f5bc30cb306d3bca40c0db60f682a26a86143 100644
--- a/aleksis/apps/untis/preferences.py
+++ b/aleksis/apps/untis/preferences.py
@@ -106,6 +106,15 @@ class DataCheckNotFoundCourseGroups(BooleanPreference):
     verbose_name = _("Register a data problem if a course group has been not found.")
 
 
+@site_preferences_registry.register
+class CourseGroupsFuzzyMatching(BooleanPreference):
+    section = untis_mysql
+    name = "course_groups_fuzzy_matching"
+    default = False
+    verbose_name = _("Match course groups by a subset of parent groups if no 100% match is found")
+    help_text = _("Works only if 'Use course groups' is activated.")
+
+
 @site_preferences_registry.register
 class IgnoreIncompleteSubstitutions(BooleanPreference):
     section = untis_mysql
diff --git a/aleksis/apps/untis/util/mysql/importers/lessons.py b/aleksis/apps/untis/util/mysql/importers/lessons.py
index 4b34f95c80c221af1942e6de4fab9d0f46a146cd..006fc497f3b57920e12237da04196912b2cc2abb 100644
--- a/aleksis/apps/untis/util/mysql/importers/lessons.py
+++ b/aleksis/apps/untis/util/mysql/importers/lessons.py
@@ -126,21 +126,54 @@ def import_lessons(
                 # Negative import_ref denotes a course group
                 group_import_ref = -int("{}{}".format(lesson_id, i))
 
-                # Search by parent groups and subject
+                # Search by parent groups, teachers/owners and subject
                 qs = core_models.Group.objects.filter(
                     parent_groups__in=[c.id for c in course_classes],
                     subject_id=subject.id,
+                    owners__in=[t.id for t in teachers],
                 ).filter(Q(school_term__isnull=True) | Q(school_term=validity_range.school_term))
 
                 # Check if found groups match
                 course_group = None
                 for found_group in qs:
-                    if compare_m2m(course_classes, found_group.parent_groups.all()):
+                    if compare_m2m(course_classes, found_group.parent_groups.all()) and compare_m2m(
+                        teachers, found_group.owners.all()
+                    ):
+                        match = True
                         course_group = found_group
                         logger.info(
-                            "    Course group found by searching by parent groups and subject"
+                            "    Course group found by searching by parent groups, "
+                            "teachers (owners) and subject"
                         )
 
+                if (
+                    not match
+                    and get_site_preferences()["untis_mysql__course_groups_fuzzy_matching"]
+                ):
+                    if qs.count() != 1:
+                        logger.warning(
+                            "    Course group not found by searching by parent groups, "
+                            "teachers (owners) and subject (fuzzy matching mode)"
+                        )
+                    else:
+                        for found_group in qs:
+                            if compare_m2m(teachers, found_group.owners.all()):
+                                if match:
+                                    logger.warning(
+                                        "    More than one course group found "
+                                        "by searching by parent groups, "
+                                        "teachers (owners) and subject (fuzzy matching mode)"
+                                    )
+                                    match = False
+                                    course_group = None
+                                else:
+                                    match = True
+                                    course_group = found_group
+                                    logger.info(
+                                        "    Course group found by searching by parent groups, "
+                                        "teachers (owners) and subject (fuzzy matching mode)"
+                                    )
+
                 changed = False
                 register_data_check = get_site_preferences()[
                     "untis_mysql__data_check_for_not_found_course_groups"
@@ -257,10 +290,7 @@ def import_lessons(
             # All times for this course
             old_lesson_periods_qs = chronos_models.LessonPeriod.objects.filter(lesson=lesson)
 
-            # If length has changed, delete all lesson periods
-            if old_lesson_periods_qs.count() != len(time_periods):
-                old_lesson_periods_qs.delete()
-                logger.info("    Lesson periods deleted")
+            existing_lesson_period_pks = []
 
             # Sync time periods
             for j, time_period in enumerate(time_periods):
@@ -274,24 +304,29 @@ def import_lessons(
                     room = None
 
                 # Check if an old lesson period is provided
-                old_lesson_period_qs = old_lesson_periods_qs.filter(element_id_untis=j)
+                old_lesson_period_qs = old_lesson_periods_qs.filter(period=time_period)
                 if old_lesson_period_qs.exists():
                     # Update old lesson period
 
-                    old_lesson_period = old_lesson_period_qs[0]
-                    if old_lesson_period.period != time_period or old_lesson_period.room != room:
-                        old_lesson_period.period = time_period
-                        old_lesson_period.room = room
-                        old_lesson_period.save()
-                        logger.info("      Time period and room updated")
+                    lesson_period = old_lesson_period_qs[0]
+                    if lesson_period.room != room or lesson_period.element_id_untis != j:
+                        lesson_period.element_id_untis = j
+                        lesson_period.room = room
+                        lesson_period.save()
+                        logger.info("      Untis reference and room updated")
                 else:
                     # Create new lesson period
 
-                    chronos_models.LessonPeriod.objects.create(
+                    lesson_period = chronos_models.LessonPeriod.objects.create(
                         lesson=lesson, period=time_period, room=room, element_id_untis=j
                     )
-                    logger.info("      New time period added")
+                    logger.info("      New lesson period added")
+
+                existing_lesson_period_pks.append(lesson_period.pk)
 
+            # delete all no-longer existing lesson periods
+            old_lesson_periods_qs.exclude(pk__in=existing_lesson_period_pks).delete()
+            logger.info("    Old lesson periods deleted")
             current_teacher_id = teacher_id
 
     for lesson in chronos_models.Lesson.objects.filter(validity=validity_range):
diff --git a/aleksis/apps/untis/util/mysql/main.py b/aleksis/apps/untis/util/mysql/main.py
index b3e6ca510ced6f8cb0bb1c13803537422501fdaa..7ae5113f890f93a2314ea6cf84924c5d479c0958 100644
--- a/aleksis/apps/untis/util/mysql/main.py
+++ b/aleksis/apps/untis/util/mysql/main.py
@@ -5,6 +5,7 @@ from django.db.models import QuerySet
 import reversion
 from tqdm import tqdm
 
+from aleksis.apps.chronos.util.change_tracker import TimetableDataChangeTracker
 from aleksis.apps.untis.util.mysql.importers.terms import import_terms
 from aleksis.apps.untis.util.mysql.util import TQDM_DEFAULTS
 
@@ -35,6 +36,8 @@ def untis_import_mysql(terms: Optional[QuerySet] = None, version: Optional[int]
         with reversion.create_revision(atomic=True):
             reversion.set_comment(f"Untis import for validity range {validity_range}")
 
+            tracker = TimetableDataChangeTracker()
+
             # Common data for Chronos
             subjects_ref = import_subjects(validity_range)
             rooms_ref = import_rooms(validity_range)
diff --git a/docs/conf.py b/docs/conf.py
index c6d2a9fa5181e38139d767e7e472553a3c1d434b..ab89cfeaf2822a867e3757347d97986de72f6b14 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -31,7 +31,7 @@ author = "The AlekSIS Team"
 # The short X.Y version
 version = "2.1"
 # The full version, including alpha/beta/rc tags
-release = "2.1.3.dev0"
+release = "2.1.4.dev0"
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/pyproject.toml b/pyproject.toml
index 468e28dba206227db2678ef421ba90049bc401e3..f26eef75d7acee3f5d82adfaaef9b5e79237ead1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-App-Untis"
-version = "2.1.3.dev0"
+version = "2.1.4.dev0"
 packages = [
     { include = "aleksis" }
 ]
@@ -41,11 +41,11 @@ python = "^3.9"
 mysqlclient = "^2.0.0"
 tqdm = "^4.44.1"
 defusedxml = "^0.7.0"
-aleksis-core = "^2.0"
-aleksis-app-chronos = "^2.0"
+aleksis-core = "^2.8"
+aleksis-app-chronos = "^2.3"
 
 [tool.poetry.dev-dependencies]
-aleksis-builddeps = "^6"
+aleksis-builddeps = "*"
 
 [tool.poetry.plugins."aleksis.app"]
 untis = "aleksis.apps.untis.apps:UntisConfig"