user.py 20.2 KB
Newer Older
Skia's avatar
Skia committed
1
2
# This file contains all the views that concern the user model
from django.shortcuts import render, redirect, get_object_or_404
Skia's avatar
Skia committed
3
from django.contrib.auth import logout as auth_logout, views
4
from django.utils.translation import ugettext as _
5
from django.core.urlresolvers import reverse
6
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist, ValidationError
Skia's avatar
Skia committed
7
from django.http import Http404
Skia's avatar
Skia committed
8
from django.views.generic.edit import UpdateView
Sli's avatar
Sli committed
9
from django.views.generic import ListView, DetailView, TemplateView, DeleteView
10
11
from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple
Skia's avatar
Skia committed
12
from django.template.response import TemplateResponse
Skia's avatar
Skia committed
13
from django.conf import settings
Sli's avatar
Sli committed
14
from django.views.generic.dates import YearMixin, MonthMixin
15

Sli's avatar
Sli committed
16
17
from django.utils import timezone
from datetime import timedelta, datetime, date
Skia's avatar
Skia committed
18
19
import logging

Skia's avatar
Skia committed
20
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, QuickNotifMixin
Skia's avatar
Skia committed
21
from core.views.forms import RegisteringForm, UserPropForm, UserProfileForm, LoginForm, UserGodfathersForm
Skia's avatar
Skia committed
22
from core.models import User, SithFile, Preferences
Lo-J's avatar
Lo-J committed
23
from club.models import Club
Skia's avatar
Skia committed
24
from subscription.models import Subscription
Skia's avatar
Skia committed
25

Skia's avatar
Skia committed
26
27
28
29
30
31
def login(request):
    """
    The login view

    Needs to be improve with correct handling of form exceptions
    """
Skia's avatar
Skia committed
32
    return views.login(request, template_name="core/login.jinja", authentication_form=LoginForm)
Skia's avatar
Skia committed
33
34
35
36
37
38
39
40
41
42
43

def logout(request):
    """
    The logout view
    """
    return views.logout_then_login(request)

def password_change(request):
    """
    Allows a user to change its password
    """
Skia's avatar
Skia committed
44
    return views.password_change(request, template_name="core/password_change.jinja", post_change_redirect=reverse("core:password_change_done"))
Skia's avatar
Skia committed
45
46
47
48
49

def password_change_done(request):
    """
    Allows a user to change its password
    """
Skia's avatar
Skia committed
50
    return views.password_change_done(request, template_name="core/password_change_done.jinja")
Skia's avatar
Skia committed
51

Skia's avatar
Skia committed
52
53
54
55
def password_root_change(request, user_id):
    """
    Allows a root user to change someone's password
    """
Skia's avatar
Skia committed
56
    if not request.user.is_root:
Skia's avatar
Skia committed
57
58
59
60
61
62
63
64
65
66
67
68
69
        raise PermissionDenied
    user = User.objects.filter(id=user_id).first()
    if not user:
        raise Http404("User not found")
    if request.method == "POST":
        form = views.SetPasswordForm(user=user, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect("core:password_change_done")
    else:
        form = views.SetPasswordForm(user=user)
    return TemplateResponse(request, "core/password_change.jinja", {'form': form, 'target': user})

Skia's avatar
Skia committed
70
def password_reset(request):
Skia's avatar
Skia committed
71
72
73
    """
    Allows someone to enter an email adresse for resetting password
    """
Skia's avatar
Skia committed
74
    return views.password_reset(request,
Skia's avatar
Skia committed
75
76
                                template_name="core/password_reset.jinja",
                                email_template_name="core/password_reset_email.jinja",
Skia's avatar
Skia committed
77
                                post_reset_redirect="core:password_reset_done",
Skia's avatar
Skia committed
78
                               )
Skia's avatar
Skia committed
79
80

def password_reset_done(request):
Skia's avatar
Skia committed
81
82
83
    """
    Confirm that the reset email has been sent
    """
Skia's avatar
Skia committed
84
    return views.password_reset_done(request, template_name="core/password_reset_done.jinja")
Skia's avatar
Skia committed
85

Skia's avatar
Skia committed
86
def password_reset_confirm(request, uidb64=None, token=None):
Skia's avatar
Skia committed
87
88
89
    """
    Provide a reset password formular
    """
Skia's avatar
Skia committed
90
91
    return views.password_reset_confirm(request, uidb64=uidb64, token=token,
                                        post_reset_redirect="core:password_reset_complete",
Skia's avatar
Skia committed
92
                                        template_name="core/password_reset_confirm.jinja",
Skia's avatar
Skia committed
93
94
95
                                       )

def password_reset_complete(request):
Skia's avatar
Skia committed
96
97
98
    """
    Confirm the password has sucessfully been reset
    """
Skia's avatar
Skia committed
99
    return views.password_reset_complete(request,
Skia's avatar
Skia committed
100
                                         template_name="core/password_reset_complete.jinja",
Skia's avatar
Skia committed
101
                                        )
Skia's avatar
Skia committed
102

Skia's avatar
Skia committed
103
def register(request):
Skia's avatar
Skia committed
104
    context = {}
Skia's avatar
Skia committed
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    if request.method == 'POST':
        form = RegisteringForm(request.POST)
        if form.is_valid():
            logging.debug("Registering "+form.cleaned_data['first_name']+form.cleaned_data['last_name'])
            u = form.save()
            context['user_registered'] = u
            context['tests'] = 'TEST_REGISTER_USER_FORM_OK'
            form = RegisteringForm()
        else:
            context['error'] = 'Erreur'
            context['tests'] = 'TEST_REGISTER_USER_FORM_FAIL'
    else:
        form = RegisteringForm()
    context['form'] = form.as_p()
Skia's avatar
Skia committed
119
    return render(request, "core/register.jinja", context)
Skia's avatar
Skia committed
120

121
122
123
124
125
126
127
128
129
130
131
class UserTabsMixin(TabedViewMixin):
    def get_tabs_title(self):
        return self.object.get_display_name()

    def get_list_of_tabs(self):
        tab_list = []
        tab_list.append({
                    'url': reverse('core:user_profile', kwargs={'user_id': self.object.id}),
                    'slug': 'infos',
                    'name': _("Infos"),
                    })
Skia's avatar
Skia committed
132
133
        tab_list.append({
                    'url': reverse('core:user_godfathers', kwargs={'user_id': self.object.id}),
Skia's avatar
Skia committed
134
                    'slug': 'godfathers',
Skia's avatar
Skia committed
135
136
                    'name': _("Godfathers"),
                    })
Skia's avatar
Skia committed
137
138
139
140
141
        tab_list.append({
                    'url': reverse('core:user_pictures', kwargs={'user_id': self.object.id}),
                    'slug': 'pictures',
                    'name': _("Pictures"),
                    })
142
143
144
145
146
147
148
149
150
151
152
153
        if self.request.user == self.object:
            tab_list.append({
                        'url': reverse('core:user_tools'),
                        'slug': 'tools',
                        'name': _("Tools"),
                        })
        if self.request.user.can_edit(self.object):
            tab_list.append({
                        'url': reverse('core:user_edit', kwargs={'user_id': self.object.id}),
                        'slug': 'edit',
                        'name': _("Edit"),
                        })
Skia's avatar
Skia committed
154
155
156
157
158
            tab_list.append({
                        'url': reverse('core:user_prefs', kwargs={'user_id': self.object.id}),
                        'slug': 'prefs',
                        'name': _("Preferences"),
                        })
Lo-J's avatar
Lo-J committed
159
160
161
162
163
164
        if self.request.user.can_view(self.object):
            tab_list.append({
                        'url': reverse('core:user_clubs', kwargs={'user_id': self.object.id}),
                        'slug': 'clubs',
                        'name': _("Clubs"),
                        })
165
166
167
168
169
170
171
172
        if self.request.user.is_owner(self.object):
            tab_list.append({
                        'url': reverse('core:user_groups', kwargs={'user_id': self.object.id}),
                        'slug': 'groups',
                        'name': _("Groups"),
                        })
        try:
            if (self.object.customer and (self.object == self.request.user
Skia's avatar
Skia committed
173
                or self.request.user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
174
                or self.request.user.is_in_group(settings.SITH_BAR_MANAGER['unix_name']+settings.SITH_BOARD_SUFFIX)
175
                or self.request.user.is_root)):
176
177
178
179
180
                tab_list.append({
                            'url': reverse('core:user_stats', kwargs={'user_id': self.object.id}),
                            'slug': 'stats',
                            'name': _("Stats"),
                            })
181
182
183
184
185
186
187
188
189
                tab_list.append({
                            'url': reverse('core:user_account', kwargs={'user_id': self.object.id}),
                            'slug': 'account',
                            'name': _("Account")+" (%s €)" % self.object.customer.amount,
                            })
        except: pass
        return tab_list

class UserView(UserTabsMixin, CanViewMixin, DetailView):
Skia's avatar
Skia committed
190
191
192
    """
    Display a user's profile
    """
Skia's avatar
Skia committed
193
194
195
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
Skia's avatar
Skia committed
196
    template_name = "core/user_detail.jinja"
197
    current_tab = 'infos'
Skia's avatar
Skia committed
198

Sli's avatar
Sli committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

def DeleteUserGodfathers(request, user_id, godfather_id, is_father):
    user = User.objects.get(id=user_id)
    if ((user == request.user) or
         request.user.is_root or
         request.user.is_board_member):
        ud = get_object_or_404(User, id=godfather_id)
        if is_father == "True":
            user.godfathers.remove(ud)
        else:
            user.godchildren.remove(ud)
    else:
        raise PermissionDenied
    return redirect('core:user_godfathers', user_id=user_id)

Skia's avatar
Skia committed
214
215
216
217
218
219
220
221
222
class UserPicturesView(UserTabsMixin, CanViewMixin, DetailView):
    """
    Display a user's pictures
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_pictures.jinja"
    current_tab = 'pictures'
Sli's avatar
Sli committed
223

Skia's avatar
Skia committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
class UserGodfathersView(UserTabsMixin, CanViewMixin, DetailView):
    """
    Display a user's godfathers
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_godfathers.jinja"
    current_tab = 'godfathers'

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = UserGodfathersForm(request.POST)
        if self.form.is_valid() and self.form.cleaned_data['user'] != self.object:
            if self.form.cleaned_data['type'] == 'godfather':
                self.object.godfathers.add(self.form.cleaned_data['user'])
                self.object.save()
            else:
                self.object.godchildren.add(self.form.cleaned_data['user'])
                self.object.save()
            self.form = UserGodfathersForm()
        return super(UserGodfathersView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs = super(UserGodfathersView, self).get_context_data(**kwargs)
        try:
            kwargs['form'] = self.form
        except:
            kwargs['form'] = UserGodfathersForm()
        return kwargs

255
class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
256
257
258
259
260
261
262
    """
    Display a user's stats
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_stats.jinja"
263
    current_tab = 'stats'
264

Sli's avatar
Sli committed
265
266
267
268
269
270
271
272
    def dispatch(self, request, *arg, **kwargs):
        profile = self.get_object()

        if (profile != request.user and not request.user.is_root):
            raise PermissionDenied

        return super(UserStatsView, self).dispatch(request, *arg, **kwargs)

273
274
    def get_context_data(self, **kwargs):
        kwargs = super(UserStatsView, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
275
276
        from counter.models import Counter, Product, Selling
        from django.db.models import Sum
Skia's avatar
Skia committed
277
278
279
        foyer = Counter.objects.filter(name="Foyer").first()
        mde = Counter.objects.filter(name="MDE").first()
        gommette = Counter.objects.filter(name="La Gommette").first()
Skia's avatar
Skia committed
280
        semester_start=Subscription.compute_start(d=date.today(), duration=3)
Skia's avatar
Skia committed
281
282
283
284
        kwargs['total_perm_time'] = sum([p.end-p.start for p in self.object.permanencies.exclude(end=None)], timedelta())
        kwargs['total_foyer_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=foyer).exclude(end=None)], timedelta())
        kwargs['total_mde_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=mde).exclude(end=None)], timedelta())
        kwargs['total_gommette_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=gommette).exclude(end=None)], timedelta())
Skia's avatar
Skia committed
285
286
287
288
289
290
        kwargs['total_foyer_buyings'] = sum([b.unit_price*b.quantity for b in
            self.object.customer.buyings.filter(counter=foyer, date__gte=semester_start)])
        kwargs['total_mde_buyings'] = sum([b.unit_price*b.quantity for b in self.object.customer.buyings.filter(counter=mde,
            date__gte=semester_start)])
        kwargs['total_gommette_buyings'] = sum([b.unit_price*b.quantity for b in
            self.object.customer.buyings.filter(counter=gommette, date__gte=semester_start)])
Skia's avatar
Skia committed
291
292
        kwargs['top_product'] = self.object.customer.buyings.values('product__name').annotate(
                product_sum=Sum('quantity')).exclude(product_sum=None).order_by('-product_sum').all()[:10]
293
294
        return kwargs

Skia's avatar
Skia committed
295
296
297
298
299
300
301
302
303
class UserMiniView(CanViewMixin, DetailView):
    """
    Display a user's profile
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_mini.jinja"

Skia's avatar
Skia committed
304
class UserListView(ListView, CanEditPropMixin):
Skia's avatar
Skia committed
305
306
307
308
    """
    Displays the user list
    """
    model = User
Skia's avatar
Skia committed
309
    template_name = "core/user_list.jinja"
Skia's avatar
Skia committed
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
class UserUploadProfilePictView(CanEditMixin, DetailView):
    """
    Handle the upload of the profile picture taken with webcam in navigator
    """
    model = User
    pk_url_kwarg = "user_id"
    template_name = "core/user_edit.jinja"

    def post(self, request, *args, **kwargs):
        from core.utils import resize_image
        from io import BytesIO
        from PIL import Image
        self.object = self.get_object()
        if self.object.profile_pict:
            raise ValidationError(_("User already has a profile picture"))
        f = request.FILES['new_profile_pict']
        parent = SithFile.objects.filter(parent=None, name="profiles").first()
        name = str(self.object.id) + "_profile.jpg" # Webcamejs uploads JPGs
        im = Image.open(BytesIO(f.read()))
        new_file = SithFile(parent=parent, name=name,
                file=resize_image(im, 400, f.content_type.split('/')[-1]),
                owner=self.object, is_folder=False, mime_type=f.content_type, size=f._size)
        new_file.file.name = name
        new_file.save()
        self.object.profile_pict = new_file
        self.object.save()
        return redirect("core:user_edit", user_id=self.object.id)

339
class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView):
Skia's avatar
Skia committed
340
341
342
343
344
    """
    Edit a user's profile
    """
    model = User
    pk_url_kwarg = "user_id"
Skia's avatar
Skia committed
345
    template_name = "core/user_edit.jinja"
346
    form_class = UserProfileForm
347
    current_tab = "edit"
348
    edit_once = ['profile_pict', 'date_of_birth', 'first_name', 'last_name']
349
    board_only = []
350

Sli's avatar
Sli committed
351
352
353
354
    def remove_restricted_fields(self, request):
        """
        Removes edit_once and board_only fields
        """
355
356
357
        for i in self.edit_once:
            if getattr(self.form.instance, i) and not (request.user.is_board_member or request.user.is_root):
                self.form.fields.pop(i, None)
Sli's avatar
Sli committed
358
359
360
        for i in self.board_only:
            if not (request.user.is_board_member or request.user.is_root):
                self.form.fields.pop(i, None)
361
362
363
364

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
Sli's avatar
Sli committed
365
        self.remove_restricted_fields(request)
366
367
368
369
370
        return self.render_to_response(self.get_context_data(form=self.form))

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
Sli's avatar
Sli committed
371
        self.remove_restricted_fields(request)
372
373
374
375
376
377
378
379
380
381
382
        files = request.FILES.items()
        self.form.process(files)
        if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid():
            return super(UserUpdateProfileView, self).form_valid(self.form)
        return self.form_invalid(self.form)

    def get_context_data(self, **kwargs):
        kwargs = super(UserUpdateProfileView, self).get_context_data(**kwargs)
        kwargs['profile'] = self.form.instance
        kwargs['form'] = self.form
        return kwargs
Skia's avatar
Skia committed
383

Lo-J's avatar
Lo-J committed
384
385
386
387
388
389
390
391
392
393
class UserClubView(UserTabsMixin, CanViewMixin, DetailView):
    """
    Display the user's club(s)
    """
    model = User
    context_object_name = "profile"
    pk_url_kwarg = "user_id"
    template_name = "core/user_clubs.jinja"
    current_tab = "clubs"

Skia's avatar
Skia committed
394
395
396
397
class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
    """
    Edit a user's preferences
    """
398
    model = User
Skia's avatar
Skia committed
399
400
    pk_url_kwarg = "user_id"
    template_name = "core/edit.jinja"
401
    form_class = modelform_factory(Preferences, fields=['receive_weekmail'])
Skia's avatar
Skia committed
402
403
404
405
406
    context_object_name = "profile"
    current_tab = "prefs"

    def get_object(self, queryset=None):
        user = get_object_or_404(User, pk=self.kwargs['user_id'])
407
408
409
410
        return user

    def get_form_kwargs(self):
        kwargs = super(UserPreferencesView, self).get_form_kwargs()
Skia's avatar
Skia committed
411
        try:
412
            pref = self.object.preferences
Skia's avatar
Skia committed
413
        except:
414
            pref = Preferences(user=self.object)
Skia's avatar
Skia committed
415
            pref.save()
416
417
        kwargs.update({'instance': pref})
        return kwargs
Skia's avatar
Skia committed
418

419
class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
Skia's avatar
Skia committed
420
421
422
423
424
    """
    Edit a user's groups
    """
    model = User
    pk_url_kwarg = "user_id"
425
426
427
    template_name = "core/user_group.jinja"
    form_class = modelform_factory(User, fields=['groups'],
            widgets={'groups':CheckboxSelectMultiple})
Skia's avatar
Skia committed
428
    context_object_name = "profile"
429
    current_tab = "groups"
Skia's avatar
Skia committed
430

Skia's avatar
Skia committed
431
class UserToolsView(QuickNotifMixin, UserTabsMixin, TemplateView):
432
433
434
    """
    Displays the logged user's tools
    """
Skia's avatar
Skia committed
435
    template_name = "core/user_tools.jinja"
436
    current_tab = "tools"
Skia's avatar
Skia committed
437

438
    def get_context_data(self, **kwargs):
439
        self.object = self.request.user
440
441
442
        from launderette.models import Launderette
        kwargs = super(UserToolsView, self).get_context_data(**kwargs)
        kwargs['launderettes'] = Launderette.objects.all()
Skia's avatar
Skia committed
443
        kwargs['profile'] = self.request.user
444
        kwargs['object'] = self.request.user
445
446
        return kwargs

Sli's avatar
Sli committed
447
class UserAccountBase(UserTabsMixin, DetailView):
Skia's avatar
Skia committed
448
    """
Sli's avatar
Sli committed
449
    Base class for UserAccount
Skia's avatar
Skia committed
450
451
452
    """
    model = User
    pk_url_kwarg = "user_id"
453
    current_tab = "account"
Skia's avatar
Skia committed
454
455

    def dispatch(self, request, *arg, **kwargs): # Manually validates the rights
Sli's avatar
Sli committed
456
        res = super(UserAccountBase, self).dispatch(request, *arg, **kwargs)
Skia's avatar
Skia committed
457
        if (self.object == request.user
Skia's avatar
Skia committed
458
                or request.user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
459
                or request.user.is_in_group(settings.SITH_BAR_MANAGER['unix_name']+settings.SITH_BOARD_SUFFIX)
Skia's avatar
Skia committed
460
                or request.user.is_root):
Skia's avatar
Skia committed
461
462
463
            return res
        raise PermissionDenied

Sli's avatar
Sli committed
464
465
466
467
468
469
470
class UserAccountView(UserAccountBase):
    """
    Display a user's account
    """
    template_name = "core/user_account.jinja"

    def expense_by_month(self, obj, calc):
Sli's avatar
Sli committed
471
472
        stats = []

473
        for year in obj.datetimes('date', 'year', order='DESC'):
Sli's avatar
Sli committed
474
            stats.append([])
Sli's avatar
Sli committed
475
476
            i = 0
            for month in obj.filter(date__year=year.year).datetimes(
477
                'date', 'month', order='DESC'):
Sli's avatar
Sli committed
478
                q = obj.filter(
Sli's avatar
Sli committed
479
480
                    date__year=month.year,
                    date__month=month.month
Sli's avatar
Sli committed
481
                )
Sli's avatar
Sli committed
482
483
484
485
                stats[i].append({
                    'sum':sum([calc(p) for p in q]),
                    'date':month
                })
Sli's avatar
Sli committed
486
            i += 1
Sli's avatar
Sli committed
487
488
        return stats

Sli's avatar
Sli committed
489
490
491
492
493
494
    def invoices_calc(self, query):
        t = 0
        for it in query.items.all():
            t += it.quantity * it.product_unit_price
        return t

Skia's avatar
Skia committed
495
496
497
498
499
    def get_context_data(self, **kwargs):
        kwargs = super(UserAccountView, self).get_context_data(**kwargs)
        kwargs['profile'] = self.object
        try:
            kwargs['customer'] = self.object.customer
Sli's avatar
Sli committed
500
501
            kwargs['buyings_month'] = self.expense_by_month(
                self.object.customer.buyings,
Sli's avatar
Sli committed
502
                (lambda q: q.unit_price * q.quantity)
Sli's avatar
Sli committed
503
504
505
506
507
508
509
            )
            kwargs['invoices_month'] = self.expense_by_month(
                self.object.customer.user.invoices,
                self.invoices_calc
            )
            kwargs['refilling_month'] = self.expense_by_month(
                self.object.customer.refillings,
Sli's avatar
Sli committed
510
                (lambda q: q.amount)
Sli's avatar
Sli committed
511
            )
Skia's avatar
Skia committed
512
            kwargs['etickets'] = self.object.customer.buyings.exclude(product__eticket=None).all()
Skia's avatar
Skia committed
513
514
        except Exception as e:
            print(repr(e))
Skia's avatar
Skia committed
515
516
        return kwargs

Sli's avatar
Sli committed
517
518
519
520
521
522
523
524
525
class UserAccountDetailView(UserAccountBase, YearMixin, MonthMixin):
    """
    Display a user's account for month
    """
    template_name = "core/user_account_detail.jinja"

    def get_context_data(self, **kwargs):
        kwargs = super(UserAccountDetailView, self).get_context_data(**kwargs)
        kwargs['profile'] = self.object
526
527
        kwargs['year'] = self.get_year()
        kwargs['month'] = self.get_month()
Sli's avatar
Sli committed
528
529
530
531
532
533
        try:
            kwargs['customer'] = self.object.customer
        except:
            pass
        kwargs['tab'] = "account"
        return kwargs
534