Tally votes, cache results and allow for publication/depublication

This commit is contained in:
Tom Hubrecht 2020-12-19 18:26:25 +01:00
parent 9c6eaeef58
commit 3387186f76
6 changed files with 97 additions and 9 deletions

View file

@ -0,0 +1,20 @@
# Generated by Django 2.2.17 on 2020-12-19 16:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("elections", "0003_auto_20201218_1954"),
]
operations = [
migrations.AddField(
model_name="option",
name="nb_votes",
field=models.PositiveSmallIntegerField(
default=0, verbose_name="nombre de votes reçus"
),
),
]

View file

@ -0,0 +1,20 @@
# Generated by Django 2.2.17 on 2020-12-19 17:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("elections", "0004_option_nb_votes"),
]
operations = [
migrations.AddField(
model_name="question",
name="max_votes",
field=models.PositiveSmallIntegerField(
default=0, verbose_name="nombre maximal de votes reçus"
),
),
]

View file

@ -29,6 +29,10 @@ class Question(models.Model):
Election, related_name="questions", on_delete=models.CASCADE
)
text = models.TextField(_("question"), blank=False)
# We cache the maximum number of votes for an option
max_votes = models.PositiveSmallIntegerField(
_("nombre maximal de votes reçus"), default=0
)
class Option(models.Model):
@ -40,3 +44,5 @@ class Option(models.Model):
User,
related_name="votes",
)
# For now, we store the amount of votes received after the election is tallied
nb_votes = models.PositiveSmallIntegerField(_("nombre de votes reçus"), default=0)

View file

@ -47,13 +47,17 @@
{% else %}
{# Lien pour la publication des résultats #}
<a class="button is-light is-outlined is-primary" href="{% url 'election.publish' election.pk %}">
<a class="button is-outlined is-primary" href="{% url 'election.publish' election.pk %}">
<span class="icon">
<i class="fas fa-edit"></i>
</span>
&nbsp;
{% if not election.results_public %}
{% trans "Publier" %}
</a>
{% else %}
{% trans "Dépublier" %}
{% endif %}
</a>&nbsp;
{# Lien pour l'archivage #}
<a class="button is-light is-outlined is-primary" href="{% url 'election.archive' election.pk %}">
@ -116,8 +120,12 @@
</a>
</div>&nbsp;&nbsp;
{% elif election.tallied %}
<span class="tag is-primary">
</span>
<span class="tag {% if o.nb_votes == q.max_votes %}is-success{% else %}is-primary{% endif %}">
<span class="icon">
<i class="fas fa-vote-yea"></i>
</span>&nbsp;
{{ o.nb_votes }}
</span>&nbsp;&nbsp;
{% endif %}
{{ o.text }}
</div>

View file

@ -8,7 +8,9 @@ urlpatterns = [
path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"),
path("tally/<int:pk>", views.ElectionTallyView.as_view(), name="election.tally"),
path(
"publish/<int:pk>", views.ElectionPublishView.as_view(), name="election.publish"
"publish/<int:pk>",
views.ElectionChangePublicationView.as_view(),
name="election.publish",
),
path(
"archive/<int:pk>", views.ElectionArchiveView.as_view(), name="election.archive"

View file

@ -50,28 +50,60 @@ class ElectionUpdateView(SuccessMessageMixin, UpdateView):
class ElectionTallyView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
def get_queryset(self):
return super().get_queryset().prefetch_related("questions__options")
def get(self, request, *args, **kwargs):
election = self.get_object()
election.update(tallied=True)
options, questions = [], []
for q in election.questions.all():
max_votes = 0
for o in q.options.all():
o.nb_votes = o.voters.count()
max_votes = max(max_votes, o.nb_votes)
options.append(o)
q.max_votes = max_votes
questions.append(q)
Option.objects.bulk_update(options, ["nb_votes"])
Question.objects.bulk_update(questions, ["max_votes"])
election.tallied = True
election.save()
messages.success(request, _("Élection dépouillée avec succès !"))
return super().get(request, *args, **kwargs)
class ElectionPublishView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
class ElectionChangePublicationView(
SuccessMessageMixin, SingleObjectMixin, RedirectView
):
model = Election
pattern_name = "election.admin"
def get(self, request, *args, **kwargs):
election = self.get_object()
election.update(tallied=True)
election.results_public = not election.results_public
election.save()
messages.success(
request,
_("Élection publiée avec succès !")
if election.results_public
else _("Élection dépubliée avec succès !"),
)
return super().get(request, *args, **kwargs)
class ElectionArchiveView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
def get(self, request, *args, **kwargs):
election = self.get_object()
election.update(tallied=True)
election.archived = True
election.save()
messages.success(request, _("Élection archivée avec succès !"))
return super().get(request, *args, **kwargs)