taiga-back/greenmine/base/notifications/models.py

135 lines
4.8 KiB
Python

# -*- coding: utf-8 -*-
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.utils.translation import ugettext_lazy as _
import reversion
class WatcherMixin(object):
NOTIFY_LEVEL_CHOICES = (
("all_owned_projects", _(u"All events on my projects")),
("only_watching", _(u"Only events for objects i watch")),
("only_assigned", _(u"Only events for objects assigned to me")),
("only_owner", _(u"Only events for objects owned by me")),
("no_events", _(u"No events")),
)
notify_level = models.CharField(max_length=32, null=False, blank=False, default="only_watching",
choices=NOTIFY_LEVEL_CHOICES, verbose_name=_(u"notify level"))
notify_changes_by_me = models.BooleanField(null=False, blank=True,
verbose_name=_(u"notify changes made by me"))
class Meta:
abstract = True
def allow_notify_owned(self):
return (self.notify_level in [
"only_owner",
"only_assigned",
"only_watching",
"all_owned_projects",
])
def allow_notify_assigned_to(self):
return (self.notify_level in [
"only_assigned",
"only_watching",
"all_owned_projects",
])
def allow_notify_suscribed(self):
return (self.notify_level in [
"only_watching",
"all_owned_projects",
])
def allow_notify_project(self, project):
return self.notify_level == "all_owned_projects" and project.owner.pk == self.pk
def allow_notify_by_me(self, changer):
return (changer.pk != self.pk) or self.notify_changes_by_me
class WatchedMixin(object):
class Meta:
abstract = True
@property
def last_version(self):
version_list = reversion.get_for_object(self)
return version_list and version_list[0] or None
def get_changed_fields_dict(self, data_dict):
field_dict = {}
for field_name, data_value in data_dict.items():
field_dict.update(self._get_changed_field(field_name, data_value))
return field_dict
def get_watchers_to_notify(self, changer):
watchers_to_notify = set()
watchers_by_role = self._get_watchers_by_role()
owner = watchers_by_role.get("owner")
if (owner and owner.allow_notify_owned()
and owner.allow_notify_by_me(changer)):
watchers_to_notify.add(owner)
assigned_to = watchers_by_role.get("assigned_to")
if (assigned_to and assigned_to.allow_notify_assigned_to()
and assigned_to.allow_notify_by_me(changer)):
watchers_to_notify.add(assigned_to)
suscribed_watchers = watchers_by_role.get("suscribed_watchers")
if suscribed_watchers:
for suscribed_watcher in suscribed_watchers:
if (suscribed_watcher and suscribed_watcher.allow_notify_suscribed()
and suscribed_watcher.allow_notify_by_me(changer)):
watchers_to_notify.add(suscribed_watcher)
#(project, project_owner) = watchers_by_role.get("project_owner")
#if project_owner \
# and project_owner.allow_notify_project(project) \
# and project_owner.allow_notify_by_me(self._changer):
# watchers_to_notify.add(project_owner)
return watchers_to_notify
def _get_changed_field_verbose_name(self, field_name):
try:
return self._meta.get_field(field_name).verbose_name
except FieldDoesNotExist:
return field_name
def _get_changed_field_old_value(self, field_name, data_value):
return (self.last_version and self.last_version.field_dict.get(field_name, data_value) or None)
def _get_changed_field_new_value(self, field_name, data_value):
return getattr(self, field_name, data_value)
def _get_changed_field(self, field_name, data_value):
verbose_name = self._get_changed_field_verbose_name(field_name)
old_value = self._get_changed_field_old_value(field_name, data_value)
new_value = self._get_changed_field_new_value(field_name, data_value)
return {field_name: {
"verbose_name": verbose_name,
"old_value": old_value,
"new_value": new_value,
}}
def _get_watchers_by_role(self):
"""
Return the actual instances of watchers of this object, classified by role.
For example:
return {
"owner": self.owner,
"assigned_to": self.assigned_to,
"suscribed_watchers": self.watchers.all(),
"project_owner": (self.project, self.project.owner),
}
"""
raise NotImplementedError("You must subclass WatchedMixin and provide _get_watchers_by_role method")