Skip to content
Snippets Groups Projects
Commit dd4ea436 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Merge branch 'feature/multiple-recipient-objects-announcement' into 'master'

Allow multiple recipient objects for one announcement

Closes #188

See merge request AlekSIS!166
parents 249022a3 b3d197d9
No related branches found
No related tags found
1 merge request!166Allow multiple recipient objects for one announcement
Pipeline #911 failed
from django.contrib import admin
from .models import Group, Person, School, SchoolTerm, Activity, Notification, Announcement
from .models import (
Group,
Person,
School,
SchoolTerm,
Activity,
Notification,
Announcement,
AnnouncementRecipient,
)
admin.site.register(Person)
admin.site.register(Group)
......@@ -8,4 +17,16 @@ admin.site.register(School)
admin.site.register(SchoolTerm)
admin.site.register(Activity)
admin.site.register(Notification)
admin.site.register(Announcement)
class AnnouncementRecipientInline(admin.StackedInline):
model = AnnouncementRecipient
class AnnouncementAdmin(admin.ModelAdmin):
inlines = [
AnnouncementRecipientInline,
]
admin.site.register(Announcement, AnnouncementAdmin)
# Generated by Django 3.0.3 on 2020-02-19 18:14
import aleksis.core.models
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('core', '0013_extensible_model_as_default'),
]
operations = [
migrations.AlterModelOptions(
name='announcement',
options={'verbose_name': 'Announcement', 'verbose_name_plural': 'Announcements'},
),
migrations.RemoveField(
model_name='announcement',
name='content_type',
),
migrations.RemoveField(
model_name='announcement',
name='recipient_id',
),
migrations.AlterField(
model_name='announcement',
name='description',
field=models.TextField(blank=True, max_length=500, verbose_name='Description'),
),
migrations.AlterField(
model_name='announcement',
name='valid_until',
field=models.DateTimeField(default=aleksis.core.util.core_helpers.now_tomorrow, verbose_name='Date and time until when to show'),
),
migrations.CreateModel(
name='AnnouncementRecipient',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('recipient_id', models.PositiveIntegerField()),
('announcement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipients', to='core.Announcement')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
),
migrations.AlterModelOptions(
name='announcementrecipient',
options={'verbose_name': 'Announcement recipient', 'verbose_name_plural': 'Announcement recipients'},
),
]
# Generated by Django 3.0.3 on 2020-02-25 15:26
import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0014_multiple_recipients_announcement'),
]
operations = [
migrations.AddField(
model_name='announcementrecipient',
name='extended_data',
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False),
),
]
......@@ -231,7 +231,7 @@ class Group(ExtensibleModel):
@property
def announcement_recipients(self):
return list(self.members) + list(self.owners)
return list(self.members.all()) + list(self.owners.all())
def __str__(self) -> str:
return "%s (%s)" % (self.name, self.short_name)
......@@ -290,10 +290,6 @@ class Announcement(ExtensibleModel):
default=now_tomorrow,
)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
recipient_id = models.PositiveIntegerField()
recipient = GenericForeignKey("content_type", "recipient_id")
@classmethod
def relevant_for(cls, obj: Union[models.Model, models.QuerySet]) -> models.QuerySet:
""" Get a QuerySet with all announcements relevant for a certain Model (e.g. a Group)
......@@ -307,7 +303,7 @@ class Announcement(ExtensibleModel):
ct = ContentType.objects.get_for_model(obj)
pks = [obj.pk]
return cls.objects.filter(content_type=ct, recipient_id__in=pks)
return cls.objects.filter(recipients__content_type=ct, recipients__recipient_id__in=pks)
@classmethod
def for_person_at_time(cls, person: Person, when: Optional[datetime] = None) -> List:
......@@ -326,10 +322,34 @@ class Announcement(ExtensibleModel):
return announcements_for_person
@property
def recipient_persons(self) -> Union[models.QuerySet, Sequence[models.Model]]:
""" Return a list of Persons this announcement is relevant for
def recipient_persons(self) -> Sequence[Person]:
""" Return a list of Persons this announcement is relevant for """
persons = []
for recipient in self.recipients.all():
persons += recipient.persons
return persons
def __str__(self):
return self.title
class Meta:
verbose_name = _("Announcement")
verbose_name_plural = _("Announcements")
If the recipient is a Person, return that object. If not, it returns the QUerySet
class AnnouncementRecipient(ExtensibleModel):
announcement = models.ForeignKey(Announcement, on_delete=models.CASCADE, related_name="recipients")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
recipient_id = models.PositiveIntegerField()
recipient = GenericForeignKey("content_type", "recipient_id")
@property
def persons(self) -> Sequence[Person]:
""" Return a list of Persons selected by this recipient object
If the recipient is a Person, return that object. If not, it returns the list
from the announcement_recipients field on the target model.
"""
......@@ -339,11 +359,11 @@ class Announcement(ExtensibleModel):
return getattr(self.recipient, "announcement_recipients", [])
def __str__(self):
return self.title
return str(self.recipient)
class Meta:
verbose_name = _("Announcement")
verbose_name_plural = _("Announcements")
verbose_name = _("Announcement recipient")
verbose_name_plural = _("Announcement recipients")
class DashboardWidget(PolymorphicModel, PureDjangoModel):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment