gault-millau/apps/notification/models.py
2020-01-28 15:09:57 +03:00

209 lines
6.8 KiB
Python

"""Notification app models."""
from django.conf import settings
from django.db import models
from django.db.models import F
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from account.models import User
from location.models import Country
from notification.tasks import send_unsubscribe_email
from utils.methods import generate_string_code
from utils.models import ProjectBaseMixin, TJSONField, TranslatedFieldsMixin
from notification.tasks import send_unsubscribe_email
class SubscriptionType(ProjectBaseMixin, TranslatedFieldsMixin):
index_name = models.CharField(max_length=255, verbose_name=_('Index name'), unique=True)
name = TJSONField(blank=True, null=True, default=None,
verbose_name=_('name'),
help_text='{"en-GB":"some text"}')
country = models.ForeignKey(Country, on_delete=models.PROTECT,
blank=True, null=True, default=None,
verbose_name=_('country'))
# todo: associate user & subscriber after users registration
class SubscriberManager(models.Manager):
"""Extended manager for Subscriber model."""
def make_subscriber(self, email=None, user=None, ip_address=None, country_code=None,
locale=None, subscription_types=None, *args, **kwargs):
"""Make subscriber and update info."""
# search existing object
if not user:
user = User.objects.filter(email=email).first()
if user:
obj = self.model.objects.filter(user=user).first()
if obj is None:
obj = self.model.objects.filter(email=user.email).first()
self.associate_user(user=user)
else:
obj = self.model.objects.filter(email=email).first()
# update or create
if obj:
if user:
obj.user = user
obj.email = None
else:
obj.email = email
obj.ip_address = ip_address
obj.country_code = country_code
obj.locale = locale
obj.update_code = generate_string_code()
obj.save()
else:
obj = self.model.objects.create(
user=user, email=email, ip_address=ip_address,
country_code=country_code, locale=locale,
)
if subscription_types is None:
subscription_types = []
obj.subscription_types.set(subscription_types)
obj.subscribe_set.update(unsubscribe_date=None)
obj.save()
return obj
def associate_user(self, user):
"""Associate user."""
obj = self.model.objects.filter(user=user).first()
if obj is None:
obj = self.model.objects.filter(email=user.email_confirmed, user__isnull=True).first()
if obj:
obj.user = user
obj.email = user.email
obj.save()
return obj
class Subscriber(ProjectBaseMixin):
"""Subscriber model."""
user = models.ForeignKey(
User,
blank=True,
null=True,
default=None,
on_delete=models.SET_NULL,
related_name='subscriber',
verbose_name=_('User'),
)
email = models.EmailField(blank=True, null=True, default=None, unique=True, verbose_name=_('Email'))
ip_address = models.GenericIPAddressField(blank=True, null=True, default=None, verbose_name=_('IP address'))
country_code = models.CharField(max_length=10, blank=True, null=True, default=None, verbose_name=_('Country code'))
locale = models.CharField(blank=True, null=True, default=None, max_length=10, verbose_name=_('Locale identifier'))
update_code = models.CharField(
max_length=254,
blank=True,
null=True,
default=None,
db_index=True,
verbose_name=_('Token'),
)
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
subscription_types = models.ManyToManyField(SubscriptionType, through='Subscribe')
objects = SubscriberManager()
class Meta:
"""Meta class."""
verbose_name = _('Subscriber')
verbose_name_plural = _('Subscribers')
def save(self, *args, **kwargs):
"""Overrided save method."""
if self.update_code is None:
self.update_code = generate_string_code()
return super(Subscriber, self).save(*args, **kwargs)
def unsubscribe(self):
"""Unsubscribe user."""
self.subscribe_set.update(
unsubscribe_date=now(),
old_subscriber_id=F('subscriber_id'),
old_subscription_type_id=F('subscription_type_id')
)
self.subscribe_set.update(
subscriber_id=None,
subscription_type_id=None
)
if settings.USE_CELERY:
send_unsubscribe_email.delay(self.pk)
else:
send_unsubscribe_email(self.pk)
@property
def send_to(self):
"""Actual email."""
return self.user.email if self.user else self.email
@property
def link_to_unsubscribe(self):
"""Link to unsubscribe."""
schema = settings.SCHEMA_URI
site_domain = settings.DOMAIN_URI
url = settings.SITE_REDIRECT_URL_UNSUBSCRIBE
query = f'?code={self.update_code}'
country_code = '%s.' % self.country_code if self.country_code else ''
return f'{schema}://{country_code}{site_domain}{url}{query}'
@property
def active_subscriptions(self):
return self.subscription_types.exclude(subscriber__subscribe__unsubscribe_date__isnull=False)
@property
def subscription_history(self):
return Subscribe.objects.subscription_history(self.pk)
class SubscribeQuerySet(models.QuerySet):
def active(self, switcher=True):
"""Fetches active subscriptions."""
return self.exclude(unsubscribe_date__isnull=not switcher)
def subscription_history(self, subscriber_id: int):
return self.filter(old_subscriber_id=subscriber_id)
class Subscribe(ProjectBaseMixin):
"""Subscribe model."""
unsubscribe_date = models.DateTimeField(_('Last unsubscribe date'), blank=True, null=True, default=None)
subscriber = models.ForeignKey(Subscriber, on_delete=models.CASCADE, null=True)
subscription_type = models.ForeignKey(SubscriptionType, on_delete=models.CASCADE, null=True)
old_subscriber_id = models.PositiveIntegerField(_("Old subscriber id"), null=True)
old_subscription_type_id = models.PositiveIntegerField(_("Old subscription type id"), null=True)
objects = SubscribeQuerySet.as_manager()
@property
def subscribe_date(self):
return self.created
class Meta:
"""Meta class."""
verbose_name = _('Subscribe')
verbose_name_plural = _('Subscribes')