|
| 1 | +from django.db import models |
| 2 | +from django.conf import settings |
| 3 | +from django.utils.translation import ugettext as _ |
| 4 | +from django.contrib.contenttypes.models import ContentType |
| 5 | +from django.contrib.contenttypes import generic |
| 6 | +from django.contrib.auth.models import User |
| 7 | +from django.template.loader import render_to_string |
| 8 | +from django.template import loader, Context |
| 9 | +from django.core.mail import send_mass_mail, EmailMessage |
| 10 | + |
| 11 | +from busylizzy.blproject.models import Project |
| 12 | + |
| 13 | +class ActivityManager(models.Manager): |
| 14 | + """ Manager for retrieving activities """ |
| 15 | + def get_activities_for_project(self, project_slug, limit=None): |
| 16 | + """ Return the latest activities for a project """ |
| 17 | + return self.filter(project__slug=project_slug) |
| 18 | + |
| 19 | +class Activity(models.Model): |
| 20 | + """ Saving an activity """ |
| 21 | + CREATE = 1 |
| 22 | + UPDATE = 2 |
| 23 | + DELETE = 3 |
| 24 | + CLOSE = 4 |
| 25 | + COMMENT = 5 |
| 26 | + INVITE = 6 |
| 27 | + START = 7 |
| 28 | + ADMIN = 8 |
| 29 | + JOIN = 9 |
| 30 | + |
| 31 | + ACTION_CHOICES = ( |
| 32 | + (CREATE, _('created')), |
| 33 | + (UPDATE, _('updated')), |
| 34 | + (DELETE, _('deleted')), |
| 35 | + (CLOSE, _('closed')), |
| 36 | + (COMMENT, _('commented on')), |
| 37 | + (INVITE, _('invited')), |
| 38 | + (START, _('started')), |
| 39 | + (ADMIN, _('permissions')), |
| 40 | + (JOIN, _('joined')), |
| 41 | + ) |
| 42 | + |
| 43 | + actor = models.ForeignKey(User, related_name='activities') |
| 44 | + action = models.SmallIntegerField(_('action'), choices=ACTION_CHOICES) |
| 45 | + project = models.ForeignKey(Project, related_name='activities') |
| 46 | + time = models.DateTimeField(_('time'), auto_now_add=True) |
| 47 | + |
| 48 | + # Direct object |
| 49 | + object_id = models.PositiveIntegerField() |
| 50 | + content_type = models.ForeignKey(ContentType, related_name='activity_objects') |
| 51 | + content_object = generic.GenericForeignKey('content_type', 'object_id') |
| 52 | + |
| 53 | + # Indirect object |
| 54 | + indirect_object_id = models.PositiveIntegerField(blank=True, null=True) |
| 55 | + indirect_content_type = models.ForeignKey(ContentType, related_name='activity_indirect_objects', blank=True, null=True) |
| 56 | + indirect_content_object = generic.GenericForeignKey('indirect_content_type', 'indirect_object_id') |
| 57 | + |
| 58 | + objects = ActivityManager() |
| 59 | + |
| 60 | + def __unicode__(self): |
| 61 | + return self.humanize(admin=True).strip() |
| 62 | + |
| 63 | + def save(self, *args, **kwargs): |
| 64 | + """ |
| 65 | + When saving an activity e-mail notification to project members |
| 66 | + """ |
| 67 | + super(Activity, self).save(*args, **kwargs) |
| 68 | + |
| 69 | + # Send mail as notification |
| 70 | + if settings.EMAIL_NOTIFICATIONS is True: |
| 71 | + mail_data = self.prepare_mail() |
| 72 | + mail_data.send() |
| 73 | + |
| 74 | + class Meta: |
| 75 | + verbose_name = _('activity') |
| 76 | + verbose_name_plural = _('activities') |
| 77 | + ordering = ['-time'] |
| 78 | + |
| 79 | + @property |
| 80 | + def app_label(self): |
| 81 | + """ |
| 82 | + Returns the ``app_label`` so we can search for the templates. |
| 83 | + |
| 84 | + """ |
| 85 | + return self.content_type.app_label |
| 86 | + |
| 87 | + def _get_template_for_action(self, mail=''): |
| 88 | + """ Returns the template for this action """ |
| 89 | + options = ['%(app_label)s/actions/%(action)s%(mail)s.txt' % {'app_label': self.app_label, |
| 90 | + 'action': self.get_action_display().replace(' ',''), |
| 91 | + 'mail': mail, |
| 92 | + }, |
| 93 | + '%(app_label)s/actions/generic%(mail)s.txt' % {'app_label': self.app_label, |
| 94 | + 'mail': mail }, |
| 95 | + 'blactivity/generic.txt'] |
| 96 | + t = loader.select_template(options) |
| 97 | + return t |
| 98 | + |
| 99 | + def humanize(self, admin=False, mail=False): |
| 100 | + """ Returns a sentence of the committed action """ |
| 101 | + if admin: |
| 102 | + template = loader.get_template('blactivity/admin.txt') |
| 103 | + elif mail: |
| 104 | + template = self._get_template_for_action('_mail') |
| 105 | + else: |
| 106 | + template = self._get_template_for_action() |
| 107 | + |
| 108 | + context = Context( |
| 109 | + {'actor': self.actor.username, |
| 110 | + 'actor_id': self.actor.id, |
| 111 | + 'action': self.get_action_display(), |
| 112 | + 'project': self.project, |
| 113 | + 'project_id': self.project.id, |
| 114 | + 'time': self.time, |
| 115 | + 'object': self.content_object, |
| 116 | + 'object_id': self.object_id, |
| 117 | + 'object_type': self.content_type, |
| 118 | + 'indirect_object': self.indirect_content_object if self.indirect_object_id else None, |
| 119 | + 'indirect_object_id': self.indirect_object_id if self.indirect_object_id else None, |
| 120 | + 'MEDIA_URL': settings.MEDIA_URL, |
| 121 | + }) |
| 122 | + sentence = template.render(context) |
| 123 | + return sentence |
| 124 | + |
| 125 | + def prepare_mail(self): |
| 126 | + """ Prepare mass mail """ |
| 127 | + subject = "[%(project)s] New activity" % {'project': self.project } |
| 128 | + message = self.humanize(mail=True) |
| 129 | + from_email = settings.EMAIL_HOST_USER |
| 130 | + |
| 131 | + email = EmailMessage(subject, message, from_email, self.recipient_list()) |
| 132 | + email.content_subtype = "html" |
| 133 | + |
| 134 | + return email |
| 135 | + |
| 136 | + def recipient_list(self): |
| 137 | + """ Return list with all recipient for mail """ |
| 138 | + recipient_list = [] |
| 139 | + for member in self.project.members.all(): |
| 140 | + try: |
| 141 | + profile = member.get_profile() |
| 142 | + except: |
| 143 | + pass |
| 144 | + else: |
| 145 | + if profile.notifications: |
| 146 | + recipient_list.append(member.email) |
| 147 | + |
| 148 | + if len(recipient_list) > 0: |
| 149 | + return recipient_list |
| 150 | + else: return None |
0 commit comments