Add duplicated field for nominees, it is necesary when chair marks duplicate nominations
Change questionnaires field in NomineePosition model to manytomany, becouse it is necessary whe chair marks duplicate nominations. Add timestamp in NomineePosition objects to see wich nomineeposition object is the last one. Better merge nominations, update questionnaires and state of primary nomineposition object See #930 - Legacy-Id: 5187
This commit is contained in:
parent
69a93c9f92
commit
bf0747a8e9
|
@ -203,7 +203,7 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
def clean_primary_email(self):
|
||||
email = self.cleaned_data['primary_email']
|
||||
nominees = Nominee.objects.filter(email__address=email,
|
||||
nomine_position__nomcom=self.nomcom)
|
||||
nominee_position__nomcom=self.nomcom)
|
||||
if not nominees:
|
||||
msg = "Does not exist a nomiee with this email"
|
||||
self._errors["primary_email"] = self.error_class([msg])
|
||||
|
@ -215,7 +215,7 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
emails = get_list(data)
|
||||
for email in emails:
|
||||
nominees = Nominee.objects.filter(email__address=email,
|
||||
nomine_position__nomcom=self.nomcom)
|
||||
nominee_position__nomcom=self.nomcom)
|
||||
if not nominees:
|
||||
msg = "Does not exist a nomiee with email %s" % email
|
||||
self._errors["primary_email"] = self.error_class([msg])
|
||||
|
@ -237,9 +237,9 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
secondary_emails = get_list(self.cleaned_data.get("secondary_emails"))
|
||||
|
||||
primary_nominee = Nominee.objects.get(email__address=primary_email,
|
||||
nomine_position__nomcom=self.nomcom)
|
||||
nominee_position__nomcom=self.nomcom)
|
||||
secondary_nominees = Nominee.objects.filter(email__address__in=secondary_emails,
|
||||
nomine_position__nomcom=self.nomcom)
|
||||
nominee_position__nomcom=self.nomcom)
|
||||
for nominee in secondary_nominees:
|
||||
# move nominations
|
||||
nominee.nomination_set.all().update(nominee=primary_nominee)
|
||||
|
@ -247,13 +247,30 @@ class MergeForm(BaseNomcomForm, forms.Form):
|
|||
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):
|
||||
primary_nominee_positions = NomineePosition.objects.filter(position=nominee_position.position,
|
||||
nominee=primary_nominee)
|
||||
primary_nominee_position = primary_nominee_positions and primary_nominee_positions[0] or None
|
||||
|
||||
if primary_nominee_position:
|
||||
# if already a nomineeposition object for a position and nominee,
|
||||
# update the nomineepostion of primary nominee with the state and questionnaire
|
||||
if nominee_position.time > primary_nominee_position.time:
|
||||
primary_nominee_position.state = nominee_position.state
|
||||
primary_nominee_position.save()
|
||||
questionnaires = nominee_position.questionnaires.all()
|
||||
if questionnaires:
|
||||
primary_nominee_position.questionnaires.add(*questionnaires)
|
||||
|
||||
else:
|
||||
# It is not allowed two or more nomineeposition objects with same position and nominee
|
||||
# move nominee_position object to primary nominee
|
||||
nominee_position.nominee = primary_nominee
|
||||
nominee_position.save()
|
||||
|
||||
secondary_nominees.delete()
|
||||
nominee.duplicated = primary_nominee
|
||||
nominee.save()
|
||||
|
||||
secondary_nominees.update(duplicated=primary_nominee)
|
||||
|
||||
|
||||
class NominateForm(BaseNomcomForm, forms.ModelForm):
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
|
||||
# Adding model 'NomCom'
|
||||
db.create_table('nomcom_nomcom', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
|
@ -34,6 +34,7 @@ class Migration(SchemaMigration):
|
|||
db.create_table('nomcom_nominee', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('email', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Email'])),
|
||||
('duplicated', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Nominee'], null=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('nomcom', ['Nominee'])
|
||||
|
||||
|
@ -43,13 +44,21 @@ class Migration(SchemaMigration):
|
|||
('position', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Position'])),
|
||||
('nominee', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Nominee'])),
|
||||
('state', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['name.NomineePositionState'])),
|
||||
('questionnaire', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='questionnaire', null=True, to=orm['nomcom.Feedback'])),
|
||||
('time', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('nomcom', ['NomineePosition'])
|
||||
|
||||
# Adding unique constraint on 'NomineePosition', fields ['position', 'nominee']
|
||||
db.create_unique('nomcom_nomineeposition', ['position_id', 'nominee_id'])
|
||||
|
||||
# Adding M2M table for field questionnaires on 'NomineePosition'
|
||||
db.create_table('nomcom_nomineeposition_questionnaires', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('nomineeposition', models.ForeignKey(orm['nomcom.nomineeposition'], null=False)),
|
||||
('feedback', models.ForeignKey(orm['nomcom.feedback'], null=False))
|
||||
))
|
||||
db.create_unique('nomcom_nomineeposition_questionnaires', ['nomineeposition_id', 'feedback_id'])
|
||||
|
||||
# Adding M2M table for field feedback on 'NomineePosition'
|
||||
db.create_table('nomcom_nomineeposition_feedback', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
|
@ -75,7 +84,7 @@ class Migration(SchemaMigration):
|
|||
# Adding model 'Feedback'
|
||||
db.create_table('nomcom_feedback', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('author', self.gf('django.db.models.fields.EmailField')(max_length=75)),
|
||||
('author', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)),
|
||||
('position', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Position'])),
|
||||
('nominee', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['nomcom.Nominee'])),
|
||||
('comments', self.gf('ietf.nomcom.fields.EncryptedTextField')()),
|
||||
|
@ -84,8 +93,9 @@ class Migration(SchemaMigration):
|
|||
))
|
||||
db.send_create_signal('nomcom', ['Feedback'])
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Removing unique constraint on 'NomineePosition', fields ['position', 'nominee']
|
||||
db.delete_unique('nomcom_nomineeposition', ['position_id', 'nominee_id'])
|
||||
|
||||
|
@ -101,6 +111,9 @@ class Migration(SchemaMigration):
|
|||
# Deleting model 'NomineePosition'
|
||||
db.delete_table('nomcom_nomineeposition')
|
||||
|
||||
# Removing M2M table for field questionnaires on 'NomineePosition'
|
||||
db.delete_table('nomcom_nomineeposition_questionnaires')
|
||||
|
||||
# Removing M2M table for field feedback on 'NomineePosition'
|
||||
db.delete_table('nomcom_nomineeposition_feedback')
|
||||
|
||||
|
@ -110,6 +123,7 @@ class Migration(SchemaMigration):
|
|||
# Deleting model 'Feedback'
|
||||
db.delete_table('nomcom_feedback')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
|
@ -327,7 +341,7 @@ class Migration(SchemaMigration):
|
|||
},
|
||||
'nomcom.feedback': {
|
||||
'Meta': {'object_name': 'Feedback'},
|
||||
'author': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
|
||||
'author': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'comments': ('ietf.nomcom.fields.EncryptedTextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'nominee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Nominee']"}),
|
||||
|
@ -355,9 +369,10 @@ class Migration(SchemaMigration):
|
|||
},
|
||||
'nomcom.nominee': {
|
||||
'Meta': {'object_name': 'Nominee'},
|
||||
'duplicated': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Nominee']", 'null': 'True', 'blank': 'True'}),
|
||||
'email': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'nomine_position': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['nomcom.Position']", 'through': "orm['nomcom.NomineePosition']", 'symmetrical': 'False'})
|
||||
'nominee_position': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['nomcom.Position']", 'through': "orm['nomcom.NomineePosition']", 'symmetrical': 'False'})
|
||||
},
|
||||
'nomcom.nomineeposition': {
|
||||
'Meta': {'unique_together': "(('position', 'nominee'),)", 'object_name': 'NomineePosition'},
|
||||
|
@ -365,8 +380,9 @@ class Migration(SchemaMigration):
|
|||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'nominee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Nominee']"}),
|
||||
'position': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['nomcom.Position']"}),
|
||||
'questionnaire': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'questionnaire'", 'null': 'True', 'to': "orm['nomcom.Feedback']"}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.NomineePositionState']"})
|
||||
'questionnaires': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'questionnaires'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['nomcom.Feedback']"}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.NomineePositionState']"}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'nomcom.position': {
|
||||
'Meta': {'object_name': 'Position'},
|
||||
|
|
|
@ -62,7 +62,8 @@ class Nomination(models.Model):
|
|||
class Nominee(models.Model):
|
||||
|
||||
email = models.ForeignKey(Email)
|
||||
nomine_position = models.ManyToManyField('Position', through='NomineePosition')
|
||||
nominee_position = models.ManyToManyField('Position', through='NomineePosition')
|
||||
duplicated = models.ForeignKey('Nominee', blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = 'Nominees'
|
||||
|
@ -76,10 +77,11 @@ class NomineePosition(models.Model):
|
|||
position = models.ForeignKey('Position')
|
||||
nominee = models.ForeignKey('Nominee')
|
||||
state = models.ForeignKey(NomineePositionState)
|
||||
questionnaire = models.ForeignKey('Feedback',
|
||||
related_name='questionnaire',
|
||||
blank=True, null=True)
|
||||
questionnaires = models.ManyToManyField('Feedback',
|
||||
related_name='questionnaires',
|
||||
blank=True, null=True)
|
||||
feedback = models.ManyToManyField('Feedback', blank=True, null=True)
|
||||
time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Nominee position'
|
||||
|
|
|
@ -2,6 +2,7 @@ import tempfile
|
|||
import os
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files import File
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.utils.pipe import pipe
|
||||
|
@ -15,6 +16,7 @@ CHAIR_USER = 'chair'
|
|||
MEMBER_USER = 'member'
|
||||
SECRETARIAT_USER = 'secretariat'
|
||||
EMAIL_DOMAIN = '@example.com'
|
||||
NOMCOM_YEAR = "2013"
|
||||
|
||||
USERS = [COMMUNITY_USER, CHAIR_USER, MEMBER_USER, SECRETARIAT_USER]
|
||||
|
||||
|
@ -98,10 +100,13 @@ def nomcom_test_data():
|
|||
group, created = Group.objects.get_or_create(name='IAB/IESG Nominating Committee 2013/2014',
|
||||
state_id='active',
|
||||
type_id='nomcom',
|
||||
acronym='nomcom2013')
|
||||
acronym='nomcom%s' % NOMCOM_YEAR)
|
||||
nomcom, created = NomCom.objects.get_or_create(group=group)
|
||||
|
||||
secretariat, created = Group.objects.get_or_create(name="Secretariat",
|
||||
cert_file, privatekey_file = generate_cert()
|
||||
nomcom.public_key.save('cert', File(open(cert_file.name, 'r')))
|
||||
|
||||
secretariat, created = Group.objects.get_or_create(name=u'IETF Secretariat',
|
||||
acronym="secretariat",
|
||||
state_id="active",
|
||||
type_id="ietf",
|
||||
|
|
|
@ -14,7 +14,7 @@ from ietf.person.models import Email, Person
|
|||
|
||||
from ietf.nomcom.test_data import nomcom_test_data, generate_cert, check_comments, \
|
||||
COMMUNITY_USER, CHAIR_USER, \
|
||||
MEMBER_USER, SECRETARIAT_USER, EMAIL_DOMAIN
|
||||
MEMBER_USER, SECRETARIAT_USER, EMAIL_DOMAIN, NOMCOM_YEAR
|
||||
from ietf.nomcom.models import NomineePosition, Position, Nominee, \
|
||||
NomineePositionState, Feedback, FeedbackType, \
|
||||
Nomination
|
||||
|
@ -33,7 +33,7 @@ class NomcomViewsTest(TestCase):
|
|||
def setUp(self):
|
||||
nomcom_test_data()
|
||||
self.cert_file, self.privatekey_file = generate_cert()
|
||||
self.year = 2013
|
||||
self.year = NOMCOM_YEAR
|
||||
|
||||
# private urls
|
||||
self.private_index_url = reverse('nomcom_private_index', kwargs={'year': self.year})
|
||||
|
@ -133,9 +133,12 @@ class NomcomViewsTest(TestCase):
|
|||
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)
|
||||
self.assertEqual(Nominee.objects.filter(email__address='nominee2@example.com',
|
||||
duplicated__isnull=False).count(), 1)
|
||||
self.assertEqual(Nominee.objects.filter(email__address='nominee3@example.com',
|
||||
duplicated__isnull=False).count(), 1)
|
||||
self.assertEqual(Nominee.objects.filter(email__address='nominee4@example.com',
|
||||
duplicated__isnull=False).count(), 1)
|
||||
|
||||
nominee = Nominee.objects.get(email__address='nominee@example.com')
|
||||
self.assertEqual(Nomination.objects.filter(nominee=nominee).count(), 4)
|
||||
|
|
Loading…
Reference in a new issue