views.py 18.6 KB
Newer Older
1 2 3 4
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
Sli's avatar
Sli committed
5
# - Sli <antoine@bartuccio.fr>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#

Skia's avatar
Skia committed
26
from django import forms
Sli's avatar
Sli committed
27
from enum import Enum
Skia's avatar
Skia committed
28
from django.views.generic import ListView, DetailView, TemplateView
Sli's avatar
Sli committed
29 30
from django.views.generic.edit import DeleteView, FormView
from django.views.generic.detail import SingleObjectMixin
Skia's avatar
Skia committed
31
from django.views.generic.edit import UpdateView, CreateView
Sli's avatar
Sli committed
32
from django.http import HttpResponseRedirect, HttpResponse
Sli's avatar
Sli committed
33
from django.core.urlresolvers import reverse, reverse_lazy
Skia's avatar
Skia committed
34
from django.utils import timezone
Skia's avatar
Skia committed
35
from django.utils.translation import ugettext_lazy as _
Sli's avatar
Sli committed
36
from django.utils.translation import ugettext as _t
Sli's avatar
Sli committed
37
from ajax_select.fields import AutoCompleteSelectField
Sli's avatar
Sli committed
38
from django.core.exceptions import PermissionDenied
Sli's avatar
Sli committed
39
from django.shortcuts import get_object_or_404
Skia's avatar
Skia committed
40

Sli's avatar
Sli committed
41
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin
Krophil's avatar
Krophil committed
42
from core.views.forms import SelectDate, SelectDateTime
Sli's avatar
Sli committed
43
from club.models import Club, Membership, Mailing, MailingSubscription
Krophil's avatar
Krophil committed
44 45 46
from sith.settings import SITH_MAXIMUM_FREE_ROLE
from counter.models import Selling, Counter

Sli's avatar
Sli committed
47 48
from django.conf import settings

Sli's avatar
Sli committed
49 50 51 52 53 54 55 56 57 58 59 60 61
# Custom forms


class MailingForm(forms.ModelForm):
    class Meta:
        model = Mailing
        fields = ('email', 'club')

    def __init__(self, *args, **kwargs):
        club_id = kwargs.pop('club_id', None)
        super(MailingForm, self).__init__(*args, **kwargs)
        if club_id:
            self.fields['club'].queryset = Club.objects.filter(id=club_id)
Sli's avatar
Sli committed
62 63
            self.fields['club'].initial = club_id
            self.fields['club'].widget = forms.HiddenInput()
Sli's avatar
Sli committed
64 65 66 67 68 69 70 71 72 73


class MailingSubscriptionForm(forms.ModelForm):
    class Meta:
        model = MailingSubscription
        fields = ('mailing', 'user', 'email')

    def __init__(self, *args, **kwargs):
        club_id = kwargs.pop('club_id', None)
        super(MailingSubscriptionForm, self).__init__(*args, **kwargs)
Sli's avatar
Sli committed
74
        self.fields['email'].required = False
Sli's avatar
Sli committed
75 76 77
        if club_id:
            self.fields['mailing'].queryset = Mailing.objects.filter(club__id=club_id)

Sli's avatar
Sli committed
78 79 80 81 82 83 84 85 86 87 88 89
    def clean(self):
        cleaned_data = super(MailingSubscriptionForm, self).clean()
        user = cleaned_data.get('user', None)
        email = cleaned_data.get('email', None)
        mailing = cleaned_data.get('mailing')
        if not user and not email:
            raise forms.ValidationError(_("At least user or email should be filled"))
        if user and not email:
            email = user.email
        if user and MailingSubscription.objects.filter(mailing=mailing, email=email).exists():
            raise forms.ValidationError(_("This email is already suscribed in this mailing"))

Sli's avatar
Sli committed
90 91
    user = AutoCompleteSelectField('users', label=_('User'), help_text=None, required=False)

92

93 94 95 96 97 98 99
class ClubTabsMixin(TabedViewMixin):
    def get_tabs_title(self):
        return self.object.get_display_name()

    def get_list_of_tabs(self):
        tab_list = []
        tab_list.append({
Krophil's avatar
Krophil committed
100 101
            'url': reverse('club:club_view', kwargs={'club_id': self.object.id}),
            'slug': 'infos',
102
                    'name': _("Infos"),
Krophil's avatar
Krophil committed
103
        })
104 105
        if self.request.user.can_view(self.object):
            tab_list.append({
Krophil's avatar
Krophil committed
106 107
                'url': reverse('club:club_members', kwargs={'club_id': self.object.id}),
                'slug': 'members',
108
                        'name': _("Members"),
Krophil's avatar
Krophil committed
109
            })
110
            tab_list.append({
Krophil's avatar
Krophil committed
111 112
                'url': reverse('club:club_old_members', kwargs={'club_id': self.object.id}),
                'slug': 'elderlies',
113
                        'name': _("Old members"),
Krophil's avatar
Krophil committed
114
            })
115 116
        if self.request.user.can_edit(self.object):
            tab_list.append({
Krophil's avatar
Krophil committed
117 118
                'url': reverse('club:tools', kwargs={'club_id': self.object.id}),
                'slug': 'tools',
119
                        'name': _("Tools"),
Krophil's avatar
Krophil committed
120
            })
121
            tab_list.append({
Krophil's avatar
Krophil committed
122 123
                'url': reverse('club:club_edit', kwargs={'club_id': self.object.id}),
                'slug': 'edit',
124
                        'name': _("Edit"),
Krophil's avatar
Krophil committed
125
            })
Skia's avatar
Skia committed
126
            tab_list.append({
Krophil's avatar
Krophil committed
127 128
                'url': reverse('club:club_sellings', kwargs={'club_id': self.object.id}),
                'slug': 'sellings',
Skia's avatar
Skia committed
129
                        'name': _("Sellings"),
Krophil's avatar
Krophil committed
130
            })
Sli's avatar
Sli committed
131 132 133 134 135
            tab_list.append({
                'url': reverse('club:mailing', kwargs={'club_id': self.object.id}),
                'slug': 'mailing',
                        'name': _("Mailing list"),
            })
136 137
        if self.request.user.is_owner(self.object):
            tab_list.append({
Krophil's avatar
Krophil committed
138 139
                'url': reverse('club:club_prop', kwargs={'club_id': self.object.id}),
                'slug': 'props',
140
                        'name': _("Props"),
Krophil's avatar
Krophil committed
141
            })
142 143
        return tab_list

Krophil's avatar
Krophil committed
144

Skia's avatar
Skia committed
145
class ClubListView(ListView):
Skia's avatar
Skia committed
146 147 148
    """
    List the Clubs
    """
149 150 151
    model = Club
    template_name = 'club/club_list.jinja'

Krophil's avatar
Krophil committed
152

153
class ClubView(ClubTabsMixin, DetailView):
Skia's avatar
Skia committed
154 155 156
    """
    Front page of a Club
    """
157 158 159
    model = Club
    pk_url_kwarg = "club_id"
    template_name = 'club/club_detail.jinja'
160
    current_tab = "infos"
161

Krophil's avatar
Krophil committed
162

163
class ClubToolsView(ClubTabsMixin, CanEditMixin, DetailView):
Skia's avatar
Skia committed
164 165 166 167 168 169
    """
    Tools page of a Club
    """
    model = Club
    pk_url_kwarg = "club_id"
    template_name = 'club/club_tools.jinja'
170
    current_tab = "tools"
Skia's avatar
Skia committed
171

Krophil's avatar
Krophil committed
172

Skia's avatar
Skia committed
173
class ClubMemberForm(forms.ModelForm):
Skia's avatar
Skia committed
174 175 176
    """
    Form handling the members of a club
    """
Skia's avatar
Skia committed
177 178
    error_css_class = 'error'
    required_css_class = 'required'
Krophil's avatar
Krophil committed
179

Skia's avatar
Skia committed
180 181
    class Meta:
        model = Membership
Skia's avatar
Skia committed
182 183
        fields = ['user', 'role', 'start_date', 'description']
        widgets = {
Krophil's avatar
Krophil committed
184 185
            'start_date': SelectDate
        }
Sli's avatar
Sli committed
186
    user = AutoCompleteSelectField('users', required=True, label=_("Select user"), help_text=None)
Skia's avatar
Skia committed
187

Skia's avatar
Skia committed
188 189 190 191
    def save(self, *args, **kwargs):
        """
        Overloaded to return the club, and not to a Membership object that has no view
        """
Krophil's avatar
Krophil committed
192
        super(ClubMemberForm, self).save(*args, **kwargs)
Skia's avatar
Skia committed
193 194
        return self.instance.club

Krophil's avatar
Krophil committed
195

196
class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
Skia's avatar
Skia committed
197 198 199
    """
    View of a club's members
    """
200 201
    model = Club
    pk_url_kwarg = "club_id"
Skia's avatar
Skia committed
202
    form_class = ClubMemberForm
203
    template_name = 'club/club_members.jinja'
204
    current_tab = "members"
205

Skia's avatar
Skia committed
206
    def get_form(self):
Skia's avatar
Skia committed
207 208 209 210
        """
        Here we get a Membership object, but the view handles Club object.
        That's why the save method of ClubMemberForm is overridden.
        """
Skia's avatar
Skia committed
211
        form = super(ClubMembersView, self).get_form()
Krophil's avatar
Krophil committed
212
        if 'user' in form.data and form.data.get('user') != '':  # Load an existing membership if possible
Skia's avatar
Skia committed
213
            form.instance = Membership.objects.filter(club=self.object).filter(user=form.data.get('user')).filter(end_date=None).first()
Krophil's avatar
Krophil committed
214
        if form.instance is None:  # Instanciate a new membership
Skia's avatar
Skia committed
215
            form.instance = Membership(club=self.object, user=self.request.user)
216 217
        if not self.request.user.is_root:
            form.fields.pop('start_date', None)
Sli's avatar
Sli committed
218 219
        # form.initial = {'user': self.request.user}
        # form._user = self.request.user
Skia's avatar
Skia committed
220 221
        return form

Sli's avatar
Sli committed
222 223 224 225 226 227 228 229 230 231
    def post(self, request, *args, **kwargs):
        """
            Check user rights
        """
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            ms = self.object.get_membership_for(request.user)
            if (form.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or
                (ms is not None and ms.role >= form.cleaned_data['role']) or
232
                request.user.is_board_member or
Krophil's avatar
Krophil committed
233
                    request.user.is_root):
Sli's avatar
Sli committed
234 235
                return self.form_valid(form)
            else:
Skia's avatar
Skia committed
236
                form.add_error(None, _("You do not have the permission to do that"))
Sli's avatar
Sli committed
237 238 239 240
                return self.form_invalid(form)
        else:
            return self.form_invalid(form)

Krophil's avatar
Krophil committed
241

242
class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):
Skia's avatar
Skia committed
243 244 245 246 247 248
    """
    Old members of a club
    """
    model = Club
    pk_url_kwarg = "club_id"
    template_name = 'club/club_old_members.jinja'
249
    current_tab = "elderlies"
Skia's avatar
Skia committed
250

Krophil's avatar
Krophil committed
251

Skia's avatar
Skia committed
252 253 254 255 256
class SellingsFormBase(forms.Form):
    begin_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Begin date"), required=False, widget=SelectDateTime)
    end_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End date"), required=False, widget=SelectDateTime)
    counter = forms.ModelChoiceField(Counter.objects.order_by('name').all(), label=_("Counter"), required=False)

Krophil's avatar
Krophil committed
257

Skia's avatar
Skia committed
258 259 260 261 262 263 264 265 266 267 268
class ClubSellingView(ClubTabsMixin, CanEditMixin, DetailView):
    """
    Sellings of a club
    """
    model = Club
    pk_url_kwarg = "club_id"
    template_name = 'club/club_sellings.jinja'
    current_tab = "sellings"

    def get_form_class(self):
        kwargs = {
Krophil's avatar
Krophil committed
269 270
            'product': forms.ModelChoiceField(self.object.products.order_by('name').all(), label=_("Product"), required=False)
        }
Skia's avatar
Skia committed
271 272 273 274
        return type('SellingsForm', (SellingsFormBase,), kwargs)

    def get_context_data(self, **kwargs):
        kwargs = super(ClubSellingView, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
275
        form = self.get_form_class()(self.request.GET)
Skia's avatar
Skia committed
276 277
        qs = Selling.objects.filter(club=self.object)
        if form.is_valid():
Skia's avatar
Skia committed
278 279
            if not len([v for v in form.cleaned_data.values() if v is not None]):
                qs = Selling.objects.filter(id=-1)
Skia's avatar
Skia committed
280 281 282 283 284 285 286 287 288 289
            if form.cleaned_data['begin_date']:
                qs = qs.filter(date__gte=form.cleaned_data['begin_date'])
            if form.cleaned_data['end_date']:
                qs = qs.filter(date__lte=form.cleaned_data['end_date'])
            if form.cleaned_data['counter']:
                qs = qs.filter(counter=form.cleaned_data['counter'])
            if form.cleaned_data['product']:
                qs = qs.filter(product__id=form.cleaned_data['product'].id)
            kwargs['result'] = qs.all().order_by('-id')
            kwargs['total'] = sum([s.quantity * s.unit_price for s in qs.all()])
Skia's avatar
Skia committed
290
            kwargs['total_quantity'] = sum([s.quantity for s in qs.all()])
Sli's avatar
Sli committed
291
            kwargs['benefit'] = kwargs['total'] - sum([s.product.purchase_price for s in qs.exclude(product=None)])
Skia's avatar
Skia committed
292 293 294 295 296
        else:
            kwargs['result'] = qs[:0]
        kwargs['form'] = form
        return kwargs

Krophil's avatar
Krophil committed
297

Sli's avatar
Sli committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311
class ClubSellingCSVView(ClubSellingView):
    """
    Generate sellings in csv for a given period
    """

    def get(self, request, *args, **kwargs):
        import csv
        response = HttpResponse(content_type='text/csv')
        self.object = self.get_object()
        name = _("Sellings") + "_" + self.object.name + ".csv"
        response['Content-Disposition'] = 'filename=' + name
        kwargs = self.get_context_data(**kwargs)
        writer = csv.writer(response, delimiter=";", lineterminator='\n', quoting=csv.QUOTE_ALL)

Sli's avatar
Sli committed
312 313 314
        writer.writerow([_t('Quantity'), kwargs['total_quantity']])
        writer.writerow([_t('Total'), kwargs['total']])
        writer.writerow([_t('Benefit'), kwargs['benefit']])
Krophil's avatar
Krophil committed
315 316
        writer.writerow([_t('Date'), _t('Counter'), _t('Barman'), _t('Customer'), _t('Label'),
                         _t('Quantity'), _t('Total'), _t('Payment method'), _t('Selling price'), _t('Purchase price'), _t('Benefit')])
Sli's avatar
Sli committed
317 318 319 320
        for o in kwargs['result']:
            row = [o.date, o.counter]
            if o.seller:
                row.append(o.seller.get_display_name())
Krophil's avatar
Krophil committed
321 322
            else:
                row.append('')
Sli's avatar
Sli committed
323 324
            if o.customer:
                row.append(o.customer.user.get_display_name())
Krophil's avatar
Krophil committed
325 326 327 328
            else:
                row.append('')
            row = row + [o.label, o.quantity, o.quantity * o.unit_price,
                         o.get_payment_method_display()]
Sli's avatar
Sli committed
329 330 331 332
            if o.product:
                row.append(o.product.selling_price)
                row.append(o.product.purchase_price)
                row.append(o.product.selling_price - o.product.purchase_price)
Krophil's avatar
Krophil committed
333 334
            else:
                row = row + ['', '', '']
Sli's avatar
Sli committed
335 336 337 338
            writer.writerow(row)

        return response

Krophil's avatar
Krophil committed
339

340
class ClubEditView(ClubTabsMixin, CanEditMixin, UpdateView):
Skia's avatar
Skia committed
341 342 343 344 345 346
    """
    Edit a Club's main informations (for the club's members)
    """
    model = Club
    pk_url_kwarg = "club_id"
    fields = ['address']
347 348
    template_name = 'core/edit.jinja'
    current_tab = "edit"
Skia's avatar
Skia committed
349

Krophil's avatar
Krophil committed
350

351
class ClubEditPropView(ClubTabsMixin, CanEditPropMixin, UpdateView):
Skia's avatar
Skia committed
352 353 354
    """
    Edit the properties of a Club object (for the Sith admins)
    """
355 356
    model = Club
    pk_url_kwarg = "club_id"
Skia's avatar
Skia committed
357
    fields = ['name', 'unix_name', 'parent']
358 359
    template_name = 'core/edit.jinja'
    current_tab = "props"
Skia's avatar
Skia committed
360

Krophil's avatar
Krophil committed
361

Skia's avatar
Skia committed
362 363 364 365 366 367 368
class ClubCreateView(CanEditPropMixin, CreateView):
    """
    Create a club (for the Sith admin)
    """
    model = Club
    pk_url_kwarg = "club_id"
    fields = ['name', 'unix_name', 'parent']
369
    template_name = 'core/edit.jinja'
Skia's avatar
Skia committed
370

Krophil's avatar
Krophil committed
371

Skia's avatar
Skia committed
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
class MembershipSetOldView(CanEditMixin, DetailView):
    """
    Set a membership as beeing old
    """
    model = Membership
    pk_url_kwarg = "membership_id"

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.end_date = timezone.now()
        self.object.save()
        return HttpResponseRedirect(reverse('club:club_members', args=self.args, kwargs={'club_id': self.object.club.id}))

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return HttpResponseRedirect(reverse('club:club_members', args=self.args, kwargs={'club_id': self.object.club.id}))

Krophil's avatar
Krophil committed
389

Skia's avatar
Skia committed
390
class ClubStatView(TemplateView):
Krophil's avatar
Krophil committed
391
    template_name = "club/stats.jinja"
Skia's avatar
Skia committed
392 393 394 395 396

    def get_context_data(self, **kwargs):
        kwargs = super(ClubStatView, self).get_context_data(**kwargs)
        kwargs['club_list'] = Club.objects.all()
        return kwargs
Sli's avatar
Sli committed
397 398 399 400 401 402 403 404


class MailingFormType(Enum):
    DISPLAY = 0
    MEMBER = 1
    MAILING = 2


Sli's avatar
Sli committed
405
class ClubMailingView(ClubTabsMixin, ListView):
Sli's avatar
Sli committed
406 407 408 409 410 411
    """
    A list of mailing for a given club
    """
    action = None
    model = Mailing
    template_name = "club/mailing.jinja"
Sli's avatar
Sli committed
412 413 414 415
    current_tab = 'mailing'

    def authorized(self):
        return self.club.has_rights_in_club(self.user) or self.user.is_root or self.user.is_board_member
Sli's avatar
Sli committed
416 417 418 419

    def dispatch(self, request, *args, **kwargs):
        self.club = get_object_or_404(Club, pk=kwargs['club_id'])
        self.user = request.user
Sli's avatar
Sli committed
420 421 422
        self.object = self.club
        if not self.authorized():
            raise PermissionDenied
Sli's avatar
Sli committed
423 424 425 426 427 428 429 430 431 432
        self.member_form = MailingSubscriptionForm(club_id=self.club.id)
        self.mailing_form = MailingForm(club_id=self.club.id)
        return super(ClubMailingView, self).dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        res = super(ClubMailingView, self).get(request, *args, **kwargs)
        if self.action != MailingFormType.DISPLAY:
            if self.action == MailingFormType.MAILING:
                form = MailingForm
                string = 'new_mailing'
Sli's avatar
Sli committed
433
                model = Mailing
Sli's avatar
Sli committed
434 435 436
            elif self.action == MailingFormType.MEMBER:
                form = MailingSubscriptionForm
                string = 'new_member'
Sli's avatar
Sli committed
437 438
                model = MailingSubscription
            return MailingGenericCreateView.as_view(model=model, list_view=self, form_class=form, form_kwarg_string=string)(request, *args, **kwargs)
Sli's avatar
Sli committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
        return res

    def get_queryset(self):
        return Mailing.objects.filter(club_id=self.club.id).all()

    def get_context_data(self, **kwargs):
        kwargs = super(ClubMailingView, self).get_context_data(**kwargs)
        kwargs['new_member'] = self.member_form
        kwargs['new_mailing'] = self.mailing_form
        kwargs['club'] = self.club
        kwargs['user'] = self.user
        kwargs['has_objects'] = len(kwargs['object_list']) > 0
        return kwargs


Sli's avatar
Sli committed
454
class MailingGenericCreateView(CreateView, SingleObjectMixin):
Sli's avatar
Sli committed
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
    """
    Create a new mailing list
    """
    list_view = None
    form_class = None
    form_kwarg_string = None

    def get_context_data(self, **kwargs):
        view_kwargs = self.list_view.get_context_data(**kwargs)
        for key, data in super(MailingGenericCreateView, self).get_context_data(**kwargs).items():
            view_kwargs[key] = data
        view_kwargs[self.form_kwarg_string] = view_kwargs['form']
        return view_kwargs

    def get_form_kwargs(self):
        kwargs = super(MailingGenericCreateView, self).get_form_kwargs()
        kwargs['club_id'] = self.list_view.club.id
        return kwargs

    def dispatch(self, request, *args, **kwargs):
Sli's avatar
Sli committed
475 476
        if not self.list_view.authorized():
            raise PermissionDenied
Sli's avatar
Sli committed
477 478 479 480 481
        self.template_name = self.list_view.template_name
        return super(MailingGenericCreateView, self).dispatch(request, *args, **kwargs)

    def get_success_url(self, **kwargs):
        return reverse_lazy('club:mailing', kwargs={'club_id': self.list_view.club.id})
Sli's avatar
Sli committed
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509


class MailingDeleteView(CanEditMixin, DeleteView):

    model = Mailing
    template_name = 'core/delete_confirm.jinja'
    pk_url_kwarg = "mailing_id"

    def dispatch(self, request, *args, **kwargs):
        self.club_id = self.get_object().club.id
        return super(MailingDeleteView, self).dispatch(request, *args, **kwargs)

    def get_success_url(self, **kwargs):
        return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id})


class MailingSubscriptionDeleteView(CanEditMixin, DeleteView):

    model = MailingSubscription
    template_name = 'core/delete_confirm.jinja'
    pk_url_kwarg = "mailing_subscription_id"

    def dispatch(self, request, *args, **kwargs):
        self.club_id = self.get_object().mailing.club.id
        return super(MailingSubscriptionDeleteView, self).dispatch(request, *args, **kwargs)

    def get_success_url(self, **kwargs):
        return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id})
Sli's avatar
Sli committed
510 511 512 513 514 515 516 517 518 519 520 521


class MailingFetchView(ListView):

    model = Mailing
    template_name = 'club/mailing_output.jinja'

    def dispatch(self, request, *args, **kwargs):
        key = request.GET.get('key', '')
        if key != settings.SITH_MAILING_FETCH_KEY:
            raise PermissionDenied
        return super(MailingFetchView, self).dispatch(request, *args, **kwargs)