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.forms import ValidationError
|
|
|
|
from django.utils import timezone
|
|
|
|
|
|
|
|
|
|
|
|
# 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)
|
2022-08-06 18:56:39 +02:00
|
|
|
profile_picture_filename = models.CharField(default="default.svg", max_length=25)
|
2022-10-15 19:37:01 +02:00
|
|
|
allowed_to_supply = models.BooleanField(default=False)
|
2023-04-13 21:19:11 +02:00
|
|
|
hide_from_userlist = models.BooleanField(default=False)
|
2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
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()
|
|
|
|
|
2023-02-11 22:14:01 +01: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:
|
2022-11-05 09:40:41 +01:00
|
|
|
verbose_name = "transaction"
|
|
|
|
verbose_name_plural = "transactions"
|
2022-11-05 09:33:58 +01:00
|
|
|
|
2022-03-16 12:11:30 +01:00
|
|
|
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)
|
2023-04-14 23:47:12 +02:00
|
|
|
is_transfer = models.BooleanField(default=False)
|
2022-03-16 12:11:30 +01:00
|
|
|
comment = models.TextField(default=" ")
|
2023-02-11 17:23:57 +01:00
|
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
2022-03-16 12:11:30 +01:00
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
if self._state.adding:
|
2023-04-14 23:47:12 +02:00
|
|
|
if self.is_user_deposit or self.is_transfer: # update user balance
|
2022-03-16 12:11:30 +01:00
|
|
|
self.user.balance += self.transaction_sum
|
|
|
|
self.user.save()
|
|
|
|
self.old_transaction_sum = self.transaction_sum
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
else:
|
|
|
|
# update user balance
|
2023-04-14 23:47:12 +02:00
|
|
|
if self.is_user_deposit or self.is_transfer:
|
|
|
|
self.user.balance += self.transaction_sum - self.old_transaction_sum
|
2022-03-16 12:11:30 +01:00
|
|
|
self.user.save()
|
2023-04-14 23:47:12 +02:00
|
|
|
# update register transaction
|
2022-03-16 12:11:30 +01:00
|
|
|
self.old_transaction_sum = self.transaction_sum
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
|
|
|
|
def delete(self, *args, **kwargs):
|
|
|
|
# update user deposit
|
2023-04-14 23:47:12 +02:00
|
|
|
if self.is_user_deposit or self.is_transfer:
|
2022-03-16 12:11:30 +01:00
|
|
|
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
|
|
|
|
)
|
2023-02-11 17:23:57 +01:00
|
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
2022-03-16 12:11:30 +01:00
|
|
|
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
|