def notify_commitment_end(): members = CommitmentMember.objects.filter( completion_date=datetime.date.today(), award_date__isnull=True) # try and load the notification template. template = None try: template = NoticeTemplate.objects.get(notice_type="commitment-ready") except NoticeTemplate.DoesNotExist: pass for member in members: message = None if template: message = template.render({"COMMITMENT": member.commitment}) else: message = "Your commitment <a href='%s'>%s</a> has end." % ( reverse("activity_task", args=( member.commitment.type, member.commitment.slug, )), member.commitment.title) message += "You can click on the link to claim your points." UserNotification.create_info_notification(member.user, message, display_alert=True, content_object=member) print "created commitment end notification for %s : %s" % ( member.user, member.commitment.slug)
def notify_round_started(): if not in_competition(): return today = datetime.datetime.today() prev_date = None current_round = "Overall Round" previous_round = 'Overall Round' for key, value in settings.COMPETITION_ROUNDS.items(): # We're looking for a round that ends today and another that starts today (or overall) start = datetime.datetime.strptime(value["start"], "%Y-%m-%d") end = datetime.datetime.strptime(value["end"], "%Y-%m-%d") # Check yesterday's round and check for the current round. if start < (today - datetime.timedelta(days=1)) < end: previous_round = key if start < today < end: current_round = key print 'Previous Round: %s' % previous_round print 'Current Round: %s' % current_round if current_round and previous_round and current_round != previous_round: print 'Sending out round transition notices.' template = NoticeTemplate.objects.get(notice_type="round-transition") message = template.render({"PREVIOUS_ROUND": previous_round, "CURRENT_ROUND": current_round,}) for user in User.objects.all(): UserNotification.create_info_notification(user, message, display_alert=True,)
def __pick_winners(self, prizes): for prize in prizes: if not prize.winner: # Randomly order the tickets and then pick a random ticket. while True: tickets = prize.raffleticket_set.order_by("?").all() if tickets.count() == 0: self.stdout.write('No tickets for %s. Skipping.\n' % prize) ticket = random.randint(0, tickets.count() - 1) user = tickets[ticket].user self.stdout.write(str(prize) + ": " + user.username + '\n') value = raw_input('Is this OK? [y/n] ') if value.lower() == 'y': prize.winner = user prize.save() self.stdout.write("Notifying %s\n" % user.username) # Notify winner using the template. try: template = NoticeTemplate.objects.get(notice_type='raffle-winner') message = template.render({'PRIZE': prize}) UserNotification.create_info_notification(user, message, True, prize) except NoticeTemplate.DoesNotExist: self.stdout.write("Could not find the raffle-winner template. User was not notified.\n") break
def __pick_winners(self, prizes): for prize in prizes: if not prize.winner: # Randomly order the tickets and then pick a random ticket. while True: tickets = prize.raffleticket_set.order_by("?").all() if tickets.count() == 0: self.stdout.write('No tickets for %s. Skipping.\n' % prize) ticket = random.randint(0, tickets.count() - 1) user = tickets[ticket].user self.stdout.write(str(prize) + ": " + user.username + '\n') value = raw_input('Is this OK? [y/n] ') if value.lower() == 'y': prize.winner = user prize.save() self.stdout.write("Notifying %s\n" % user.username) # Notify winner using the template. try: template = NoticeTemplate.objects.get( notice_type='raffle-winner') message = template.render({'PRIZE': prize}) UserNotification.create_info_notification( user, message, True, prize) except NoticeTemplate.DoesNotExist: self.stdout.write( "Could not find the raffle-winner template. User was not notified.\n" ) break
def _handle_rejected(self): """ Creates a notification for rejected tasks. This also creates an email message if it is configured. """ # Construct the message to be sent. message = "Your response to <a href='%s'>%s</a> %s was not approved." % ( reverse("activity_task", args=(self.activity.type, self.activity.slug,)), self.activity.title, # The below is to tell the javascript to convert into a pretty date. # See the prettyDate function in media/js/makahiki.js "<span class='rejection-date' title='%s'></span>" % self.submission_date.isoformat(), ) message += " You can still get points by clicking on the link and trying again." UserNotification.create_error_notification(self.user, message, content_object=self) subject = "[%s] Your response to '%s' was not approved" % (settings.COMPETITION_NAME, self.activity.title) current_site = Site.objects.get(id=settings.SITE_ID) message = render_to_string("email/rejected_activity.txt", { "object": self, "COMPETITION_NAME": settings.COMPETITION_NAME, "domain": current_site.domain, }) html_message = render_to_string("email/rejected_activity.html", { "object": self, "COMPETITION_NAME": settings.COMPETITION_NAME, "domain": current_site.domain, }) UserNotification.create_email_notification(self.user.email, subject, message, html_message)
def testAlertNotifications(self): alert = UserNotification(recipient=self.user, contents="Alert notification", display_alert=True) alert.save() response = self.client.get(reverse("home_index")) self.assertContains(response, "notification-dialog", msg_prefix="Alert should be shown") response = self.client.get(reverse("profile_index")) self.assertNotContains(response, "notification-dialog", msg_prefix="Dialog should not be displayed")
def process_rsvp(): members = ActivityMember.objects.filter(Q(activity__type="event")|Q(activity__type="excursion"),approval_status="pending") # try and load the notification template. template_noshow = None try: template_noshow = NoticeTemplate.objects.get(notice_type="event-noshow-penalty") except NoticeTemplate.DoesNotExist: pass template_reminder = None try: template_reminder = NoticeTemplate.objects.get(notice_type="event-post-reminder") except NoticeTemplate.DoesNotExist: pass for member in members: activity = member.activity user = member.user profile = user.get_profile() diff = datetime.date.today() - activity.event_date.date() if diff.days == 3: message = "%s: %s (No Show)" % (activity.type.capitalize(), activity.title) profile.remove_points(4, datetime.datetime.today() - datetime.timedelta(minutes=1), message, member) profile.save() print "removed 4 points from %s for '%s'" % (profile.name, message) if template_noshow: message = template_noshow.render({"ACTIVITY": activity}) else: message = "4 points had been deducted from you, because you signed up but did not enter the confirmation code 2 days after the %s <a href='%s'>%s</a>, " % ( activity.type.capitalize(), reverse("activity_task", args=(activity.type, activity.slug,)), activity.title) message += " If you did attend, please click on the link to claim your points and reverse the deduction." UserNotification.create_info_notification(user, message, display_alert=True, content_object=member) print "created no-show penalty notification for %s for %s" % (profile.name, activity.title) if diff.days == 2: if template_reminder: message = template_reminder.render({"ACTIVITY": activity}) else: message = "Hi %s, <p/> We just wanted to remind you that the %s <a href='http://%s%s'>%s</a> had ended. Please click on the link to claim your points." % ( profile.name, activity.type.capitalize(), Site.objects.get(id=settings.SITE_ID).domain, reverse("activity_task", args=(activity.type, activity.slug,)), activity.title) message += "<p/>Because you signed up for the event/excursion, if you do not enter the confirmation code within 2 days after the event/excusion, a total of 4 points (2 point signup bonus plus 2 point no-show penalty) will be deducted from your total points. So please enter your confirmation code early to avoid the penalty." message += "<p/><p/>Kukui Cup Administrators" subject = "[Kukui Cup] Reminder to enter your event/excursion confirmation code" UserNotification.create_email_notification(user.email, subject, message, message) print "sent post event email reminder to %s for %s" % (profile.name, activity.title)
def testAjaxReadNotifications(self): """Test that notifications can be marked as read via AJAX.""" notification = UserNotification(recipient=self.user, contents="Test notification") notification.save() response = self.client.post(reverse("notifications_read", args=(notification.pk,)), {}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.failUnlessEqual(response.status_code, 200) response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification", msg_prefix="Notification should be read")
def testReadNotifications(self): """Test that notifications can be marked as read without AJAX.""" notification = UserNotification(recipient=self.user, contents="Test notification") notification.save() response = self.client.post( reverse("notifications_read", args=(notification.pk, )), {}) self.assertRedirects(response, reverse("home_index"), msg_prefix="Marking as read should redirect.") response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification", msg_prefix="Notification should be read") # Test with a referring page. notification = UserNotification(recipient=self.user, contents="Test notification 2") notification.save() response = self.client.post(reverse("notifications_read", args=(notification.pk, )), {}, HTTP_REFERER=reverse("help_index")) self.assertRedirects(response, reverse("help_index"), msg_prefix="Marking as read should redirect.") response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification 2", msg_prefix="Notification should be read")
def testGetUnread(self): """ Test that we can get the user's unread notifications. """ user = User.objects.create_user("test", "*****@*****.**") for i in range(0, 3): notification = UserNotification(recipient=user, contents="Test notification %i" % i) notification.save() notifications = get_unread_notifications(user) self.assertEqual(notifications["alerts"].count(), 0, "There should not be any alert notifications.") unread = notifications["unread"] self.assertEqual(unread.count(), 3, "There should be three unread notifications.") alert = UserNotification(recipient=user, contents="Alert notification", display_alert=True) alert.save() notifications = get_unread_notifications(user) self.assertEqual(notifications["alerts"][0], alert, "Alert notification should have been returned.") self.assertEqual(unread.count(), 4, "There should be four unread notifications.")
def handle(self, *args, **options): """ Awards points to a user or a building and lounge. Format of the command is either: python manage.py add_points <username> <points> <short-message> <long-message> python manage.py add_points <residence-hall> <floor-number> <points> <short-message> <long-message> """ if len(args) < 4 or len(args) > 5: usage = """ Usage is either:\n 'python manage.py add_points <username> <points> <short-message> <long-message>' or\n 'python manage.py add_points <residence-hall> <floor-number> <points> <short-message> <long-message>'\n """ self.stderr.write(usage) return 1 today = datetime.datetime.today() # If there are 4 args, try and get the user. if len(args) == 4: try: user = User.objects.get(username=args[0]) profile = user.get_profile() profile.add_points(int(args[1]), datetime.datetime.today(), args[2]) profile.save() UserNotification.create_success_notification(user, args[3]) except User.DoesNotExist: self.stderr.write("User with username %s does not exist" % args[0]) return 1 else: try: floor = Floor.objects.get(dorm__name=args[0], number=args[1]) for profile in floor.profile_set.all(): profile = user.get_profile() profile.add_points(int(args[2]), datetime.datetime.today(), args[3]) profile.save() UserNotification.create_success_notification( profile.user, args[4]) except Floor.DoesNotExist: self.stderr.write( "Floor with building name %s and floor %s does not exist" % (args[0], args[1])) return 1
def testAjaxReadNotifications(self): """Test that notifications can be marked as read via AJAX.""" notification = UserNotification(recipient=self.user, contents="Test notification") notification.save() response = self.client.post(reverse("notifications_read", args=(notification.pk, )), {}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.failUnlessEqual(response.status_code, 200) response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification", msg_prefix="Notification should be read")
def testShowNotifications(self): """ Test that we can show notifications to the user. """ for i in range(0, 3): notification = UserNotification(recipient=self.user, contents="Test notification %i" % i) notification.save() response = self.client.get(reverse("home_index")) self.assertNotContains(response, "The following item(s) need your attention", msg_prefix="Alert should not be shown" ) for i in range(0, 3): self.assertContains(response, "Test notification %i" % i, msg_prefix="Notification %i is not shown" % i )
def testShowNotifications(self): """ Test that we can show notifications to the user. """ for i in range(0, 3): notification = UserNotification(recipient=self.user, contents="Test notification %i" % i) notification.save() response = self.client.get(reverse("home_index")) self.assertNotContains(response, "The following item(s) need your attention", msg_prefix="Alert should not be shown") for i in range(0, 3): self.assertContains(response, "Test notification %i" % i, msg_prefix="Notification %i is not shown" % i)
def send(self): """ Sends a reminder text to the user via an email. """ number = self.text_number.replace("-", "") email = number + "@" + self.TEXT_EMAILS[self.text_carrier] if not self.sent: # subject = "[%s] Reminder for %s" % (settings.COMPETITION_NAME, self.activity.title) current_site = Site.objects.get(id=settings.SITE_ID) message = render_to_string("email/activity_text_reminder.txt", { "activity": self.activity, "user": self.user, }) UserNotification.create_email_notification(email, "", message) self.sent = True self.save()
def possibly_completed_quests(user): """ Check if the user may have completed one of their quests. Returns an array of the completed quests. """ user_quests = user.quest_set.filter(questmember__completed=False, questmember__opt_out=False) completed = [] for quest in user_quests: if quest.completed_quest(user): member = QuestMember.objects.get(user=user, quest=quest) member.completed = True member.save() completed.append(quest) # Create quest notification. message = "Congratulations! You completed the '%s' quest." % quest.name UserNotification.create_success_notification(user, message, display_alert=True) return completed
def handle(self, *args, **options): """ Awards points to a user or a building and lounge. Format of the command is either: python manage.py add_points <username> <points> <short-message> <long-message> python manage.py add_points <residence-hall> <floor-number> <points> <short-message> <long-message> """ if len(args) < 4 or len(args) > 5: usage = """ Usage is either:\n 'python manage.py add_points <username> <points> <short-message> <long-message>' or\n 'python manage.py add_points <residence-hall> <floor-number> <points> <short-message> <long-message>'\n """ self.stderr.write(usage) return 1 today = datetime.datetime.today() # If there are 4 args, try and get the user. if len(args) == 4: try: user = User.objects.get(username=args[0]) profile = user.get_profile() profile.add_points(int(args[1]), datetime.datetime.today(), args[2]) profile.save() UserNotification.create_success_notification(user, args[3]) except User.DoesNotExist: self.stderr.write("User with username %s does not exist" % args[0]) return 1 else: try: floor = Floor.objects.get(dorm__name=args[0], number=args[1]) for profile in floor.profile_set.all(): profile = user.get_profile() profile.add_points(int(args[2]), datetime.datetime.today(), args[3]) profile.save() UserNotification.create_success_notification(profile.user, args[4]) except Floor.DoesNotExist: self.stderr.write("Floor with building name %s and floor %s does not exist" % (args[0], args[1])) return 1
def __create_notifications(self, user): try: template = NoticeTemplate.objects.get(notice_type='canopy-elevation') contents = template.render() UserNotification.create_info_notification(user, contents, True) except NoticeTemplate.DoesNotExist: # Use default message. message = "Congratulations! You have been added to the canopy!" UserNotification.create_info_notification(user, message, True) if user.email and len(user.email) > 0: subject = "[%s] Congratulations! You have been added to the canopy!" % (settings.COMPETITION_NAME,) current_site = Site.objects.get(id=settings.SITE_ID) message = render_to_string("email/added_to_canopy.txt", { "user": user, "competition_name": settings.COMPETITION_NAME, "domain": current_site.domain, }) html_message = render_to_string("email/added_to_canopy.html", { "user": user, "competition_name": settings.COMPETITION_NAME, "domain": current_site.domain, }) self.stdout.write('Sending email to %s\n' % user.email) UserNotification.create_email_notification(user.email, subject, message, html_message) else: self.stdout.write("'%s' does not have a valid email address. Skipping\n" % user.username)
def send(self): """ Sends a reminder email to the user. """ if not self.sent: subject = "[%s] Reminder for %s" % (settings.COMPETITION_NAME, self.activity.title) current_site = Site.objects.get(id=settings.SITE_ID) message = render_to_string("email/activity_reminder.txt", { "activity": self.activity, "user": self.user, "COMPETITION_NAME": settings.COMPETITION_NAME, "domain": current_site.domain, }) html_message = render_to_string("email/activity_reminder.html", { "activity": self.activity, "user": self.user, "COMPETITION_NAME": settings.COMPETITION_NAME, "domain": current_site.domain, }) UserNotification.create_email_notification(self.email_address, subject, message, html_message) self.sent = True self.save()
def notify_commitment_end(): members = CommitmentMember.objects.filter(completion_date=datetime.date.today(), award_date__isnull=True) # try and load the notification template. template = None try: template = NoticeTemplate.objects.get(notice_type="commitment-ready") except NoticeTemplate.DoesNotExist: pass for member in members: message = None if template: message = template.render({"COMMITMENT": member.commitment}) else: message = "Your commitment <a href='%s'>%s</a> has end." % ( reverse("activity_task", args=(member.commitment.type, member.commitment.slug,)), member.commitment.title) message += "You can click on the link to claim your points." UserNotification.create_info_notification(member.user, message, display_alert=True, content_object=member) print "created commitment end notification for %s : %s" % (member.user, member.commitment.slug)
def notify_round_started(): if not in_competition(): return today = datetime.datetime.today() prev_date = None current_round = "Overall Round" previous_round = 'Overall Round' for key, value in settings.COMPETITION_ROUNDS.items(): # We're looking for a round that ends today and another that starts today (or overall) start = datetime.datetime.strptime(value["start"], "%Y-%m-%d") end = datetime.datetime.strptime(value["end"], "%Y-%m-%d") # Check yesterday's round and check for the current round. if start < (today - datetime.timedelta(days=1)) < end: previous_round = key if start < today < end: current_round = key print 'Previous Round: %s' % previous_round print 'Current Round: %s' % current_round if current_round and previous_round and current_round != previous_round: print 'Sending out round transition notices.' template = NoticeTemplate.objects.get(notice_type="round-transition") message = template.render({ "PREVIOUS_ROUND": previous_round, "CURRENT_ROUND": current_round, }) for user in User.objects.all(): UserNotification.create_info_notification( user, message, display_alert=True, )
def testReadNotifications(self): """Test that notifications can be marked as read without AJAX.""" notification = UserNotification(recipient=self.user, contents="Test notification") notification.save() response = self.client.post(reverse("notifications_read", args=(notification.pk,)), {}) self.assertRedirects(response, reverse("home_index"), msg_prefix="Marking as read should redirect.") response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification", msg_prefix="Notification should be read") # Test with a referring page. notification = UserNotification(recipient=self.user, contents="Test notification 2") notification.save() response = self.client.post(reverse("notifications_read", args=(notification.pk,)), {}, HTTP_REFERER=reverse("help_index")) self.assertRedirects(response, reverse("help_index"), msg_prefix="Marking as read should redirect.") response = self.client.get(reverse("home_index")) self.assertNotContains(response, "Test notification 2", msg_prefix="Notification should be read")
def save(self, *args, **kwargs): """Custom save method to award/remove points if the activitymember is approved or rejected.""" if self.approval_status == u"pending": # Mark pending items as submitted. self.submission_date = datetime.datetime.today() elif self.approval_status == u"approved" and not self.award_date: # Award users points and update wall. self.award_date = datetime.datetime.today() # Determine how many points to award. if self.activity.has_variable_points: points = self.points_awarded else: points = self.activity.point_value if not self.submission_date: # This may happen if it is an item with a confirmation code. self.submission_date = self.award_date profile = self.user.get_profile() profile.add_points(points, self.submission_date) profile.save() if profile.floor: # Post on the user's floor wall. message = " has been awarded %d points for completing \"%s\"." % ( points, self.activity.title, ) post = Post(user=self.user, floor=profile.floor, text=message, style_class="system_post") post.save() elif self.approval_status != u"approved" and self.award_date: # Removing user points and resetting award date. # Determine how many points to remove. if self.activity.has_variable_points: points = self.points_awarded else: points = self.activity.point_value profile = self.user.get_profile() profile.remove_points(points, self.submission_date) profile.save() self.award_date = None self.submission_date = None # User will have to resubmit. super(ActivityMember, self).save() # We check here for a rejected item because it should have an id now. if self.approval_status == u"rejected": # Construct the message to be sent. message = "Your response to <a href='%s'>%s</a> was not approved." % ( reverse("activity_task", args=(self.activity.id,)), self.activity.title ) message += " You can still get points by clicking on the link and trying again." # message += " Please check your <a href='%s'>profile</a> for more information." % ( # reverse("profile_rejected", args=(self.id,)), # ) UserNotification.create_error_notification(self.user, message)
def process_rsvp(): members = ActivityMember.objects.filter(Q(activity__type="event") | Q(activity__type="excursion"), approval_status="pending") # try and load the notification template. template_noshow = None try: template_noshow = NoticeTemplate.objects.get( notice_type="event-noshow-penalty") except NoticeTemplate.DoesNotExist: pass template_reminder = None try: template_reminder = NoticeTemplate.objects.get( notice_type="event-post-reminder") except NoticeTemplate.DoesNotExist: pass for member in members: activity = member.activity user = member.user profile = user.get_profile() diff = datetime.date.today() - activity.event_date.date() if diff.days == 3: message = "%s: %s (No Show)" % (activity.type.capitalize(), activity.title) profile.remove_points( 4, datetime.datetime.today() - datetime.timedelta(minutes=1), message, member) profile.save() print "removed 4 points from %s for '%s'" % (profile.name, message) if template_noshow: message = template_noshow.render({"ACTIVITY": activity}) else: message = "4 points had been deducted from you, because you signed up but did not enter the confirmation code 2 days after the %s <a href='%s'>%s</a>, " % ( activity.type.capitalize(), reverse("activity_task", args=( activity.type, activity.slug, )), activity.title) message += " If you did attend, please click on the link to claim your points and reverse the deduction." UserNotification.create_info_notification(user, message, display_alert=True, content_object=member) print "created no-show penalty notification for %s for %s" % ( profile.name, activity.title) if diff.days == 2: if template_reminder: message = template_reminder.render({"ACTIVITY": activity}) else: message = "Hi %s, <p/> We just wanted to remind you that the %s <a href='http://%s%s'>%s</a> had ended. Please click on the link to claim your points." % ( profile.name, activity.type.capitalize(), Site.objects.get(id=settings.SITE_ID).domain, reverse("activity_task", args=( activity.type, activity.slug, )), activity.title) message += "<p/>Because you signed up for the event/excursion, if you do not enter the confirmation code within 2 days after the event/excusion, a total of 4 points (2 point signup bonus plus 2 point no-show penalty) will be deducted from your total points. So please enter your confirmation code early to avoid the penalty." message += "<p/><p/>Kukui Cup Administrators" subject = "[Kukui Cup] Reminder to enter your event/excursion confirmation code" UserNotification.create_email_notification(user.email, subject, message, message) print "sent post event email reminder to %s for %s" % ( profile.name, activity.title)