Sith/counter/models.py

593 lines
24 KiB
Python
Raw Normal View History

# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
#
# 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.
#
#
2017-06-12 07:47:24 +00:00
from django.db import models
2016-03-28 12:54:35 +00:00
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
2016-03-28 12:54:35 +00:00
from django.conf import settings
2016-03-29 08:30:24 +00:00
from django.core.urlresolvers import reverse
2016-08-01 22:32:55 +00:00
from django.forms import ValidationError
from django.utils.functional import cached_property
2016-03-28 12:54:35 +00:00
from datetime import timedelta, date
2016-08-04 22:50:25 +00:00
import random
import string
2016-10-03 17:30:05 +00:00
import os
import base64
2016-10-16 16:52:04 +00:00
import datetime
2016-03-28 12:54:35 +00:00
from club.models import Club
from accounting.models import CurrencyField
2016-12-08 18:47:28 +00:00
from core.models import Group, User, Notification
2016-12-10 00:58:30 +00:00
from subscription.models import Subscription
2016-03-28 12:54:35 +00:00
2017-06-12 07:47:24 +00:00
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)
2016-05-31 17:32:15 +00:00
amount = CurrencyField(_('amount'))
2017-07-21 19:39:49 +00:00
recorded_products = models.IntegerField(_('recorded product'), default=0)
class Meta:
verbose_name = _('customer')
verbose_name_plural = _('customers')
2017-06-12 07:47:24 +00:00
ordering = ['account_id', ]
def __str__(self):
2016-08-14 17:28:14 +00:00
return "%s - %s" % (self.user.username, self.account_id)
2017-07-21 19:39:49 +00:00
@property
def can_record(self):
2017-08-15 00:09:44 +00:00
return self.recorded_products > -settings.SITH_ECOCUP_LIMIT
2017-07-21 19:39:49 +00:00
def can_record_more(self, number):
2017-08-15 00:09:44 +00:00
return self.recorded_products - number >= -settings.SITH_ECOCUP_LIMIT
2017-07-21 19:39:49 +00:00
@property
def can_buy(self):
return (self.user.subscriptions.last() and
(date.today() - self.user.subscriptions.last().subscription_end) < timedelta(days=90))
2016-08-04 22:50:25 +00:00
def generate_account_id(number):
number = str(number)
letter = random.choice(string.ascii_lowercase)
2017-06-12 07:47:24 +00:00
while Customer.objects.filter(account_id=number + letter).exists():
2016-08-04 22:50:25 +00:00
letter = random.choice(string.ascii_lowercase)
2017-06-12 07:47:24 +00:00
return number + letter
2017-08-15 00:09:44 +00:00
def save(self, allow_negative=False, is_selling=False, *args, **kwargs):
2017-08-15 12:03:56 +00:00
"""
is_selling : tell if the current action is a selling
allow_negative : ignored if not a selling. Allow a selling to put the account in negative
Those two parameters avoid blocking the save method of a customer if his account is negative
"""
2017-08-15 00:09:44 +00:00
if self.amount < 0 and (is_selling and not allow_negative):
2016-08-01 22:32:55 +00:00
raise ValidationError(_("Not enough money"))
super(Customer, self).save(*args, **kwargs)
2016-09-21 12:09:16 +00:00
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()
def get_absolute_url(self):
return reverse('core:user_account', kwargs={'user_id': self.user.pk})
def get_full_url(self):
2016-10-25 16:25:59 +00:00
return ''.join(['https://', settings.SITH_URL, self.get_absolute_url()])
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)
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _('product type')
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
2016-12-10 00:29:56 +00:00
if user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID):
return True
return False
def __str__(self):
return self.name
2016-07-27 18:05:45 +00:00
def get_absolute_url(self):
return reverse('counter:producttype_list')
2017-06-12 07:47:24 +00:00
class Product(models.Model):
"""
This describes a product, with all its related informations
"""
name = models.CharField(_('name'), max_length=64)
description = models.TextField(_('description'), blank=True)
product_type = models.ForeignKey(ProductType, related_name='products', verbose_name=_("product type"), null=True, blank=True,
2017-06-12 07:47:24 +00:00
on_delete=models.SET_NULL)
code = models.CharField(_('code'), max_length=16, blank=True)
purchase_price = CurrencyField(_('purchase price'))
selling_price = CurrencyField(_('selling price'))
special_selling_price = CurrencyField(_('special selling price'))
icon = models.ImageField(upload_to='products', null=True, blank=True, verbose_name=_("icon"))
club = models.ForeignKey(Club, related_name="products", verbose_name=_("club"))
limit_age = models.IntegerField(_('limit age'), default=0)
tray = models.BooleanField(_('tray price'), default=False)
parent_product = models.ForeignKey('self', related_name='children_products', verbose_name=_("parent product"), null=True,
2017-06-12 07:47:24 +00:00
blank=True, on_delete=models.SET_NULL)
2016-08-31 13:29:16 +00:00
buying_groups = models.ManyToManyField(Group, related_name='products', verbose_name=_("buying groups"), blank=True)
archived = models.BooleanField(_("archived"), default=False)
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _('product')
2017-07-21 19:39:49 +00:00
@property
def is_record_product(self):
2017-08-15 00:09:44 +00:00
return settings.SITH_ECOCUP_CONS == self.id
2017-07-21 19:39:49 +00:00
@property
def is_unrecord_product(self):
2017-08-15 00:09:44 +00:00
return settings.SITH_ECOCUP_DECO == self.id
2017-07-21 19:39:49 +00:00
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
2016-12-10 00:29:56 +00:00
if user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) or user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID):
return True
return False
def __str__(self):
2016-10-04 14:40:43 +00:00
return "%s (%s)" % (self.name, self.code)
2016-07-27 15:23:02 +00:00
def get_absolute_url(self):
return reverse('counter:product_list')
2017-06-12 07:47:24 +00:00
2016-03-28 12:54:35 +00:00
class Counter(models.Model):
name = models.CharField(_('name'), max_length=30)
club = models.ForeignKey(Club, related_name="counters", verbose_name=_("club"))
products = models.ManyToManyField(Product, related_name="counters", verbose_name=_("products"), blank=True)
type = models.CharField(_('counter type'),
2017-06-12 07:47:24 +00:00
max_length=255,
choices=[('BAR', _('Bar')), ('OFFICE', _('Office')), ('EBOUTIC', _('Eboutic'))])
2016-12-10 00:58:30 +00:00
sellers = models.ManyToManyField(User, verbose_name=_('sellers'), related_name='counters', blank=True)
2016-03-28 12:54:35 +00:00
edit_groups = models.ManyToManyField(Group, related_name="editable_counters", blank=True)
view_groups = models.ManyToManyField(Group, related_name="viewable_counters", blank=True)
token = models.CharField(_('token'), max_length=30, null=True, blank=True)
2016-03-28 12:54:35 +00:00
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _('counter')
2016-03-28 12:54:35 +00:00
def __getattribute__(self, name):
if name == "edit_groups":
2017-06-12 07:47:24 +00:00
return Group.objects.filter(name=self.club.unix_name + settings.SITH_BOARD_SUFFIX).all()
2016-03-28 12:54:35 +00:00
return object.__getattribute__(self, name)
def __str__(self):
return self.name
2016-03-29 08:30:24 +00:00
def get_absolute_url(self):
2016-07-22 11:34:34 +00:00
if self.type == "EBOUTIC":
return reverse('eboutic:main')
2016-03-29 08:30:24 +00:00
return reverse('counter:details', kwargs={'counter_id': self.id})
def is_owned_by(self, user):
mem = self.club.get_membership_for(user)
if mem and mem.role >= 7:
return True
2016-12-10 00:29:56 +00:00
return user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID)
2016-03-29 08:30:24 +00:00
def can_be_viewed_by(self, user):
2017-01-04 18:39:37 +00:00
if self.type == "BAR":
return True
2017-01-03 13:29:44 +00:00
return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user in self.sellers.all()
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()
def add_barman(self, user):
2016-07-18 11:22:50 +00:00
"""
Logs a barman in to the given counter
A user is stored as a tuple with its login time
"""
Permanency(user=user, counter=self, start=timezone.now(), end=None).save()
def del_barman(self, user):
2016-07-18 11:22:50 +00:00
"""
Logs a barman out and store its permanency
"""
perm = Permanency.objects.filter(counter=self, user=user, end=None).all()
for p in perm:
p.end = p.activity
p.save()
2016-07-18 11:22:50 +00:00
@cached_property
def barmen_list(self):
return self.get_barmen_list()
2016-08-06 10:37:36 +00:00
def get_barmen_list(self):
2016-07-18 11:22:50 +00:00
"""
2016-07-21 18:03:31 +00:00
Returns the barman list as list of User
2016-07-18 11:22:50 +00:00
Also handle the timeout of the barmen
"""
pl = Permanency.objects.filter(counter=self, end=None).all()
bl = []
for p in pl:
if timezone.now() - p.activity < timedelta(minutes=settings.SITH_BARMAN_TIMEOUT):
bl.append(p.user)
else:
p.end = p.activity
p.save()
return bl
2016-08-06 10:37:36 +00:00
def get_random_barman(self):
2016-09-12 15:34:33 +00:00
"""
Return a random user being currently a barman
"""
2016-08-06 10:37:36 +00:00
bl = self.get_barmen_list()
2016-08-18 19:06:10 +00:00
return bl[random.randrange(0, len(bl))]
2016-05-31 17:32:15 +00:00
2016-09-12 15:34:33 +00:00
def update_activity(self):
"""
Update the barman activity to prevent timeout
"""
for p in Permanency.objects.filter(counter=self, end=None).all():
2017-06-12 07:47:24 +00:00
p.save() # Update activity
2016-09-12 15:34:33 +00:00
2016-08-05 18:01:23 +00:00
def is_open(self):
return len(self.barmen_list) > 0
2016-08-05 18:01:23 +00:00
2016-10-16 16:52:04 +00:00
def is_inactive(self):
"""
Returns True if the counter self is inactive from SITH_COUNTER_MINUTE_INACTIVE's value minutes, else False
2016-10-16 16:52:04 +00:00
"""
return self.is_open() and ((timezone.now() - self.permanencies.order_by('-activity').first().activity) > datetime.timedelta(minutes=settings.SITH_COUNTER_MINUTE_INACTIVE))
2016-10-16 16:52:04 +00:00
2016-08-06 10:37:36 +00:00
def barman_list(self):
2016-09-12 15:34:33 +00:00
"""
Returns the barman id list
"""
2016-08-06 10:37:36 +00:00
return [b.id for b in self.get_barmen_list()]
2017-06-12 07:47:24 +00:00
2016-05-31 17:32:15 +00:00
class Refilling(models.Model):
"""
Handle the refilling
"""
counter = models.ForeignKey(Counter, related_name="refillings", blank=False)
amount = CurrencyField(_('amount'))
operator = models.ForeignKey(User, related_name="refillings_as_operator", blank=False)
customer = models.ForeignKey(Customer, related_name="refillings", blank=False)
date = models.DateTimeField(_('date'))
2016-05-31 17:32:15 +00:00
payment_method = models.CharField(_('payment method'), max_length=255,
2017-06-12 07:47:24 +00:00
choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='CASH')
bank = models.CharField(_('bank'), max_length=255,
2017-06-12 07:47:24 +00:00
choices=settings.SITH_COUNTER_BANK, default='OTHER')
2016-08-01 22:32:55 +00:00
is_validated = models.BooleanField(_('is validated'), default=False)
2016-05-31 17:32:15 +00:00
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _("refilling")
2016-05-31 17:32:15 +00:00
def __str__(self):
2016-06-26 18:07:29 +00:00
return "Refilling: %.2f for %s" % (self.amount, self.customer.user.get_display_name())
2016-05-31 17:32:15 +00:00
2016-08-18 19:06:10 +00:00
def is_owned_by(self, user):
return user.is_owner(self.counter) and self.payment_method != "CARD"
2016-05-31 17:32:15 +00:00
2016-08-18 19:06:10 +00:00
def delete(self, *args, **kwargs):
self.customer.amount -= self.amount
self.customer.save()
super(Refilling, self).delete(*args, **kwargs)
2016-05-31 17:32:15 +00:00
def save(self, *args, **kwargs):
if not self.date:
2016-08-18 19:06:10 +00:00
self.date = timezone.now()
2016-05-31 17:32:15 +00:00
self.full_clean()
2016-08-01 22:32:55 +00:00
if not self.is_validated:
self.customer.amount += self.amount
self.customer.save()
self.is_validated = True
if self.customer.user.preferences.notify_on_refill:
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}),
param=str(self.amount),
type="REFILLING",
).save()
2016-06-26 18:07:29 +00:00
super(Refilling, self).save(*args, **kwargs)
2016-05-31 17:32:15 +00:00
2017-06-12 07:47:24 +00:00
2016-05-31 17:32:15 +00:00
class Selling(models.Model):
"""
Handle the sellings
"""
label = models.CharField(_("label"), max_length=64)
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)
2016-05-31 17:32:15 +00:00
unit_price = CurrencyField(_('unit price'))
quantity = models.IntegerField(_('quantity'))
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,
2017-06-12 07:47:24 +00:00
choices=[('SITH_ACCOUNT', _('Sith account')), ('CARD', _('Credit card'))], default='SITH_ACCOUNT')
2016-08-01 22:32:55 +00:00
is_validated = models.BooleanField(_('is validated'), default=False)
2016-05-31 17:32:15 +00:00
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _("selling")
2016-05-31 17:32:15 +00:00
def __str__(self):
2016-08-01 22:32:55 +00:00
return "Selling: %d x %s (%f) for %s" % (self.quantity, self.label,
2017-06-12 07:47:24 +00:00
self.quantity * self.unit_price, self.customer.user.get_display_name())
2016-05-31 17:32:15 +00:00
2016-08-18 19:06:10 +00:00
def is_owned_by(self, user):
return user.is_owner(self.counter) and self.payment_method != "CARD"
2016-08-18 19:06:10 +00:00
2016-10-03 17:30:05 +00:00
def can_be_viewed_by(self, user):
return user == self.customer.user
2016-08-18 19:06:10 +00:00
def delete(self, *args, **kwargs):
if self.payment_method == "SITH_ACCOUNT":
self.customer.amount += self.quantity * self.unit_price
self.customer.save()
2016-08-18 19:06:10 +00:00
super(Selling, self).delete(*args, **kwargs)
def send_mail_customer(self):
2016-10-25 19:53:40 +00:00
event = self.product.eticket.event_title or _("Unknown event")
2016-10-25 16:25:59 +00:00
subject = _('Eticket bought for the event %(event)s') % {'event': event}
message_html = _(
"You bought an eticket for the event %(event)s.\nYou can download it on this page %(url)s."
) % {
2016-10-25 16:25:59 +00:00
'event': event,
2017-06-12 07:47:24 +00:00
'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."
) % {
2016-10-25 16:25:59 +00:00
'event': event,
'url': self.customer.get_full_url(),
}
self.customer.user.email_user(
subject,
message_txt,
html_message=message_html
)
2017-08-14 11:52:58 +00:00
def save(self, allow_negative=False, *args, **kwargs):
2017-08-15 12:03:56 +00:00
"""
allow_negative : Allow this selling to use more money than available for this user
"""
if not self.date:
2016-08-18 19:06:10 +00:00
self.date = timezone.now()
2016-05-31 17:32:15 +00:00
self.full_clean()
2016-08-01 22:32:55 +00:00
if not self.is_validated:
self.customer.amount -= self.quantity * self.unit_price
2017-08-15 00:09:44 +00:00
self.customer.save(allow_negative=allow_negative, is_selling=True)
2016-08-01 22:32:55 +00:00
self.is_validated = True
u = User.objects.filter(id=self.customer.user.id).first()
if u.was_subscribed:
if self.product and self.product.id == settings.SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER:
sub = Subscription(
2017-06-12 07:47:24 +00:00
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(
2017-06-12 07:47:24 +00:00
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(
2017-06-12 07:47:24 +00:00
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(
2017-06-12 07:47:24 +00:00
duration=settings.SITH_SUBSCRIPTIONS[sub.subscription_type]['duration'],
start=sub.subscription_start)
sub.save()
try:
if self.product.eticket:
self.send_mail_customer()
2017-06-12 07:47:24 +00:00
except:
pass
if self.customer.user.preferences.notify_on_click:
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}),
param="%d x %s" % (self.quantity, self.label),
type="SELLING",
).save()
2016-05-31 17:32:15 +00:00
super(Selling, self).save(*args, **kwargs)
2017-06-12 07:47:24 +00:00
2016-07-18 11:22:50 +00:00
class Permanency(models.Model):
"""
This class aims at storing a traceability of who was barman where and when
"""
user = models.ForeignKey(User, related_name="permanencies", verbose_name=_("user"))
counter = models.ForeignKey(Counter, related_name="permanencies", verbose_name=_("counter"))
2016-07-18 11:22:50 +00:00
start = models.DateTimeField(_('start date'))
2017-05-20 10:37:51 +00:00
end = models.DateTimeField(_('end date'), null=True, db_index=True)
activity = models.DateTimeField(_('last activity date'), auto_now=True)
2016-07-18 11:22:50 +00:00
2016-07-27 18:05:45 +00:00
class Meta:
verbose_name = _("permanency")
2016-07-18 11:22:50 +00:00
def __str__(self):
2016-09-12 15:34:33 +00:00
return "%s in %s from %s (last activity: %s) to %s" % (self.user, self.counter,
2017-06-12 07:47:24 +00:00
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 "",
)
2016-07-18 11:22:50 +00:00
2016-08-26 18:57:04 +00:00
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())
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)
2016-09-13 00:04:49 +00:00
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
2016-12-10 00:29:56 +00:00
if user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID):
2016-09-13 00:04:49 +00:00
return True
return False
2016-08-26 18:57:04 +00:00
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)
def get_absolute_url(self):
return reverse('counter:cash_summary_list')
2017-06-12 07:47:24 +00:00
2016-08-26 18:57:04 +00:00
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")
2017-06-12 07:47:24 +00:00
2016-10-03 17:30:05 +00:00
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
"""
2016-12-10 00:29:56 +00:00
return user.is_in_group(settings.SITH_GROUP_COUNTER_ADMIN_ID)
2016-10-03 17:30:05 +00:00
def get_hash(self, string):
2017-06-12 07:47:24 +00:00
import hashlib
import hmac
2016-10-03 17:30:05 +00:00
return hmac.new(bytes(self.secret, 'utf-8'), bytes(string, 'utf-8'), hashlib.sha1).hexdigest()