diff --git a/opentech/apply/activity/messaging.py b/opentech/apply/activity/messaging.py index c0ceeea24868c5e1191c711de847e312543d7bac..0310a560f0a9b3078d01e85e650579e9c74c4dc3 100644 --- a/opentech/apply/activity/messaging.py +++ b/opentech/apply/activity/messaging.py @@ -12,6 +12,11 @@ def link_to(target, request): return request.scheme + '://' + request.get_host() + target.get_absolute_url() +neat_related = { + MESSAGES.DETERMINATION_OUTCOME: 'determination', +} + + class AdapterBase: messages = {} always_send = False @@ -38,10 +43,29 @@ class AdapterBase: def extra_kwargs(self, message_type, **kwargs): return {} + def get_neat_related(self, message_type, related): + # We translate the related kwarg into something we can understand + try: + neat_name = neat_related[message_type] + except KeyError: + # Message type doesn't expect a related object + if related: + raise ValueError(f"Unexpected 'related' kwarg provided for {message_type}") from None + + if not related: + raise ValueError(f"{message_type} expects a 'related' kwarg") + return {neat_name: related} + def recipients(self, message_type, **kwargs): raise NotImplementedError() - def process(self, message_type, event, **kwargs): + def process(self, message_type, event, user, submission, related=None): + kwargs = { + 'user': user, + 'submission': submission, + 'related': related, + } + kwargs.update(self.get_neat_related(message_type, related)) kwargs.update(self.extra_kwargs(message_type, **kwargs)) message = self.message(message_type, **kwargs) @@ -124,6 +148,7 @@ class ActivityAdapter(AdapterBase): submission=submission, message=message, visibility=visibility, + related_object=kwargs['related'] ) @@ -265,11 +290,11 @@ class MessengerBackend: def __call__(self, message_type, request, user, submission, **kwargs): return self.send(message_type, request=request, user=user, submission=submission, **kwargs) - def send(self, message_type, user, submission, **kwargs): + def send(self, message_type, user, submission, related): from .models import Event event = Event.objects.create(type=message_type.name, by=user, submission=submission) for adapter in self.adapters: - adapter.process(message_type, event, user=user, submission=submission, **kwargs) + adapter.process(message_type, event, user=user, submission=submission, related=related) adapters = [ diff --git a/opentech/apply/activity/migrations/0012_add_generic_relation_to_activity.py b/opentech/apply/activity/migrations/0012_add_generic_relation_to_activity.py new file mode 100644 index 0000000000000000000000000000000000000000..be9a21f8ab9e406dc485c86033e304fee85cdeb2 --- /dev/null +++ b/opentech/apply/activity/migrations/0012_add_generic_relation_to_activity.py @@ -0,0 +1,25 @@ +# Generated by Django 2.0.2 on 2018-09-06 09:43 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('activity', '0011_add_new_event_type'), + ] + + operations = [ + migrations.AddField( + model_name='activity', + name='content_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AddField( + model_name='activity', + name='object_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/opentech/apply/activity/models.py b/opentech/apply/activity/models.py index 4aef2ec4c5c1e9bd7921bf798baabb8d9e7cc784..cabc295831be94bc29954fe864d51fe2e33e99ae 100644 --- a/opentech/apply/activity/models.py +++ b/opentech/apply/activity/models.py @@ -1,4 +1,6 @@ from django.conf import settings +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import Case, When, Value from django.db.models.functions import Concat @@ -81,6 +83,11 @@ class Activity(models.Model): message = models.TextField() visibility = models.CharField(choices=VISIBILITY.items(), default=PUBLIC, max_length=10) + # Fields for generic relations to other objects. related_object should implement `get_absolute_url` + content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE) + object_id = models.PositiveIntegerField(blank=True, null=True) + related_object = GenericForeignKey('content_type', 'object_id') + objects = models.Manager.from_queryset(ActivityQuerySet)() comments = CommentManger.from_queryset(CommentQueryset)() actions = ActionManager.from_queryset(ActionQueryset)() diff --git a/opentech/apply/determinations/views.py b/opentech/apply/determinations/views.py index 2225a20aed84cf1d0b2ef5777802bddbd1959d78..8a12b46cc7734fec8530e77e78f274deb489ba94 100644 --- a/opentech/apply/determinations/views.py +++ b/opentech/apply/determinations/views.py @@ -92,7 +92,7 @@ class DeterminationCreateOrUpdateView(CreateOrUpdateView): request=self.request, user=self.object.author, submission=self.object.submission, - determination=self.object, + related=self.object, ) transition = transition_from_outcome(int(form.cleaned_data.get('outcome')), self.submission)