From 0a100d4587566875244a713ca3ba81361de15311 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Tue, 15 Mar 2022 13:54:48 +0100
Subject: [PATCH] [WIP] Implement variant changing for customers

---
 aleksis/apps/tezor/predicates.py              | 10 +++
 aleksis/apps/tezor/rules.py                   |  4 +-
 .../tezor/templates/tezor/invoice/full.html   | 87 ++++++++++---------
 aleksis/apps/tezor/views.py                   | 12 +++
 4 files changed, 71 insertions(+), 42 deletions(-)

diff --git a/aleksis/apps/tezor/predicates.py b/aleksis/apps/tezor/predicates.py
index bfcab33..8d8a25c 100644
--- a/aleksis/apps/tezor/predicates.py
+++ b/aleksis/apps/tezor/predicates.py
@@ -27,3 +27,13 @@ def is_in_payment_status(status: str):
         return obj.status == status
 
     return _predicate
+
+
+def has_payment_variant(variant: str):
+    """Predicate which checks whether the invoice has a specific variant."""
+
+    @predicate
+    def _predicate(user: User, obj: Invoice):
+        return obj.variant == variant
+
+    return _predicate
diff --git a/aleksis/apps/tezor/rules.py b/aleksis/apps/tezor/rules.py
index 8fc73d0..edc7ede 100644
--- a/aleksis/apps/tezor/rules.py
+++ b/aleksis/apps/tezor/rules.py
@@ -11,7 +11,7 @@ from aleksis.core.util.predicates import (
 
 from .models.base import Client
 from .models.invoice import InvoiceGroup
-from .predicates import has_no_payment_variant, is_in_payment_status, is_own_invoice
+from .predicates import has_no_payment_variant, has_payment_variant, is_in_payment_status, is_own_invoice
 
 # View clients
 view_clients_predicate = has_person & (
@@ -97,7 +97,7 @@ change_payment_variant_predicate = (
     has_person
     & is_in_payment_status(PaymentStatus.WAITING)
     & (
-        (is_own_invoice & has_no_payment_variant)
+        (is_own_invoice & (has_no_payment_variant | has_payment_variant("pledge")))
         | has_global_perm("tezor.change_payment_variant")
         | has_object_perm("tezor.change_payment_variant")
     )
diff --git a/aleksis/apps/tezor/templates/tezor/invoice/full.html b/aleksis/apps/tezor/templates/tezor/invoice/full.html
index 01576f3..1c506f4 100644
--- a/aleksis/apps/tezor/templates/tezor/invoice/full.html
+++ b/aleksis/apps/tezor/templates/tezor/invoice/full.html
@@ -13,6 +13,7 @@
     {% has_perm 'tezor.display_billing_rule' user object as can_view_billing_information %}
     {% has_perm 'tezor.print_invoice_rule' user object as can_print_invoice %}
     {% has_perm 'tezor.send_invoice_email_rule' user object as can_send_invoice_email %}
+    {% has_perm 'tezor.change_payment_variant' user object as can_change_variant %}
 
     <h1>{% trans "Invoice" %} {{ object.number }} — {{ object.created.date }}</h1>
 
@@ -60,48 +61,54 @@
           </div>
         </div>
       </div>
-    {% endif %}
-      <div class="col s12 m6">
-        <div class="card">
-          <div class="card-content">
-            <span class="card-title">{% trans "Payment" %}</span>
-            <table class="highlight">
-              <tr>
-                <td>
-                  <i class="material-icons iconify" data-icon="{{ object.get_variant_icon }}"></i>
-                </td>
-                <td>
-                  {{ object.get_variant_name }}
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <i class="material-icons iconify" data-icon="{{ object.get_status_icon }}"></i>
-                </td>
-                <td>
-                  {{ object.get_status_display }}
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <i class="material-icons iconify" data-icon="mdi:calendar-end"></i>
-                </td>
-                <td>
-                  {{ object.due_date }}
-                </td>
-              </tr>
-            </table>
-          </div>
-          {% if object.status == "waiting" or object.status == "rejected" or object.status == "input" and can_do_payment %}
-          <div class="card-action">
-            <a class="btn waves-effect waves-light green" href="{% url 'do_payment' object.token %}">
-              <i class="material-icons left iconify" data-icon="mdi:cash-fast"></i>
-              {% trans "Pay now" %}
-            </a>
+      {% endif %}
+      <form action="{% url 'do_payment' object.token %}">
+        <div class="col s12 m6">
+          <div class="card">
+            <div class="card-content">
+              <span class="card-title">{% trans "Payment" %}</span>
+              <table class="highlight">
+                <tr>
+                  <td>
+                    <i class="material-icons iconify" data-icon="{{ object.get_variant_icon }}"></i>
+                  </td>
+                  <td>
+                    <select name="variant" {% if not can_change_variant %}disabled{% endif %}>
+                      {% for choice in object.get_variant_choices %}
+                        <option value="{{ choice.0 }}" {% if object.get_variant_name == choice.0 %}selected{% endif %}>{{ choice.1 }}</option>
+                      {% endfor %}
+                    </select>
+                  </td>
+                </tr>
+                <tr>
+                  <td>
+                    <i class="material-icons iconify" data-icon="{{ object.get_status_icon }}"></i>
+                  </td>
+                  <td>
+                    {{ object.get_status_display }}
+                  </td>
+                </tr>
+                <tr>
+                  <td>
+                    <i class="material-icons iconify" data-icon="mdi:calendar-end"></i>
+                  </td>
+                  <td>
+                    {{ object.due_date }}
+                  </td>
+                </tr>
+              </table>
+            </div>
+            {% if object.status == "waiting" or object.status == "rejected" or object.status == "input" and can_do_payment %}
+            <div class="card-action">
+              <button class="btn waves-effect waves-light green" type="submit">
+                <i class="material-icons left iconify" data-icon="mdi:cash-fast"></i>
+                {% trans "Pay now" %}
+              </button>
+            </div>
+            {% endif %}
           </div>
-          {% endif %}
         </div>
-      </div>
+      </form>
     </div>
 
     {% if can_view_purchased_items %}
diff --git a/aleksis/apps/tezor/views.py b/aleksis/apps/tezor/views.py
index cbc4703..1870c2b 100644
--- a/aleksis/apps/tezor/views.py
+++ b/aleksis/apps/tezor/views.py
@@ -1,3 +1,4 @@
+from django.conf import settings
 from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse_lazy
 from django.utils.decorators import method_decorator
@@ -42,6 +43,17 @@ class DoPaymentView(PermissionRequiredMixin, View):
     def dispatch(self, request, token):
         self.object = get_object_or_404(self.model, token=token)
 
+        new_variant = request.GET.get("variant", None)
+        if new_variant:
+            if xxx_has_perm("tezor.change_payment_variant", self.object):  # FIXME
+                if variant in settings.PAYMENT_VARIANTS:
+                    object.variant = variant
+                    object.save()
+                else:
+                    raise xxxbadrequest  # FIXME
+            else:
+                raise permissiondenied  # FIXME
+
         if self.object.status not in [
             PaymentStatus.WAITING,
             PaymentStatus.INPUT,
-- 
GitLab