From e4ea057ecb71ecd5ca5187002ffd51ef938bf3fc Mon Sep 17 00:00:00 2001 From: Flo Ha Date: Sun, 4 Sep 2022 13:33:45 +0200 Subject: [PATCH] rewrite models --- gaehsnitz/models.py | 172 ++++++++++++++++++++++++++++++++--- gaehsnitzproject/settings.py | 2 + 2 files changed, 160 insertions(+), 14 deletions(-) diff --git a/gaehsnitz/models.py b/gaehsnitz/models.py index 77e9e98..22b23c1 100644 --- a/gaehsnitz/models.py +++ b/gaehsnitz/models.py @@ -1,26 +1,170 @@ +from django.contrib.auth.models import AbstractUser from django.db import models +from django.db.models import Sum, F + + +class PriceField(models.DecimalField): + + def __init__(self, verbose_name=None, name=None, **kwargs): + kwargs.update({"max_digits": 6, "decimal_places": 2}) + super().__init__(verbose_name, name, **kwargs) + + +class User(AbstractUser): + + @property + def paid_drinks(self): + return self.consumption_list.filter(for_free=False) + + @property + def free_drinks(self): + return self.consumption_list.filter(for_free=True) + + @property + def donations_made(self): + query = self.donations.aggregate(sum=Sum("amount")) + return query["sum"] or 0 + + @property + def consumed_drinks_price(self): + query = self.paid_drinks \ + .annotate(cost=F("amount") * F("drink__sale_price_per_bottle")) \ + .aggregate(sum=Sum("cost")) + return query["sum"] or 0 + + @property + def other_payments_made(self): + query = self.payments.aggregate(sum=Sum("amount")) + return query["sum"] or 0 + + @property + def paybacks_received(self): + query = self.paybacks.aggregate(sum=Sum("amount")) + return query["sum"] or 0 + + @property + def balance(self): + return self.donations_made - self.consumed_drinks_price + self.other_payments_made - self.paybacks_received + + +class Donation(models.Model): + from_user = models.ForeignKey( + to=User, on_delete=models.PROTECT, + related_name="donations", related_query_name="donation") + date = models.DateField() + amount = PriceField() + note = models.CharField(max_length=64, blank=True, default="") class Payment(models.Model): class Topic(models.IntegerChoices): - # positive - donation = 0, "Spenden/Vorauszahlungen" - admission_fee = 1, "Eintrittsgeld" - supply_sale = 2, "Getränke-/Essensverkauf" - # negative site = 10, "Gelände" bands = 11, "Bands" supply_purchase = 12, "Getränke-/Essenseinkauf" - other_party = models.TextField() - topic = models.PositiveSmallIntegerField(choices=Topic.choices) - amount = models.PositiveIntegerField() + purpose = models.CharField(max_length=64) date = models.DateField() - note = models.TextField(blank=True) - is_estimated = models.BooleanField(default=False) + amount = PriceField() + from_user = models.ForeignKey( + to=User, on_delete=models.PROTECT, + related_name="payments", related_query_name="payment") - def is_incoming(self): - return self.topic < 10 - def is_outgoing(self): - return not self.is_incoming() +class Payback(models.Model): + to_user = models.ForeignKey( + to=User, on_delete=models.PROTECT, + related_name="paybacks", related_query_name="payback") + date = models.DateField() + amount = PriceField() + note = models.CharField(max_length=64, blank=True, default="") + + +class Drink(models.Model): + name = models.CharField(max_length=32, unique=True) + crates_ordered = models.PositiveSmallIntegerField( + help_text="just informational to see how good we planned, not the actual consumed/paid drinks" + ) + crates_purchased = models.PositiveSmallIntegerField() + crates_returned = models.PositiveSmallIntegerField() + purchase_price_per_crate = PriceField() + deposit_per_crate = PriceField() + bottles_per_crate = models.PositiveSmallIntegerField() + bottle_size = models.FloatField() + sale_price_per_bottle = PriceField() + + def __str__(self): + return self.name + + @property + def bottles_total(self): + return self.bottles_per_crate * self.crates_purchased + + @property + def bottles_returned(self): + return self.bottles_per_crate * self.crates_returned + + @property + def amount_per_crate(self): + return self.bottle_size * self.bottles_per_crate + + @property + def amount_total(self): + return self.amount_per_crate * self.crates_purchased + + @property + def purchase_price_per_bottle(self): + return self.purchase_price_per_crate / self.bottles_per_crate + + @property + def purchase_price_total(self): + return self.purchase_price_per_crate * self.crates_purchased + + @property + def deposit_total(self): + return self.deposit_per_crate * self.crates_purchased + + @property + def deposit_refund(self): + return self.deposit_per_crate * self.crates_returned + + @property + def deposit_kept(self): + return self.deposit_total - self.deposit_refund + + @property + def bottles_sold(self): + query = self.consumption_list.filter(for_free=False).aggregate(sum=Sum("amount")) + return query["sum"] or 0 + + @property + def sales_purchase_value(self): + return self.bottles_sold * self.purchase_price_per_bottle + + @property + def sale_price_total(self): + return self.bottles_sold * self.sale_price_per_bottle + + @property + def bottles_given_away(self): + query = self.consumption_list.filter(for_free=True).aggregate(sum=Sum("amount")) + return query["sum"] or 0 + + @property + def giveaway_purchase_value(self): + return self.bottles_given_away * self.purchase_price_per_bottle + + @property + def balance(self): + return self.sale_price_total - self.sales_purchase_value - self.giveaway_purchase_value + + +class Consumption(models.Model): + user = models.ForeignKey( + to=User, on_delete=models.CASCADE, + related_name="consumption_list", related_query_name="consumption") + drink = models.ForeignKey( + to=Drink, on_delete=models.CASCADE, + related_name="consumption_list", related_query_name="consumption") + amount = models.PositiveSmallIntegerField() + day = models.PositiveSmallIntegerField(choices=[(1, "Do"), (2, "Fr"), (3, "Sa")]) + for_free = models.BooleanField(default=False) diff --git a/gaehsnitzproject/settings.py b/gaehsnitzproject/settings.py index 8db2150..d6b1e9b 100644 --- a/gaehsnitzproject/settings.py +++ b/gaehsnitzproject/settings.py @@ -99,3 +99,5 @@ USE_L10N = False USE_TZ = True STATIC_URL = "/static/" + +AUTH_USER_MODEL = "gaehsnitz.User"