Skip to content
Snippets Groups Projects
Verified Commit 12323283 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Re-model manual invoices to use only one Invoice object

parent 8f2b3e64
No related branches found
No related tags found
1 merge request!10Add models for manual invoicing
Pipeline #59359 canceled
...@@ -2,6 +2,7 @@ from django.conf import settings ...@@ -2,6 +2,7 @@ from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.db.models import Q
from django.shortcuts import reverse from django.shortcuts import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
...@@ -52,6 +53,10 @@ class Invoice(BasePayment, PureDjangoModel): ...@@ -52,6 +53,10 @@ class Invoice(BasePayment, PureDjangoModel):
for_object_id = models.PositiveIntegerField() for_object_id = models.PositiveIntegerField()
for_object = GenericForeignKey("for_content_type", "for_object_id") 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 @classmethod
def get_variant_choices(cls): def get_variant_choices(cls):
choices = [] choices = []
...@@ -66,10 +71,15 @@ class Invoice(BasePayment, PureDjangoModel): ...@@ -66,10 +71,15 @@ class Invoice(BasePayment, PureDjangoModel):
return self.__class__.VARIANT_DISPLAY[self.variant][1] return self.__class__.VARIANT_DISPLAY[self.variant][1]
def get_purchased_items(self): 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): 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 return self.for_object.person
elif hasattr(self.for_object, "get_person"): elif hasattr(self.for_object, "get_person"):
return self.for_object.get_person() return self.for_object.get_person()
...@@ -78,7 +88,8 @@ class Invoice(BasePayment, PureDjangoModel): ...@@ -78,7 +88,8 @@ class Invoice(BasePayment, PureDjangoModel):
class Meta: class Meta:
constraints = [ 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 @property
...@@ -116,35 +127,12 @@ class Invoice(BasePayment, PureDjangoModel): ...@@ -116,35 +127,12 @@ class Invoice(BasePayment, PureDjangoModel):
return reverse("invoice_by_token", kwargs={"slug": self.token}) return reverse("invoice_by_token", kwargs={"slug": self.token})
class ManualInvoice(ExtensibleModel): class InvoiceItem(ExtensibleModel):
invoice_group = models.ForeignKey(InvoiceGroup, on_delete=models.CASCADE, verbose_name=_("Invoice group")) sku = models.CharField(max_length=255, verbose_name=_("Article no."), blank=True)
person = models.ForeignKey(Person, on_delete=models.SET_NULL, verbose_name=_("Invoice recipient (person)")) description = models.CharField(max_length=255, verbose_name=_("Purchased item"))
item_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") 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")) 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") 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 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)
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment