From 09e8c93e8d3ecbf416c0dbda61f278c05856f321 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Sun, 28 May 2017 23:40:47 +0300 Subject: [PATCH] Create view and model for duplicate member conflicts --- members/admin.py | 3 +- members/migrations/0012_memberconflict.py | 24 ++++++++++++++ members/models.py | 18 ++++++++++ members/static/css/members.css | 4 +++ members/templates/member_duplicates.html | 40 +++++++++++++++++++++++ members/urls.py | 7 ++-- members/views.py | 15 ++++++++- 7 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 members/migrations/0012_memberconflict.py create mode 100644 members/templates/member_duplicates.html diff --git a/members/admin.py b/members/admin.py index bb6b8e0..2251173 100644 --- a/members/admin.py +++ b/members/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin -from members.models import Member, Request, Payment +from members.models import Member, Request, Payment, MemberConflict # Register your models here. admin.site.register(Member) admin.site.register(Request) admin.site.register(Payment) +admin.site.register(MemberConflict) diff --git a/members/migrations/0012_memberconflict.py b/members/migrations/0012_memberconflict.py new file mode 100644 index 0000000..f9ec985 --- /dev/null +++ b/members/migrations/0012_memberconflict.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-05-28 20:32 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0011_auto_20170526_2013'), + ] + + operations = [ + migrations.CreateModel( + name='MemberConflict', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('first_member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberconflict_first_member', to='members.Member')), + ('second_member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberconflict_second_member', to='members.Member')), + ], + ), + ] diff --git a/members/models.py b/members/models.py index 08550e1..1afdde3 100644 --- a/members/models.py +++ b/members/models.py @@ -119,3 +119,21 @@ class Member(BaseMember): AYY=bool(array[4]), jas=bool(array[5]), ) + + +class MemberConflict(models.Model): + + first_member = models.ForeignKey('Member', related_name='%(class)s_first_member') + second_member = models.ForeignKey('Member', related_name='%(class)s_second_member') + + @property + def first_member_form(self): + return MemberForm(instance=self.first_member) + + @property + def second_member_form(self): + return MemberForm(instance=self.second_member) + + +# To avoid problems with a cyclical import, this is at the bottom of the file +from members.forms import MemberForm # nopep8 diff --git a/members/static/css/members.css b/members/static/css/members.css index 23d0aeb..9b99baf 100644 --- a/members/static/css/members.css +++ b/members/static/css/members.css @@ -246,3 +246,7 @@ input { max-width: 100%; height: 10rem !important; } + +.conflict-row { + overflow: auto; +} diff --git a/members/templates/member_duplicates.html b/members/templates/member_duplicates.html new file mode 100644 index 0000000..359329e --- /dev/null +++ b/members/templates/member_duplicates.html @@ -0,0 +1,40 @@ +{% extends "members_base.html" %} + +{% load i18n %} +{% load bootstrap3 %} + +{% block content %} +
+
+

{% trans "Conflicting member entries" %}

+
+ +
+

{% blocktrans %}Found conflicting member entries. Choose how to handle the problematic data.{% endblocktrans %}

+ + {% for conflict in conflicts %} +
+
+ + {{ conflict.first_member_form }} +
+
+
+ + {{ conflict.second_member_form }} +
+
+
+
{% csrf_token %} +

{% blocktrans %}Which one has the correct information for this member?{% endblocktrans %}

+ + + + +
+
+
+ {% endfor %} +
+
+{% endblock content %} diff --git a/members/urls.py b/members/urls.py index 792a1c7..d4a8fe9 100644 --- a/members/urls.py +++ b/members/urls.py @@ -16,6 +16,7 @@ from members.views import member_update from members.views import member_delete_confirm from members.views import member_delete from members.views import payment_list +from members.views import member_duplicates # rest api from members.views import MemberDetail @@ -102,9 +103,7 @@ urlpatterns = [ # rest api url url(r'^api/members/(?P\d+)$', MemberDetail.as_view()), - # email validation - # url(r'^validate/(?P[0-9A-Za-z_\-\']+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', validateEmail, name='user-activation-link'), - # url(r'^validate/success/$', validate_success), - # url(r'^validate/failure/$', validate_fail), + # member duplicate resolution view + url(r'^duplicates$', member_duplicates) ] diff --git a/members/views.py b/members/views.py index 7dbd7cc..4a7acbf 100644 --- a/members/views.py +++ b/members/views.py @@ -26,7 +26,7 @@ import logging import html import csv -from members.models import Member, Request, Payment +from members.models import Member, Request, Payment, MemberConflict from members.forms import MemberForm, PaymentForm, ApplicationForm # Logger function, you can use the same idea when implementing other loggers to other apps @@ -455,6 +455,19 @@ def export_csv(request, *args, **kwargs): return response +@ensure_csrf_cookie +@require_http_methods(["GET"]) +@permission_required('members.change_member', login_url='/login') +def member_duplicates(request, *args, **kwargs): + # TODO + conflicts = MemberConflict.objects.all() + context = { + 'conflicts': conflicts + } + + return render(request, 'member_duplicates.html', context) + + def send_mail_wrapper(subject, message, email_to): send_mail(subject, message,