# -*- coding: utf-8 -*- """Forms for emencia.django.newsletter""" from datetime import date, datetime, timedelta import xlrd from city.models import City from country.models import Area, Country from django import forms from django.core.exceptions import ValidationError from django.db.models import Sum from django.http import Http404 from django.utils import translation from django.utils.translation import ugettext_lazy as _ from emencia.django.newsletter.models import ( Contact, ContactMailingStatus, ContactSettings, MailingList, Newsletter, PopupCount ) from functions.form_check import translit_with_separator as tr from functions.search_forms import get_by_lang from haystack.query import SearchQuerySet from theme.models import Theme class MailingListSubscriptionForm(forms.ModelForm): """Form for subscribing to a mailing list""" # Notes : This form will not check the uniquess of # the 'email' field, by defining it explictly and setting6 # it the Meta.exclude list, for allowing registration # to a mailing list even if the contact already exists. # Then the contact is always added to the subscribers field # of the mailing list because it will be cleaned with no # double. email = forms.EmailField(label=_('Email'), max_length=75) def save(self, mailing_list): data = self.cleaned_data contact, created = Contact.objects.get_or_create( email=data['email'], defaults={'first_name': data['first_name'], 'last_name': data['last_name']}) mailing_list.subscribers.add(contact) mailing_list.unsubscribers.remove(contact) class Meta: model = Contact fields = ('first_name', 'last_name') exclude = ('email',) class AllMailingListSubscriptionForm(MailingListSubscriptionForm): """Form for subscribing to all mailing list""" mailing_lists = forms.ModelMultipleChoiceField( queryset=MailingList.objects.all(), initial=[obj.id for obj in MailingList.objects.all()], label=_('Mailing lists'), widget=forms.CheckboxSelectMultiple()) def save(self, mailing_list): data = self.cleaned_data contact, created = Contact.objects.get_or_create( email=data['email'], defaults={'first_name': data['first_name'], 'last_name': data['last_name']}) for mailing_list in data['mailing_lists']: mailing_list.subscribers.add(contact) mailing_list.unsubscribers.remove(contact) class ContactForm(forms.ModelForm): email = forms.CharField(required=True, widget=forms.TextInput(attrs={'placeholder': _(u'Ваш e-mail')})) first_name = forms.CharField(required=True, widget=forms.TextInput(attrs={'placeholder': _(u'Ваше имя')})) class Meta: model = Contact fields = ('email', 'first_name', ) def clean_first_name(self): name = self.cleaned_data['first_name'] return name.capitalize() class ContactSettingsForm(forms.ModelForm): theme = forms.MultipleChoiceField(choices=[(str(item.id), item.name) for item in list(Theme.objects.language().all())], widget=forms.CheckboxSelectMultiple(attrs={'class': 'pr-checkbox'}), required=False) class Meta: model = ContactSettings fields = ('exponent_practicum', 'organiser_practicum', 'theme') def clean_theme(self): theme = self.cleaned_data.get('theme') if theme: return Theme.objects.filter(id__in=theme) else: return Theme.objects.none() class ContactFilterForm(forms.Form): email = forms.EmailField( label="Email", max_length=255, required=False, widget=forms.TextInput(attrs={'class':'input-xlarge search-query','placeholder': 'Email'}) ) theme = forms.MultipleChoiceField( label="Тематика", choices=[(t.id, t.name) for t in Theme.objects.language()], required=False ) country = forms.MultipleChoiceField( label="Страна", choices=[(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))], required=False ) city = forms.MultipleChoiceField( label="Город", choices=[(c.id, c.name) for c in list(set(City.objects.language('ru').filter(contactsettings__isnull=False)))], required=False, widget= forms.SelectMultiple(attrs={'id':'cities'}) ) area = forms.MultipleChoiceField( label="Area", choices=[(c.id, c.name) for c in list(set(Area.objects.language()))], required=False ) mailinglist = forms.ModelChoiceField( queryset=MailingList.objects.all(), label="Список рассылки", required=False ) created_from = forms.CharField(max_length=255, label=_(u"Создан с"), required=False) created_to = forms.CharField(max_length=255, label=_(u"Создан по"), required=False) not_active = forms.BooleanField(label=_(u"Не подтверждена подписка"), required=False) not_valid = forms.BooleanField(label=_(u"Неалидный Email"), required=False) not_subscriber = forms.BooleanField(label=_(u"Отписался"), required=False) def filter(self): title = u'contact list ' qs = Contact.objects.all().select_related('contactsettings') if self.cleaned_data.get('mailinglist'): qs = qs.filter(mailinglist_subscriber__id=self.cleaned_data['mailinglist'].pk) title += u" mailinglist: %s" % self.cleaned_data['mailinglist'].name if self.cleaned_data.get('country'): qs = qs.filter(contactsettings__country__id__in=self.cleaned_data['country']) title += u" countries: %s" % ','.join([obj.url for obj in Country.objects.language().filter(id__in=self.cleaned_data['country'])]) if self.cleaned_data.get('email'): qs = qs.filter(email__icontains=self.cleaned_data['email']) if self.cleaned_data.get('theme'): qs = qs.filter(contactsettings__theme__id__in=self.cleaned_data['theme']) title += u" themes: %s" % ','.join([obj.url for obj in Theme.objects.language().filter(id__in=self.cleaned_data['theme'])]) if self.cleaned_data.get('city'): qs = qs.filter(contactsettings__city__id__in=self.cleaned_data['city']) title += u" cities: %s" % ','.join([obj.url for obj in Country.objects.language().filter(id__in=self.cleaned_data['country'])]) if self.cleaned_data.get('area'): qs = qs.filter(contactsettings__area__id__in=self.cleaned_data['area']) title += u" geo area: %s" % ','.join([tr(obj.name) for obj in Area.objects.language('en').filter(id__in=self.cleaned_data['area'])]) if self.cleaned_data.get('not_active'): title = u' not active ' + title qs = qs.filter(activated=False) else: qs = qs.filter(activated=True) if self.cleaned_data.get('not_valid'): title = u'not valid e-mail ' + title qs = qs.filter(valid=False) else: qs = qs.filter(valid=True) if self.cleaned_data.get("created_from"): qs = qs.filter(creation_date__gte=datetime.strptime(self.cleaned_data['created_from'], "%d.%m.%Y")) if self.cleaned_data.get("created_to"): qs = qs.filter(creation_date__lt=datetime.strptime(self.cleaned_data['created_to'], "%d.%m.%Y")) if self.cleaned_data.get('not_subscriber'): qs = qs.filter(subscriber=False) else: qs = qs.filter(subscriber=True) qs = qs.distinct() return qs, title.replace('"', '\"').replace('\n', '') COUNTRY_CHOICES = [(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))] COUNTRY_CHOICES.insert(0, ('', _(u'Страна'))) class ContactImportForm(forms.Form): excel_file = forms.FileField(label=_(u'Выберите файл')) activated = forms.BooleanField(label=_(u"Активные"), required=False) is_tester = forms.BooleanField(label=_(u"Тестовые"), required=False) country = forms.ChoiceField(label=_(u"Страна"), choices=COUNTRY_CHOICES, required=False) def save(self): data = self.cleaned_data country_id = self.cleaned_data.get('country') country = None if country_id: country = Country.objects.get(id=country_id) activated = data['activated'] is_tester = data['is_tester'] f = data['excel_file'] book = xlrd.open_workbook(file_contents=f.read()) sheet = book.sheet_by_index(0) row_list = [sheet.row_values(row_number) for row_number in range(1, sheet.nrows)] for row in row_list: c = Contact(email = row[0], first_name=row[1], last_name="", tester=is_tester, activated=activated, valid=True, subscriber=True) try: c.save() except: continue cs = ContactSettings() cs.contact = c cs.save() if country: cs.country.add(country) cs.save() class AbstractSubscribeForm(forms.ModelForm): email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'})) class Meta: model = ContactSettings fields = ('periodic', 'exponent_practicum', 'organiser_practicum', 'theme', 'country', 'city') def clean_email(self): email = self.cleaned_data['email'] try: Contact.objects.get(email=email) except Contact.DoesNotExist: return email raise ValidationError(_(u'Такой email уже есть в базе даных')) def clean_city(self): cities = self.cleaned_data.get('city') if cities: res = [] for id in cities.split(','): try: res.append(int(id)) except ValueError: continue return City.objects.filter(id__in=res) else: return City.objects.none() def clean_country(self): countries = self.cleaned_data['country'] return Country.objects.filter(id__in=countries) def clean_theme(self): themes = self.cleaned_data['theme'] return Theme.objects.filter(id__in=themes) class SubscribeAssideForm(AbstractSubscribeForm): city = forms.CharField( widget=forms.HiddenInput(attrs={'id': 'id_subscription_city', 'placeholder': _(u'Город')}), required=False) periodic = forms.ChoiceField( choices=ContactSettings.PERIODIC_CHOICES, required=False, widget=forms.Select(attrs={'placeholder': _(u'Периодичность'), 'id': 'id_subscription_periodic'})) def __init__(self, *args, **kwargs): super(SubscribeAssideForm, self).__init__(*args, **kwargs) lang = translation.get_language() self.fields['theme'] = forms.MultipleChoiceField( choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()], widget=forms.SelectMultiple(attrs={'placeholder': _(u'Тематики'), 'id': 'id_subscription_theme'})) self.fields['country'] = forms.MultipleChoiceField( choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()], required=False, widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_subscription_country'})) class SubscribeSettingsForm(AbstractSubscribeForm): NA_ID = 12 ASIA_ID = 9 EUROPE_ID = 4 city = forms.CharField( widget=forms.HiddenInput(attrs={'id': 'id_sub_set_city', 'placeholder': _(u'Город')}), required=False) get_announce = forms.BooleanField(required=False, label=_(u'Получать анонсы')) na_expo = forms.BooleanField(required=False, label=_(u'Выставки Северной Америки')) asia_expo = forms.BooleanField(required=False, label=_(u'Выставки Азии')) europe_expo = forms.BooleanField(required=False, label=_(u'Выставки Европы')) def __init__(self, *args, **kwargs): self.contact = kwargs.pop('contact') self.activation_send = False lang = translation.get_language() self.cities_choices = dict(City.objects.language(lang).all().values_list('pk', 'name')) super(SubscribeSettingsForm, self).__init__(*args, **kwargs) self.fields['theme'] = forms.MultipleChoiceField( choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()], required=False, widget=forms.SelectMultiple(attrs={'placeholder': _(u'Тематики'), 'id': 'id_sub_set_theme'})) self.fields['country'] = forms.MultipleChoiceField( choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()], required=False, widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_sub_set_country'})) if self.instance.pk: self.initial['get_announce'] = self.instance.exponent_practicum or self.instance.organiser_practicum or self.instance.theme.exists() self.initial['city'] = ','.join(['%s:%s'%(pk, self.cities_choices.get(pk)) for pk in set(self.instance.city.all().values_list('pk', flat=True))]) def make_pretty_city_val(self): self.data = self.data.copy() self.data['city'] = ','.join(['%s:%s'%(pk, self.cities_choices.get(pk)) for pk in set(self.instance.city.all().values_list('pk', flat=True))]) def save_additional_fields(self, settings): get_announce = self.cleaned_data.get('get_announce') na_expo = self.cleaned_data.get('na_expo') asia_expo = self.cleaned_data.get('asia_expo') europe_expo = self.cleaned_data.get('europe_expo') if not get_announce: settings.organiser_practicum = False settings.exponent_practicum = False settings.save() settings.theme.clear() if na_expo: settings.area.add(Area.objects.get(id=self.NA_ID)) else: settings.area.remove(Area.objects.get(id=self.NA_ID)) if asia_expo: settings.area.add(Area.objects.get(id=self.ASIA_ID)) else: settings.area.remove(Area.objects.get(id=self.ASIA_ID)) if europe_expo: settings.area.add(Area.objects.get(id=self.EUROPE_ID)) else: settings.area.remove(Area.objects.get(id=self.EUROPE_ID)) return settings def save(self, commit=True): contactsettings = super(SubscribeSettingsForm, self).save(commit=False) # Prepare a 'save_m2m' method for the form, old_save_m2m = self.save_m2m def save_m2m(): old_save_m2m() contactsettings.theme.clear() for theme in self.cleaned_data['theme']: contactsettings.theme.add(theme) contactsettings.country.clear() for country in self.cleaned_data['country']: contactsettings.country.add(country) contactsettings.city.clear() for city in self.cleaned_data['city']: contactsettings.city.add(city) self.save_m2m = save_m2m if commit: contactsettings.save() self.save_m2m() return contactsettings def clean_email(self): if not self.contact: return super(SubscribeSettingsForm, self).clean_email() email = self.cleaned_data['email'] if self.contact.email != email: self.contact.activated = False self.contact.send_activation() self.save() self.activation_send = True return self.cleaned_data['email'] class PopupCountFilter(forms.Form): fr = forms.DateField(required=False) to = forms.DateField(required=False) def filter(self): fr = self.cleaned_data.get('fr') to = self.cleaned_data.get('to') if not fr and not to: fr = date.today() qs = PopupCount.objects.filter(date__gte=fr) contacts = Contact.objects.filter(creation_date__gte=fr) if to: contacts = contacts.filter(creation_date__lte=to+timedelta(days=1)) qs = qs.filter(date__lte=to) subscribed = contacts.count() activated = contacts.filter(activated=True).count() popups = qs.aggregate(count=Sum('cnt'))['count'] return {'subscribed': subscribed, 'activated': activated, 'popups': popups} class MailingStatusFilter(forms.Form): status = forms.ChoiceField(choices=[('', _(u'Не выбрано'))] + [(item[0], item[1]) for item in ContactMailingStatus.STATUS_CHOICES], required=False) email = forms.CharField(required=False, widget=forms.TextInput(attrs={'placeholder': 'Email'})) ab = forms.TypedChoiceField(required=False, choices=((0, _(u'Любое')), ) + Newsletter.AB_FINAL_CHOICE, coerce=int, empty_value=0) def filter(self, newsletter): status = self.cleaned_data.get('status') email = self.cleaned_data.get('email') ab = self.cleaned_data.get('ab') qs = ContactMailingStatus.objects.select_related().filter(newsletter=newsletter) if status: qs = qs.filter(status=status) if email: qs = qs.filter(contact__email=email) if ab: qs = qs.filter(ab=ab) return qs