From 787e868847737a120250c24b76710034baed9fb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org>
Date: Sun, 2 Jul 2023 18:03:05 +0900
Subject: [PATCH] finish approval logic

---
 contracts/admin.py                  |  9 ++---
 contracts/forms.py                  | 63 +++++++++++++++++++++++++++--
 contracts/models.py                 |  2 +-
 registry/templates/admin/index.html |  2 +-
 4 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/contracts/admin.py b/contracts/admin.py
index 8a6d17b..c49ebfe 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -213,6 +213,7 @@ class ContractAdmin(
                         "summary",
                         "is_public",
                         "is_valid",
+                        "status",
                         "primary_contract",
                     ]
                 },
@@ -254,7 +255,6 @@ class ContractAdmin(
                     ]
                 },
             ),
-            ("Stav", {"fields": ["status"]}),
             (
                 "Doplňující informace",
                 {
@@ -281,7 +281,7 @@ class ContractAdmin(
 
         return fieldsets
 
-    fieldsets_and_inlines_order = order = [
+    fieldsets_and_inlines_order = [
         FieldsetInlineOrder.FIELDSET,
         FieldsetInlineOrder.FIELDSET,
         FieldsetInlineOrder.FIELDSET,
@@ -291,7 +291,6 @@ class ContractAdmin(
         FieldsetInlineOrder.FIELDSET,
         FieldsetInlineOrder.INLINE,
         FieldsetInlineOrder.INLINE,
-        FieldsetInlineOrder.FIELDSET,
         FieldsetInlineOrder.INLINE,
         FieldsetInlineOrder.FIELDSET,
     ]
@@ -422,7 +421,7 @@ class ContractAdmin(
                         settings.NASTENKA_API_URL,
                         data=json.dumps(
                             {
-                                "name": f"Smlouva odmĂ­tnuta - {obj.name}",
+                                "name": f"Smlouva zamĂ­tnuta - {obj.name}",
                                 "description": (
                                     obj.summary
                                     if obj.summary is not None
@@ -476,7 +475,7 @@ class ContractAdmin(
         AutocompleteFilterFactory("Spisovna", "filing_area"),
         AutocompleteFilterFactory("Problém", "issues"),
         AutocompleteFilterFactory(
-            "Naše smluvná strana", "contractee_signatures__contractee"
+            "Naše smluvní strana", "contractee_signatures__contractee"
         ),
         AutocompleteFilterFactory("Jiná smluvní strana", "signee_signatures__signee"),
         "status",
diff --git a/contracts/forms.py b/contracts/forms.py
index 04ca974..3f9b300 100644
--- a/contracts/forms.py
+++ b/contracts/forms.py
@@ -23,20 +23,75 @@ class AtLeastOneRequiredInlineFormSet(BaseInlineFormSet):
 
 
 class ContractAdminForm(forms.ModelForm):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        if "status" in self.fields:
+            allowed_choices = []
+
+            for choice_key, choice_label in Contract.StatusTypes.choices:
+                # Not yet created
+                if self.instance.id is None:
+                    if choice_key in (
+                        Contract.StatusTypes.WORK_IN_PROGRESS,
+                        Contract.StatusTypes.TO_BE_APPROVED
+                    ):
+                        allowed_choices.append((choice_key, choice_label,))
+
+                    continue
+
+                if self.instance.status == choice_key:
+                    allowed_choices.append((choice_key, choice_label,))
+                    continue
+
+                if self.instance.status in (
+                    Contract.StatusTypes.WORK_IN_PROGRESS,
+                    Contract.StatusTypes.TO_BE_APPROVED
+                ):
+                    if self.current_user.has_perm("contract.approve"):
+                        if choice_key in (
+                            Contract.StatusTypes.APPROVED,
+                            Contract.StatusTypes.REJECTED
+                        ):
+                            allowed_choices.append((choice_key, choice_label,))
+                            continue
+
+                if self.instance.status == Contract.StatusTypes.REJECTED:
+                    if choice_key in (
+                        Contract.StatusTypes.WORK_IN_PROGRESS,
+                        Contract.StatusTypes.TO_BE_APPROVED
+                    ):
+                        allowed_choices.append((choice_key, choice_label,))
+                        continue
+
+            self.fields["status"].widget = forms.Select(choices=allowed_choices)
+
     def clean(self):
         clean_data = super().clean()
 
         if (
-            not self.current_user.is_superuser
-            and self.instance.status
+            self.instance.status
+            == clean_data.get("status")
+            == self.instance.StatusTypes.REJECTED
+        ):
+            raise ValidationError(
+                {
+                    "status": (
+                        "Smlouvu nelze upravovat, zatímco je zamítnutá."
+                    )
+                }
+            )
+
+        if (
+            clean_data.get("status", self.instance.status)
             in (self.instance.StatusTypes.APPROVED, self.instance.StatusTypes.REJECTED)
-            and (self.instance.status == clean_data.get("status", self.instance.status))
+            and self.instance.status != clean_data.get("status", self.instance.status)
             and self.current_user == self.instance.created_by
         ):
             raise ValidationError(
                 {
                     "status": (
-                        "Smlouva nemůže být schválena uživatelem, který ji nahrál."
+                        "Smlouva nemůže být schválena / zamítnuta uživatelem, který ji nahrál."
                     )
                 }
             )
diff --git a/contracts/models.py b/contracts/models.py
index c2a6786..80d5899 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -500,7 +500,7 @@ class Contract(NameStrMixin, models.Model):
         choices=StatusTypes.choices,
         max_length=16,
         default=StatusTypes.WORK_IN_PROGRESS,
-        verbose_name="Status",
+        verbose_name="Stav",
         help_text='Označením jako "Ke schválení" se smlouva předá schvalovateli.',
     )
 
diff --git a/registry/templates/admin/index.html b/registry/templates/admin/index.html
index 7f6888e..cab182c 100644
--- a/registry/templates/admin/index.html
+++ b/registry/templates/admin/index.html
@@ -6,7 +6,7 @@
     <div class="index-action-buttons">
         {% if request.user.can_approve_contracts %}
             <a
-                href="contracts/contract/?status__exact=approved"
+                href="contracts/contract/?status__exact=to_be_approved"
                 aria-role="button"
             >Smlouvy ke schválení ({{ request.user.contracts_to_approve_count }})</a>
         {% endif %}
-- 
GitLab