diff --git a/elections/models.py b/elections/models.py
index 5e7c203..570c5d2 100644
--- a/elections/models.py
+++ b/elections/models.py
@@ -14,6 +14,7 @@ from .staticdefs import (
VALIDATE_FUNCTIONS,
)
from .utils import (
+ BallotsData,
CastFunctions,
ResultsData,
TallyFunctions,
@@ -116,6 +117,10 @@ class Question(models.Model):
results_function = getattr(ResultsData, BALLOT_TYPE[self.type])
return results_function(self)
+ def display_ballots(self):
+ display_function = getattr(BallotsData, BALLOT_TYPE[self.type])
+ return display_function(self)
+
@property
def vote_type(self):
return BALLOT_TYPE[self.type]
diff --git a/elections/templates/elections/ballots/select.html b/elections/templates/elections/ballots/select.html
new file mode 100644
index 0000000..fceeec1
--- /dev/null
+++ b/elections/templates/elections/ballots/select.html
@@ -0,0 +1,25 @@
+{% load i18n %}
+
+
+
+
+ {% for o in options %}
+ {{ o }} |
+ {% endfor %}
+
+
+
+
+ {% for ballot in ballots.values %}
+
+ {% for v in ballot %}
+
+
+
+
+ |
+ {% endfor %}
+
+ {% endfor %}
+
+
diff --git a/elections/templates/elections/election_ballots.html b/elections/templates/elections/election_ballots.html
new file mode 100644
index 0000000..5d768fe
--- /dev/null
+++ b/elections/templates/elections/election_ballots.html
@@ -0,0 +1,36 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+
+{% block content %}
+
+ {# Titre de l'élection #}
+
+
{{ election.name }}
+
+
+
+
+
+
+
+
{% trans "Liste des bulletins" %}
+
+
+
+
+{# Tableau des bulletins par question #}
+{% for q in election.questions.all %}
+{{ q.display_ballots }}
+{% endfor %}
+
+{% endblock %}
diff --git a/elections/urls.py b/elections/urls.py
index 662954e..974f6fa 100644
--- a/elections/urls.py
+++ b/elections/urls.py
@@ -76,5 +76,10 @@ urlpatterns = [
views.ElectionVotersView.as_view(),
name="election.voters",
),
+ path(
+ "view//ballots",
+ views.ElectionBallotsView.as_view(),
+ name="election.ballots",
+ ),
path("vote/", views.VoteView.as_view(), name="election.vote"),
]
diff --git a/elections/utils.py b/elections/utils.py
index 373dea1..708753b 100644
--- a/elections/utils.py
+++ b/elections/utils.py
@@ -271,6 +271,31 @@ class ResultsData:
)
+class BallotsData:
+ """Classe pour afficher les bulletins d'une question"""
+
+ def select(question):
+ from .models import Vote
+
+ votes = Vote.objects.filter(option__question=question)
+
+ options = list(question.options.all())
+
+ ballots = {}
+ for v in votes:
+ ballot = ballots.get(v.user, [False] * len(options))
+ ballot[options.index(v.option)] = True
+
+ ballots[v.user] = ballot
+
+ return render_to_string(
+ "elections/ballots/select.html", {"options": options, "ballots": ballots}
+ )
+
+ def rank(question):
+ return ""
+
+
# #############################################################################
# Fonctions pour importer une liste de votant·e·s
# #############################################################################
diff --git a/elections/views.py b/elections/views.py
index 34e20b0..46863d9 100644
--- a/elections/views.py
+++ b/elections/views.py
@@ -479,6 +479,19 @@ class ElectionVotersView(NotArchivedMixin, DetailView):
return context
+class ElectionBallotsView(NotArchivedMixin, DetailView):
+ model = Election
+ template_name = "elections/election_ballots.html"
+
+ def get_queryset(self):
+ return (
+ super()
+ .get_queryset()
+ .filter(tallied=True)
+ .prefetch_related("questions__options")
+ )
+
+
class VoteView(OpenElectionOnlyMixin, DetailView):
model = Question