From 7e830643e5f1240f3e0c2ec6d82d4f969a5ff0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Jim=C3=A9nez?= Date: Mon, 14 Jan 2013 19:00:25 +0000 Subject: [PATCH] Add nominee merge view. See #930 - Legacy-Id: 5183 --- ietf/nomcom/forms.py | 47 ++++++++++++++- ietf/nomcom/tests.py | 67 +++++++++++++++++++-- ietf/nomcom/views.py | 14 ++++- ietf/templates/nomcom/private_merge.html | 32 +++++++++- ietf/templates/nomcom/private_nominate.html | 6 +- 5 files changed, 153 insertions(+), 13 deletions(-) diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py index 286a03d15..0fb807892 100644 --- a/ietf/nomcom/forms.py +++ b/ietf/nomcom/forms.py @@ -82,7 +82,8 @@ class EditMembersFormPreview(FormPreview): self.form.base_fields['members'].initial = ',\r\n'.join([role.email.address for role in members]) def process_preview(self, request, form, context): - members_email = form.cleaned_data['members'].replace('\r\n', '').replace(' ', '').split(',') + emails = form.cleaned_data['members'].replace('\r\n', '') + members_email = map(unicode.strip, emails.split(',')) members_info = [] emails_not_found = [] @@ -184,6 +185,50 @@ class EditPublicKeyForm(BaseNomcomForm, forms.ModelForm): self.fields['public_key'].required = True +class MergeForm(BaseNomcomForm, forms.Form): + + secondary_emails = custom_fields.MultiEmailField(label="Secondary email address (remove this):") + primary_email = forms.EmailField(label="Primary email address", + widget=forms.TextInput(attrs={'size': '40'})) + + fieldsets = [('Emails', ('primary_email', 'secondary_emails'))] + + def __init__(self, *args, **kwargs): + self.nomcom = kwargs.pop('nomcom', None) + super(MergeForm, self).__init__(*args, **kwargs) + + def clean(self): + primary_email = self.cleaned_data.get("primary_email") + secondary_emails = self.cleaned_data.get("secondary_emails") + if primary_email and secondary_emails: + if primary_email in secondary_emails: + msg = "Primary and secondary email address must be differents" + self._errors["primary_email"] = self.error_class([msg]) + return self.cleaned_data + + def save(self): + primary_email = self.cleaned_data.get("primary_email") + secondary_emails = self.cleaned_data.get("secondary_emails").replace('\r\n', '') + secondary_emails = map(unicode.strip, secondary_emails.split(',')) + + primary_nominee = Nominee.objects.get(email__address=primary_email) + secondary_nominees = Nominee.objects.filter(email__address__in=secondary_emails) + for nominee in secondary_nominees: + # move nominations + nominee.nomination_set.all().update(nominee=primary_nominee) + # move feedback + nominee.feedback_set.all().update(nominee=primary_nominee) + # move nomineepositions + for nominee_position in nominee.nomineeposition_set.all(): + if not NomineePosition.objects.filter(position=nominee_position.position, + nominee=primary_nominee): + + nominee_position.nominee = primary_nominee + nominee_position.save() + + secondary_nominees.delete() + + class NominateForm(BaseNomcomForm, forms.ModelForm): comments = forms.CharField(label='Comments', widget=forms.Textarea()) diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py index ab4fc994e..f0ceb3765 100644 --- a/ietf/nomcom/tests.py +++ b/ietf/nomcom/tests.py @@ -77,8 +77,59 @@ class NomcomViewsTest(TestCase): def test_private_merge_view(self): """Verify private merge view""" - # TODO: complete merge nominations + + # do nominations + login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url) + self.nominate_view(public=True, nominee_email=u'nominee@example.com', + position='IAOC') + self.nominate_view(public=True, nominee_email=u'nominee2@example.com', + position='IAOC') + self.nominate_view(public=True, nominee_email=u'nominee3@example.com', + position='IAB') + self.nominate_view(public=True, nominee_email=u'nominee4@example.com', + position='TSV') + + self.client.logout() + + # merge nominations self.access_chair_url(self.private_merge_url) + + test_data = {"secondary_emails": "nominee@example.com, nominee2@example.com", + "primary_email": "nominee@example.com"} + response = self.client.post(self.private_merge_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "info-message-error") + + test_data = {"primary_email": "nominee@example.com", + "secondary_emails": ""} + response = self.client.post(self.private_merge_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "info-message-error") + + test_data = {"primary_email": "", + "secondary_emails": "nominee@example.com"} + response = self.client.post(self.private_merge_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "info-message-error") + + test_data = {"secondary_emails": """nominee2@example.com, + nominee3@example.com, + nominee4@example.com""", + "primary_email": "nominee@example.com"} + + response = self.client.post(self.private_merge_url, test_data) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "info-message-success") + + self.assertEqual(Nominee.objects.filter(email__address='nominee2@example.com').count(), 0) + self.assertEqual(Nominee.objects.filter(email__address='nominee3@example.com').count(), 0) + self.assertEqual(Nominee.objects.filter(email__address='nominee4@example.com').count(), 0) + + nominee = Nominee.objects.get(email__address='nominee@example.com') + self.assertEqual(Nomination.objects.filter(nominee=nominee).count(), 4) + self.assertEqual(Feedback.objects.filter(nominee=nominee).count(), 4) + self.assertEqual(NomineePosition.objects.filter(nominee=nominee).count(), 3) + self.client.logout() def change_members(self, members): @@ -188,13 +239,18 @@ class NomcomViewsTest(TestCase): def test_public_nominate(self): login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url) return self.nominate_view(public=True) + self.client.logout() def test_private_nominate(self): self.access_member_url(self.private_nominate_url) return self.nominate_view(public=False) + self.client.logout() + + def nominate_view(self, *args, **kwargs): + public = kwargs.pop('public', True) + nominee_email = kwargs.pop('nominee_email', u'nominee@example.com') + position_name = kwargs.pop('position', 'IAOC') - def nominate_view(self, public=True): - """Verify nominate view""" if public: nominate_url = self.public_nominate_url else: @@ -214,8 +270,8 @@ class NomcomViewsTest(TestCase): self.assertEqual(response.status_code, 200) self.assertContains(response, "nominateform") - position = Position.objects.get(name='IAOC') - candidate_email = u'nominee@example.com' + position = Position.objects.get(name=position_name) + candidate_email = nominee_email candidate_name = u'nominee' comments = 'test nominate view' candidate_phone = u'123456' @@ -252,7 +308,6 @@ class NomcomViewsTest(TestCase): nominee=nominee, comments=feedback, nominator_email="%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN)) - self.client.logout() class NomineePositionStateSaveTest(TestCase): diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index 4ac6c1460..cf3fc7e0d 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -8,7 +8,7 @@ from django.utils import simplejson from ietf.nomcom.utils import get_nomcom_by_year, HOME_TEMPLATE from ietf.nomcom.decorators import member_required -from ietf.nomcom.forms import EditPublicKeyForm, NominateForm +from ietf.nomcom.forms import EditPublicKeyForm, NominateForm, MergeForm from ietf.nomcom.models import Position @@ -34,11 +34,21 @@ def private_index(request, year): @member_required(role='chair') def private_merge(request, year): - # TODO: complete merge nominations nomcom = get_nomcom_by_year(year) + message = None + if request.method == 'POST': + form = MergeForm(request.POST, nomcom=nomcom) + if form.is_valid(): + form.save() + message = ('success', 'The emails has been unified') + else: + form = MergeForm(nomcom=nomcom) + return render_to_response('nomcom/private_merge.html', {'nomcom': nomcom, 'year': year, + 'form': form, + 'message': message, 'selected': 'merge'}, RequestContext(request)) diff --git a/ietf/templates/nomcom/private_merge.html b/ietf/templates/nomcom/private_merge.html index 809758ccd..07a28e20f 100644 --- a/ietf/templates/nomcom/private_merge.html +++ b/ietf/templates/nomcom/private_merge.html @@ -5,5 +5,35 @@ {% block nomcom_content %}

Merging nominee email addresses

-

If a nominee has been nominated with multiple email addresses, the nominee will appear multiple times in the nomination list, as the email address is used as the unique identifier for each nominee. In order to permit comments and nominations to be submitted under multiple email addresses, there is a list of secondary email addresses which needs to be kept up-to-date. When nominations of one particular nominee have already been made under different email addresses, the nomination comments from the secondary address also needs to be merged with those under the primary address. It doesn't matter particularly which email address is used as primary, as far as the nominee information maintenance goes, but it's probably handier for the nomcom if the primary address is the one which the nominee prefers at the time.

+

+ If a nominee has been nominated with multiple email addresses, the nominee will + appear multiple times in the nomination list, as the email address is used as + the unique identifier for each nominee. In order to permit comments and nominations + to be submitted under multiple email addresses, there is a list of secondary email + addresses which needs to be kept up-to-date. When nominations of one particular nominee + have already been made under different email addresses, the nomination comments from the + secondary address also needs to be merged with those under the primary address. +

+

+ It doesn't matter particularly which email address is used as primary, as far as the + nominee information maintenance goes, but it's probably handier for the nomcom if the + primary address is the one which the nominee prefers at the time. +

+ + + {% if message %} +
{{ message.1 }}
+ {% endif %} + + {% if form.errors %}
Please correct the following errors
{% endif %} + +
{% csrf_token %} + {{ form }} + +
+ +
+ +
+ {% endblock %} diff --git a/ietf/templates/nomcom/private_nominate.html b/ietf/templates/nomcom/private_nominate.html index 9324e80bf..522e774f2 100644 --- a/ietf/templates/nomcom/private_nominate.html +++ b/ietf/templates/nomcom/private_nominate.html @@ -30,9 +30,9 @@
{% csrf_token %} {{ form }} -
- -
+
+ +
{% endif %}