From d9fef6497cf429616ae5d73f81f142c86fcfab23 Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Thu, 12 Jul 2018 20:07:03 +0200
Subject: [PATCH] Link Funders to Organizations

---
 funders/forms.py                              | 10 +++++
 .../migrations/0007_funder_organization.py    | 22 ++++++++++
 .../funders/funder_link_organization.html     | 44 +++++++++++++++++++
 .../templates/funders/funders_dashboard.html  | 10 ++++-
 funders/urls.py                               |  3 ++
 funders/views.py                              | 19 +++++++-
 journals/views.py                             |  7 +--
 news/templates/news/newsitem_update.html      |  1 +
 partners/forms.py                             |  2 -
 .../templates/partners/organization_list.html |  3 +-
 partners/views.py                             |  8 ++++
 11 files changed, 115 insertions(+), 14 deletions(-)
 create mode 100644 funders/migrations/0007_funder_organization.py
 create mode 100644 funders/templates/funders/funder_link_organization.html

diff --git a/funders/forms.py b/funders/forms.py
index ce80aab17..15af6c74b 100644
--- a/funders/forms.py
+++ b/funders/forms.py
@@ -6,6 +6,8 @@ from django import forms
 
 from .models import Funder, Grant
 
+from ajax_select.fields import AutoCompleteSelectField
+
 from scipost.forms import HttpRefererFormMixin
 from scipost.models import Contributor
 
@@ -24,6 +26,14 @@ class FunderSelectForm(forms.Form):
     funder = forms.ModelChoiceField(queryset=Funder.objects.all())
 
 
+class FunderOrganizationSelectForm(forms.ModelForm):
+    organization = AutoCompleteSelectField('organization_lookup')
+
+    class Meta:
+        model = Funder
+        fields = []
+
+
 class GrantForm(HttpRefererFormMixin, forms.ModelForm):
     class Meta:
         model = Grant
diff --git a/funders/migrations/0007_funder_organization.py b/funders/migrations/0007_funder_organization.py
new file mode 100644
index 000000000..cfc8b121e
--- /dev/null
+++ b/funders/migrations/0007_funder_organization.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-07-12 07:13
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('partners', '0008_auto_20180711_0623'),
+        ('funders', '0006_auto_20180425_2212'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='funder',
+            name='organization',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='partners.Organization'),
+        ),
+    ]
diff --git a/funders/templates/funders/funder_link_organization.html b/funders/templates/funders/funder_link_organization.html
new file mode 100644
index 000000000..c52c8b7d2
--- /dev/null
+++ b/funders/templates/funders/funder_link_organization.html
@@ -0,0 +1,44 @@
+{% extends 'funders/base.html' %}
+
+{% block pagetitle %}: link Funder to Organization{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+{{ block.super }}
+<span class="breadcrumb-item">{{ funder.name }}</span>
+{% endblock %}
+
+{% block content %}
+
+<h1>Funder: link to Organization</h1>
+<div class="row">
+  <div class="col-4">
+    <table class="table">
+      <tbody>
+	<tr><td>Name:</td><td>{{ funder.name }}</td></tr>
+	<tr><td>Acronym:</td><td>{{ funder.acronym }}</td></tr>
+	<tr><td>Identifier:</td><td>{{ funder.identifier }}</td></tr>
+	<tr><td>Organization:</td><td>{{ funder.organization }}</td></tr>
+      </tbody>
+    </table>
+  </div>
+  <div class="col-6">
+    <h3>Link to:</h3>
+    <form action="{% url 'funders:link_to_organization' pk=funder.pk %}" method="post">
+      {% csrf_token %}
+      {{ form|bootstrap }}
+      <input type="submit" value="Link" class="btn btn-primary">
+    </form>
+  </div>
+  <div class="col-2">
+    <p>Can't find it in the selector? <a href="{% url 'partners:organization_create' %}" target="_blank">Add a new organization to our database</a> (opens in new window)</p>
+  </div>
+</div>
+
+{% endblock content %}
+
+{% block footer_script %}
+{{ block.super }}
+{{ form.media }}
+{% endblock footer_script %}
diff --git a/funders/templates/funders/funders_dashboard.html b/funders/templates/funders/funders_dashboard.html
index 16ea8e04a..78d6c2321 100644
--- a/funders/templates/funders/funders_dashboard.html
+++ b/funders/templates/funders/funders_dashboard.html
@@ -64,7 +64,8 @@
 	      <th>Name</th>
 	      <th>Acronym</th>
 	      <th>Identifier</th>
-          <th></th>
+	      <th>Organization</th>
+              <th>Actions</th>
 	    </tr>
 	  </thead>
 	  <tbody id="accordion" role="tablist" aria-multiselectable="true">
@@ -73,7 +74,12 @@
 	      <td>{{ funder.name }}</td>
 	      <td>{{ funder.acronym }}</td>
 	      <td>{{ funder.identifier }}</td>
-          <td><a href="{% url 'funders:funder_publications' funder.id %}">See all Publications for Funder</a></td>
+	      <td>{{ funder.organization }}</td>
+              <td>
+		<ul>
+		  <li><a href="{% url 'funders:link_to_organization' pk=funder.id %}">{% if not funder.organization %}Link to an{% else %}Edit the{% endif %} Organization</a></li>
+		  <li><a href="{% url 'funders:funder_publications' funder.id %}">See all Publications for Funder</a></li>
+	      </td>
 	    </tr>
             {% empty %}
             <tr>
diff --git a/funders/urls.py b/funders/urls.py
index 48f99d288..df982d8cd 100644
--- a/funders/urls.py
+++ b/funders/urls.py
@@ -14,4 +14,7 @@ urlpatterns = [
     url(r'^add$', views.add_funder, name='add_funder'),
     url(r'^(?P<funder_id>[0-9]+)/$', views.funder_publications, name='funder_publications'),
     url(r'^grants/add$', views.CreateGrantView.as_view(), name='add_grant'),
+    url(r'^(?P<pk>[0-9]+)/link_to_organization/$',
+        views.LinkFunderToOrganizationView.as_view(),
+        name='link_to_organization'),
 ]
diff --git a/funders/views.py b/funders/views.py
index f6b2d5b56..13de71395 100644
--- a/funders/views.py
+++ b/funders/views.py
@@ -10,11 +10,11 @@ from django.contrib.auth.decorators import permission_required
 from django.core.urlresolvers import reverse, reverse_lazy
 from django.db import transaction
 from django.utils.decorators import method_decorator
-from django.views.generic.edit import CreateView
+from django.views.generic.edit import CreateView, UpdateView
 from django.shortcuts import get_object_or_404, render, redirect
 
 from .models import Funder, Grant
-from .forms import FunderRegistrySearchForm, FunderForm, GrantForm
+from .forms import FunderRegistrySearchForm, FunderForm, FunderOrganizationSelectForm, GrantForm
 
 from scipost.mixins import PermissionsMixin
 
@@ -91,6 +91,21 @@ class HttpRefererMixin:
         return super().form_valid(form)
 
 
+class LinkFunderToOrganizationView(PermissionsMixin, UpdateView):
+    """
+    For an existing Funder instance, specify the link to an Organization.
+    """
+    permission_required = 'scipost.can_create_grants'
+    model = Funder
+    form_class = FunderOrganizationSelectForm
+    template_name = 'funders/funder_link_organization.html'
+    success_url = reverse_lazy('funders:funders_dashboard')
+
+    def form_valid(self, form):
+        form.instance.organization = form.cleaned_data['organization']
+        return super().form_valid(form)
+
+
 @method_decorator(transaction.atomic, name='dispatch')
 class CreateGrantView(PermissionsMixin, HttpRefererMixin, CreateView):
     """
diff --git a/journals/views.py b/journals/views.py
index f4055c681..cc7a2a4d3 100644
--- a/journals/views.py
+++ b/journals/views.py
@@ -395,14 +395,9 @@ def add_affiliation(request, doi_label, pk):
         return redirect(reverse('journals:author_affiliations',
                                 kwargs={'doi_label': doi_label}))
     context = {'table': table, 'add_affiliation_form': form}
-    # if table.contributor:
-    #     context['auth'] = table.contributor
-    # elif table.unregistered_author:
-    #     context['auth'] = unregistered_author
-    # else:
-    #     raise
     return render(request, 'journals/author_affiliation_add.html', context)
 
+
 @permission_required('scipost.can_draft_publication', return_403=True)
 @transaction.atomic
 def remove_affiliation(request, doi_label, pk, organization_id):
diff --git a/news/templates/news/newsitem_update.html b/news/templates/news/newsitem_update.html
index b9ff3e7aa..c4b641568 100644
--- a/news/templates/news/newsitem_update.html
+++ b/news/templates/news/newsitem_update.html
@@ -32,6 +32,7 @@
       {% csrf_token %}
       {{ form|bootstrap }}
       <input type="submit" value="Submit" class="btn btn-primary">
+    </form>
   </div>
 </div>
 {% endblock content %}
diff --git a/partners/forms.py b/partners/forms.py
index 82958e6d3..f4a94bd97 100644
--- a/partners/forms.py
+++ b/partners/forms.py
@@ -14,8 +14,6 @@ from django_countries import countries
 from django_countries.widgets import CountrySelectWidget
 from django_countries.fields import LazyTypedChoiceField
 
-from ajax_select.fields import AutoCompleteSelectField
-
 from .constants import PARTNER_KINDS, PROSPECTIVE_PARTNER_PROCESSED, CONTACT_TYPES,\
                        PARTNER_STATUS_UPDATE, REQUEST_PROCESSED, REQUEST_DECLINED, CONTACT_GENERAL
 from .models import Partner, ProspectivePartner, ProspectiveContact, ProspectivePartnerEvent,\
diff --git a/partners/templates/partners/organization_list.html b/partners/templates/partners/organization_list.html
index 3685c45fe..b0ca89ff5 100644
--- a/partners/templates/partners/organization_list.html
+++ b/partners/templates/partners/organization_list.html
@@ -4,7 +4,6 @@
 
 {% load staticfiles %}
 {% load partners_extras %}
-{% load funders_extras %}
 
 {% block content %}
 <div class="row">
@@ -14,7 +13,7 @@
       <h3>Management actions:</h3>
       <ul>
 	<li><a href="{% url 'partners:organization_create' %}">Create a new Organization instance</a></li>
-	<li><a href="{% url 'funders:funders_dashboard' %}">Link Funders to Organizations</a> (nr with no linked organization (to handle): {% count_funders_wo_organization %})</li>
+	<li><a href="{% url 'funders:funders_dashboard' %}">Link Funders to Organizations</a> ({{ nr_funders_wo_organization }} found in need of linking)</li>
       </ul>
       {% endif %}
     </div>
diff --git a/partners/views.py b/partners/views.py
index df9733cd2..44b699869 100644
--- a/partners/views.py
+++ b/partners/views.py
@@ -37,6 +37,8 @@ from .forms import ProspectivePartnerForm, ProspectiveContactForm,\
     ProcessRequestContactForm, PartnersAttachmentFormSet, PartnersAttachmentForm
 
 
+from funders.models import Funder
+
 from journals.models import Publication
 
 from scipost.mixins import PermissionsMixin
@@ -77,6 +79,12 @@ class OrganizationDeleteView(PermissionsMixin, DeleteView):
 class OrganizationListView(ListView):
     model = Organization
 
+    def get_context_data(self, *args, **kwargs):
+        context = super().get_context_data(*args, **kwargs)
+        if self.request.user.has_perm('scipost.can_manage_organizations'):
+            context['nr_funders_wo_organization'] = Funder.objects.filter(organization=None).count()
+        return context
+
 
 class OrganizationDetailView(DetailView):
     model = Organization
-- 
GitLab