2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
from django.db import models
|
|
|
|
from django.conf import settings
|
|
|
|
from django.contrib.auth.models import AbstractUser
|
|
|
|
from django_currentuser.db.models import CurrentUserField
|
|
|
|
from django.forms import ValidationError
|
|
|
|
from django.utils import timezone
|
|
|
|
|
|
|
|
|
|
|
|
# helper
|
|
|
|
|
|
|
|
def make_register_transaction(transaction_sum:float):
|
|
|
|
regbalance = Global.objects.get(name="register_balance")
|
|
|
|
regbalance.value_float += float(round(float(transaction_sum), 2))
|
|
|
|
regbalance.save()
|
|
|
|
|
|
|
|
|
|
|
|
# Custom user model
|
|
|
|
class User(AbstractUser):
|
|
|
|
|
|
|
|
balance = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
|
|
|
|
allow_order_with_negative_balance = models.BooleanField(default=False)
|
|
|
|
|
|
|
|
def delete(self, *args, **kwargs):
|
|
|
|
self.balance = 0
|
|
|
|
self.is_active = False
|
|
|
|
self.username = f"<deleted user #{self.pk}>"
|
|
|
|
self.last_name = ""
|
|
|
|
self.first_name = ""
|
|
|
|
self.email = ""
|
|
|
|
super().save()
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
class Drink(models.Model):
|
|
|
|
|
|
|
|
product_name = models.CharField(max_length=64)
|
|
|
|
content_litres = models.DecimalField(max_digits=6, decimal_places=3, default=0.5)
|
|
|
|
price = models.DecimalField(max_digits=6, decimal_places=2, default=0.00)
|
|
|
|
available = models.PositiveIntegerField(default=0)
|
|
|
|
deleted = models.BooleanField(default=False)
|
|
|
|
|
2022-05-24 18:49:04 +02:00
|
|
|
# when the following field is true, the amount of drinks will
|
|
|
|
# not change and will not be displayed.
|
2022-03-16 12:11:30 +01:00
|
|
|
# available > 0 -> there is a indefinetly amount of drinks left
|
|
|
|
# available < 1 -> there are no drinks left
|
2022-05-24 18:49:04 +02:00
|
|
|
do_not_count = models.BooleanField(default=False)
|
2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
def delete(self, *args, **kwargs):
|
|
|
|
self.deleted = True
|
|
|
|
super().save()
|
|
|
|
|
2022-06-13 19:22:36 +02:00
|
|
|
def __str__(self): return f"{self.product_name} ({float(self.content_litres):.2f}l) - {self.price}{settings.CURRENCY_SUFFIX}"
|
2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
|
|
|
|
class RegisterTransaction(models.Model):
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = "register transaction"
|
|
|
|
verbose_name_plural = "register"
|
|
|
|
|
|
|
|
transaction_sum = models.DecimalField(max_digits=6, decimal_places=2, default=0.00)
|
|
|
|
# the following original_transaction_sum is needed when need to be
|
|
|
|
# updated, but the old value needs to be known (field is hidden)
|
|
|
|
old_transaction_sum = models.DecimalField(max_digits=6, decimal_places=2, default=0.00)
|
|
|
|
datetime = models.DateTimeField(default=timezone.now)
|
|
|
|
is_user_deposit = models.BooleanField(default=False)
|
|
|
|
comment = models.TextField(default=" ")
|
|
|
|
user = CurrentUserField()
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
if self._state.adding:
|
|
|
|
make_register_transaction(self.transaction_sum)
|
|
|
|
if self.is_user_deposit == True: # update user balance
|
|
|
|
self.user.balance += self.transaction_sum
|
|
|
|
self.user.save()
|
|
|
|
self.old_transaction_sum = self.transaction_sum
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
else:
|
|
|
|
# update register transaction
|
|
|
|
sum_diff = self.transaction_sum - self.old_transaction_sum
|
|
|
|
make_register_transaction(sum_diff)
|
|
|
|
# update user balance
|
|
|
|
if self.is_user_deposit == True:
|
|
|
|
ub_sum_diff = self.transaction_sum - self.old_transaction_sum
|
|
|
|
self.user.balance += ub_sum_diff
|
|
|
|
self.user.save()
|
|
|
|
self.old_transaction_sum = self.transaction_sum
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
|
|
|
|
def delete(self, *args, **kwargs):
|
|
|
|
make_register_transaction(-self.transaction_sum)
|
|
|
|
# update user deposit
|
|
|
|
if self.is_user_deposit:
|
|
|
|
self.user.balance -= self.transaction_sum
|
|
|
|
self.user.save()
|
|
|
|
super().delete(*args, kwargs)
|
|
|
|
|
|
|
|
def __str__(self): return f"{self.transaction_sum}{settings.CURRENCY_SUFFIX} by {self.user}"
|
|
|
|
|
|
|
|
|
|
|
|
class Order(models.Model):
|
|
|
|
|
|
|
|
drink = models.ForeignKey(
|
|
|
|
"Drink",
|
|
|
|
on_delete=models.SET_NULL,
|
|
|
|
null=True,
|
|
|
|
limit_choices_to=models.Q(available__gt=0) # Query only those drinks with a availability greater than (gt) 0
|
|
|
|
)
|
|
|
|
user = CurrentUserField()
|
|
|
|
datetime = models.DateTimeField(default=timezone.now)
|
|
|
|
amount = models.PositiveIntegerField(default=1, editable=False)
|
|
|
|
|
|
|
|
# the following fields will be set automatically
|
|
|
|
# won't use foreign key, because the values of the foreign objects may change over time.
|
|
|
|
product_name = models.CharField(max_length=64, editable=False)
|
|
|
|
price_sum = models.DecimalField(max_digits=6, decimal_places=2, default=0, editable=False)
|
|
|
|
content_litres = models.DecimalField(max_digits=6, decimal_places=3, default=0, editable=False)
|
|
|
|
|
|
|
|
# TODO: Add more comments on how and why the save & delete functions are implemented
|
|
|
|
# address this in a refactoring issue.
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
drink = Drink.objects.get(pk=self.drink.pk)
|
|
|
|
if self._state.adding and drink.available > 0:
|
2022-05-24 18:49:04 +02:00
|
|
|
if not drink.do_not_count:
|
2022-03-16 12:11:30 +01:00
|
|
|
drink.available -= self.amount
|
|
|
|
drink.save()
|
|
|
|
self.product_name = drink.product_name
|
|
|
|
self.price_sum = drink.price * self.amount
|
|
|
|
self.content_litres = drink.content_litres
|
|
|
|
self.user.balance -= self.price_sum
|
|
|
|
self.user.save()
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
else:
|
|
|
|
raise ValidationError("This entry can't be changed.")
|
|
|
|
|
|
|
|
def delete(self, *args, **kwargs):
|
|
|
|
self.user.balance += self.price_sum
|
|
|
|
self.user.save()
|
|
|
|
drink = Drink.objects.get(pk=self.drink.pk)
|
2022-05-24 18:49:04 +02:00
|
|
|
if not drink.do_not_count:
|
2022-03-16 12:11:30 +01:00
|
|
|
drink.available += self.amount
|
|
|
|
drink.save()
|
|
|
|
super().delete(*args, **kwargs)
|
|
|
|
|
2022-06-13 19:22:36 +02:00
|
|
|
def __str__(self): return f"{self.drink.product_name} ({float(self.drink.content_litres):.2f}l) x {self.amount} - {self.price_sum}{settings.CURRENCY_SUFFIX}"
|
2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Global(models.Model):
|
|
|
|
|
|
|
|
# this contains global values that are generated/calculated by code
|
|
|
|
# e.g. the current balance of the register, ...
|
|
|
|
|
|
|
|
name = models.CharField(max_length=42, unique=True, primary_key=True)
|
|
|
|
comment = models.TextField()
|
|
|
|
value_float = models.FloatField(default=0.00)
|
|
|
|
value_string = models.TextField()
|
|
|
|
|
|
|
|
def __str__(self): return self.name
|