From a380248198faa3224e38e08593c0ef8e21d4d35c Mon Sep 17 00:00:00 2001
From: Dan Braghis <dan.braghis@torchbox.com>
Date: Thu, 14 Jun 2018 10:24:44 +0100
Subject: [PATCH] Add view and templates

---
 .../determinations/determination_detail.html  |  25 ++++
 .../determinations/determination_form.html    |  41 ++++++
 .../includes/determination_button.html        |  12 ++
 .../determinations/templatetags/__init__.py   |   0
 .../templatetags/determination_tags.py        |  21 +++
 opentech/apply/determinations/urls.py         |   1 +
 opentech/apply/determinations/views.py        | 138 ++++++++++++++++++
 .../applicationsubmission_admin_detail.html   |  10 ++
 .../funds/applicationsubmission_detail.html   |   3 +
 .../apply/funds/templatetags/workflow_tags.py |   5 +
 10 files changed, 256 insertions(+)
 create mode 100644 opentech/apply/determinations/templates/determinations/determination_detail.html
 create mode 100644 opentech/apply/determinations/templates/determinations/determination_form.html
 create mode 100644 opentech/apply/determinations/templates/determinations/includes/determination_button.html
 create mode 100644 opentech/apply/determinations/templatetags/__init__.py
 create mode 100644 opentech/apply/determinations/templatetags/determination_tags.py
 create mode 100644 opentech/apply/determinations/views.py

diff --git a/opentech/apply/determinations/templates/determinations/determination_detail.html b/opentech/apply/determinations/templates/determinations/determination_detail.html
new file mode 100644
index 000000000..02737f68c
--- /dev/null
+++ b/opentech/apply/determinations/templates/determinations/determination_detail.html
@@ -0,0 +1,25 @@
+{% extends "base-apply.html" %}
+{% load bleach_tags %}
+
+{% block content %}
+<div class="wrapper wrapper--breakout wrapper--admin">
+    <div class="wrapper wrapper--large">
+        <h2 class="heading heading--no-margin">Determination</h2>
+        <h5>For <a href="{% url "funds:submission" determination.submission.id %}">{{ determination.submission.title }}</a></h5>
+    </div>
+</div>
+
+<div class="grid">
+    <div>
+        <h5>Determination</h5>
+        <p>{{ determination.determination }}</p>
+    </div>
+</div>
+
+<div class="rich-text rich-text--answers">
+    {% for question, answer in determination_data.items %}
+        <h5>{{ question }}</h5>
+        {{ answer|bleach }}
+    {% endfor %}
+</div>
+{% endblock %}
diff --git a/opentech/apply/determinations/templates/determinations/determination_form.html b/opentech/apply/determinations/templates/determinations/determination_form.html
new file mode 100644
index 000000000..172e6fc95
--- /dev/null
+++ b/opentech/apply/determinations/templates/determinations/determination_form.html
@@ -0,0 +1,41 @@
+{% extends "base-apply.html" %}
+{% block title %}Create a determination{% endblock %}
+{% block content %}
+<div class="wrapper wrapper--breakout wrapper--admin">
+    <div class="wrapper wrapper--medium">
+        <h2 class="heading heading--no-margin">{{ title|default:"Create Determination" }}</h2>
+        <h5>For <a href="{% url "funds:submission" submission.id %}">{{ submission.title }}</a></h5>
+    </div>
+</div>
+
+<div class="wrapper wrapper--medium wrapper--inner-space-medium">
+{% if not has_submitted_determination %}
+    <form class="form form--with-p-tags" action="" method="post" novalidate>
+        {{ form.media }}
+        {% csrf_token %}
+        {% for field in form %}
+            {# to be replaced with better logic when we use stream form #}
+            {% ifchanged field.field.group %}
+                {% for key, value in form.titles.items %}
+                    {% if key == field.field.group %}
+                        <h2>{{ value }}</h2>
+                    {% endif %}
+                {% endfor %}
+            {% endifchanged %}
+
+            {% if field.field %}
+                {% include "funds/includes/field.html" %}
+            {% else %}
+                {{ field }}
+            {% endif %}
+        {% endfor %}
+        <input class="button button--primary" type="submit" value="Send Determination" name="submit" />
+        {% if not object.id or object.is_draft %}
+            <input class="button button--secondary button--white" type="submit" value="Save Draft" name="{{ form.draft_button_name }}" />
+        {% endif %}
+    </form>
+{% else %}
+    <p>You have already added a determination for this submission</p>
+{% endif %}
+</div>
+{% endblock %}
diff --git a/opentech/apply/determinations/templates/determinations/includes/determination_button.html b/opentech/apply/determinations/templates/determinations/includes/determination_button.html
new file mode 100644
index 000000000..f0bd15129
--- /dev/null
+++ b/opentech/apply/determinations/templates/determinations/includes/determination_button.html
@@ -0,0 +1,12 @@
+{% load determination_tags workflow_tags %}
+{% if request.user.is_apply_staff %}
+    {% if request.user|has_draft:submission or request.user|can_add_determination:submission %}
+        <a href="{% url 'apply:determinations:form' submission_pk=submission.id %}" class="button button--primary button--half-width">
+            {% if request.user|has_draft:submission %}
+                Update determination draft
+            {% elif request.user|can_add_determination:submission %}
+                Add determination
+            {% endif %}
+        </a>
+    {% endif %}
+{% endif %}
diff --git a/opentech/apply/determinations/templatetags/__init__.py b/opentech/apply/determinations/templatetags/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/opentech/apply/determinations/templatetags/determination_tags.py b/opentech/apply/determinations/templatetags/determination_tags.py
new file mode 100644
index 000000000..f65cd2403
--- /dev/null
+++ b/opentech/apply/determinations/templatetags/determination_tags.py
@@ -0,0 +1,21 @@
+from django import template
+from django.core.exceptions import ObjectDoesNotExist
+
+register = template.Library()
+
+
+@register.filter
+def can_add_determination(user, submission):
+    try:
+        has_determination = submission.determination
+    except ObjectDoesNotExist:
+        has_determination = False
+    return submission.has_permission_to_add_determination(user) and not has_determination
+
+
+@register.filter
+def has_draft(user, submission):
+    try:
+        return submission.has_permission_to_add_determination(user) and submission.determination.is_draft
+    except ObjectDoesNotExist:
+        return False
diff --git a/opentech/apply/determinations/urls.py b/opentech/apply/determinations/urls.py
index 7e11903e5..0cb98c4eb 100644
--- a/opentech/apply/determinations/urls.py
+++ b/opentech/apply/determinations/urls.py
@@ -6,4 +6,5 @@ app_name = 'determinations'
 
 urlpatterns = [
     path('determination/', DeterminationCreateOrUpdateView.as_view(), name="form"),
+    path('determination/<int:pk>', DeterminationDetailView.as_view(), name="determination"),
 ]
diff --git a/opentech/apply/determinations/views.py b/opentech/apply/determinations/views.py
new file mode 100644
index 000000000..11e2f4278
--- /dev/null
+++ b/opentech/apply/determinations/views.py
@@ -0,0 +1,138 @@
+from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
+from django.http import HttpResponseRedirect
+from django.shortcuts import get_object_or_404
+from django.urls import reverse_lazy
+from django.utils.decorators import method_decorator
+from django.views.generic import DetailView
+from django.views.generic.detail import SingleObjectTemplateResponseMixin
+from django.views.generic.edit import ProcessFormView, ModelFormMixin
+
+from opentech.apply.funds.models import ApplicationSubmission
+from opentech.apply.users.decorators import staff_required
+
+from .forms import ConceptDeterminationForm, ProposalDeterminationForm
+from .models import Determination
+
+
+def get_form_for_stage(submission):
+    forms = [ConceptDeterminationForm, ProposalDeterminationForm]
+    index = [
+        i for i, stage in enumerate(submission.workflow.stages)
+        if submission.stage.name == stage.name
+    ][0]
+    return forms[index]
+
+
+class CreateOrUpdateView(SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView):
+
+    def get(self, request, *args, **kwargs):
+        try:
+            self.object = self.get_object()
+        except self.model.DoesNotExist:
+            self.object = None
+
+        return super().get(request, *args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        try:
+            self.object = self.get_object()
+        except self.model.DoesNotExist:
+            self.object = None
+
+        return super().post(request, *args, **kwargs)
+
+
+class DeterminationCreateOrUpdateView(CreateOrUpdateView):
+    model = Determination
+    template_name = 'determinations/determination_form.html'
+
+    def get_object(self, queryset=None):
+        return self.model.objects.get(submission=self.submission, author=self.request.user)
+
+    def dispatch(self, request, *args, **kwargs):
+        self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk'])
+
+        # TODO add proper permission
+        # if not self.submission.phase.has_perm(request.user, 'add_determination') or \
+        if not self.submission.has_permission_to_add_determination(request.user):
+            raise PermissionDenied()
+
+        if self.request.POST:
+            return self.get(request, *args, **kwargs)
+
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        try:
+            has_submitted_determination = not self.submission.determination.is_draft
+        except ObjectDoesNotExist:
+            has_submitted_determination = False
+
+        return super().get_context_data(
+            submission=self.submission,
+            has_submitted_determination=has_submitted_determination,
+            title="Update Determination draft" if self.object else 'Add Determination',
+            **kwargs
+        )
+
+    def get_form_class(self):
+        return get_form_for_stage(self.submission)
+
+    def get_form_kwargs(self):
+        kwargs = super().get_form_kwargs()
+        kwargs['request'] = self.request
+        kwargs['submission'] = self.submission
+
+        if self.object:
+            kwargs['initial'] = self.object.determination_data
+            kwargs['initial']['determination'] = self.object.determination
+
+        return kwargs
+
+    def get_success_url(self):
+        return self.submission.get_absolute_url()
+
+
+@method_decorator(staff_required, name='dispatch')
+class DeterminationDetailView(DetailView):
+    model = Determination
+
+    def dispatch(self, request, *args, **kwargs):
+        determination = self.get_object()
+
+        if request.user != determination.submission.lead and not request.user.is_superuser:
+            raise PermissionDenied
+
+        if determination.is_draft:
+            return HttpResponseRedirect(reverse_lazy('apply:determinations:form', args=(determination.submission.id,)))
+
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        determination = self.get_object().determination
+        form_used = get_form_for_stage(self.get_object().submission)
+        determination_data = {}
+
+        for name, field in form_used.base_fields.items():
+            try:
+                # Add titles which exist
+                title = form_used.titles[field.group]
+                determination_data.setdefault(title, [])
+            except AttributeError:
+                pass
+
+            value = determination[name]
+            try:
+                choices = dict(field.choices)
+            except AttributeError:
+                pass
+            else:
+                # Update the stored value to the display value
+                value = choices[int(value)]
+
+            determination_data.setdefault(field.label, str(value))
+
+        return super().get_context_data(
+            determination_data=determination_data,
+            **kwargs
+        )
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
index fc0040d53..e9cabb5f6 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
@@ -12,6 +12,16 @@
         {% include "funds/includes/update_reviewer_form.html" %}
 {% endblock %}
 
+{% block determination %}
+    <div class="sidebar__inner">
+        <h5>Determination</h5>
+        {% if object.determination %}
+            {{ object.determination.determination }} | {{ object.determination.author }}
+        {% endif %}
+        {% include 'determinations/includes/determination_button.html' with submission=object %}
+    </div>
+{% endblock %}
+
 {% block reviews %}
     <div class="sidebar__inner">
         <h5>Reviews &amp; assignees</h5>
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
index d121c37ba..3038b522e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -88,6 +88,9 @@
                     {% endblock %}
                 {% endif %}
 
+                {% block determination %}
+                {% endblock %}
+
                 {% block reviews %}
                 {% endblock %}
 
diff --git a/opentech/apply/funds/templatetags/workflow_tags.py b/opentech/apply/funds/templatetags/workflow_tags.py
index b2923a6da..928d47dd1 100644
--- a/opentech/apply/funds/templatetags/workflow_tags.py
+++ b/opentech/apply/funds/templatetags/workflow_tags.py
@@ -16,3 +16,8 @@ def has_edit_perm(user, submission):
 @register.filter
 def has_review_perm(user, submission):
     return check_permission(user, 'review', submission)
+
+
+@register.filter
+def has_determination_perm(user, submission):
+    return check_permission(user, 'create_determination', submission)
-- 
GitLab