From e99798ba5ce950fb4610fa11fd098207b83d0f0f Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 11:39:55 +0200
Subject: [PATCH 01/11] feat: Completely rework notification framework
This change is needed as
a) there are many different types of notifications. A notification about a new comment does not only relate the comment but also adoption notice and a user that made the comment. Therefore, I introduce a new general notification that has optional links to other objects.
b) this change allows to define a different representation of e-mails vs. display on the website. The new notification type is in charge of representation from now on. Title and text will be deprecated and eventually removed
---
src/fellchensammlung/admin.py | 6 +-
src/fellchensammlung/api/views.py | 16 ++---
src/fellchensammlung/mail.py | 37 ++++++++---
...2_remove_basenotification_user_and_more.py | 54 ++++++++++++++++
...r_notification_adoption_notice_and_more.py | 40 ++++++++++++
src/fellchensammlung/models.py | 63 ++++++++++++-------
src/fellchensammlung/receivers.py | 23 ++++---
.../mail/notifications/an-deactivated.html | 16 +++++
.../notifications/an-for-search-found.html | 16 +++++
.../mail/notifications/an-to-be-checked.html | 16 +++++
.../mail/notifications/new-comment.html | 19 ++++++
.../mail/notifications/new-user.html | 19 ++++++
.../mail/{ => notifications}/report.html | 4 +-
src/fellchensammlung/tools/admin.py | 11 ++--
src/fellchensammlung/tools/notifications.py | 13 ++--
src/fellchensammlung/tools/search.py | 12 ++--
src/fellchensammlung/views.py | 37 ++++++-----
src/tests/test_models.py | 8 +--
18 files changed, 317 insertions(+), 93 deletions(-)
create mode 100644 src/fellchensammlung/migrations/0052_remove_basenotification_user_and_more.py
create mode 100644 src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
create mode 100644 src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
create mode 100644 src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
create mode 100644 src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
create mode 100644 src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
create mode 100644 src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-user.html
rename src/fellchensammlung/templates/fellchensammlung/mail/{ => notifications}/report.html (86%)
diff --git a/src/fellchensammlung/admin.py b/src/fellchensammlung/admin.py
index 0553052..827968d 100644
--- a/src/fellchensammlung/admin.py
+++ b/src/fellchensammlung/admin.py
@@ -11,7 +11,7 @@ from .models import User, Language, Text, ReportComment, ReportAdoptionNotice, L
SpeciesSpecificURL, ImportantLocation, SpeciesSpecialization
from .models import Animal, Species, RescueOrganization, AdoptionNotice, Location, Rule, Image, ModerationAction, \
- Comment, Report, Announcement, AdoptionNoticeStatus, User, Subscriptions, BaseNotification
+ Comment, Report, Announcement, AdoptionNoticeStatus, User, Subscriptions, Notification
from django.utils.translation import gettext_lazy as _
@@ -127,9 +127,9 @@ class CommentAdmin(admin.ModelAdmin):
list_filter = ("user",)
-@admin.register(BaseNotification)
+@admin.register(Notification)
class BaseNotificationAdmin(admin.ModelAdmin):
- list_filter = ("user", "read")
+ list_filter = ("user_to_notify", "read")
@admin.register(SearchSubscription)
diff --git a/src/fellchensammlung/api/views.py b/src/fellchensammlung/api/views.py
index 3e0bfb2..29e9bd7 100644
--- a/src/fellchensammlung/api/views.py
+++ b/src/fellchensammlung/api/views.py
@@ -66,22 +66,22 @@ class AdoptionNoticeApiView(APIView):
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- adoption_notice = serializer.save(owner=request.user)
+ adoption_notice = serializer.save(owner=request.user_to_notify)
# Add the location
post_adoption_notice_save.delay_on_commit(adoption_notice.pk)
# Only set active when user has trust level moderator or higher
- if request.user.trust_level >= TrustLevel.MODERATOR:
+ if request.user_to_notify.trust_level >= TrustLevel.MODERATOR:
adoption_notice.set_active()
else:
adoption_notice.set_unchecked()
# Log the action
Log.objects.create(
- user=request.user,
+ user=request.user_to_notify,
action="add_adoption_notice",
- text=f"{request.user} added adoption notice {adoption_notice.pk} via API",
+ text=f"{request.user_to_notify} added adoption notice {adoption_notice.pk} via API",
)
# Return success response with new adoption notice details
@@ -130,7 +130,7 @@ class AnimalApiView(APIView):
"""
serializer = AnimalCreateSerializer(data=request.data, context={"request": request})
if serializer.is_valid():
- animal = serializer.save(owner=request.user)
+ animal = serializer.save(owner=request.user_to_notify)
return Response(
{"message": "Animal created successfully!", "id": animal.id},
status=status.HTTP_201_CREATED,
@@ -289,7 +289,7 @@ class AddImageApiView(APIView):
raise ValueError("Unknown attach_to_type given, should not happen. Check serializer")
serializer.validated_data.pop('attach_to_type', None)
serializer.validated_data.pop('attach_to', None)
- image = serializer.save(owner=request.user)
+ image = serializer.save(owner=request.user_to_notify)
object_to_attach_to.photos.add(image)
return Response(
{"message": "Image added successfully!", "id": image.id},
@@ -360,9 +360,9 @@ class LocationApiView(APIView):
# Log the action
Log.objects.create(
- user=request.user,
+ user=request.user_to_notify,
action="add_location",
- text=f"{request.user} added adoption notice {location.pk} via API",
+ text=f"{request.user_to_notify} added adoption notice {location.pk} via API",
)
# Return success response with new adoption notice details
diff --git a/src/fellchensammlung/mail.py b/src/fellchensammlung/mail.py
index 126c4bb..e376fac 100644
--- a/src/fellchensammlung/mail.py
+++ b/src/fellchensammlung/mail.py
@@ -6,7 +6,7 @@ from django.utils.html import strip_tags
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from django.core import mail
-from fellchensammlung.models import User, CommentNotification, BaseNotification, TrustLevel
+from fellchensammlung.models import User, Notification, TrustLevel, NotificationTypeChoices
from notfellchen.settings import host
NEWLINE = "\r\n"
@@ -19,10 +19,10 @@ def mail_admins_new_report(report):
for moderator in User.objects.filter(trust_level__gt=TrustLevel.MODERATOR):
report_url = "https://" + host + report.get_absolute_url()
context = {"report_url": report_url,
- "user_comment": report.user_comment,}
+ "user_comment": report.user_comment, }
subject = _("Neue Meldung")
- html_message = render_to_string('fellchensammlung/mail/report.html', context)
+ html_message = render_to_string('fellchensammlung/mail/notifications/report.html', context)
plain_message = strip_tags(html_message)
mail.send_mail(subject,
@@ -33,11 +33,28 @@ def mail_admins_new_report(report):
def send_notification_email(notification_pk):
- try:
- notification = CommentNotification.objects.get(pk=notification_pk)
- except CommentNotification.DoesNotExist:
- notification = BaseNotification.objects.get(pk=notification_pk)
+ notification = Notification.objects.get(pk=notification_pk)
+
subject = f"🔔 {notification.title}"
- body_text = notification.text
- message = mail.EmailMessage(subject, body_text, settings.DEFAULT_FROM_EMAIL, [notification.user.email])
- message.send()
+ context = {"notification": notification, }
+ if notification.notification_type == NotificationTypeChoices.NEW_REPORT_COMMENT or notification.notification_type == NotificationTypeChoices.NEW_REPORT_AN:
+ context["user_comment"] = notification.report.user_comment
+ context["report_url"] = notification.report.get_absolute_url()
+ html_message = render_to_string('fellchensammlung/mail/notifications/report.html', context)
+ elif notification.notification_type == NotificationTypeChoices.NEW_USER:
+ html_message = render_to_string('fellchensammlung/mail/notifications/new-user.html', context)
+ elif notification.notification_type == NotificationTypeChoices.AN_IS_TO_BE_CHECKED:
+ html_message = render_to_string('fellchensammlung/mail/notifications/an-to-be-checked.html', context)
+ elif notification.notification_type == NotificationTypeChoices.AN_WAS_DEACTIVATED:
+ html_message = render_to_string('fellchensammlung/mail/notifications/an-deactivated.html', context)
+ elif notification.notification_type == NotificationTypeChoices.AN_FOR_SEARCH_FOUND:
+ html_message = render_to_string('fellchensammlung/mail/notifications/report.html', context)
+ elif notification.notification_type == NotificationTypeChoices.NEW_COMMENT:
+ html_message = render_to_string('fellchensammlung/mail/notifications/new-comment.html', context)
+ else:
+ raise NotImplementedError("Unknown notification type")
+
+ plain_message = strip_tags(html_message)
+ mail.send_mail(subject, plain_message, settings.DEFAULT_FROM_EMAIL,
+ [notification.user_to_notify.email],
+ html_message=html_message)
diff --git a/src/fellchensammlung/migrations/0052_remove_basenotification_user_and_more.py b/src/fellchensammlung/migrations/0052_remove_basenotification_user_and_more.py
new file mode 100644
index 0000000..13b580c
--- /dev/null
+++ b/src/fellchensammlung/migrations/0052_remove_basenotification_user_and_more.py
@@ -0,0 +1,54 @@
+# Generated by Django 5.2.1 on 2025-07-11 09:01
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('fellchensammlung', '0051_rescueorganization_parent_org_speciesspecialization'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='basenotification',
+ name='user',
+ ),
+ migrations.RemoveField(
+ model_name='commentnotification',
+ name='basenotification_ptr',
+ ),
+ migrations.RemoveField(
+ model_name='commentnotification',
+ name='comment',
+ ),
+ migrations.CreateModel(
+ name='Notification',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('updated_at', models.DateTimeField(auto_now=True)),
+ ('read_at', models.DateTimeField(blank=True, null=True, verbose_name='Gelesen am')),
+ ('notification_type', models.CharField(choices=[('new_user', 'Useraccount wurde erstellt'), ('new_report_an', 'Vermittlung wurde gemeldet'), ('new_report_comment', 'Kommentar wurde gemeldet'), ('an_is_to_be_checked', 'Vermittlung muss überprüft werden'), ('an_was_deactivated', 'Vermittlung wurde deaktiviert'), ('an_for_search_found', 'Vermittlung für Suche gefunden')], max_length=200, verbose_name='Benachrichtigungsgrund')),
+ ('title', models.CharField(max_length=100, verbose_name='Titel')),
+ ('text', models.TextField(verbose_name='Inhalt')),
+ ('read', models.BooleanField(default=False)),
+ ('adoption_notice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.adoptionnotice', verbose_name='Vermittlung')),
+ ('comment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.comment', verbose_name='Antwort')),
+ ('report', models.ForeignKey(help_text='Report auf den sich die Benachrichtigung bezieht.', on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.report', verbose_name='Report')),
+ ('user_related', models.ForeignKey(help_text='Useraccount auf den sich die Benachrichtigung bezieht.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Verwandter Useraccount')),
+ ('user_to_notify', models.ForeignKey(help_text='Useraccount der Benachrichtigt wird', on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL, verbose_name='Nutzer*in')),
+ ],
+ ),
+ migrations.DeleteModel(
+ name='AdoptionNoticeNotification',
+ ),
+ migrations.DeleteModel(
+ name='BaseNotification',
+ ),
+ migrations.DeleteModel(
+ name='CommentNotification',
+ ),
+ ]
diff --git a/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py b/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
new file mode 100644
index 0000000..6534fcc
--- /dev/null
+++ b/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
@@ -0,0 +1,40 @@
+# Generated by Django 5.2.1 on 2025-07-11 09:10
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('fellchensammlung', '0052_remove_basenotification_user_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='notification',
+ name='adoption_notice',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.adoptionnotice', verbose_name='Vermittlung'),
+ ),
+ migrations.AlterField(
+ model_name='notification',
+ name='notification_type',
+ field=models.CharField(choices=[('new_user', 'Useraccount wurde erstellt'), ('new_report_an', 'Vermittlung wurde gemeldet'), ('new_report_comment', 'Kommentar wurde gemeldet'), ('an_is_to_be_checked', 'Vermittlung muss überprüft werden'), ('an_was_deactivated', 'Vermittlung wurde deaktiviert'), ('an_for_search_found', 'Vermittlung für Suche gefunden'), ('new_comment', 'Neuer Kommentar')], max_length=200, verbose_name='Benachrichtigungsgrund'),
+ ),
+ migrations.AlterField(
+ model_name='notification',
+ name='report',
+ field=models.ForeignKey(blank=True, help_text='Report auf den sich die Benachrichtigung bezieht.', null=True, on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.report', verbose_name='Report'),
+ ),
+ migrations.AlterField(
+ model_name='notification',
+ name='user_related',
+ field=models.ForeignKey(blank=True, help_text='Useraccount auf den sich die Benachrichtigung bezieht.', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Verwandter Useraccount'),
+ ),
+ migrations.AlterField(
+ model_name='notification',
+ name='user_to_notify',
+ field=models.ForeignKey(blank=True, help_text='Useraccount der Benachrichtigt wird', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL, verbose_name='Nutzer*in'),
+ ),
+ ]
diff --git a/src/fellchensammlung/models.py b/src/fellchensammlung/models.py
index 07e8c18..b2d60b0 100644
--- a/src/fellchensammlung/models.py
+++ b/src/fellchensammlung/models.py
@@ -256,10 +256,10 @@ class User(AbstractUser):
return self.get_absolute_url()
def get_unread_notifications(self):
- return BaseNotification.objects.filter(user=self, read=False)
+ return Notification.objects.filter(user=self, read=False)
def get_num_unread_notifications(self):
- return BaseNotification.objects.filter(user=self, read=False).count()
+ return Notification.objects.filter(user=self, read=False).count()
@property
def adoption_notices(self):
@@ -479,7 +479,11 @@ class AdoptionNotice(models.Model):
for subscription in self.get_subscriptions():
notification_title = _("Vermittlung deaktiviert:") + f" {self.name}"
text = _("Die folgende Vermittlung wurde deaktiviert: ") + f"[{self.name}]({self.get_absolute_url()})"
- BaseNotification.objects.create(user=subscription.owner, text=text, title=notification_title)
+ Notification.objects.create(user_to_notify=subscription.owner,
+ notification_type=NotificationTypeChoices.AN_WAS_DEACTIVATED,
+ adoption_notice=self,
+ text=text,
+ title=notification_title)
class AdoptionNoticeStatus(models.Model):
@@ -902,20 +906,49 @@ class Comment(models.Model):
return self.adoption_notice.get_absolute_url()
-class BaseNotification(models.Model):
+class NotificationTypeChoices(models.TextChoices):
+ NEW_USER = "new_user", _("Useraccount wurde erstellt")
+ NEW_REPORT_AN = "new_report_an", _("Vermittlung wurde gemeldet")
+ NEW_REPORT_COMMENT = "new_report_comment", _("Kommentar wurde gemeldet")
+ AN_IS_TO_BE_CHECKED = "an_is_to_be_checked", _("Vermittlung muss überprüft werden")
+ AN_WAS_DEACTIVATED = "an_was_deactivated", _("Vermittlung wurde deaktiviert")
+ AN_FOR_SEARCH_FOUND = "an_for_search_found", _("Vermittlung für Suche gefunden")
+ NEW_COMMENT = "new_comment", _("Neuer Kommentar")
+
+
+class Notification(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
read_at = models.DateTimeField(blank=True, null=True, verbose_name=_("Gelesen am"))
+ notification_type = models.CharField(max_length=200,
+ choices=NotificationTypeChoices.choices,
+ verbose_name=_('Benachrichtigungsgrund'))
title = models.CharField(max_length=100, verbose_name=_("Titel"))
text = models.TextField(verbose_name="Inhalt")
- user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Nutzer*in'))
+ user_to_notify = models.ForeignKey(User,
+ on_delete=models.CASCADE,
+ blank=True, null=True,
+ verbose_name=_('Nutzer*in'),
+ help_text=_("Useraccount der Benachrichtigt wird"),
+ related_name='user')
read = models.BooleanField(default=False)
+ comment = models.ForeignKey(Comment, blank=True, null=True, on_delete=models.CASCADE, verbose_name=_('Antwort'))
+ adoption_notice = models.ForeignKey(AdoptionNotice, blank=True, null=True, on_delete=models.CASCADE, verbose_name=_('Vermittlung'))
+ user_related = models.ForeignKey(User,
+ blank=True, null=True,
+ on_delete=models.CASCADE, verbose_name=_('Verwandter Useraccount'),
+ help_text=_("Useraccount auf den sich die Benachrichtigung bezieht."))
+ report = models.ForeignKey(Report,
+ blank=True, null=True,
+ on_delete=models.CASCADE,
+ verbose_name=_('Report'),
+ help_text=_("Report auf den sich die Benachrichtigung bezieht."))
def __str__(self):
- return f"[{self.user}] {self.title} ({self.created_at})"
+ return f"[{self.user_to_notify}] {self.title} ({self.created_at})"
def get_absolute_url(self):
- self.user.get_notifications_url()
+ self.user_to_notify.get_notifications_url()
def mark_read(self):
self.read = True
@@ -923,22 +956,6 @@ class BaseNotification(models.Model):
self.save()
-class CommentNotification(BaseNotification):
- comment = models.ForeignKey(Comment, on_delete=models.CASCADE, verbose_name=_('Antwort'))
-
- @property
- def url(self):
- return self.comment.get_absolute_url
-
-
-class AdoptionNoticeNotification(BaseNotification):
- adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE, verbose_name=_('Vermittlung'))
-
- @property
- def url(self):
- return self.adoption_notice.get_absolute_url
-
-
class Subscriptions(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('Nutzer*in'))
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE, verbose_name=_('AdoptionNotice'))
diff --git a/src/fellchensammlung/receivers.py b/src/fellchensammlung/receivers.py
index ba61a73..db5e426 100644
--- a/src/fellchensammlung/receivers.py
+++ b/src/fellchensammlung/receivers.py
@@ -1,23 +1,22 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
-from fellchensammlung.models import BaseNotification, CommentNotification, User, TrustLevel, RescueOrganization
+from fellchensammlung.models import Notification, User, TrustLevel, RescueOrganization, \
+ NotificationTypeChoices
from .tasks import task_send_notification_email
from notfellchen.settings import host
from django.utils.translation import gettext_lazy as _
-@receiver(post_save, sender=CommentNotification)
-def comment_notification_receiver(sender, instance: BaseNotification, created: bool, **kwargs):
- base_notification_receiver(sender, instance, created, **kwargs)
-
-
-@receiver(post_save, sender=BaseNotification)
-def base_notification_receiver(sender, instance: BaseNotification, created: bool, **kwargs):
- if not created or not instance.user.email_notifications:
+@receiver(post_save, sender=Notification)
+def base_notification_receiver(sender, instance: Notification, created: bool, **kwargs):
+ print("Dada")
+ if not created or not instance.user_to_notify.email_notifications:
return
else:
+ print("Dodo")
task_send_notification_email.delay(instance.pk)
+
@receiver(post_save, sender=RescueOrganization)
def rescue_org_receiver(sender, instance: RescueOrganization, created: bool, **kwargs):
if instance.location:
@@ -40,5 +39,9 @@ def notification_new_user(sender, instance: User, created: bool, **kwargs):
link_text = f"Um alle Details zu sehen, geh bitte auf: {user_url}"
body_text = new_user_text + user_detail_text + link_text
for moderator in User.objects.filter(trust_level__gt=TrustLevel.MODERATOR):
- notification = BaseNotification.objects.create(title=subject, text=body_text, user=moderator)
+ notification = Notification.objects.create(title=subject,
+ text=body_text,
+ notification_type=NotificationTypeChoices.NEW_USER,
+ user_to_notify=moderator,
+ user_related=instance)
notification.save()
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
new file mode 100644
index 0000000..9ec7f28
--- /dev/null
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
@@ -0,0 +1,16 @@
+{% extends "fellchensammlung/mail/base.html" %}
+{% load i18n %}
+{% block title %}
+ {% translate 'Vermittlung wurde deaktiviert' %}
+{% endblock %}
+
+{% block content %}
+ Moin,
+
+ die Vermittlung {{ notification.adoption_notice }} wurde deaktiviert.
+
+
+
+ {% translate 'Vermittlung anzeigen' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
new file mode 100644
index 0000000..05517f4
--- /dev/null
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
@@ -0,0 +1,16 @@
+{% extends "fellchensammlung/mail/base.html" %}
+{% load i18n %}
+{% block title %}
+ {% translate 'Neue Vermittlung gefunden' %}
+{% endblock %}
+
+{% block content %}
+ Moin,
+
+ es wurde eine neue Vermittlung gefunden die deinen Kriterien entspricht: {{ notification.adoption_notice }}
+
+
+
+ {% translate 'Vermittlung anzeigen' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
new file mode 100644
index 0000000..7c4b8a0
--- /dev/null
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
@@ -0,0 +1,16 @@
+{% extends "fellchensammlung/mail/base.html" %}
+{% load i18n %}
+{% block title %}
+ {% translate 'Vermittlung muss überprüft werden' %}
+{% endblock %}
+
+{% block content %}
+ Moin,
+
+ die Vermittlung {{ notification.adoption_notice }} muss überprüft werden.
+
+
+
+ {% translate 'Vermittlung anzeigen' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
new file mode 100644
index 0000000..708b374
--- /dev/null
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
@@ -0,0 +1,19 @@
+{% extends "fellchensammlung/mail/base.html" %}
+{% load i18n %}
+{% load custom_tags %}
+{% block title %}
+ {% translate 'Vermittlung muss überprüft werden' %}
+{% endblock %}
+
+{% block content %}
+ Moin,
+
+ folgender Kommentar wurde zur Vermittlung {{ notification.adoption_notice }} hinzugefügt:
+
+
+ {{ notification.comment.text | render_markdown }}
+
+
+ {% translate 'Vermittlung anzeigen' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-user.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-user.html
new file mode 100644
index 0000000..3bffbac
--- /dev/null
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-user.html
@@ -0,0 +1,19 @@
+{% extends "fellchensammlung/mail/base.html" %}
+{% load i18n %}
+{% block title %}
+ {% translate 'Neuer User' %}
+{% endblock %}
+
+{% block content %}
+ Moin,
+
+ es wurde ein neuer Useraccount erstellt.
+
+
+
+ Details findest du hier
+
+
+ {% translate 'User anzeigen' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/report.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/report.html
similarity index 86%
rename from src/fellchensammlung/templates/fellchensammlung/mail/report.html
rename to src/fellchensammlung/templates/fellchensammlung/mail/notifications/report.html
index f9cdd14..8bfc26b 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/report.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/report.html
@@ -7,7 +7,7 @@
{% block content %}
Moin,
- es gibt eine neue Meldung. Folgende Nachricht wurde zur Meldung hinzugefügt.
+ es gibt eine neue Meldung. Folgende Nachricht wurde zur Meldung hinzugefügt:
@@ -17,7 +17,7 @@
- Bitte bearbeite die Meldung möglichst bald
+ Bitte bearbeite die Meldung möglichst bald.
{% translate 'Report bearbeiten' %}
diff --git a/src/fellchensammlung/tools/admin.py b/src/fellchensammlung/tools/admin.py
index 7f37cef..11b890a 100644
--- a/src/fellchensammlung/tools/admin.py
+++ b/src/fellchensammlung/tools/admin.py
@@ -10,7 +10,7 @@ from django.core import mail
from django.utils.html import strip_tags
from fellchensammlung.models import AdoptionNotice, Location, RescueOrganization, AdoptionNoticeStatus, Log, \
- AdoptionNoticeNotification
+ Notification, NotificationTypeChoices
from fellchensammlung.tools.misc import is_404
@@ -92,10 +92,11 @@ def deactivate_404_adoption_notices():
deactivation_message = f'Die Vermittlung [{adoption_notice.name}]({adoption_notice.get_absolute_url()}) wurde automatisch deaktiviert, da die Website unter "Mehr Informationen" nicht mehr online ist.'
for subscription in adoption_notice.get_subscriptions():
- AdoptionNoticeNotification.objects.create(user=subscription.owner,
- title="Vermittlung deaktiviert",
- adoption_notice=adoption_notice,
- text=deactivation_message)
+ Notification.objects.create(user_to_notify=subscription.owner,
+ notification_type=NotificationTypeChoices.AN_WAS_DEACTIVATED,
+ title="Vermittlung deaktiviert",
+ adoption_notice=adoption_notice,
+ text=deactivation_message)
def dedup_location(location: Location, destructive=False):
diff --git a/src/fellchensammlung/tools/notifications.py b/src/fellchensammlung/tools/notifications.py
index 63fd1f0..3430d0d 100644
--- a/src/fellchensammlung/tools/notifications.py
+++ b/src/fellchensammlung/tools/notifications.py
@@ -1,4 +1,4 @@
-from fellchensammlung.models import User, AdoptionNoticeNotification, TrustLevel
+from fellchensammlung.models import User, Notification, TrustLevel, NotificationTypeChoices
def notify_of_AN_to_be_checked(adoption_notice):
@@ -6,8 +6,9 @@ def notify_of_AN_to_be_checked(adoption_notice):
users_to_notify = set(User.objects.filter(trust_level__gt=TrustLevel.MODERATOR))
users_to_notify.add(adoption_notice.owner)
for user in users_to_notify:
- AdoptionNoticeNotification.objects.create(adoption_notice=adoption_notice,
- user=user,
- title=f" Prüfe Vermittlung {adoption_notice}",
- text=f"{adoption_notice} muss geprüft werden bevor sie veröffentlicht wird.",
- )
\ No newline at end of file
+ Notification.objects.create(adoption_notice=adoption_notice,
+ user_to_notify=user,
+ notification_type=NotificationTypeChoices.AN_IS_TO_BE_CHECKED,
+ title=f" Prüfe Vermittlung {adoption_notice}",
+ text=f"{adoption_notice} muss geprüft werden bevor sie veröffentlicht wird.",
+ )
diff --git a/src/fellchensammlung/tools/search.py b/src/fellchensammlung/tools/search.py
index 49237da..ad36b4c 100644
--- a/src/fellchensammlung/tools/search.py
+++ b/src/fellchensammlung/tools/search.py
@@ -3,7 +3,8 @@ from django.utils.translation import gettext_lazy as _
from .geo import LocationProxy, Position
from ..forms import AdoptionNoticeSearchForm
-from ..models import SearchSubscription, AdoptionNotice, AdoptionNoticeNotification, SexChoicesWithAll, Location
+from ..models import SearchSubscription, AdoptionNotice, SexChoicesWithAll, Location, \
+ Notification, NotificationTypeChoices
def notify_search_subscribers(adoption_notice: AdoptionNotice, only_if_active: bool = True):
@@ -20,10 +21,11 @@ def notify_search_subscribers(adoption_notice: AdoptionNotice, only_if_active: b
search = Search(search_subscription=search_subscription)
if search.adoption_notice_fits_search(adoption_notice):
notification_text = f"{_('Zu deiner Suche')} {search_subscription} wurde eine neue Vermittlung gefunden"
- AdoptionNoticeNotification.objects.create(user=search_subscription.owner,
- title=f"{_('Neue Vermittlung')}: {adoption_notice}",
- adoption_notice=adoption_notice,
- text=notification_text)
+ Notification.objects.create(user_to_notify=search_subscription.owner,
+ notification_type=NotificationTypeChoices.AN_FOR_SEARCH_FOUND,
+ title=f"{_('Neue Vermittlung')}: {adoption_notice}",
+ adoption_notice=adoption_notice,
+ text=notification_text)
logging.debug(f"Notification for search subscription {search_subscription} was sent.")
else:
logging.debug(f"Adoption notice {adoption_notice} was not fitting the search subscription.")
diff --git a/src/fellchensammlung/views.py b/src/fellchensammlung/views.py
index 9b69c78..f368824 100644
--- a/src/fellchensammlung/views.py
+++ b/src/fellchensammlung/views.py
@@ -20,9 +20,9 @@ from notfellchen import settings
from fellchensammlung import logger
from .models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \
- User, Location, AdoptionNoticeStatus, Subscriptions, CommentNotification, BaseNotification, RescueOrganization, \
- Species, Log, Timestamp, TrustLevel, SexChoicesWithAll, SearchSubscription, AdoptionNoticeNotification, \
- ImportantLocation, SpeciesSpecificURL
+ User, Location, AdoptionNoticeStatus, Subscriptions, Notification, RescueOrganization, \
+ Species, Log, Timestamp, TrustLevel, SexChoicesWithAll, SearchSubscription, \
+ ImportantLocation, SpeciesSpecificURL, NotificationTypeChoices
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, \
CommentForm, ReportCommentForm, AnimalForm, AdoptionNoticeFormAutoAnimal, SpeciesURLForm, RescueOrgInternalComment
from .models import Language, Announcement
@@ -121,10 +121,12 @@ def adoption_notice_detail(request, adoption_notice_id):
for subscription in adoption_notice.get_subscriptions():
# Create a notification but only if the user is not the one that posted the comment
if subscription.owner != request.user:
- notification = CommentNotification(user=subscription.owner,
- title=f"{adoption_notice.name} - Neuer Kommentar",
- text=f"{request.user}: {comment_instance.text}",
- comment=comment_instance)
+ notification = Notification(user_to_notify=subscription.owner,
+ adoption_notice=adoption_notice,
+ notification_type=NotificationTypeChoices.NEW_COMMENT,
+ title=f"{adoption_notice.name} - Neuer Kommentar",
+ text=f"{request.user}: {comment_instance.text}",
+ comment=comment_instance)
notification.save()
else:
comment_form = CommentForm(instance=adoption_notice)
@@ -177,7 +179,8 @@ def search_important_locations(request, important_location_slug):
search.search_from_predefined_i_location(i_location)
site_title = _("Ratten in %(location_name)s") % {"location_name": i_location.name}
- site_description = _("Ratten in Tierheimen und Rattenhilfen in der Nähe von %(location_name)s suchen.") % {"location_name": i_location.name}
+ site_description = _("Ratten in Tierheimen und Rattenhilfen in der Nähe von %(location_name)s suchen.") % {
+ "location_name": i_location.name}
canonical_url = reverse("search-by-location", args=[i_location.slug])
context = {"adoption_notices": search.get_adoption_notices(),
@@ -528,7 +531,7 @@ def report_detail_success(request, report_id):
def user_detail(request, user, token=None):
context = {"user": user,
"adoption_notices": AdoptionNotice.objects.filter(owner=user),
- "notifications": BaseNotification.objects.filter(user=user, read=False),
+ "notifications": Notification.objects.filter(user_to_notify=user, read=False),
"search_subscriptions": SearchSubscription.objects.filter(owner=user), }
if token is not None:
context["token"] = token
@@ -561,13 +564,11 @@ def my_profile(request):
action = request.POST.get("action")
if action == "notification_mark_read":
notification_id = request.POST.get("notification_id")
- try:
- notification = CommentNotification.objects.get(pk=notification_id)
- except CommentNotification.DoesNotExist:
- notification = BaseNotification.objects.get(pk=notification_id)
+
+ notification = Notification.objects.get(pk=notification_id)
notification.mark_read()
elif action == "notification_mark_all_read":
- notifications = CommentNotification.objects.filter(user=request.user, mark_read=False)
+ notifications = Notification.objects.filter(user=request.user, mark_read=False)
for notification in notifications:
notification.mark_read()
elif action == "search_subscription_delete":
@@ -770,11 +771,13 @@ def rescue_organization_check(request, context=None):
}
rescue_orgs_last_checked = RescueOrganization.objects.filter().order_by("-last_checked")[:10]
timeframe = timezone.now().date() - timedelta(days=14)
- num_rescue_orgs_to_check = RescueOrganization.objects.filter(exclude_from_check=False).filter(last_checked__lt=timeframe).count()
- num_rescue_orgs_checked = RescueOrganization.objects.filter(exclude_from_check=False).filter(last_checked__gte=timeframe).count()
+ num_rescue_orgs_to_check = RescueOrganization.objects.filter(exclude_from_check=False).filter(
+ last_checked__lt=timeframe).count()
+ num_rescue_orgs_checked = RescueOrganization.objects.filter(exclude_from_check=False).filter(
+ last_checked__gte=timeframe).count()
try:
- percentage_checked = 100*num_rescue_orgs_checked/(num_rescue_orgs_to_check+num_rescue_orgs_checked)
+ percentage_checked = 100 * num_rescue_orgs_checked / (num_rescue_orgs_to_check + num_rescue_orgs_checked)
except ZeroDivisionError:
percentage_checked = 100
diff --git a/src/tests/test_models.py b/src/tests/test_models.py
index 9aff0fe..68882af 100644
--- a/src/tests/test_models.py
+++ b/src/tests/test_models.py
@@ -4,7 +4,7 @@ from django.utils import timezone
from django.test import TestCase
from model_bakery import baker
-from fellchensammlung.models import Announcement, Language, User, TrustLevel, BaseNotification
+from fellchensammlung.models import Announcement, Language, User, TrustLevel, Notification
class UserTest(TestCase):
@@ -85,9 +85,9 @@ class TestNotifications(TestCase):
cls.test_user_1 = User.objects.create(username="Testuser1", password="SUPERSECRET", email="test@example.org")
def test_mark_read(self):
- not1 = BaseNotification.objects.create(user=self.test_user_1, text="New rats to adopt", title="🔔 New Rat alert")
- not2 = BaseNotification.objects.create(user=self.test_user_1,
- text="New wombat to adopt", title="🔔 New Wombat alert")
+ not1 = Notification.objects.create(user=self.test_user_1, text="New rats to adopt", title="🔔 New Rat alert")
+ not2 = Notification.objects.create(user=self.test_user_1,
+ text="New wombat to adopt", title="🔔 New Wombat alert")
not1.mark_read()
self.assertTrue(not1.read)
From 8a691d59e745271aafc871d89b4b1d86ccd26288 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 16:53:01 +0200
Subject: [PATCH 02/11] feat: add base url in order to properly do URLs in
e-mails
---
src/fellchensammlung/mail.py | 6 +++---
src/notfellchen/settings.py | 4 ++++
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/fellchensammlung/mail.py b/src/fellchensammlung/mail.py
index e376fac..94c0c46 100644
--- a/src/fellchensammlung/mail.py
+++ b/src/fellchensammlung/mail.py
@@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from django.conf import settings
from django.core import mail
from fellchensammlung.models import User, Notification, TrustLevel, NotificationTypeChoices
-from notfellchen.settings import host
+from notfellchen.settings import base_url
NEWLINE = "\r\n"
@@ -17,7 +17,7 @@ def mail_admins_new_report(report):
Sends an e-mail to all users that should handle the report.
"""
for moderator in User.objects.filter(trust_level__gt=TrustLevel.MODERATOR):
- report_url = "https://" + host + report.get_absolute_url()
+ report_url = base_url + report.get_absolute_url()
context = {"report_url": report_url,
"user_comment": report.user_comment, }
@@ -39,7 +39,7 @@ def send_notification_email(notification_pk):
context = {"notification": notification, }
if notification.notification_type == NotificationTypeChoices.NEW_REPORT_COMMENT or notification.notification_type == NotificationTypeChoices.NEW_REPORT_AN:
context["user_comment"] = notification.report.user_comment
- context["report_url"] = notification.report.get_absolute_url()
+ context["report_url"] = f"{base_url}{notification.report.get_absolute_url()}"
html_message = render_to_string('fellchensammlung/mail/notifications/report.html', context)
elif notification.notification_type == NotificationTypeChoices.NEW_USER:
html_message = render_to_string('fellchensammlung/mail/notifications/new-user.html', context)
diff --git a/src/notfellchen/settings.py b/src/notfellchen/settings.py
index d283cd7..df3d12e 100644
--- a/src/notfellchen/settings.py
+++ b/src/notfellchen/settings.py
@@ -145,6 +145,10 @@ MEDIA_URL = config.get("urls", "media", fallback="/media/")
# Take all three into account when modifying
host = config.get("notfellchen", "host", fallback='*')
+# The base URL will be used to build URLS
+# See https://forum.djangoproject.com/t/putting-full-url-link-on-email-how-to-get-current-domain-name-to-put-on-url/13806/3
+base_url = config.get("notfellchen", "base_url", fallback=f"https://{host}")
+
# see https://docs.djangoproject.com/en/3.2/ref/settings/#std-setting-ALLOWED_HOSTS
ALLOWED_HOSTS = [host]
CSRF_TRUSTED_ORIGINS = [f"https://{host}"]
From 5bc4b538e65e368683ecc2acd8152ce67c61b564 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 17:33:58 +0200
Subject: [PATCH 03/11] refactor: formatting
---
src/fellchensammlung/tasks.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/fellchensammlung/tasks.py b/src/fellchensammlung/tasks.py
index 016abc0..a5b179c 100644
--- a/src/fellchensammlung/tasks.py
+++ b/src/fellchensammlung/tasks.py
@@ -48,6 +48,7 @@ def post_adoption_notice_save(pk):
notify_search_subscribers(instance, only_if_active=True)
notify_of_AN_to_be_checked(instance)
+
@celery_app.task(name="tools.healthcheck")
def task_healthcheck():
healthcheck_ok()
@@ -58,9 +59,10 @@ def task_healthcheck():
def task_send_notification_email(notification_pk):
send_notification_email(notification_pk)
+
@celery_app.task(name="commit.post_rescue_org_save")
def post_rescue_org_save(pk):
instance = RescueOrganization.objects.get(pk=pk)
Location.add_location_to_object(instance)
set_timestamp("add_rescue_org_location")
- logging.info(f"Location was added to Rescue Organization {pk}")
\ No newline at end of file
+ logging.info(f"Location was added to Rescue Organization {pk}")
From 554de17e9e7a9139d01499bc58ad408d61898294 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 17:34:18 +0200
Subject: [PATCH 04/11] fix: Add missing migration
---
.../0054_alter_notification_comment.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 src/fellchensammlung/migrations/0054_alter_notification_comment.py
diff --git a/src/fellchensammlung/migrations/0054_alter_notification_comment.py b/src/fellchensammlung/migrations/0054_alter_notification_comment.py
new file mode 100644
index 0000000..6806812
--- /dev/null
+++ b/src/fellchensammlung/migrations/0054_alter_notification_comment.py
@@ -0,0 +1,19 @@
+# Generated by Django 5.2.1 on 2025-07-11 11:47
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('fellchensammlung', '0053_alter_notification_adoption_notice_and_more'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='notification',
+ name='comment',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.comment', verbose_name='Antwort'),
+ ),
+ ]
From ba64661217ea79397066691be8617b8de408dab3 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 17:34:39 +0200
Subject: [PATCH 05/11] refactor: remove prints
---
src/fellchensammlung/receivers.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/fellchensammlung/receivers.py b/src/fellchensammlung/receivers.py
index db5e426..17927e9 100644
--- a/src/fellchensammlung/receivers.py
+++ b/src/fellchensammlung/receivers.py
@@ -9,11 +9,9 @@ from django.utils.translation import gettext_lazy as _
@receiver(post_save, sender=Notification)
def base_notification_receiver(sender, instance: Notification, created: bool, **kwargs):
- print("Dada")
if not created or not instance.user_to_notify.email_notifications:
return
else:
- print("Dodo")
task_send_notification_email.delay(instance.pk)
From d53c5707b88078738a13606079a1483b2badd18e Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 17:34:55 +0200
Subject: [PATCH 06/11] feat: remove notification bell that might not get
displayed
---
src/fellchensammlung/mail.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fellchensammlung/mail.py b/src/fellchensammlung/mail.py
index 94c0c46..211844a 100644
--- a/src/fellchensammlung/mail.py
+++ b/src/fellchensammlung/mail.py
@@ -35,7 +35,7 @@ def mail_admins_new_report(report):
def send_notification_email(notification_pk):
notification = Notification.objects.get(pk=notification_pk)
- subject = f"🔔 {notification.title}"
+ subject = f"{notification.title}"
context = {"notification": notification, }
if notification.notification_type == NotificationTypeChoices.NEW_REPORT_COMMENT or notification.notification_type == NotificationTypeChoices.NEW_REPORT_AN:
context["user_comment"] = notification.report.user_comment
From 4b3286f12d22fd0d01f448e23b173aa66fe0e5d0 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 17:51:39 +0200
Subject: [PATCH 07/11] fix: revert allowing an empty user to notify
---
.../0053_alter_notification_adoption_notice_and_more.py | 2 +-
src/fellchensammlung/models.py | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py b/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
index 6534fcc..5d8b11f 100644
--- a/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
+++ b/src/fellchensammlung/migrations/0053_alter_notification_adoption_notice_and_more.py
@@ -35,6 +35,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='notification',
name='user_to_notify',
- field=models.ForeignKey(blank=True, help_text='Useraccount der Benachrichtigt wird', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL, verbose_name='Nutzer*in'),
+ field=models.ForeignKey(help_text='Useraccount der Benachrichtigt wird', on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL, verbose_name='Nutzer*in'),
),
]
diff --git a/src/fellchensammlung/models.py b/src/fellchensammlung/models.py
index b2d60b0..7fdf9da 100644
--- a/src/fellchensammlung/models.py
+++ b/src/fellchensammlung/models.py
@@ -927,7 +927,6 @@ class Notification(models.Model):
text = models.TextField(verbose_name="Inhalt")
user_to_notify = models.ForeignKey(User,
on_delete=models.CASCADE,
- blank=True, null=True,
verbose_name=_('Nutzer*in'),
help_text=_("Useraccount der Benachrichtigt wird"),
related_name='user')
From 2f12dc6a5ebd4847adf363f3ea569fb75f408234 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 18:19:28 +0200
Subject: [PATCH 08/11] fix: use complete URL
---
src/fellchensammlung/models.py | 6 +++++-
.../mail/notifications/an-to-be-checked.html | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/fellchensammlung/models.py b/src/fellchensammlung/models.py
index 7fdf9da..15bd6af 100644
--- a/src/fellchensammlung/models.py
+++ b/src/fellchensammlung/models.py
@@ -14,7 +14,7 @@ from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from .tools import misc, geo
-from notfellchen.settings import MEDIA_URL
+from notfellchen.settings import MEDIA_URL, base_url
from .tools.geo import LocationProxy, Position
from .tools.misc import age_as_hr_string, time_since_as_hr_string
@@ -389,6 +389,10 @@ class AdoptionNotice(models.Model):
"""Returns the url to access a detailed page for the adoption notice."""
return reverse('adoption-notice-detail', args=[str(self.id)])
+ def get_full_url(self):
+ """Returns the url including protocol and domain"""
+ return f"{base_url}{self.get_absolute_url()}"
+
def get_report_url(self):
"""Returns the url to report an adoption notice."""
return reverse('report-adoption-notice', args=[str(self.id)])
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
index 7c4b8a0..8563f4e 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
@@ -11,6 +11,6 @@
- {% translate 'Vermittlung anzeigen' %}
+ {% translate 'Vermittlung anzeigen' %}
{% endblock %}
\ No newline at end of file
From 2d1df879dc6ac96eb5ba302b22d6990ff94adfd8 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 18:26:41 +0200
Subject: [PATCH 09/11] fix: use complete URL
---
.../fellchensammlung/mail/notifications/an-deactivated.html | 2 +-
.../fellchensammlung/mail/notifications/an-to-be-checked.html | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
index 9ec7f28..7794f18 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-deactivated.html
@@ -11,6 +11,6 @@
- {% translate 'Vermittlung anzeigen' %}
+ {% translate 'Vermittlung anzeigen' %}
{% endblock %}
\ No newline at end of file
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
index 8563f4e..814c3d4 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-to-be-checked.html
@@ -8,7 +8,6 @@
Moin,
die Vermittlung {{ notification.adoption_notice }} muss überprüft werden.
-
{% translate 'Vermittlung anzeigen' %}
From 9858dfc1bde727d22c07ab44d447d9dcebf17c34 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 18:34:30 +0200
Subject: [PATCH 10/11] fix: search notification
---
src/fellchensammlung/mail.py | 2 +-
.../mail/notifications/an-for-search-found.html | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/fellchensammlung/mail.py b/src/fellchensammlung/mail.py
index 211844a..2421787 100644
--- a/src/fellchensammlung/mail.py
+++ b/src/fellchensammlung/mail.py
@@ -48,7 +48,7 @@ def send_notification_email(notification_pk):
elif notification.notification_type == NotificationTypeChoices.AN_WAS_DEACTIVATED:
html_message = render_to_string('fellchensammlung/mail/notifications/an-deactivated.html', context)
elif notification.notification_type == NotificationTypeChoices.AN_FOR_SEARCH_FOUND:
- html_message = render_to_string('fellchensammlung/mail/notifications/report.html', context)
+ html_message = render_to_string('fellchensammlung/mail/notifications/an-for-search-found.html', context)
elif notification.notification_type == NotificationTypeChoices.NEW_COMMENT:
html_message = render_to_string('fellchensammlung/mail/notifications/new-comment.html', context)
else:
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
index 05517f4..fdd2850 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/an-for-search-found.html
@@ -8,9 +8,8 @@
Moin,
es wurde eine neue Vermittlung gefunden die deinen Kriterien entspricht: {{ notification.adoption_notice }}
-
- {% translate 'Vermittlung anzeigen' %}
+ {% translate 'Vermittlung anzeigen' %}
{% endblock %}
\ No newline at end of file
From 26f999c4cfbe3151c320e6cbce359469edb36f66 Mon Sep 17 00:00:00 2001
From: moanos
Date: Fri, 11 Jul 2025 18:37:43 +0200
Subject: [PATCH 11/11] fix: url
---
.../fellchensammlung/mail/notifications/new-comment.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
index 708b374..443f949 100644
--- a/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
+++ b/src/fellchensammlung/templates/fellchensammlung/mail/notifications/new-comment.html
@@ -14,6 +14,6 @@
{{ notification.comment.text | render_markdown }}
- {% translate 'Vermittlung anzeigen' %}
+ {% translate 'Vermittlung anzeigen' %}
{% endblock %}
\ No newline at end of file