From ae28154b84f8a8658b717835d8a6ccfb784c847f Mon Sep 17 00:00:00 2001 From: Dominik George <dominik.george@teckids.org> Date: Sun, 13 Mar 2022 15:03:37 +0100 Subject: [PATCH] Reformat --- aleksis/apps/tezor/apps.py | 51 ++++++++++++-------- aleksis/apps/tezor/forms.py | 5 +- aleksis/apps/tezor/models/invoice.py | 71 ++++++++++++++++++++-------- aleksis/apps/tezor/predicates.py | 3 ++ aleksis/apps/tezor/preferences.py | 4 +- aleksis/apps/tezor/rules.py | 67 +++++++++++++++++++++----- aleksis/apps/tezor/tables.py | 2 + aleksis/apps/tezor/views.py | 31 +++++++----- 8 files changed, 169 insertions(+), 65 deletions(-) diff --git a/aleksis/apps/tezor/apps.py b/aleksis/apps/tezor/apps.py index 194ffad..f30b4eb 100644 --- a/aleksis/apps/tezor/apps.py +++ b/aleksis/apps/tezor/apps.py @@ -13,10 +13,14 @@ class DefaultConfig(AppConfig): "Repository": "https://edugit.org/AlekSIS/onboarding//AlekSIS-App-Tezor", } licence = "EUPL-1.2+" - copyright_info = (([2022], "Dominik George", "dominik.george@teckids.org"), ([2022], "Tom Teichler", "tom.teichler@teckids.org"),) + copyright_info = ( + ([2022], "Dominik George", "dominik.george@teckids.org"), + ([2022], "Tom Teichler", "tom.teichler@teckids.org"), + ) def ready(self): from django.conf import settings # noqa + settings.PAYMENT_VARIANTS = {} for app_config in apps.app_configs.values(): @@ -31,30 +35,37 @@ class DefaultConfig(AppConfig): variants = {} if prefs["payments__sofort_api_id"]: - variants["sofort"] = ("payments.sofort.SofortProvider", { - "id": prefs["payments__sofort_api_id"], - "key": prefs["payments__sofort_api_key"], - "project_id": prefs["payments__sofort_project_id"], - "endpoint": "https://api.sofort.com/api/xml", - }) + variants["sofort"] = ( + "payments.sofort.SofortProvider", + { + "id": prefs["payments__sofort_api_id"], + "key": prefs["payments__sofort_api_key"], + "project_id": prefs["payments__sofort_project_id"], + "endpoint": "https://api.sofort.com/api/xml", + }, + ) if prefs["payments__paypal_client_id"]: - variants["paypal"] = ("payments.paypal.PaypalProvider", { - "client_id": prefs["payments__paypal_client_id"], - "secret": prefs["payments__paypal_secret"], - "capture": not prefs["payments__paypal_capture"], - "endpoint": "https://api.paypal.com", - }) + variants["paypal"] = ( + "payments.paypal.PaypalProvider", + { + "client_id": prefs["payments__paypal_client_id"], + "secret": prefs["payments__paypal_secret"], + "capture": not prefs["payments__paypal_capture"], + "endpoint": "https://api.paypal.com", + }, + ) if prefs["payments__pledge_enabled"]: - variants["pledge"] = ("djp_sepa.providers.PaymentPledgeProvider", { - }) - + variants["pledge"] = ("djp_sepa.providers.PaymentPledgeProvider", {}) if prefs["payments__sdd_creditor_identifier"]: - variants["sdd"] = ("djp_sepa.providers.DirectDebitProvider", { - "creditor": prefs["payments__sdd_creditor"], - "creditor_identifier": prefs["payments__sdd_creditor_identifier"], - }) + variants["sdd"] = ( + "djp_sepa.providers.DirectDebitProvider", + { + "creditor": prefs["payments__sdd_creditor"], + "creditor_identifier": prefs["payments__sdd_creditor_identifier"], + }, + ) return variants diff --git a/aleksis/apps/tezor/forms.py b/aleksis/apps/tezor/forms.py index 6f35f89..47eb6c6 100644 --- a/aleksis/apps/tezor/forms.py +++ b/aleksis/apps/tezor/forms.py @@ -5,6 +5,7 @@ from aleksis.core.mixins import ExtensibleForm from .models.base import Client from .models.invoice import InvoiceGroup + class EditClientForm(ExtensibleForm): """Form to create or edit clients.""" @@ -17,9 +18,7 @@ class EditClientForm(ExtensibleForm): class EditInvoiceGroupForm(ExtensibleForm): - layout = Layout( - Row("name", "template_name") - ) + layout = Layout(Row("name", "template_name")) class Meta: model = InvoiceGroup diff --git a/aleksis/apps/tezor/models/invoice.py b/aleksis/apps/tezor/models/invoice.py index 7c87380..af5cb87 100644 --- a/aleksis/apps/tezor/models/invoice.py +++ b/aleksis/apps/tezor/models/invoice.py @@ -19,15 +19,20 @@ from .base import Client class InvoiceGroup(ExtensibleModel): name = models.CharField(verbose_name=_("Invoice group name"), max_length=255) client = models.ForeignKey( - Client, verbose_name=_("Linked client"), related_name="invoice_groups", on_delete=models.SET_NULL, null=True + Client, + verbose_name=_("Linked client"), + related_name="invoice_groups", + on_delete=models.SET_NULL, + null=True, ) - template_name = models.CharField(verbose_name=_("Template to render invoices with as PDF"), blank=True, max_length=255) + template_name = models.CharField( + verbose_name=_("Template to render invoices with as PDF"), blank=True, max_length=255 + ) def __str__(self) -> str: return self.name - class Meta: constraints = [ models.UniqueConstraint(fields=["client", "name"], name="group_uniq_per_client") @@ -52,7 +57,11 @@ class Invoice(BasePayment, PureDjangoModel): } group = models.ForeignKey( - InvoiceGroup, verbose_name=_("Invoice group"), related_name="invoices", on_delete=models.SET_NULL, null=True + InvoiceGroup, + verbose_name=_("Invoice group"), + related_name="invoices", + on_delete=models.SET_NULL, + null=True, ) number = models.CharField(verbose_name=_("Invoice number"), max_length=255) @@ -63,7 +72,13 @@ class Invoice(BasePayment, PureDjangoModel): 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) + 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 @@ -101,7 +116,10 @@ class Invoice(BasePayment, PureDjangoModel): class Meta: constraints = [ models.UniqueConstraint(fields=["number", "group"], name="number_uniq_per_group"), - models.CheckConstraint(check=(Q(for_object_id__isnull=True) | Q(person__isnull=True)), name="object_or_person"), + models.CheckConstraint( + check=(Q(for_object_id__isnull=True) | Q(person__isnull=True)), + name="object_or_person", + ), ] @property @@ -118,17 +136,21 @@ class Invoice(BasePayment, PureDjangoModel): values = [] for tax_rate, total in tax_amounts.items(): - values.append({ - "name": _("Included VAT {} %").format(tax_rate), - "value": total, + values.append( + { + "name": _("Included VAT {} %").format(tax_rate), + "value": total, + "currency": self.currency, + } + ) + + values.append( + { + "name": _("Gross total"), + "value": self.total, "currency": self.currency, - }) - - values.append({ - "name": _("Gross total"), - "value": self.total, - "currency": self.currency, - }) + } + ) return TotalsTable(values) @@ -142,9 +164,20 @@ class Invoice(BasePayment, PureDjangoModel): 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") + 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") + tax_rate = models.DecimalField( + verbose_name=_("Tax rate"), max_digits=4, decimal_places=1, default="0.0" + ) 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) + yield PurchasedItem( + name=self.description, + quantity=1, + price=self.price, + currency=self.currency, + sku=self.sku, + tax_rate=self.tax_rate, + ) diff --git a/aleksis/apps/tezor/predicates.py b/aleksis/apps/tezor/predicates.py index e9fb75d..bfcab33 100644 --- a/aleksis/apps/tezor/predicates.py +++ b/aleksis/apps/tezor/predicates.py @@ -6,16 +6,19 @@ from .models.invoice import Invoice User = get_user_model() + @predicate def is_own_invoice(user: User, obj: Invoice): """Predicate which checks if the invoice is linked to the current user.""" return obj.get_person() == user.person + @predicate def has_no_payment_variant(user: User, obj: Invoice): """Predicate which checks that the invoice has no payment variant.""" return not obj.variant + def is_in_payment_status(status: str): """Predicate which checks whether the invoice is in a specific state.""" diff --git a/aleksis/apps/tezor/preferences.py b/aleksis/apps/tezor/preferences.py index 8a25f34..5c8b799 100644 --- a/aleksis/apps/tezor/preferences.py +++ b/aleksis/apps/tezor/preferences.py @@ -15,7 +15,9 @@ class EnablePledge(BooleanPreference): section = payments name = "public_payments" verbose_name = _("Public payments") - help_text = _("Allow anyone (including guests) to make payments. Basic invoice information will be visible to anyone who knows the invoice token.") + help_text = _( + "Allow anyone (including guests) to make payments. Basic invoice information will be visible to anyone who knows the invoice token." + ) default = True required = False diff --git a/aleksis/apps/tezor/rules.py b/aleksis/apps/tezor/rules.py index 12a27e3..8f2e4f8 100644 --- a/aleksis/apps/tezor/rules.py +++ b/aleksis/apps/tezor/rules.py @@ -1,11 +1,17 @@ import rules from payments import PaymentStatus -from aleksis.core.util.predicates import has_person, has_global_perm, has_any_object, has_object_perm, is_site_preference_set +from aleksis.core.util.predicates import ( + has_any_object, + has_global_perm, + has_object_perm, + has_person, + is_site_preference_set, +) from .models.base import Client from .models.invoice import Invoice, InvoiceGroup -from .predicates import has_no_payment_variant, is_own_invoice, is_in_payment_status +from .predicates import has_no_payment_variant, is_in_payment_status, is_own_invoice # View clients view_clients_predicate = has_person & ( @@ -39,7 +45,8 @@ rules.add_perm("tezor.delete_client_rule", delete_client_predicate) # View invoice groups view_invoice_groups_predicate = has_person & ( - has_global_perm("tezor.view_invoice_group") | has_any_object("tezor.view_invoice_group", InvoiceGroup) + has_global_perm("tezor.view_invoice_group") + | has_any_object("tezor.view_invoice_group", InvoiceGroup) ) rules.add_perm("tezor.view_invoice_groups_rule", view_invoice_groups_predicate) @@ -57,35 +64,73 @@ rules.add_perm("tezor.edit_invoice_group_rule", edit_invoice_group_predicate) # Create invoice groups create_invoice_groups_predicate = has_person & ( - has_global_perm("tezor.create_invoice_group") | has_any_object("tezor.create_invoice_group", InvoiceGroup) + has_global_perm("tezor.create_invoice_group") + | has_any_object("tezor.create_invoice_group", InvoiceGroup) ) rules.add_perm("tezor.create_invoice_groups_rule", create_invoice_groups_predicate) # Delete invoice groups delete_invoice_groups_predicate = has_person & ( - has_global_perm("tezor.delete_invoice_group") | has_any_object("tezor.delete_invoice_group", InvoiceGroup) + has_global_perm("tezor.delete_invoice_group") + | has_any_object("tezor.delete_invoice_group", InvoiceGroup) ) rules.add_perm("tezor.delete_invoice_groups_rule", delete_invoice_groups_predicate) # Display invoice billing information -display_billing_predicate = has_person & (is_own_invoice | has_global_perm("tezor.display_billing") | has_object_perm("tezor.display_billing")) +display_billing_predicate = has_person & ( + is_own_invoice + | has_global_perm("tezor.display_billing") + | has_object_perm("tezor.display_billing") +) rules.add_perm("tezor.display_billing_rule", display_billing_predicate) # Display invoice purchased items -display_purchased_items_predicate = has_person & (is_own_invoice | has_global_perm("tezor.display_purchased_items") | has_object_perm("tezor.display_purchased_items")) +display_purchased_items_predicate = has_person & ( + is_own_invoice + | has_global_perm("tezor.display_purchased_items") + | has_object_perm("tezor.display_purchased_items") +) rules.add_perm("tezor.display_purchased_items_rule", display_purchased_items_predicate) # Change payment variant -change_payment_variant_predicate = has_person & is_in_payment_status(PaymentStatus.WAITING) & ((is_own_invoice & has_no_payment_variant) | has_global_perm("tezor.change_payment_variant") | has_object_perm("tezor.change_payment_variant")) +change_payment_variant_predicate = ( + has_person + & is_in_payment_status(PaymentStatus.WAITING) + & ( + (is_own_invoice & has_no_payment_variant) + | has_global_perm("tezor.change_payment_variant") + | has_object_perm("tezor.change_payment_variant") + ) +) rules.add_perm("tezor.change_payment_variant", change_payment_variant_predicate) # Start payment -do_payment_predicate = has_person & (is_in_payment_status(PaymentStatus.WAITING) | is_in_payment_status(PaymentStatus.INPUT) | is_in_payment_status(PaymentStatus.ERROR) | is_in_payment_status(PaymentStatus.REJECTED)) & ((is_own_invoice | is_site_preference_set("payments", "public_payments")) | has_global_perm("tezor.do_payment") | has_object_perm("tezor.do_payment")) +do_payment_predicate = ( + has_person + & ( + is_in_payment_status(PaymentStatus.WAITING) + | is_in_payment_status(PaymentStatus.INPUT) + | is_in_payment_status(PaymentStatus.ERROR) + | is_in_payment_status(PaymentStatus.REJECTED) + ) + & ( + (is_own_invoice | is_site_preference_set("payments", "public_payments")) + | has_global_perm("tezor.do_payment") + | has_object_perm("tezor.do_payment") + ) +) rules.add_perm("tezor.do_payment", do_payment_predicate) # View invoice -view_invoice_predicate = has_person & is_own_invoice | is_site_preference_set("payments", "public_payments") | has_global_perm("tezor.view_invoice") | has_object_perm("tezor.view_invoice") +view_invoice_predicate = ( + has_person & is_own_invoice + | is_site_preference_set("payments", "public_payments") + | has_global_perm("tezor.view_invoice") + | has_object_perm("tezor.view_invoice") +) rules.add_perm("tezor.view_invoice_rule", view_invoice_predicate) -print_invoice_predicate = (view_invoice_predicate & display_billing_predicate & display_purchased_items_predicate) +print_invoice_predicate = ( + view_invoice_predicate & display_billing_predicate & display_purchased_items_predicate +) rules.add_perm("tezor.print_invoice_rule", print_invoice_predicate) diff --git a/aleksis/apps/tezor/tables.py b/aleksis/apps/tezor/tables.py index 16ed8a0..f1d1c23 100644 --- a/aleksis/apps/tezor/tables.py +++ b/aleksis/apps/tezor/tables.py @@ -60,6 +60,7 @@ class ClientsTable(tables.Table): text=_("Delete"), ) + class InvoiceGroupsTable(tables.Table): name = tables.Column() @@ -83,6 +84,7 @@ class InvoiceGroupsTable(tables.Table): text=_("Delete"), ) + class InvoicesTable(tables.Table): number = tables.Column() diff --git a/aleksis/apps/tezor/views.py b/aleksis/apps/tezor/views.py index 06a4df8..33b49a8 100644 --- a/aleksis/apps/tezor/views.py +++ b/aleksis/apps/tezor/views.py @@ -1,22 +1,22 @@ -from django.shortcuts import redirect, render, get_object_or_404 -from django.views.decorators.cache import never_cache -from django.views.generic import FormView, TemplateView, View -from django.views.generic.detail import DetailView +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse, reverse_lazy from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _ +from django.views.decorators.cache import never_cache +from django.views.generic import FormView, TemplateView, View +from django.views.generic.detail import DetailView -from payments import get_payment_model, PaymentStatus, RedirectNeeded +from django_tables2.views import RequestConfig, SingleTableView +from payments import PaymentStatus, RedirectNeeded, get_payment_model from rules.contrib.views import PermissionRequiredMixin -from django_tables2.views import SingleTableView, RequestConfig -from aleksis.core.views import RenderPDFView from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView +from aleksis.core.views import RenderPDFView -from .tables import ClientsTable, InvoiceGroupsTable, InvoicesTable from .forms import EditClientForm, EditInvoiceGroupForm from .models.base import Client from .models.invoice import Invoice, InvoiceGroup +from .tables import ClientsTable, InvoiceGroupsTable, InvoicesTable class GetInvoicePDF(PermissionRequiredMixin, RenderPDFView): @@ -42,7 +42,11 @@ class DoPaymentView(PermissionRequiredMixin, View): def dispatch(self, request, token): self.object = get_object_or_404(self.model, token=token) - if self.object.status not in [PaymentStatus.WAITING, PaymentStatus.INPUT, PaymentStatus.REJECTED]: + if self.object.status not in [ + PaymentStatus.WAITING, + PaymentStatus.INPUT, + PaymentStatus.REJECTED, + ]: return redirect(self.object.get_success_url()) try: @@ -117,6 +121,7 @@ class ClientDetailView(PermissionRequiredMixin, DetailView): return context + class InvoiceGroupDetailView(PermissionRequiredMixin, DetailView): model = InvoiceGroup @@ -145,13 +150,17 @@ class InvoiceGroupCreateView(PermissionRequiredMixin, AdvancedCreateView): success_url = reverse_lazy("clients") success_message = _("The invoice_group has been created.") - def form_valid(self, form): client = Client.objects.get(id=self.kwargs["pk"]) - InvoiceGroup.objects.create(client=client, name=form.cleaned_data["name"], template_name=form.cleaned_data["template_name"]) + InvoiceGroup.objects.create( + client=client, + name=form.cleaned_data["name"], + template_name=form.cleaned_data["template_name"], + ) return super().form_valid(form) + @method_decorator(never_cache, name="dispatch") class InvoiceGroupEditView(PermissionRequiredMixin, AdvancedEditView): """Edit view for invoice_groups.""" -- GitLab