From 66cff4acc3b5ee9d8096f8835a4ceedc31f659a0 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Mon, 9 Aug 2021 19:59:10 +0200
Subject: [PATCH 1/6] Activate test engine

(cherry picked from commit 064786a3258ed261d486e873d242508e3f1cb079)
---
 .gitignore     | 3 +++
 .gitlab-ci.yml | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 11164f019..b3fa1ad84 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,3 +56,6 @@ docs/_build/
 
 # Test
 .tox/
+.coverage
+.mypy_cache/
+htmlcov/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index dcdec3c59..27a9c8b5f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,8 @@
 include:
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/general.yml
-#    - project: "AlekSIS/official/AlekSIS"
-#      file: /ci/test/test.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/test/test.yml
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/test/lint.yml
     - project: "AlekSIS/official/AlekSIS"
-- 
GitLab


From 99d7726591601fc1840521c2b57987a6e130aed6 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Mon, 9 Aug 2021 19:59:29 +0200
Subject: [PATCH 2/6] Fix bulk_update in delete_personal_note action

This includes tests to reproduce the error.

(cherry picked from commit 68a4e7103f358c14ab06cc6a51d20fabcdf0009a)
---
 CHANGELOG.rst                              |  8 ++
 aleksis/apps/alsijil/actions.py            |  4 +-
 aleksis/apps/alsijil/tests/test_actions.py | 96 ++++++++++++++++++++++
 3 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 aleksis/apps/alsijil/tests/test_actions.py

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5d702b571..5f4e9ef13 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
 The format is based on `Keep a Changelog`_,
 and this project adheres to `Semantic Versioning`_.
 
+Unreleased
+----------
+
+Fixed
+~~~~~
+
+* The _Delete personal note_ action didn't work due to wrong usage of ``bulk_update``.
+
 `2.0rc4`_ - 2021-08-01
 ----------------------
 
diff --git a/aleksis/apps/alsijil/actions.py b/aleksis/apps/alsijil/actions.py
index 2d42d6134..9c307017e 100644
--- a/aleksis/apps/alsijil/actions.py
+++ b/aleksis/apps/alsijil/actions.py
@@ -40,7 +40,9 @@ def delete_personal_note(modeladmin, request, queryset):
     for personal_note in queryset:
         personal_note.reset_values()
         notes.append(personal_note)
-    PersonalNote.objects.bulk_update(notes)
+    PersonalNote.objects.bulk_update(
+        notes, fields=["absent", "excused", "late", "excuse_type", "remarks"]
+    )
 
 
 delete_personal_note.short_description = _("Delete")
diff --git a/aleksis/apps/alsijil/tests/test_actions.py b/aleksis/apps/alsijil/tests/test_actions.py
new file mode 100644
index 000000000..6f1bd6ef4
--- /dev/null
+++ b/aleksis/apps/alsijil/tests/test_actions.py
@@ -0,0 +1,96 @@
+from datetime import date, time
+
+import pytest
+
+from aleksis.apps.alsijil.actions import (
+    delete_personal_note,
+    mark_as_excuse_type_generator,
+    mark_as_excused,
+    mark_as_unexcused,
+)
+from aleksis.apps.alsijil.models import ExcuseType, PersonalNote
+from aleksis.apps.chronos.models import Event, TimePeriod
+from aleksis.core.models import Person
+
+pytestmark = pytest.mark.django_db
+
+
+def _generate_event(day: date):
+    period_from = TimePeriod.objects.create(
+        weekday=0, period=1, time_start=time(10, 00), time_end=time(11, 00)
+    )
+    period_to = TimePeriod.objects.create(
+        weekday=0, period=2, time_start=time(11, 00), time_end=time(12, 00)
+    )
+
+    event = Event.objects.create(
+        date_start=day, date_end=day, period_from=period_from, period_to=period_to
+    )
+    return event
+
+
+def _prepare_notes():
+    """Create some minimal personal notes."""
+    person, __ = Person.objects.get_or_create(first_name="Jane", last_name="Doe")
+
+    excuse_type, __ = ExcuseType.objects.get_or_create(short_name="Foo", name="Fooooooooooooo")
+    notes = [
+        PersonalNote(
+            person=person,
+            event=_generate_event(date(2021, 10, 1)),
+            absent=True,
+            remarks="This is baz.",
+        ),
+        PersonalNote(person=person, event=_generate_event(date(2021, 11, 1)), absent=True),
+        PersonalNote(
+            person=person, event=_generate_event(date(2022, 10, 1)), absent=True, excused=True
+        ),
+        PersonalNote(
+            person=person,
+            event=_generate_event(date(2021, 3, 1)),
+            absent=True,
+            excused=True,
+            excuse_type=excuse_type,
+        ),
+        PersonalNote(person=person, event=_generate_event(date(2021, 10, 4)), late=10),
+        PersonalNote(
+            person=person, event=_generate_event(date(2032, 10, 11)), remarks="Good work!"
+        ),
+        PersonalNote(person=person, event=_generate_event(date(2032, 10, 11))),
+    ]
+    PersonalNote.objects.bulk_create(notes)
+    return notes
+
+
+def test_mark_as_excused_action():
+    notes = _prepare_notes()
+    assert PersonalNote.objects.filter(excused=True).count() == 2
+    mark_as_excused(None, None, PersonalNote.objects.all())
+    assert PersonalNote.objects.filter(excused=True).count() == 4
+    assert PersonalNote.objects.filter(excuse_type=None, excused=True).count() == 4
+
+
+def test_mark_as_unexcused_action():
+    notes = _prepare_notes()
+    assert PersonalNote.objects.filter(excused=True).count() == 2
+    mark_as_unexcused(None, None, PersonalNote.objects.all())
+    assert PersonalNote.objects.filter(excused=True).count() == 0
+    assert PersonalNote.objects.filter(excuse_type=None, excused=True).count() == 0
+
+
+def test_mark_as_excuse_type_generator_action():
+    excuse_type, __ = ExcuseType.objects.get_or_create(short_name="Foo", name="Fooooooooooooo")
+    notes = _prepare_notes()
+    assert PersonalNote.objects.filter(excused=True).count() == 2
+    assert PersonalNote.objects.filter(excused=True, excuse_type=excuse_type).count() == 1
+    mark_as_foo = mark_as_excuse_type_generator(excuse_type=excuse_type)
+    mark_as_foo(None, None, PersonalNote.objects.all())
+    assert PersonalNote.objects.filter(excused=True).count() == 4
+    assert PersonalNote.objects.filter(excuse_type=excuse_type, excused=True).count() == 4
+
+
+def test_delete_personal_note_action():
+    notes = _prepare_notes()
+    assert PersonalNote.objects.not_empty().count() == 6
+    delete_personal_note(None, None, PersonalNote.objects.all())
+    assert PersonalNote.objects.not_empty().count() == 0
-- 
GitLab


From 8da49bc8bdd23d76af56c8aafa62620e2339e29d Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Thu, 12 Aug 2021 15:49:36 +0200
Subject: [PATCH 3/6] Update poetry.lock

---
 poetry.lock | 131 ++++++++++++++++++++++++----------------------------
 1 file changed, 61 insertions(+), 70 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index 4e973f05e..78e4db6e5 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -8,7 +8,7 @@ python-versions = "*"
 
 [[package]]
 name = "aleksis-app-chronos"
-version = "2.0rc1+20210623211739.053fedbd"
+version = "2.0rc2+20210801140820.175e97fc"
 description = "AlekSIS (School Information System) — App Χρόνος (digital timetables)"
 category = "main"
 optional = false
@@ -66,7 +66,7 @@ reference = "gitlab"
 
 [[package]]
 name = "aleksis-core"
-version = "2.1.dev0+20210729094035.c0b56c31"
+version = "2.1.dev0+20210805205937.c775be2f"
 description = "AlekSIS (School Information System) — Core"
 category = "main"
 optional = false
@@ -294,11 +294,11 @@ d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
 
 [[package]]
 name = "bleach"
-version = "3.3.1"
+version = "4.0.0"
 description = "An easy safelist-based HTML-sanitizing tool."
 category = "main"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.6"
 
 [package.dependencies]
 packaging = "*"
@@ -608,7 +608,7 @@ python-versions = "*"
 
 [[package]]
 name = "django"
-version = "3.2.5"
+version = "3.2.6"
 description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
 category = "main"
 optional = false
@@ -1316,7 +1316,7 @@ yaml = ["ruamel.yaml"]
 
 [[package]]
 name = "faker"
-version = "8.10.3"
+version = "8.11.0"
 description = "Faker is a Python package that generates fake data for you."
 category = "main"
 optional = false
@@ -1545,7 +1545,7 @@ python-versions = "*"
 
 [[package]]
 name = "ipython"
-version = "7.25.0"
+version = "7.26.0"
 description = "IPython: Productive Interactive Computing"
 category = "main"
 optional = false
@@ -1628,7 +1628,7 @@ i18n = ["Babel (>=2.7)"]
 
 [[package]]
 name = "jwcrypto"
-version = "0.9.1"
+version = "1.0"
 description = "Implementation of JOSE Web standards"
 category = "main"
 optional = false
@@ -1637,7 +1637,6 @@ python-versions = "*"
 [package.dependencies]
 cryptography = ">=2.3"
 deprecated = "*"
-six = "*"
 
 [[package]]
 name = "kombu"
@@ -1833,7 +1832,7 @@ scramp = ">=1.4.0"
 
 [[package]]
 name = "phonenumbers"
-version = "8.12.28"
+version = "8.12.29"
 description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
 category = "main"
 optional = false
@@ -2174,7 +2173,7 @@ hiredis = ["hiredis (>=0.1.3)"]
 
 [[package]]
 name = "regex"
-version = "2021.7.6"
+version = "2021.8.3"
 description = "Alternative regular expression module, to replace re."
 category = "dev"
 optional = false
@@ -2578,7 +2577,7 @@ test = ["pytest"]
 
 [[package]]
 name = "twilio"
-version = "6.62.1"
+version = "6.63.0"
 description = "Twilio API client and TwiML generator"
 category = "main"
 optional = false
@@ -2681,15 +2680,15 @@ alabaster = [
     {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
 ]
 aleksis-app-chronos = [
-    {file = "AlekSIS-App-Chronos-2.0rc1+20210623211739.053fedbd.tar.gz", hash = "sha256:45a32e88c2a6ad7e0114aedac7edd166d2f9830aa3392504a0b886a515870f73"},
-    {file = "AlekSIS_App_Chronos-2.0rc1+20210623211739.053fedbd-py3-none-any.whl", hash = "sha256:ad2cdbf24680701b8f52c85f9d2d52a0dcdf68875e8361472eeb3884e835b08d"},
+    {file = "AlekSIS-App-Chronos-2.0rc2+20210801140820.175e97fc.tar.gz", hash = "sha256:ecbb318610d602968d25b21c2b9d616d46f7114ee164a0a0329aac7c13efc3b8"},
+    {file = "AlekSIS_App_Chronos-2.0rc2+20210801140820.175e97fc-py3-none-any.whl", hash = "sha256:ef1217e3d53d5211eb859a63c8a0d797df354c3f616270369370c8c995de0c28"},
 ]
 aleksis-builddeps = [
     {file = "AlekSIS-Builddeps-4.tar.gz", hash = "sha256:aaaa22965228b9b9b7de812e3e7fa9cbfdbf8635bb22d6f3a201dc0cc6d8d307"},
 ]
 aleksis-core = [
-    {file = "AlekSIS-Core-2.1.dev0+20210729094035.c0b56c31.tar.gz", hash = "sha256:b125c662c0621019646a22d206aebf0856f937f7154ac03914c9e414e8c69f20"},
-    {file = "AlekSIS_Core-2.1.dev0+20210729094035.c0b56c31-py3-none-any.whl", hash = "sha256:5ce65c7f9b5d7a9c513d600603da85d3536ca85e7a7fbb599e0af23921cf6e5e"},
+    {file = "AlekSIS-Core-2.1.dev0+20210805205937.c775be2f.tar.gz", hash = "sha256:174623a2bf33a4ea508b0b18951413072ce1ce7edd0d57233d5f9cf09609358a"},
+    {file = "AlekSIS_Core-2.1.dev0+20210805205937.c775be2f-py3-none-any.whl", hash = "sha256:84a7642863d32ce8b87bb6e6ee62e4ad3824632ee7398392cf9956ea2c2f2580"},
 ]
 amqp = [
     {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"},
@@ -2745,8 +2744,8 @@ black = [
     {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"},
 ]
 bleach = [
-    {file = "bleach-3.3.1-py2.py3-none-any.whl", hash = "sha256:ae976d7174bba988c0b632def82fdc94235756edfb14e6558a9c5be555c9fb78"},
-    {file = "bleach-3.3.1.tar.gz", hash = "sha256:306483a5a9795474160ad57fce3ddd1b50551e981eed8e15a582d34cef28aafa"},
+    {file = "bleach-4.0.0-py2.py3-none-any.whl", hash = "sha256:c1685a132e6a9a38bf93752e5faab33a9517a6c0bb2f37b785e47bf253bdb51d"},
+    {file = "bleach-4.0.0.tar.gz", hash = "sha256:ffa9221c6ac29399cc50fcc33473366edd0cf8d5e2cbbbb63296dc327fb67cc8"},
 ]
 "boolean.py" = [
     {file = "boolean.py-3.8-py2.py3-none-any.whl", hash = "sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26"},
@@ -2941,8 +2940,8 @@ dj-database-url = [
     {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"},
 ]
 django = [
-    {file = "Django-3.2.5-py3-none-any.whl", hash = "sha256:c58b5f19c5ae0afe6d75cbdd7df561e6eb929339985dbbda2565e1cabb19a62e"},
-    {file = "Django-3.2.5.tar.gz", hash = "sha256:3da05fea54fdec2315b54a563d5b59f3b4e2b1e69c3a5841dda35019c01855cd"},
+    {file = "Django-3.2.6-py3-none-any.whl", hash = "sha256:7f92413529aa0e291f3be78ab19be31aefb1e1c9a52cd59e130f505f27a51f13"},
+    {file = "Django-3.2.6.tar.gz", hash = "sha256:f27f8544c9d4c383bbe007c57e3235918e258364577373d4920e9162837be022"},
 ]
 django-allauth = [
     {file = "django-allauth-0.45.0.tar.gz", hash = "sha256:6d46be0e1480316ccd45476db3aefb39db70e038d2a543112d314b76bb999a4e"},
@@ -3171,8 +3170,8 @@ dynaconf = [
     {file = "dynaconf-3.1.4.tar.gz", hash = "sha256:b2f472d83052f809c5925565b8a2ba76a103d5dc1dbb9748b693ed67212781b9"},
 ]
 faker = [
-    {file = "Faker-8.10.3-py3-none-any.whl", hash = "sha256:f27a2a5c34042752f9d5fea2a9667aed5265d7d7bdd5ce83bc03b2f8a540d148"},
-    {file = "Faker-8.10.3.tar.gz", hash = "sha256:771b21ab55924867ac865f4b0c2f547c200172293b1056be16289584ef1215cb"},
+    {file = "Faker-8.11.0-py3-none-any.whl", hash = "sha256:3e737576ff50cd98dfed643d6b3fd63194eca9df00e7f595960fe7da5220723d"},
+    {file = "Faker-8.11.0.tar.gz", hash = "sha256:b9e81e9da3dda3ac54189e034cfb943de576a259caeb226ccab43fcbcf6a7891"},
 ]
 flake8 = [
     {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
@@ -3250,8 +3249,8 @@ iniconfig = [
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 ipython = [
-    {file = "ipython-7.25.0-py3-none-any.whl", hash = "sha256:aa21412f2b04ad1a652e30564fff6b4de04726ce875eab222c8430edc6db383a"},
-    {file = "ipython-7.25.0.tar.gz", hash = "sha256:54bbd1fe3882457aaf28ae060a5ccdef97f212a741754e420028d4ec5c2291dc"},
+    {file = "ipython-7.26.0-py3-none-any.whl", hash = "sha256:892743b65c21ed72b806a3a602cca408520b3200b89d1924f4b3d2cdb3692362"},
+    {file = "ipython-7.26.0.tar.gz", hash = "sha256:0cff04bb042800129348701f7bd68a430a844e8fb193979c08f6c99f28bb735e"},
 ]
 ipython-genutils = [
     {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"},
@@ -3270,8 +3269,8 @@ jinja2 = [
     {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
 ]
 jwcrypto = [
-    {file = "jwcrypto-0.9.1-py2.py3-none-any.whl", hash = "sha256:12976a09895ec0076ce17c49ab7be64d6e63bcd7fd9a773e3fedf8011537a5f6"},
-    {file = "jwcrypto-0.9.1.tar.gz", hash = "sha256:63531529218ba9869e14ef8c9e7b516865ede3facf9b0ef3d3ba68014da211f9"},
+    {file = "jwcrypto-1.0-py2.py3-none-any.whl", hash = "sha256:db93a656d9a7a35dda5a68deb5c9f301f4e60507d8aef1559e0637b9ac497137"},
+    {file = "jwcrypto-1.0.tar.gz", hash = "sha256:f88816eb0a41b8f006af978ced5f171f33782525006cdb055b536a40f4d46ac9"},
 ]
 kombu = [
     {file = "kombu-5.1.0-py3-none-any.whl", hash = "sha256:e2dedd8a86c9077c350555153825a31e456a0dc20c15d5751f00137ec9c75f0a"},
@@ -3401,8 +3400,8 @@ pg8000 = [
     {file = "pg8000-1.21.0.tar.gz", hash = "sha256:c99108c630b1c468668a8def38be4c91b2fb7cf0154ce7918e7a3912e60652d7"},
 ]
 phonenumbers = [
-    {file = "phonenumbers-8.12.28-py2.py3-none-any.whl", hash = "sha256:f8ce05f82955d2faeefe2303350b2ccb7369dd39b6e45231a09475d67eb7e83b"},
-    {file = "phonenumbers-8.12.28.tar.gz", hash = "sha256:42ea4f946d5cce0056cbce257842ea6b281e69828ad2e7f27b29d3908e5b06bd"},
+    {file = "phonenumbers-8.12.29-py2.py3-none-any.whl", hash = "sha256:885b7b4521bb9105b31a8597d3baa6da11155f819f1231434590db2f130a27cd"},
+    {file = "phonenumbers-8.12.29.tar.gz", hash = "sha256:9a396a4d69ed4cf1f8513114869cbed4f12542644374a5d5f11bc7fd66a2098a"},
 ]
 pickleshare = [
     {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
@@ -3648,47 +3647,39 @@ redis = [
     {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"},
 ]
 regex = [
-    {file = "regex-2021.7.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222"},
-    {file = "regex-2021.7.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407"},
-    {file = "regex-2021.7.6-cp36-cp36m-win32.whl", hash = "sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b"},
-    {file = "regex-2021.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb"},
-    {file = "regex-2021.7.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad"},
-    {file = "regex-2021.7.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895"},
-    {file = "regex-2021.7.6-cp37-cp37m-win32.whl", hash = "sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5"},
-    {file = "regex-2021.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f"},
-    {file = "regex-2021.7.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761"},
-    {file = "regex-2021.7.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068"},
-    {file = "regex-2021.7.6-cp38-cp38-win32.whl", hash = "sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0"},
-    {file = "regex-2021.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4"},
-    {file = "regex-2021.7.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58"},
-    {file = "regex-2021.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3"},
-    {file = "regex-2021.7.6-cp39-cp39-win32.whl", hash = "sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035"},
-    {file = "regex-2021.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c"},
-    {file = "regex-2021.7.6.tar.gz", hash = "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d"},
+    {file = "regex-2021.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8764a78c5464ac6bde91a8c87dd718c27c1cabb7ed2b4beaf36d3e8e390567f9"},
+    {file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4551728b767f35f86b8e5ec19a363df87450c7376d7419c3cac5b9ceb4bce576"},
+    {file = "regex-2021.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:577737ec3d4c195c4aef01b757905779a9e9aee608fa1cf0aec16b5576c893d3"},
+    {file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c856ec9b42e5af4fe2d8e75970fcc3a2c15925cbcc6e7a9bcb44583b10b95e80"},
+    {file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3835de96524a7b6869a6c710b26c90e94558c31006e96ca3cf6af6751b27dca1"},
+    {file = "regex-2021.8.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cea56288eeda8b7511d507bbe7790d89ae7049daa5f51ae31a35ae3c05408531"},
+    {file = "regex-2021.8.3-cp36-cp36m-win32.whl", hash = "sha256:a4eddbe2a715b2dd3849afbdeacf1cc283160b24e09baf64fa5675f51940419d"},
+    {file = "regex-2021.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:57fece29f7cc55d882fe282d9de52f2f522bb85290555b49394102f3621751ee"},
+    {file = "regex-2021.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a5c6dbe09aff091adfa8c7cfc1a0e83fdb8021ddb2c183512775a14f1435fe16"},
+    {file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff4a8ad9638b7ca52313d8732f37ecd5fd3c8e3aff10a8ccb93176fd5b3812f6"},
+    {file = "regex-2021.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b63e3571b24a7959017573b6455e05b675050bbbea69408f35f3cb984ec54363"},
+    {file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fbc20975eee093efa2071de80df7f972b7b35e560b213aafabcec7c0bd00bd8c"},
+    {file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14caacd1853e40103f59571f169704367e79fb78fac3d6d09ac84d9197cadd16"},
+    {file = "regex-2021.8.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb350eb1060591d8e89d6bac4713d41006cd4d479f5e11db334a48ff8999512f"},
+    {file = "regex-2021.8.3-cp37-cp37m-win32.whl", hash = "sha256:18fdc51458abc0a974822333bd3a932d4e06ba2a3243e9a1da305668bd62ec6d"},
+    {file = "regex-2021.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:026beb631097a4a3def7299aa5825e05e057de3c6d72b139c37813bfa351274b"},
+    {file = "regex-2021.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:16d9eaa8c7e91537516c20da37db975f09ac2e7772a0694b245076c6d68f85da"},
+    {file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3905c86cc4ab6d71635d6419a6f8d972cab7c634539bba6053c47354fd04452c"},
+    {file = "regex-2021.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937b20955806381e08e54bd9d71f83276d1f883264808521b70b33d98e4dec5d"},
+    {file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:28e8af338240b6f39713a34e337c3813047896ace09d51593d6907c66c0708ba"},
+    {file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c09d88a07483231119f5017904db8f60ad67906efac3f1baa31b9b7f7cca281"},
+    {file = "regex-2021.8.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:85f568892422a0e96235eb8ea6c5a41c8ccbf55576a2260c0160800dbd7c4f20"},
+    {file = "regex-2021.8.3-cp38-cp38-win32.whl", hash = "sha256:bf6d987edd4a44dd2fa2723fca2790f9442ae4de2c8438e53fcb1befdf5d823a"},
+    {file = "regex-2021.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:8fe58d9f6e3d1abf690174fd75800fda9bdc23d2a287e77758dc0e8567e38ce6"},
+    {file = "regex-2021.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7976d410e42be9ae7458c1816a416218364e06e162b82e42f7060737e711d9ce"},
+    {file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9569da9e78f0947b249370cb8fadf1015a193c359e7e442ac9ecc585d937f08d"},
+    {file = "regex-2021.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bbe342c5b2dec5c5223e7c363f291558bc27982ef39ffd6569e8c082bdc83"},
+    {file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f421e3cdd3a273bace013751c345f4ebeef08f05e8c10757533ada360b51a39"},
+    {file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea212df6e5d3f60341aef46401d32fcfded85593af1d82b8b4a7a68cd67fdd6b"},
+    {file = "regex-2021.8.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a3b73390511edd2db2d34ff09aa0b2c08be974c71b4c0505b4a048d5dc128c2b"},
+    {file = "regex-2021.8.3-cp39-cp39-win32.whl", hash = "sha256:f35567470ee6dbfb946f069ed5f5615b40edcbb5f1e6e1d3d2b114468d505fc6"},
+    {file = "regex-2021.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:bfa6a679410b394600eafd16336b2ce8de43e9b13f7fb9247d84ef5ad2b45e91"},
+    {file = "regex-2021.8.3.tar.gz", hash = "sha256:8935937dad2c9b369c3d932b0edbc52a62647c2afb2fafc0c280f14a8bf56a6a"},
 ]
 requests = [
     {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
@@ -3843,7 +3834,7 @@ traitlets = [
     {file = "traitlets-5.0.5.tar.gz", hash = "sha256:178f4ce988f69189f7e523337a3e11d91c786ded9360174a3d9ca83e79bc5396"},
 ]
 twilio = [
-    {file = "twilio-6.62.1.tar.gz", hash = "sha256:18abcd69049b150a90d543b59d246ac6fd7a4db08c3fdbe600534de60f71345b"},
+    {file = "twilio-6.63.0.tar.gz", hash = "sha256:012f576afed6d161fc6d88cfa7de183e9217363ca3779295d6f12476f42cc4c5"},
 ]
 typed-ast = [
     {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
-- 
GitLab


From dbff619980897e19ac9b44dd6278d37701eaa975 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Tue, 10 Aug 2021 20:14:34 +0200
Subject: [PATCH 4/6] Add distinct to permission-related queries in
 FilterRegisterObjectForm and AssignGroupRoleForm

(cherry picked from commit c44746467e85616fbbefb0f29692a372feede1ea)
---
 CHANGELOG.rst                 |  1 +
 aleksis/apps/alsijil/forms.py | 10 ++++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5f4e9ef13..e1970a31b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -13,6 +13,7 @@ Fixed
 ~~~~~
 
 * The _Delete personal note_ action didn't work due to wrong usage of ``bulk_update``.
+* Groups and persons were shown multiple times in some forms due to filtering by permissions.
 
 `2.0rc4`_ - 2021-08-01
 ----------------------
diff --git a/aleksis/apps/alsijil/forms.py b/aleksis/apps/alsijil/forms.py
index cb12a4eb8..042b25336 100644
--- a/aleksis/apps/alsijil/forms.py
+++ b/aleksis/apps/alsijil/forms.py
@@ -256,11 +256,13 @@ class AssignGroupRoleForm(forms.ModelForm):
                 )
             else:
                 persons = persons.filter(member_of__owners=self.request.user.person)
-            self.fields["person"].queryset = persons
+            self.fields["person"].queryset = persons.distinct()
 
             if "groups" not in initial:
-                groups = Group.objects.for_current_school_term_or_all().filter(
-                    owners=self.request.user.person
+                groups = (
+                    Group.objects.for_current_school_term_or_all()
+                    .filter(owners=self.request.user.person)
+                    .distinct()
                 )
                 self.fields["groups"].queryset = groups
 
@@ -332,7 +334,7 @@ class FilterRegisterObjectForm(forms.Form):
                 | Q(lessons__lesson_periods__substitutions__teachers=person)
                 | Q(events__teachers=person)
                 | Q(extra_lessons__teachers=person)
-            )
+            ).distinct()
         elif not for_person:
             groups = Group.objects.all()
         self.fields["group"].queryset = groups
-- 
GitLab


From 53af715485fa0e3012efe78fee2b6b3fc27a2ff0 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Thu, 12 Aug 2021 15:50:33 +0200
Subject: [PATCH 5/6] Update changelog for 2.0rc5

---
 CHANGELOG.rst | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e1970a31b..91bd7719c 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,8 +6,8 @@ All notable changes to this project will be documented in this file.
 The format is based on `Keep a Changelog`_,
 and this project adheres to `Semantic Versioning`_.
 
-Unreleased
-----------
+`2.0rc5`_ - 2021-08-12
+----------------------
 
 Fixed
 ~~~~~
@@ -180,3 +180,4 @@ Fixed
 .. _2.0rc2: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/2.0rc2
 .. _2.0rc3: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/2.0rc3
 .. _2.0rc4: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/2.0rc4
+.. _2.0rc5: https://edugit.org/AlekSIS/Official/AlekSIS-App-Alsijil/-/tags/2.0rc5
-- 
GitLab


From df5dec19ae63646beaa85031b8b89a530e31cfb0 Mon Sep 17 00:00:00 2001
From: Jonathan Weth <git@jonathanweth.de>
Date: Thu, 12 Aug 2021 15:50:46 +0200
Subject: [PATCH 6/6] Bump version to 2.0rc5

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index f778b4da6..808cf3dc4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-App-Alsijil"
-version = "2.0rc4"
+version = "2.0rc5"
 packages = [
     { include = "aleksis" }
 ]
-- 
GitLab