From 12323283b31b494c6ab2093c35375674fad0f47b Mon Sep 17 00:00:00 2001 From: Dominik George <dominik.george@teckids.org> Date: Sat, 12 Mar 2022 12:41:39 +0100 Subject: [PATCH] Re-model manual invoices to use only one Invoice object --- aleksis/apps/tezor/models/invoice.py | 50 +++++++++++----------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/aleksis/apps/tezor/models/invoice.py b/aleksis/apps/tezor/models/invoice.py index 8954842..28fc66c 100644 --- a/aleksis/apps/tezor/models/invoice.py +++ b/aleksis/apps/tezor/models/invoice.py @@ -2,6 +2,7 @@ from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models +from django.db.models import Q from django.shortcuts import reverse from django.utils.translation import gettext_lazy as _ @@ -52,6 +53,10 @@ class Invoice(BasePayment, PureDjangoModel): for_object_id = models.PositiveIntegerField() for_object = GenericForeignKey("for_content_type", "for_object_id") + # For manual invoicing + person = models.ForeignKey(Person, on_delete=models.SET_NULL, verbose_name=_("Invoice recipient (person)"), blank=True, null=True) + items = models.ManyToManyField("InvoiceItem", verbose_name=_("Invoice items")) + @classmethod def get_variant_choices(cls): choices = [] @@ -66,10 +71,15 @@ class Invoice(BasePayment, PureDjangoModel): return self.__class__.VARIANT_DISPLAY[self.variant][1] def get_purchased_items(self): - return self.for_object.get_purchased_items() + for item in self.items.all(): + yield item.as_purchased_item() + else: + return self.for_object.get_purchased_items() def get_person(self): - if hasattr(self.for_object, "person"): + if self.person: + return self.person + elif hasattr(self.for_object, "person"): return self.for_object.person elif hasattr(self.for_object, "get_person"): return self.for_object.get_person() @@ -78,7 +88,8 @@ class Invoice(BasePayment, PureDjangoModel): class Meta: constraints = [ - models.UniqueConstraint(fields=["number", "group"], name="number_uniq_per_group") + models.UniqueConstraint(fields=["number", "group"], name="number_uniq_per_group"), + models.CheckConstraint(Q(for_object_id__isnull=True) | Q(person__isnull=True)), ] @property @@ -116,35 +127,12 @@ class Invoice(BasePayment, PureDjangoModel): return reverse("invoice_by_token", kwargs={"slug": self.token}) -class ManualInvoice(ExtensibleModel): - invoice_group = models.ForeignKey(InvoiceGroup, on_delete=models.CASCADE, verbose_name=_("Invoice group")) - person = models.ForeignKey(Person, on_delete=models.SET_NULL, verbose_name=_("Invoice recipient (person)")) - - item_description = models.CharField(max_length=255, verbose_name=_("Purchased item")) +class InvoiceItem(ExtensibleModel): + sku = models.CharField(max_length=255, verbose_name=_("Article no."), blank=True) + description = models.CharField(max_length=255, verbose_name=_("Purchased item")) price = models.DecimalField(verbose_name=_("Item gross price"), max_digits=9, decimal_places=2, default="0.0") currency = models.CharField(max_length=10, verbose_name=_("Currency")) tax_rate = models.DecimalField(verbose_name=_("Tax rate"), max_digits=4, decimal_places=1, default="0.0") - variant = models.CharField(verbose_name=_("Payment variant"), max_length=255, blank=True) - - def get_purchased_items(self): - yield PurchasedItem(name=self.item_description, quantity=1, price=self.price, currency=self.currency, sku="", tax_rate=self.tax_rate) - - def get_invoice(self): - invoice, __ = Invoice.objects.get_or_create(for_content_type=ContentType.objects.get_for_model(self), for_object_id=self.pk, defaults={ - "group": self.invoice_group, - "variant": self.variant, - "number": f"FIXME", - "currency": self.currency, - "total": self.price, - "tax": self.total / (self.tax_rate + 100) * self.tax_rate, - "description": self.item_description, - "billing_first_name": self.person.first_name, - "billing_last_name": self.person.last_name, - "billing_address_1": f"{self.person.street} {self.person.housenumber}", - "billing_city": self.person.place, - "billing_postcode": self.person.postal_code, - "billing_email": self.person.email, - }) - - return invoice + def as_purchased_item(self): + yield PurchasedItem(name=self.description, quantity=1, price=self.price, currency=self.currency, sku=self.sku, tax_rate=self.tax_rate) -- GitLab