models.py 21 KB
Newer Older
Skia's avatar
Skia committed
1
from django.db import models, DataError
Skia's avatar
Skia committed
2
from django.utils.translation import ugettext_lazy as _
3
from django.utils import timezone
Skia's avatar
Skia committed
4
from django.conf import settings
Skia's avatar
Skia committed
5
from django.core.urlresolvers import reverse
Skia's avatar
Skia committed
6
from django.forms import ValidationError
7
from django.contrib.sites.shortcuts import get_current_site
Skia's avatar
Skia committed
8

9
from datetime import timedelta, date
Skia's avatar
Skia committed
10
11
import random
import string
Skia's avatar
Skia committed
12
13
import os
import base64
Lo-J's avatar
Lo-J committed
14
import datetime
15

Skia's avatar
Skia committed
16
from club.models import Club
17
from accounting.models import CurrencyField
Skia's avatar
Skia committed
18
from core.models import Group, User, Notification
Skia's avatar
Skia committed
19
from subscription.models import Subscription
Skia's avatar
Skia committed
20

21
22
23
24
25
26
27
class Customer(models.Model):
    """
    This class extends a user to make a customer. It adds some basic customers informations, such as the accound ID, and
    is used by other accounting classes as reference to the customer, rather than using User
    """
    user = models.OneToOneField(User, primary_key=True)
    account_id = models.CharField(_('account id'), max_length=10, unique=True)
Skia's avatar
Skia committed
28
    amount = CurrencyField(_('amount'))
29
30
31
32

    class Meta:
        verbose_name = _('customer')
        verbose_name_plural = _('customers')
Skia's avatar
Skia committed
33
        ordering = ['account_id',]
34
35

    def __str__(self):
Skia's avatar
Skia committed
36
        return "%s - %s" % (self.user.username, self.account_id)
37

38
39
40
41
42
    @property
    def can_buy(self):
        return (self.user.subscriptions.last() and
                (date.today() - self.user.subscriptions.last().subscription_end) < timedelta(days=90))

Skia's avatar
Skia committed
43
44
45
46
47
48
    def generate_account_id(number):
        number = str(number)
        letter = random.choice(string.ascii_lowercase)
        while Customer.objects.filter(account_id=number+letter).exists():
            letter = random.choice(string.ascii_lowercase)
        return number+letter
49

Skia's avatar
Skia committed
50
51
52
53
54
    def save(self, *args, **kwargs):
        if self.amount < 0:
            raise ValidationError(_("Not enough money"))
        super(Customer, self).save(*args, **kwargs)

Skia's avatar
Skia committed
55
56
57
58
59
60
61
62
    def recompute_amount(self):
        self.amount = 0
        for r in self.refillings.all():
            self.amount += r.amount
        for s in self.buyings.filter(payment_method="SITH_ACCOUNT"):
            self.amount -= s.quantity * s.unit_price
            self.save()

63
64
65
66
    def get_absolute_url(self):
        return reverse('core:user_account', kwargs={'user_id': self.user.pk})

    def get_full_url(self):
Sli's avatar
Sli committed
67
        return ''.join(['https://', settings.SITH_URL, self.get_absolute_url()])
68
69


70
71
72
73
74
75
76
77
78
class ProductType(models.Model):
    """
    This describes a product type
    Useful only for categorizing, changes are made at the product level for now
    """
    name = models.CharField(_('name'), max_length=30)
    description = models.TextField(_('description'), null=True, blank=True)
    icon = models.ImageField(upload_to='products', null=True, blank=True)

Skia's avatar
Skia committed
79
80
81
    class Meta:
        verbose_name = _('product type')

82
83
84
85
    def is_owned_by(self, user):
        """
        Method to see if that object can be edited by the given user
        """
Skia's avatar
Skia committed
86
        if user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID):
87
88
89
90
91
92
            return True
        return False

    def __str__(self):
        return self.name

Skia's avatar
Skia committed
93
94
95
    def get_absolute_url(self):
        return reverse('counter:producttype_list')

96
97
98
99
class Product(models.Model):
    """
    This describes a product, with all its related informations
    """
100
    name = models.CharField(_('name'), max_length=64)
101
    description = models.TextField(_('description'), blank=True)
102
103
    product_type = models.ForeignKey(ProductType, related_name='products', verbose_name=_("product type"), null=True, blank=True,
            on_delete=models.SET_NULL)
104
    code = models.CharField(_('code'), max_length=16, blank=True)
105
106
107
    purchase_price = CurrencyField(_('purchase price'))
    selling_price = CurrencyField(_('selling price'))
    special_selling_price = CurrencyField(_('special selling price'))
108
109
    icon = models.ImageField(upload_to='products', null=True, blank=True, verbose_name=_("icon"))
    club = models.ForeignKey(Club, related_name="products", verbose_name=_("club"))
110
111
    limit_age = models.IntegerField(_('limit age'), default=0)
    tray = models.BooleanField(_('tray price'), default=False)
112
113
    parent_product = models.ForeignKey('self', related_name='children_products', verbose_name=_("parent product"), null=True,
            blank=True, on_delete=models.SET_NULL)
Skia's avatar
Skia committed
114
    buying_groups = models.ManyToManyField(Group, related_name='products', verbose_name=_("buying groups"), blank=True)
Skia's avatar
Skia committed
115
    archived = models.BooleanField(_("archived"), default=False)
116

Skia's avatar
Skia committed
117
118
119
    class Meta:
        verbose_name = _('product')

120
    def is_owned_by(self, user):
121
122
123
        """
        Method to see if that object can be edited by the given user
        """
Skia's avatar
Skia committed
124
        if user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) or user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID):
125
126
127
128
            return True
        return False

    def __str__(self):
Skia's avatar
Skia committed
129
        return "%s (%s)" % (self.name, self.code)
130

Skia's avatar
Skia committed
131
132
133
    def get_absolute_url(self):
        return reverse('counter:product_list')

Skia's avatar
Skia committed
134
135
class Counter(models.Model):
    name = models.CharField(_('name'), max_length=30)
136
137
    club = models.ForeignKey(Club, related_name="counters", verbose_name=_("club"))
    products = models.ManyToManyField(Product, related_name="counters", verbose_name=_("products"), blank=True)
138
    type = models.CharField(_('counter type'),
Skia's avatar
Skia committed
139
            max_length=255,
Skia's avatar
Skia committed
140
            choices=[('BAR',_('Bar')), ('OFFICE',_('Office')), ('EBOUTIC',_('Eboutic'))])
Skia's avatar
Skia committed
141
    sellers = models.ManyToManyField(User, verbose_name=_('sellers'), related_name='counters', blank=True)
Skia's avatar
Skia committed
142
143
    edit_groups = models.ManyToManyField(Group, related_name="editable_counters", blank=True)
    view_groups = models.ManyToManyField(Group, related_name="viewable_counters", blank=True)
144
    token = models.CharField(_('token'), max_length=30, null=True, blank=True)
Skia's avatar
Skia committed
145

Skia's avatar
Skia committed
146
147
148
    class Meta:
        verbose_name = _('counter')

Skia's avatar
Skia committed
149
    def __getattribute__(self, name):
150
151
        if name == "edit_groups":
            return Group.objects.filter(name=self.club.unix_name+settings.SITH_BOARD_SUFFIX).all()
Skia's avatar
Skia committed
152
153
154
155
        return object.__getattribute__(self, name)

    def __str__(self):
        return self.name
Skia's avatar
Skia committed
156
157

    def get_absolute_url(self):
Skia's avatar
Skia committed
158
159
        if self.type == "EBOUTIC":
            return reverse('eboutic:main')
Skia's avatar
Skia committed
160
161
        return reverse('counter:details', kwargs={'counter_id': self.id})

162
    def is_owned_by(self, user):
163
164
165
        mem = self.club.get_membership_for(user)
        if mem and mem.role >= 7:
            return True
Skia's avatar
Skia committed
166
        return user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID)
167

Skia's avatar
Skia committed
168
    def can_be_viewed_by(self, user):
Skia's avatar
Skia committed
169
        if self.type == "BAR":
170
            return True
Skia's avatar
Skia committed
171
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user in self.sellers.all()
172

173
174
175
176
177
    def gen_token(self):
        """Generate a new token for this counter"""
        self.token = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30))
        self.save()

178
    def add_barman(self, user):
Skia's avatar
Skia committed
179
180
181
182
        """
        Logs a barman in to the given counter
        A user is stored as a tuple with its login time
        """
183
184
185
        Permanency(user=user, counter=self, start=timezone.now(), end=None).save()

    def del_barman(self, user):
Skia's avatar
Skia committed
186
187
188
        """
        Logs a barman out and store its permanency
        """
189
190
191
192
        perm = Permanency.objects.filter(counter=self, user=user, end=None).all()
        for p in perm:
            p.end = p.activity
            p.save()
Skia's avatar
Skia committed
193

Skia's avatar
Skia committed
194
    def get_barmen_list(self):
Skia's avatar
Skia committed
195
        """
Skia's avatar
Skia committed
196
        Returns the barman list as list of User
Skia's avatar
Skia committed
197
198
199

        Also handle the timeout of the barmen
        """
200
        pl = Permanency.objects.filter(counter=self, end=None).all()
201
        bl = []
202
203
204
        for p in pl:
            if timezone.now() - p.activity < timedelta(minutes=settings.SITH_BARMAN_TIMEOUT):
                bl.append(p.user)
205
            else:
206
207
                p.end = p.activity
                p.save()
208
209
        return bl

Skia's avatar
Skia committed
210
    def get_random_barman(self):
Skia's avatar
Skia committed
211
212
213
        """
        Return a random user being currently a barman
        """
Skia's avatar
Skia committed
214
        bl = self.get_barmen_list()
Skia's avatar
Skia committed
215
        return bl[random.randrange(0, len(bl))]
Skia's avatar
Skia committed
216

Skia's avatar
Skia committed
217
218
219
220
221
222
223
    def update_activity(self):
        """
        Update the barman activity to prevent timeout
        """
        for p in Permanency.objects.filter(counter=self, end=None).all():
            p.save() # Update activity

Sli's avatar
Sli committed
224
    def is_open(self):
Skia's avatar
Skia committed
225
        return len(self.get_barmen_list()) > 0
Sli's avatar
Sli committed
226

Lo-J's avatar
Lo-J committed
227
228
    def is_inactive(self):
        """
229
        Returns True if the counter self is inactive from SITH_COUNTER_MINUTE_INACTIVE's value minutes, else False
Lo-J's avatar
Lo-J committed
230
        """
231
        return self.is_open() and ((timezone.now() - self.permanencies.order_by('-activity').first().activity) > datetime.timedelta(minutes=settings.SITH_COUNTER_MINUTE_INACTIVE))
Lo-J's avatar
Lo-J committed
232

Skia's avatar
Skia committed
233
    def barman_list(self):
Skia's avatar
Skia committed
234
235
236
        """
        Returns the barman id list
        """
Skia's avatar
Skia committed
237
238
        return [b.id for b in self.get_barmen_list()]

Skia's avatar
Skia committed
239
240
241
242
243
244
class Refilling(models.Model):
    """
    Handle the refilling
    """
    counter = models.ForeignKey(Counter, related_name="refillings", blank=False)
    amount = CurrencyField(_('amount'))
245
246
    operator = models.ForeignKey(User, related_name="refillings_as_operator", blank=False)
    customer = models.ForeignKey(Customer, related_name="refillings", blank=False)
247
    date = models.DateTimeField(_('date'))
Skia's avatar
Skia committed
248
    payment_method = models.CharField(_('payment method'), max_length=255,
249
            choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='CASH')
250
    bank = models.CharField(_('bank'), max_length=255,
251
            choices=settings.SITH_COUNTER_BANK, default='OTHER')
Skia's avatar
Skia committed
252
    is_validated = models.BooleanField(_('is validated'), default=False)
Skia's avatar
Skia committed
253

Skia's avatar
Skia committed
254
255
256
    class Meta:
        verbose_name = _("refilling")

Skia's avatar
Skia committed
257
    def __str__(self):
Skia's avatar
Skia committed
258
        return "Refilling: %.2f for %s" % (self.amount, self.customer.user.get_display_name())
Skia's avatar
Skia committed
259

Skia's avatar
Skia committed
260
    def is_owned_by(self, user):
261
        return user.is_owner(self.counter) and self.payment_method != "CARD"
Skia's avatar
Skia committed
262

Skia's avatar
Skia committed
263
264
265
266
267
    def delete(self, *args, **kwargs):
        self.customer.amount -= self.amount
        self.customer.save()
        super(Refilling, self).delete(*args, **kwargs)

Skia's avatar
Skia committed
268
    def save(self, *args, **kwargs):
269
        if not self.date:
Skia's avatar
Skia committed
270
            self.date = timezone.now()
Skia's avatar
Skia committed
271
        self.full_clean()
Skia's avatar
Skia committed
272
273
274
275
        if not self.is_validated:
            self.customer.amount += self.amount
            self.customer.save()
            self.is_validated = True
Skia's avatar
Skia committed
276
        Notification(user=self.customer.user, url=reverse('core:user_account_detail',
Skia's avatar
Skia committed
277
                    kwargs={'user_id': self.customer.user.id, 'year': self.date.year, 'month': self.date.month}),
Skia's avatar
Skia committed
278
279
                param=str(self.amount),
                type="REFILLING",
Skia's avatar
Skia committed
280
                ).save()
Skia's avatar
Skia committed
281
        super(Refilling, self).save(*args, **kwargs)
Skia's avatar
Skia committed
282
283
284
285
286

class Selling(models.Model):
    """
    Handle the sellings
    """
287
    label = models.CharField(_("label"), max_length=64)
288
289
290
    product = models.ForeignKey(Product, related_name="sellings", null=True, blank=True, on_delete=models.SET_NULL)
    counter = models.ForeignKey(Counter, related_name="sellings", null=True, blank=False, on_delete=models.SET_NULL)
    club = models.ForeignKey(Club, related_name="sellings", null=True, blank=False, on_delete=models.SET_NULL)
Skia's avatar
Skia committed
291
292
    unit_price = CurrencyField(_('unit price'))
    quantity = models.IntegerField(_('quantity'))
293
294
295
296
297
    seller = models.ForeignKey(User, related_name="sellings_as_operator", null=True, blank=False, on_delete=models.SET_NULL)
    customer = models.ForeignKey(Customer, related_name="buyings", null=True, blank=False, on_delete=models.SET_NULL)
    date = models.DateTimeField(_('date'))
    payment_method = models.CharField(_('payment method'), max_length=255,
            choices=[('SITH_ACCOUNT', _('Sith account')), ('CARD', _('Credit card'))], default='SITH_ACCOUNT')
Skia's avatar
Skia committed
298
    is_validated = models.BooleanField(_('is validated'), default=False)
Skia's avatar
Skia committed
299

Skia's avatar
Skia committed
300
301
302
    class Meta:
        verbose_name = _("selling")

Skia's avatar
Skia committed
303
    def __str__(self):
Skia's avatar
Skia committed
304
        return "Selling: %d x %s (%f) for %s" % (self.quantity, self.label,
Skia's avatar
Skia committed
305
306
                self.quantity*self.unit_price, self.customer.user.get_display_name())

Skia's avatar
Skia committed
307
    def is_owned_by(self, user):
308
        return user.is_owner(self.counter) and self.payment_method != "CARD"
Skia's avatar
Skia committed
309

Skia's avatar
Skia committed
310
311
312
    def can_be_viewed_by(self, user):
        return user == self.customer.user

Skia's avatar
Skia committed
313
    def delete(self, *args, **kwargs):
314
315
316
        if self.payment_method == "SITH_ACCOUNT":
            self.customer.amount += self.quantity * self.unit_price
            self.customer.save()
Skia's avatar
Skia committed
317
318
        super(Selling, self).delete(*args, **kwargs)

319
    def send_mail_customer(self):
Sli's avatar
Sli committed
320
        event = self.product.eticket.event_title or _("Unknown event")
Sli's avatar
Sli committed
321
        subject = _('Eticket bought for the event %(event)s') % {'event': event}
322
323
324
        message_html = _(
            "You bought an eticket for the event %(event)s.\nYou can download it on this page %(url)s."
        ) % {
Sli's avatar
Sli committed
325
            'event': event,
326
327
328
329
330
331
332
333
334
335
336
            'url':''.join((
                    '<a href="',
                    self.customer.get_full_url(),
                    '">',
                    self.customer.get_full_url(),
                    '</a>'
                ))
        }
        message_txt = _(
            "You bought an eticket for the event %(event)s.\nYou can download it on this page %(url)s."
        ) % {
Sli's avatar
Sli committed
337
            'event': event,
338
339
340
341
342
            'url': self.customer.get_full_url(),
        }
        self.customer.user.email_user(
            subject,
            message_txt,
343
            html_message=message_html
344
345
        )

Skia's avatar
Skia committed
346
    def save(self, *args, **kwargs):
347
        if not self.date:
Skia's avatar
Skia committed
348
            self.date = timezone.now()
Skia's avatar
Skia committed
349
        self.full_clean()
Skia's avatar
Skia committed
350
351
352
353
        if not self.is_validated:
            self.customer.amount -= self.quantity * self.unit_price
            self.customer.save()
            self.is_validated = True
354
        u = User.objects.filter(id=self.customer.user.id).first()
355
        if u.was_subscribed:
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
            if self.product and self.product.id == settings.SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER:
                sub = Subscription(
                        member=u,
                        subscription_type='un-semestre',
                        payment_method="EBOUTIC",
                        location="EBOUTIC",
                        )
                sub.subscription_start = Subscription.compute_start()
                sub.subscription_start = Subscription.compute_start(
                    duration=settings.SITH_SUBSCRIPTIONS[sub.subscription_type]['duration'])
                sub.subscription_end = Subscription.compute_end(
                        duration=settings.SITH_SUBSCRIPTIONS[sub.subscription_type]['duration'],
                        start=sub.subscription_start)
                sub.save()
            elif self.product and self.product.id == settings.SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS:
                u = User.objects.filter(id=self.customer.user.id).first()
                sub = Subscription(
                        member=u,
                        subscription_type='deux-semestres',
                        payment_method="EBOUTIC",
                        location="EBOUTIC",
                        )
                sub.subscription_start = Subscription.compute_start()
                sub.subscription_start = Subscription.compute_start(
                    duration=settings.SITH_SUBSCRIPTIONS[sub.subscription_type]['duration'])
                sub.subscription_end = Subscription.compute_end(
                        duration=settings.SITH_SUBSCRIPTIONS[sub.subscription_type]['duration'],
                        start=sub.subscription_start)
                sub.save()
385
386
387
        try:
            if self.product.eticket:
                self.send_mail_customer()
Sli's avatar
Sli committed
388
        except: pass
Skia's avatar
Skia committed
389
390
391
392
        Notification(
                user=self.customer.user,
                url=reverse('core:user_account_detail',
                    kwargs={'user_id': self.customer.user.id, 'year': self.date.year, 'month': self.date.month}),
Skia's avatar
Skia committed
393
394
                param="%d x %s" % (self.quantity, self.label),
                type="SELLING",
Skia's avatar
Skia committed
395
                ).save()
Skia's avatar
Skia committed
396
397
        super(Selling, self).save(*args, **kwargs)

Skia's avatar
Skia committed
398
399
400
401
class Permanency(models.Model):
    """
    This class aims at storing a traceability of who was barman where and when
    """
402
403
    user = models.ForeignKey(User, related_name="permanencies", verbose_name=_("user"))
    counter = models.ForeignKey(Counter, related_name="permanencies", verbose_name=_("counter"))
Skia's avatar
Skia committed
404
    start = models.DateTimeField(_('start date'))
405
406
    end = models.DateTimeField(_('end date'), null=True)
    activity = models.DateTimeField(_('last activity date'), auto_now=True)
Skia's avatar
Skia committed
407

Skia's avatar
Skia committed
408
409
410
    class Meta:
        verbose_name = _("permanency")

Skia's avatar
Skia committed
411
    def __str__(self):
Skia's avatar
Skia committed
412
413
414
415
416
        return "%s in %s from %s (last activity: %s) to %s" % (self.user, self.counter,
                self.start.strftime("%Y-%m-%d %H:%M:%S"),
                self.activity.strftime("%Y-%m-%d %H:%M:%S"),
                self.end.strftime("%Y-%m-%d %H:%M:%S") if self.end else "",
                )
Skia's avatar
Skia committed
417

Skia's avatar
Skia committed
418
419
420
421
422
423
424
425
426
427
428
429
430
class CashRegisterSummary(models.Model):
    user = models.ForeignKey(User, related_name="cash_summaries", verbose_name=_("user"))
    counter = models.ForeignKey(Counter, related_name="cash_summaries", verbose_name=_("counter"))
    date = models.DateTimeField(_('date'))
    comment = models.TextField(_('comment'), null=True, blank=True)
    emptied = models.BooleanField(_('emptied'), default=False)

    class Meta:
        verbose_name = _("cash register summary")

    def __str__(self):
        return "At %s by %s - Total: %s €" % (self.counter, self.user, self.get_total())

431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
    def __getattribute__(self, name):
        if name[:5] == 'check':
            checks = self.items.filter(check=True).order_by('value').all()
        if name == 'ten_cents':
            return self.items.filter(value=0.1, check=False).first()
        elif name == 'twenty_cents':
            return self.items.filter(value=0.2, check=False).first()
        elif name == 'fifty_cents':
            return self.items.filter(value=0.5, check=False).first()
        elif name == 'one_euro':
            return self.items.filter(value=1, check=False).first()
        elif name == 'two_euros':
            return self.items.filter(value=2, check=False).first()
        elif name == 'five_euros':
            return self.items.filter(value=5, check=False).first()
        elif name == 'ten_euros':
            return self.items.filter(value=10, check=False).first()
        elif name == 'twenty_euros':
            return self.items.filter(value=20, check=False).first()
        elif name == 'fifty_euros':
            return self.items.filter(value=50, check=False).first()
        elif name == 'hundred_euros':
            return self.items.filter(value=100, check=False).first()
        elif name == 'check_1':
            return checks[0] if 0 < len(checks) else None
        elif name == 'check_2':
            return checks[1] if 1 < len(checks) else None
        elif name == 'check_3':
            return checks[2] if 2 < len(checks) else None
        elif name == 'check_4':
            return checks[3] if 3 < len(checks) else None
        elif name == 'check_5':
            return checks[4] if 4 < len(checks) else None
        else:
            return object.__getattribute__(self, name)

Skia's avatar
Skia committed
467
468
469
470
    def is_owned_by(self, user):
        """
        Method to see if that object can be edited by the given user
        """
Skia's avatar
Skia committed
471
        if user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID):
Skia's avatar
Skia committed
472
473
474
            return True
        return False

Skia's avatar
Skia committed
475
476
477
478
479
480
481
482
483
484
485
    def get_total(self):
        t = 0
        for it in self.items.all():
            t += it.quantity * it.value
        return t

    def save(self, *args, **kwargs):
        if not self.id:
            self.date = timezone.now()
        return super(CashRegisterSummary, self).save(*args, **kwargs)

486
487
488
    def get_absolute_url(self):
        return reverse('counter:cash_summary_list')

Skia's avatar
Skia committed
489
490
491
492
493
494
495
496
class CashRegisterSummaryItem(models.Model):
    cash_summary = models.ForeignKey(CashRegisterSummary, related_name="items", verbose_name=_("cash summary"))
    value = CurrencyField(_("value"))
    quantity = models.IntegerField(_('quantity'), default=0)
    check = models.BooleanField(_('check'), default=False)

    class Meta:
        verbose_name = _("cash register summary item")
497

Skia's avatar
Skia committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
class Eticket(models.Model):
    """
    Eticket can be linked to a product an allows PDF generation
    """
    product = models.OneToOneField(Product, related_name='eticket', verbose_name=_("product"))
    banner = models.ImageField(upload_to='etickets', null=True, blank=True, verbose_name=_("banner"))
    event_date = models.DateField(_('event date'), null=True, blank=True)
    event_title = models.CharField(_('event title'), max_length=64, null=True, blank=True)
    secret = models.CharField(_('secret'), max_length=64, unique=True)

    def __str__(self):
        return "%s" % (self.product.name)

    def get_absolute_url(self):
        return reverse('counter:eticket_list')

    def save(self, *args, **kwargs):
        if not self.id:
            self.secret = base64.b64encode(os.urandom(32))
        return super(Eticket, self).save(*args, **kwargs)

    def is_owned_by(self, user):
        """
        Method to see if that object can be edited by the given user
        """
Skia's avatar
Skia committed
523
        return user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID)
Skia's avatar
Skia committed
524
525
526
527
528

    def get_hash(self, string):
        import hashlib, hmac
        return hmac.new(bytes(self.secret, 'utf-8'), bytes(string, 'utf-8'), hashlib.sha1).hexdigest()