From 67b16cfb83f92c20ae2c812e5d9f855aeb352057 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Sun, 6 Mar 2022 21:26:20 +0100
Subject: [PATCH] Replace invoicing with django-payments

---
 aleksis/apps/tezor/models/base.py    | 22 --------------
 aleksis/apps/tezor/models/invoice.py | 43 +++++++++-------------------
 aleksis/apps/tezor/settings.py       |  1 +
 aleksis/apps/tezor/urls.py           |  3 +-
 pyproject.toml                       |  1 +
 5 files changed, 17 insertions(+), 53 deletions(-)
 create mode 100644 aleksis/apps/tezor/settings.py

diff --git a/aleksis/apps/tezor/models/base.py b/aleksis/apps/tezor/models/base.py
index a7e9020..e8feec9 100644
--- a/aleksis/apps/tezor/models/base.py
+++ b/aleksis/apps/tezor/models/base.py
@@ -1,5 +1,3 @@
-from django.contrib.contenttypes.fields import GenericForeignKey
-from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
@@ -13,23 +11,3 @@ class Client(ExtensibleModel):
         constraints = [
             models.UniqueConstraint(fields=["name", "site"], name="uniq_client_per_site")
         ]
-
-
-class Subject(ExtensibleModel):
-    content_type = models.ForeignKey(ContetType, on_delete=models.SET_NULL)
-    object_id = models.PositiveIntegerField()
-    related = GenericForeignKey("content_type", "object_id")
-
-    def get_address(self):
-        if hasattr(self.related, "get_address"):
-            return self.related.get_address()
-        elif hasattr(self.related, "addressing_name") and hasattr(self.related, "street") and hasattr(self.related, "housenumber") and hasattr(self.related, "postal_code") and hasattr(self.related, "place"):
-            # FIXME Use proper locale-based address generation
-            return f"{self.related.addressing_name}\n{self.related.street} {self.related.housenumber}\n{self.related.postal_code} {self.related.place}"
-
-    @classmethod
-    def from_person(cls, person):
-        ct = ContentType.objects.get_for_model(person)
-        subject, created = cls.objects.get_or_create(content_type=ct, object_id=person)
-
-        return subject
diff --git a/aleksis/apps/tezor/models/invoice.py b/aleksis/apps/tezor/models/invoice.py
index e18fb9a..54bb6d3 100644
--- a/aleksis/apps/tezor/models/invoice.py
+++ b/aleksis/apps/tezor/models/invoice.py
@@ -1,9 +1,13 @@
+from django.contrib.contenttypes.fields import GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
 from django.db import models
 from django.utils.translation import gettext_lazy as _
 
 from djmoney.models.fields import CurrencyField, MoneyField
+from payments import PurchasedItem
+from payments.models import BasePayment
 
-from aleksis.core.mixins import ExtensibleModel
+from aleksis.core.mixins import ExtensibleModel, PureDjangoModel
 
 from .base import Client, Subject
 
@@ -20,41 +24,20 @@ class InvoiceGroup(ExtensibleModel):
         ]
 
 
-class Invoice(ExtensibleModel):
+class Invoice(BasePayment, PureDjangoModel):
     group = models.ForeignKey(
         InvoiceGroup, verbose_name=_("Invoice group"), related_name="invoices"
     )
-
     number = models.CharField(verbose_name=_("Invoice number"))
-    date = models.DateField(verbose_name=_("Invoice date"))
-    recipient = models.ForeignKey(Subject, verbose_name=_("Recipient"), on_delete=models.SET_NULL)
 
-    @property
-    def currency(self):
-        try:
-            return self.positions.first().net_amount_currency
-        except InvoicePosition.DoesNotExist:
-            return None
+    for_content_type = models.ForeignKey(ContetType, on_delete=models.SET_NULL)
+    for_object_id = models.PositiveIntegerField()
+    for_object = GenericForeignKey("content_type", "object_id")
+
+    def get_purchased_items(self):
+        return self.for_object.get_purchased_items()
 
     class Meta:
         constraints = [
-            models.UniqueConstraint(fields=["group", "number"], name="number_uniq_per_group")
+            models.UniqueConstraint(fields=["number", "token"], name="number_uniq_per_group")
         ]
-
-
-class InvoicePosition(ExtensibleModel):
-    invoice = models.ForeignKey(Invoice, verbose_name=_("Invoice"), related_name="positions")
-
-    description = models.TextField(verbose_name=_("Description"))
-
-    vat_rate = models.PositiveSmallIntegerField(verbose_name=_("VAT rate"), default=0)
-    net_amount = models.MoneyField(verbose_name=_("Net amount"))
-
-    @property
-    def gross_amount(self):
-        # FIXME turn into manager/annotation/etc.
-        return self.net_amount * (1 + self.vat_rate / 100)
-
-    class Meta:
-        # FIXME Add check constraint for currency
-        pass
diff --git a/aleksis/apps/tezor/settings.py b/aleksis/apps/tezor/settings.py
new file mode 100644
index 0000000..dabd92b
--- /dev/null
+++ b/aleksis/apps/tezor/settings.py
@@ -0,0 +1 @@
+INSTALLED_APPS = ["payments"]
diff --git a/aleksis/apps/tezor/urls.py b/aleksis/apps/tezor/urls.py
index 3545de1..0c1cdfe 100644
--- a/aleksis/apps/tezor/urls.py
+++ b/aleksis/apps/tezor/urls.py
@@ -1,7 +1,8 @@
-from django.urls import path
+from django.urls import include, path
 
 from . import views
 
 urlpatterns = [
     path("empty", views.empty, name="empty"),
+    path("payments/", include("payments.urls")),
 ]
diff --git a/pyproject.toml b/pyproject.toml
index f770a12..63f198e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,6 +32,7 @@ secondary = true
 python = "^3.9"
 aleksis-core = "^2.7"
 django-money = "^2.1.1"
+django-payments = "^0.15.0"
 
 [tool.poetry.dev-dependencies]
 aleksis-builddeps = "*"
-- 
GitLab