From 7b1bad2f62c1cedaf085211c91b635b925b669fc Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Sun, 25 Aug 2019 22:30:22 +0200
Subject: [PATCH] Add view to link persons to accounts. Closes #48.

---
 biscuit/core/forms.py                         | 34 +++++++++++++++++++
 .../core/templates/core/persons_accounts.html | 32 +++++++++++++++++
 biscuit/core/urls.py                          |  1 +
 biscuit/core/views.py                         | 19 +++++++++++
 4 files changed, 86 insertions(+)
 create mode 100644 biscuit/core/forms.py
 create mode 100644 biscuit/core/templates/core/persons_accounts.html

diff --git a/biscuit/core/forms.py b/biscuit/core/forms.py
new file mode 100644
index 000000000..c40e149fc
--- /dev/null
+++ b/biscuit/core/forms.py
@@ -0,0 +1,34 @@
+from django import forms
+from django.contrib.auth import create_user, get_user_model
+from django.utils.translation import ugettext_lazy as _
+
+from .models import Person
+
+
+class PersonAccountForm(forms.ModelForm):
+    class Meta:
+        model = Person
+        fields = ['user']
+
+    last_name = forms.CharField(disabled=True)
+    first_name = forms.CharField(disabled=True)
+    user = forms.ModelChoiceField(queryset=get_user_model().objects.all())
+    new_user = forms.CharField(required=False)
+
+    def clean(self) -> None:
+        if 'new_user' in self.cleaned_data:
+            if 'user' in self.cleaned_data and self.cleaned_data['user']:
+                self.add_error('new_user', _('You cannot set a new username when also selecting an existing user.'))
+            elif get_user_model().objects.filter(username=self.cleaned_data['new_user']).exists():
+                self.add_error('new_user', _('This username is already in use.'))
+            else:
+                new_user_obj = create_user(self.cleaned_data['new_user'],
+                                           self.instance.email,
+                                           first_name=self.instance.first_name,
+                                           last_name=self.instance.last_name)
+
+                self.cleaned_data['user'] = new_user_obj
+
+
+PersonsAccountsFormSet = forms.modelformset_factory(
+    Person, form=PersonAccountForm, max_num=0, extra=0)
diff --git a/biscuit/core/templates/core/persons_accounts.html b/biscuit/core/templates/core/persons_accounts.html
new file mode 100644
index 000000000..e0cc072d2
--- /dev/null
+++ b/biscuit/core/templates/core/persons_accounts.html
@@ -0,0 +1,32 @@
+{# -*- engine:django -*- #}
+{% extends "core/base.html" %}
+{% load bootstrap4 i18n %}
+
+{% block page_title %}
+ {% blocktrans %}Link persons to accounts{% endblocktrans %}
+{% endblock %}
+
+{% block content %}
+ <form method="post">
+  {% csrf_token %}
+  {{ persons_accounts_formset.management_form }}
+
+  <table class="table table-striped table-bordered table-hover table-condensed table-responsive w-100 d-block d-md-table">
+   <tr>
+    <th>{% blocktrans %}Person{% endblocktrans %}</th>
+    <th>{% blocktrans %}Existing account{% endblocktrans %}</th>
+    <th>{% blocktrans %}New account{% endblocktrans %}</th>
+   </tr>
+   {% for form in persons_accounts_formset %}
+    {{ form.id }}
+    <tr>
+     <td>{{ form.person_name }}</td>
+     <td>{{ form.user }}</td>
+     <td>{{ form.new_user }}</td>
+    </tr>
+   {% endfor %}
+  </table>
+
+  <input type="submit" value="Update" />
+ </form>
+{% endblock %}
diff --git a/biscuit/core/urls.py b/biscuit/core/urls.py
index 0eba6e8e5..d34151930 100644
--- a/biscuit/core/urls.py
+++ b/biscuit/core/urls.py
@@ -10,6 +10,7 @@ urlpatterns = [
     path('admin/', admin.site.urls),
     path('accounts/', include('django.contrib.auth.urls')),
     path('persons', views.persons, name='persons'),
+    path('persons/accounts', views.persons_accounts, name='persons_accounts'),
     path('person', views.person, name='person'),
     path('person/<int:id_>', views.person,
          {'template': 'full'}, name='person_by_id'),
diff --git a/biscuit/core/views.py b/biscuit/core/views.py
index 7ae920cce..bce4001ee 100644
--- a/biscuit/core/views.py
+++ b/biscuit/core/views.py
@@ -6,6 +6,9 @@ from django.http import Http404, HttpRequest, HttpResponse
 from django.shortcuts import render
 from django_tables2 import RequestConfig
 from django.utils.translation import ugettext_lazy as _
+
+from .decorators import admin_required
+from .forms import PersonsAccountsFormSet
 from .models import Person, Group
 from .tables import PersonsTable, GroupsTable
 
@@ -120,3 +123,19 @@ def groups(request: HttpRequest) -> HttpResponse:
     context['groups_table'] = groups_table
 
     return render(request, 'core/groups.html', context)
+
+
+@admin_required
+def persons_accounts(request: HttpRequest) -> HttpResponse:
+    context = {}
+
+    persons_qs = Person.objects.all()
+    persons_accounts_formset = PersonsAccountsFormSet(request.POST or None, queryset=persons_qs)
+
+    if request.method == 'POST':
+        if persons_accounts_formset.is_valid():
+            persons_accounts_formset.save()
+
+    context['persons_accounts_formset'] = persons_accounts_formset
+
+    return render(request, 'core/persons_accounts.html', context)
-- 
GitLab