diff options
Diffstat (limited to 'src/notifier')
-rw-r--r-- | src/notifier/__init__.py | 8 | ||||
-rw-r--r-- | src/notifier/admin.py | 4 | ||||
-rw-r--r-- | src/notifier/apps.py | 3 | ||||
-rw-r--r-- | src/notifier/dispatchers.py | 4 | ||||
-rw-r--r-- | src/notifier/manager.py | 98 | ||||
-rw-r--r-- | src/notifier/migrations/0001_initial.py | 25 | ||||
-rw-r--r-- | src/notifier/models.py | 33 | ||||
-rw-r--r-- | src/notifier/tests/test_dispatcher.py | 17 | ||||
-rw-r--r-- | src/notifier/tests/test_models.py | 29 | ||||
-rw-r--r-- | src/notifier/urls.py | 21 | ||||
-rw-r--r-- | src/notifier/views.py | 34 |
11 files changed, 258 insertions, 18 deletions
diff --git a/src/notifier/__init__.py b/src/notifier/__init__.py index e69de29..d65b13a 100644 --- a/src/notifier/__init__.py +++ b/src/notifier/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## diff --git a/src/notifier/admin.py b/src/notifier/admin.py index cfbe778..d3e8be5 100644 --- a/src/notifier/admin.py +++ b/src/notifier/admin.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -12,3 +12,5 @@ from django.contrib import admin from notifier.models import * admin.site.register(Notifier) +admin.site.register(MetaBooking) +admin.site.register(LabMessage) diff --git a/src/notifier/apps.py b/src/notifier/apps.py index da5d3b0..52902da 100644 --- a/src/notifier/apps.py +++ b/src/notifier/apps.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -7,6 +7,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## + from django.apps import AppConfig diff --git a/src/notifier/dispatchers.py b/src/notifier/dispatchers.py index c35fe2b..1b66b37 100644 --- a/src/notifier/dispatchers.py +++ b/src/notifier/dispatchers.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -30,4 +30,4 @@ class DispatchHandler(): instance.sender,[instance.user.email_addr], fail_silently=False) def webnotification(instance): - instance.msg_sent='by web notification'
\ No newline at end of file + instance.msg_sent='by web notification' diff --git a/src/notifier/manager.py b/src/notifier/manager.py new file mode 100644 index 0000000..a705d00 --- /dev/null +++ b/src/notifier/manager.py @@ -0,0 +1,98 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from booking.models import * +from notifier.models import Notifier, MetaBooking, LabMessage +from django.utils import timezone +from datetime import timedelta +from django.template import Template, Context +from account.models import UserProfile + +from django.db import models + +class NotifyPeriodic(object): + def task(): + bookings_new = Booking.objects.filter(metabooking__isnull=True) + bookings_old = Booking.objects.filter(end__lte=timezone.now() + timedelta(hours=24)).filter(metabooking__ended_notified=False) + + for booking in bookings_old: + metabooking = booking.metabooking + if booking.end <= timezone.now() + timedelta(hours=24): + if not metabooking.ending_notified: + Notify().notify(Notify.TOCLEAN, booking) + metabooking.ending_notified = True + metabooking.save() + if booking.end <= timezone.now(): + metabooking = booking.metabooking + if not metabooking.ended_notified: + Notify().notify(Notify.CLEANED, booking) + metabooking.ended_notified = True + metabooking.save() + + for booking in bookings_new: + metabooking = MetaBooking() + metabooking.booking = booking + metabooking.created_notified = True + metabooking.save() + + Notify().notify(Notify.CREATED, booking) + + +class Notify(object): + + CREATED = "created" + TOCLEAN = "toclean" + CLEANED = "cleaned" + + TITLES = {} + TITLES["created"] = "Your booking has been confirmed" + TITLES["toclean"] = "Your booking is ending soon" + TITLES["cleaned"] = "Your booking has ended" + + """ + Lab message is provided with the following context elements: + * if is for owner or for collaborator (if owner) + * recipient username (<owner, collaborator>.username) + * recipient full name (<owner, collaborator>.userprofile.full_name) + * booking it pertains to (booking) + * status message should convey (currently "created", "toclean" and "cleaned" as strings) + It should be a django template that can be rendered with these context elements + and should generally use all of them in one way or another. + It should be applicable to email, the web based general view, and should be scalable for + all device formats across those mediums. + """ + def notify(self, notifier_type, booking): + template = Template(LabMessage.objects.filter(lab=booking.lab).first().msg) + + context = {} + context["owner"] = booking.owner + context["notify_type"] = notifier_type + context["booking"] = booking + message = template.render(Context(context)) + notifier = Notifier() + notifier.title = self.TITLES[notifier_type] + notifier.content = message + notifier.user = booking.owner.userprofile + notifier.sender = str(booking.lab) + notifier.save() + notifier.send() + + + context["owner"] = False + + for user in booking.collaborators.all(): + context["collaborator"] = user + message = template.render(Context(context)) + notifier = Notifier() + notifier.title = self.TITLES[notifier_type] + notifier.content = message + notifier.user = UserProfile.objects.get(user=user) + notifier.sender = str(booking.lab) + notifier.save() + notifier.send() diff --git a/src/notifier/migrations/0001_initial.py b/src/notifier/migrations/0001_initial.py index cac4d04..e5d0009 100644 --- a/src/notifier/migrations/0001_initial.py +++ b/src/notifier/migrations/0001_initial.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-12-14 21:41 -from __future__ import unicode_literals +# Generated by Django 2.1 on 2018-09-14 14:48 from django.db import migrations, models import django.db.models.deletion @@ -12,11 +10,30 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('dashboard', '0002_auto_20170505_0815'), + ('account', '0001_initial'), + ('booking', '0001_initial'), ] operations = [ migrations.CreateModel( + name='LabMessage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('msg', models.TextField()), + ('lab', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.Lab')), + ], + ), + migrations.CreateModel( + name='MetaBooking', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('ending_notified', models.BooleanField(default=False)), + ('ended_notified', models.BooleanField(default=False)), + ('created_notified', models.BooleanField(default=False)), + ('booking', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='metabooking', to='booking.Booking')), + ], + ), + migrations.CreateModel( name='Notifier', fields=[ ('id', models.AutoField(primary_key=True, serialize=False)), diff --git a/src/notifier/models.py b/src/notifier/models.py index 9ebc6fc..ed0edeb 100644 --- a/src/notifier/models.py +++ b/src/notifier/models.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -8,14 +8,24 @@ ############################################################################## from django.db import models -from jira import JIRA, JIRAError -from dashboard.models import Resource from booking.models import Booking -from django.contrib.auth.models import User from account.models import UserProfile -from django.contrib import messages -from django.db.models.signals import pre_save from fernet_fields import EncryptedTextField +from account.models import Lab + + +class MetaBooking(models.Model): + id = models.AutoField(primary_key=True) + booking = models.OneToOneField(Booking, on_delete=models.CASCADE, related_name="metabooking") + ending_notified = models.BooleanField(default=False) + ended_notified = models.BooleanField(default=False) + created_notified = models.BooleanField(default=False) + + +class LabMessage(models.Model): + lab = models.ForeignKey(Lab, on_delete=models.CASCADE) + msg = models.TextField() # django template should be put here + class Notifier(models.Model): id = models.AutoField(primary_key=True) @@ -24,15 +34,18 @@ class Notifier(models.Model): user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True, blank=True) sender = models.CharField(max_length=240, default='unknown') message_type = models.CharField(max_length=240, default='email', choices=( - ('email','Email'), + ('email', 'Email'), ('webnotification', 'Web Notification'))) msg_sent = '' - import notifier.dispatchers - def __str__(self): return self.title + """ + Implement for next PR: send Notifier by media agreed to by user + """ + def send(self): + pass + def getEmail(self): return self.user.email_addr - diff --git a/src/notifier/tests/test_dispatcher.py b/src/notifier/tests/test_dispatcher.py new file mode 100644 index 0000000..07d8387 --- /dev/null +++ b/src/notifier/tests/test_dispatcher.py @@ -0,0 +1,17 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +from django.test import TestCase +from notifier.models import * +from django.contrib.auth.models import User + +class DispatchTestCase(TestCase): + # This is a stub, it will be filled out as this feature is remade with saner practices. + pass diff --git a/src/notifier/tests/test_models.py b/src/notifier/tests/test_models.py new file mode 100644 index 0000000..10aec3e --- /dev/null +++ b/src/notifier/tests/test_models.py @@ -0,0 +1,29 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +from django.test import TestCase +from notifier.models import * +from django.contrib.auth.models import User + +class NotifierTestCase(TestCase): + + def test_valid_notifier_saves(self): + + sender = User.objects.create() + recipient = User.objects.create() + self.assertTrue( + Notifier.objects.create( + title='notification title', + content='notification body', + user=recipient, + sender=sender, + message_type='email' + ) + ) diff --git a/src/notifier/urls.py b/src/notifier/urls.py new file mode 100644 index 0000000..9bbc3bf --- /dev/null +++ b/src/notifier/urls.py @@ -0,0 +1,21 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +from django.conf.urls import url + +from notifier.views import * + +app_name = "notifier" +urlpatterns = [ + + + url(r'^$', InboxView, name='messages'), + url(r'^notification/(?P<notification_id>[0-9]+)/$', NotificationView, name='notifier_single') +] diff --git a/src/notifier/views.py b/src/notifier/views.py new file mode 100644 index 0000000..026894a --- /dev/null +++ b/src/notifier/views.py @@ -0,0 +1,34 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from notifier.models import * +from django.shortcuts import render + +def InboxView(request): + if request.user.is_authenticated: + user = request.user + else: + return render(request, "dashboard/login.html", {'title': 'Authentication Required'}) + + return render(request, "notifier/inbox.html", {'notifier_messages': Notifier.objects.filter(user=user.userprofile)}) + + +def NotificationView(request, notification_id): + if notification_id == 0: + pass + if request.user.is_authenticated: + user = request.user + else: + return render(request, "dashboard/login.html", {'title': 'Authentication Required'}) + + notification = Notifier.objects.get(id=notification_id) + if not notification.user.user.username == user.username: + return render(request, "dashboard/login.html", {'title': 'Access Denied'}) + + return render(request, "notifier/notification.html", {'notification': notification}) |