From 90a8ad33ba4f7465dc2226624d38cc6817406a05 Mon Sep 17 00:00:00 2001 From: Aiq0 <66842415+Aiq0@users.noreply.github.com> Date: Sun, 6 Sep 2026 17:58:59 +0200 Subject: [PATCH 1/4] fix: types --- trojstenid/schools/models.py | 10 ++++++---- trojstenid/users/serializers.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/trojstenid/schools/models.py b/trojstenid/schools/models.py index df167e3..6760cc4 100644 --- a/trojstenid/schools/models.py +++ b/trojstenid/schools/models.py @@ -1,5 +1,5 @@ from datetime import date, timedelta -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, ClassVar from django.conf import settings from django.contrib.postgres.fields import ArrayField @@ -28,7 +28,7 @@ def __str__(self) -> str: return self.name -class SchoolQuerySet(models.QuerySet): +class SchoolQuerySet(models.QuerySet["School"]): def search(self, query: str): return self.filter( Q(name__unaccent__icontains=query) | Q(address__unaccent__icontains=query) @@ -43,7 +43,9 @@ class School(models.Model): types = models.ManyToManyField(SchoolType) is_selectable = models.BooleanField(default=True) - objects: SchoolQuerySet = SchoolQuerySet.as_manager() # pyright:ignore + objects: ClassVar[SchoolQuerySet] = ( + SchoolQuerySet.as_manager() + ) # ty: ignore[invalid-assignment] class Meta: ordering = ["eduid", "name"] @@ -107,7 +109,7 @@ class UserSchoolRecord(models.Model): start_year = models.PositiveIntegerField(default=0) end_date = models.DateField(blank=True, null=True) - objects: "UserSchoolRecordManager" = UserSchoolRecordManager() # pyright: ignore + objects: ClassVar["UserSchoolRecordManager"] = UserSchoolRecordManager() class Meta: ordering = ["user_id", "start_date"] diff --git a/trojstenid/users/serializers.py b/trojstenid/users/serializers.py index 172ac73..afff824 100644 --- a/trojstenid/users/serializers.py +++ b/trojstenid/users/serializers.py @@ -12,7 +12,7 @@ def to_representation(self, instance): class EmailAddressSerializer(serializers.ModelSerializer): - class Meta: # type:ignore + class Meta: model = EmailAddress fields = ["email", "verified", "primary"] @@ -25,7 +25,7 @@ class UserSerializer(serializers.ModelSerializer): emails = EmailAddressSerializer(many=True, source="emailaddress_set") avatar = serializers.SerializerMethodField() - class Meta: # type:ignore + class Meta: model = User fields = [ "id", From d72a136c96e3ef1932100a30c21ef315546e1c07 Mon Sep 17 00:00:00 2001 From: Aiq0 <66842415+Aiq0@users.noreply.github.com> Date: Sun, 6 Sep 2026 18:10:52 +0200 Subject: [PATCH 2/4] feat: add `created_at` and `updated_at` to `UserSchoolRecord` --- ...04_userschoolrecord_created_at_and_more.py | 36 +++++++++++++++++++ trojstenid/schools/models.py | 3 ++ 2 files changed, 39 insertions(+) create mode 100644 trojstenid/schools/migrations/0004_userschoolrecord_created_at_and_more.py diff --git a/trojstenid/schools/migrations/0004_userschoolrecord_created_at_and_more.py b/trojstenid/schools/migrations/0004_userschoolrecord_created_at_and_more.py new file mode 100644 index 0000000..72164a8 --- /dev/null +++ b/trojstenid/schools/migrations/0004_userschoolrecord_created_at_and_more.py @@ -0,0 +1,36 @@ +# Generated by Django 5.2.16 on 2026-09-06 16:09 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ( + "trojstenid_schools", + "0003_alter_school_options_alter_schooltype_options_and_more", + ), + ] + + operations = [ + migrations.AddField( + model_name="userschoolrecord", + name="created_at", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name="userschoolrecord", + name="updated_at", + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name="userschoolrecord", + name="created_at", + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name="userschoolrecord", + name="updated_at", + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/trojstenid/schools/models.py b/trojstenid/schools/models.py index 6760cc4..b20fecc 100644 --- a/trojstenid/schools/models.py +++ b/trojstenid/schools/models.py @@ -109,6 +109,9 @@ class UserSchoolRecord(models.Model): start_year = models.PositiveIntegerField(default=0) end_date = models.DateField(blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + objects: ClassVar["UserSchoolRecordManager"] = UserSchoolRecordManager() class Meta: From 2c0f5901113a758471ff8e47b692a17efe630f9a Mon Sep 17 00:00:00 2001 From: Aiq0 <66842415+Aiq0@users.noreply.github.com> Date: Wed, 9 Sep 2026 11:05:43 +0200 Subject: [PATCH 3/4] feat: annual school record check --- trojstenid/app.css | 10 +++-- trojstenid/schools/models.py | 5 +++ .../templates/settings/school_list.html | 42 ++++++++++++++++--- trojstenid/schools/urls.py | 6 +++ trojstenid/schools/views.py | 18 ++++++++ 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/trojstenid/app.css b/trojstenid/app.css index 130dc6b..7d8f46b 100644 --- a/trojstenid/app.css +++ b/trojstenid/app.css @@ -37,15 +37,19 @@ } .btn-blue { - @apply bg-blue-500 hover:bg-blue-600 focus-visible:outline-blue-600; + @apply bg-blue-500 hover:bg-blue-600 focus-visible:outline-blue-600; } .btn-black { - @apply bg-gray-900 hover:bg-gray-800 focus-visible:outline-gray-800; + @apply bg-gray-900 hover:bg-gray-800 focus-visible:outline-gray-800; } .btn-red { - @apply bg-red-500 hover:bg-red-600 focus-visible:outline-red-600; + @apply bg-red-500 hover:bg-red-600 focus-visible:outline-red-600; +} + +.btn-green { + @apply bg-green-600 hover:bg-green-700 focus-visible:outline-green-700; } .link { diff --git a/trojstenid/schools/models.py b/trojstenid/schools/models.py index b20fecc..83b7e8a 100644 --- a/trojstenid/schools/models.py +++ b/trojstenid/schools/models.py @@ -146,6 +146,11 @@ def is_active(self): return False return True + def needs_confirmation(self): + return date_to_academic_year(self.updated_at) < date_to_academic_year( + timezone.now() + ) + def clean(self): if self.end_date and self.start_date >= self.end_date: raise ValidationError("Dátum nástupu musí byť skôr ako dátum ukončenia.") diff --git a/trojstenid/schools/templates/settings/school_list.html b/trojstenid/schools/templates/settings/school_list.html index b4e3ebf..cac118d 100644 --- a/trojstenid/schools/templates/settings/school_list.html +++ b/trojstenid/schools/templates/settings/school_list.html @@ -1,5 +1,4 @@ {% extends "settings_base.html" %} -{% load forms %} {% block title %}Školy - {{ block.super }}{% endblock %} @@ -7,9 +6,39 @@

Informácie o školách

-
- {% csrf_token %} + {% if current_school_record.needs_confirmation %} +
+

+ Skontroluj si prosím aktuálnosť údajov +

+

+ Podľa zadaných údajov navštevuješ tento školský rok + + {{ current_school_record.get_current_year_display }} + ({{ current_school_record.school_type.short }}) + + na škole {{ current_school_record.school }}. +

+

+ Je to správne? +

+
+ + + Zmeniť informácie o škole + + + {% csrf_token %} + + +
+
+ {% endif %} +
{% for record in object_list %}
@@ -37,7 +66,10 @@

Informácie o školách

Pre zmenu historických dát kontaktuj info@trojsten.sk.

- Zmeniť informácie o škole - + + + Zmeniť informácie o škole + +
{% endblock content %} diff --git a/trojstenid/schools/urls.py b/trojstenid/schools/urls.py index 03441da..61b5322 100644 --- a/trojstenid/schools/urls.py +++ b/trojstenid/schools/urls.py @@ -3,11 +3,17 @@ from trojstenid.schools.views import ( SchoolRecordCreateView, SchoolRecordListView, + SchoolRecordVerifyView, SchoolSearchView, ) urlpatterns = [ path("accounts/school/", SchoolRecordListView.as_view(), name="account_school"), + path( + "accounts/school/verify/", + SchoolRecordVerifyView.as_view(), + name="account_school_verify", + ), path( "accounts/school/create/", SchoolRecordCreateView.as_view(), diff --git a/trojstenid/schools/views.py b/trojstenid/schools/views.py index 5432991..40e5f8b 100644 --- a/trojstenid/schools/views.py +++ b/trojstenid/schools/views.py @@ -8,6 +8,7 @@ from django.urls import reverse from django.utils import timezone from django.utils.functional import cached_property +from django.views import View from django.views.generic import FormView, ListView, TemplateView from trojstenid.schools.forms import SchoolRecordForm @@ -23,6 +24,13 @@ def get_queryset(self) -> QuerySet[Any]: "school", "school_type" ) + def get_context_data(self, **kwargs: Any) -> dict[str, Any]: + assert isinstance(self.request.user, User) + + ctx = super().get_context_data(**kwargs) + ctx["current_school_record"] = self.request.user.get_current_school_record() + return ctx + class SchoolRecordCreateView(LoginRequiredMixin, FormView): template_name = "settings/school_create.html" @@ -87,6 +95,16 @@ def save_record(self, form: SchoolRecordForm, record: UserSchoolRecord): return HttpResponseRedirect(reverse("account_school")) +class SchoolRecordVerifyView(LoginRequiredMixin, View): + http_method_names = ["post"] + + def post(self, request): + record = request.user.get_current_school_record() + if record is not None: + record.save() + return HttpResponseRedirect(reverse("account_school")) + + class SchoolSearchView(LoginRequiredMixin, TemplateView): template_name = "settings/school_search.html" From 4c3cb517d8345ab7df0236041d5b9e59f60175a6 Mon Sep 17 00:00:00 2001 From: Aiq0 <66842415+Aiq0@users.noreply.github.com> Date: Wed, 9 Sep 2026 11:17:46 +0200 Subject: [PATCH 4/4] feat: include `updated_at` in school record --- trojstenid/schools/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trojstenid/schools/models.py b/trojstenid/schools/models.py index 83b7e8a..14b4cc5 100644 --- a/trojstenid/schools/models.py +++ b/trojstenid/schools/models.py @@ -180,4 +180,5 @@ def to_dict(self) -> dict[str, Any]: "current_year": self.get_current_year(), "current_year_display": self.get_current_year_display(), "school_type": self.school_type.identifier, + "updated_at": self.updated_at.isoformat(), }