Skip to content

Commit

Permalink
Merge pull request #472 from elixir-luxembourg/implement-notification…
Browse files Browse the repository at this point in the history
…-models

Updating notification models for new notification system;
  • Loading branch information
Fancien authored Oct 31, 2023
2 parents 3aa78ad + e779ba6 commit 4aa16fe
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 269 deletions.
28 changes: 0 additions & 28 deletions core/models/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,10 @@

from core.models import Dataset, Project, User, Contract
from core.search_indexes import DatasetIndex, ProjectIndex, ContractIndex
from notification.models import Notification, NotificationVerb, NotificationStyle

logger = logging.getLogger("daisy.signals")


@receiver(post_save, sender=Dataset, dispatch_uid="dataset_change")
def dataset_changed(sender, instance, created, **kwargs):
"""
Dataset changed
* create a notification
"""
from notification import tasks

# log an activity for each custodians
for custodian in instance.local_custodians.all():
Notification.objects.create(
actor=custodian,
verb=created
and NotificationVerb.new_dataset
or NotificationVerb.update_dataset,
content_object=instance,
)
# send an email if notif setting is every time
if not settings.NOTIFICATIONS_DISABLED and (
not hasattr(custodian, "notification_setting")
or custodian.notification_setting == NotificationStyle.every_time
):
tasks.send_dataset_notification_for_user.delay(
custodian.pk, instance.pk, created
)


@receiver(
m2m_changed,
sender=Dataset.local_custodians.through,
Expand Down
97 changes: 97 additions & 0 deletions notification/migrations/0004_auto_20231025_1100.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Generated by Django 3.2.20 on 2023-10-25 09:00

from django.db import migrations, models, connection
import enumchoicefield.fields
import notification.models


def empty_notification_table(apps, schema_editor):
with connection.cursor() as cursor:
cursor.execute("TRUNCATE TABLE notification_notification;")


def rollback_empty_notification_table(apps, schema_editor):
pass


class Migration(migrations.Migration):
dependencies = [
("notification", "0003_auto_20220726_1343"),
]

operations = [
migrations.RunPython(
empty_notification_table, rollback_empty_notification_table
),
migrations.RenameField(
model_name="notification",
old_name="actor",
new_name="recipient",
),
migrations.RemoveField(
model_name="notificationsetting",
name="style",
),
migrations.AddField(
model_name="notification",
name="dismissed",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="notification",
name="dispatch_by_email",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="notification",
name="dispatch_in_app",
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name="notification",
name="message",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="notification",
name="on",
field=models.DateTimeField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name="notification",
name="processing_date",
field=models.DateField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name="notificationsetting",
name="notification_offset",
field=models.PositiveSmallIntegerField(
default=90,
help_text="Define how many days before the actual event you want to receive the notification",
verbose_name="Notification time",
),
),
migrations.AddField(
model_name="notificationsetting",
name="send_email",
field=models.BooleanField(
default=False,
help_text="Notifications will be send directly to your email. See your [profile page] for more detail.",
),
),
migrations.AddField(
model_name="notificationsetting",
name="send_in_app",
field=models.BooleanField(
default=True,
help_text="Notification will be displayed in DAISY interface",
),
),
migrations.AlterField(
model_name="notification",
name="verb",
field=enumchoicefield.fields.EnumChoiceField(
enum_class=notification.models.NotificationVerb, max_length=13
),
),
]
41 changes: 31 additions & 10 deletions notification/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.apps import apps
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import get_user_model

from django.conf import settings

Expand All @@ -23,23 +24,36 @@ class NotificationStyle(ChoiceEnum):


class NotificationVerb(ChoiceEnum):
new_dataset = "New dataset"
update_dataset = "Dataset update"
data_storage_expiry = "Data storage expiry"
document_expiry = "Document expiry"
expire = "expire"
start = "start"
end = "end"
embargo_start = "embargo_start"
embargo_end = "embargo_end"


class NotificationSetting(models.Model):
class Meta:
app_label = "notification"

user = models.OneToOneField(
"core.User", related_name="notification_setting", on_delete=models.CASCADE
get_user_model(), related_name="notification_setting", on_delete=models.CASCADE
)
send_email = models.BooleanField(
default=False,
help_text="Notifications will be send directly to your email. See your [profile page] for more detail.",
)
send_in_app = models.BooleanField(
default=True,
help_text="Notification will be displayed in DAISY interface",
)
notification_offset = models.PositiveSmallIntegerField(
default=90,
verbose_name="Notification time",
help_text="Define how many days before the actual event you want to receive the notification",
)
style = EnumChoiceField(NotificationStyle, default=NotificationStyle.never)

def __str__(self):
return f"{self.user}: {self.style}"
return f"{self.user}: {self.notification_offset} days"


class NotificationQuerySet(models.QuerySet):
Expand All @@ -59,10 +73,17 @@ class Notification(models.Model):
class Meta:
app_label = "notification"

actor = models.ForeignKey(
"core.User", related_name="notifications", on_delete=models.CASCADE
recipient = models.ForeignKey(
get_user_model(), related_name="notifications", on_delete=models.CASCADE
)
verb = EnumChoiceField(NotificationVerb)
on = models.DateTimeField(null=True, blank=True, default=None)

dispatch_in_app = models.BooleanField(default=True)
dispatch_by_email = models.BooleanField(default=False)
dismissed = models.BooleanField(default=False)
processing_date = models.DateField(default=None, null=True, blank=True)
message = models.TextField(default="")

content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
Expand Down Expand Up @@ -94,4 +115,4 @@ def get_full_url(self):
)

def __str__(self):
return f"N: {self.actor} {self.verb} {self.object_id} {self.time}"
return f"N: {self.recipient} {self.verb} {self.object_id} {self.time}"
151 changes: 0 additions & 151 deletions notification/tasks.py

This file was deleted.

14 changes: 14 additions & 0 deletions notification/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest

from test.factories import DatasetFactory, DatasetNotificationFactory


@pytest.mark.parametrize(
"factory, object_factory", [(DatasetNotificationFactory, DatasetFactory)]
)
def test_notification_urls(user_normal, factory, object_factory):
notification = factory(recipient=user_normal, content_object=object_factory())
assert (
notification.get_absolute_url()
== notification.content_object.get_absolute_url()
)
Loading

0 comments on commit 4aa16fe

Please sign in to comment.