From 420e05bcbe66a7a8cb99a29a1c36d48494d0af0d Mon Sep 17 00:00:00 2001 From: Ben Adida <ben@adida.net> Date: Thu, 30 Dec 2010 12:11:19 -0800 Subject: [PATCH] tweaked migration, started adding quarantined cast votes --- ...0002_v3_1_new_election_and_voter_fields.py | 3 ++- helios/models.py | 19 +++++++++++++++++++ helios/tests.py | 13 +++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/helios/migrations/0002_v3_1_new_election_and_voter_fields.py b/helios/migrations/0002_v3_1_new_election_and_voter_fields.py index dd41fc6..e75643d 100644 --- a/helios/migrations/0002_v3_1_new_election_and_voter_fields.py +++ b/helios/migrations/0002_v3_1_new_election_and_voter_fields.py @@ -24,7 +24,8 @@ class Migration(SchemaMigration): db.add_column('helios_voter', 'voter_email', self.gf('django.db.models.fields.CharField')(max_length=250, null=True), keep_default=False) # Adding field 'Election.datatype' - db.add_column('helios_election', 'datatype', self.gf('django.db.models.fields.CharField')(default='2011/01/election', max_length=250), keep_default=False) + # manually tweaked default value to ensure proper datatype for older elections + db.add_column('helios_election', 'datatype', self.gf('django.db.models.fields.CharField')(default='legacy/election', max_length=250), keep_default=False) # Adding field 'Election.election_type' db.add_column('helios_election', 'election_type', self.gf('django.db.models.fields.CharField')(default='election', max_length=250), keep_default=False) diff --git a/helios/models.py b/helios/models.py index ba0e3a1..1150564 100644 --- a/helios/models.py +++ b/helios/models.py @@ -87,6 +87,13 @@ class Election(models.Model, electionalgs.Election): registration_starts_at = models.DateTimeField(auto_now_add=False, default=None, null=True) voting_starts_at = models.DateTimeField(auto_now_add=False, default=None, null=True) voting_ends_at = models.DateTimeField(auto_now_add=False, default=None, null=True) + + # if this is non-null, then a complaint period, where people can cast a quarantined ballot. + # we do NOT call this a "provisional" ballot, since provisional implies that the voter has not + # been qualified. We may eventually add this, but it can't be in the same CastVote table, which + # is tied to a voter. + complaint_period_ends_at = models.DateTimeField(auto_now_add=False, default=None, null=True) + tallying_starts_at = models.DateTimeField(auto_now_add=False, default=None, null=True) # dates when things were forced to be performed @@ -730,6 +737,10 @@ class CastVote(models.Model, electionalgs.CastVote): cast_at = models.DateTimeField(auto_now_add=True) + # some ballots can be quarantined (this is not the same thing as provisional) + quarantined_p = modelsBooleanField(default=False, null=False) + released_from_quarantine_at = models.DateTimeField(auto_now_add=False, null=True) + # when is the vote verified? verified_at = models.DateTimeField(null=True) invalidated_at = models.DateTimeField(null=True) @@ -742,6 +753,10 @@ class CastVote(models.Model, electionalgs.CastVote): def voter_hash(self): return self.voter.hash + @property + def is_quarantined(self): + return self.quarantined_p and not self.released_from_quarantine_at + def set_tinyhash(self): """ find a tiny version of the hash for a URL slug. @@ -774,6 +789,10 @@ class CastVote(models.Model, electionalgs.CastVote): return cls.objects.filter(voter = voter).order_by('-cast_at') def verify_and_store(self): + # if it's quarantined, don't let this go through + if self.is_quarantined: + raise Exception("cast vote is quarantined, verification and storage is delayed.") + result = self.vote.verify(self.voter.election) if result: diff --git a/helios/tests.py b/helios/tests.py index 17d123f..078b914 100644 --- a/helios/tests.py +++ b/helios/tests.py @@ -200,6 +200,19 @@ class VoterModelTests(TestCase): # check that you can get at the voter user structure self.assertEquals(v.user.user_id, v.voter_email) + +class CastVoteModelTests(TestCase): + fixtures = ['users.json', 'election.json'] + + def setUp(self): + self.election = models.Election.objects.get(short_name='test') + self.user = auth_models.User.objects.get(user_id='ben@adida.net', user_type='google') + + # register the voter + self.voter = models.Voter.register_user_in_election(self.user, self.election) + + def test_cast_vote(self): + assert False ## ## Black box tests ## -- GitLab