Skip to content
Snippets Groups Projects

Add models for manual invoicing

Merged Nik | Klampfradler requested to merge 2-add-manual-invoicing into master
1 file
+ 19
31
Compare changes
  • Side-by-side
  • Inline
@@ -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
Loading