diff --git a/election/migrations/0003_auto_20171202_1819.py b/election/migrations/0003_auto_20171202_1819.py
new file mode 100644
index 00000000..ef7868d6
--- /dev/null
+++ b/election/migrations/0003_auto_20171202_1819.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('election', '0002_election_archived'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='role',
+ options={'ordering': ('order',)},
+ ),
+ migrations.AddField(
+ model_name='role',
+ name='order',
+ field=models.PositiveIntegerField(editable=False, default=0, db_index=True),
+ preserve_default=False,
+ ),
+ ]
diff --git a/election/models.py b/election/models.py
index 2d4599e7..937bca74 100644
--- a/election/models.py
+++ b/election/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from ordered_model.models import OrderedModel
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
@@ -81,10 +82,15 @@ class Election(models.Model):
results[role.title] = role.results(total_vote)
return results
+ def delete(self):
+ for election_list in self.election_lists.all():
+ election_list.delete()
+ super(Election, self).delete()
+
# Permissions
-class Role(models.Model):
+class Role(OrderedModel):
"""
This class allows to create a new role avaliable for a candidature
"""
@@ -149,6 +155,10 @@ class Candidature(models.Model):
program = models.TextField(_('description'), null=True, blank=True)
election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election list'))
+ def delete(self):
+ for vote in self.votes.all():
+ vote.delete()
+
def can_be_edited_by(self, user):
return (user == self.user) or user.can_edit(self.role.election)
diff --git a/election/templates/election/election_detail.jinja b/election/templates/election/election_detail.jinja
index 0dbafeab..26be2e3d 100644
--- a/election/templates/election/election_detail.jinja
+++ b/election/templates/election/election_detail.jinja
@@ -273,7 +273,8 @@ th {
{%- endfor %}
- {%- for role in election.roles.all() %}
+ {%- set role_list = election.roles.order_by('order').all() %}
+ {%- for role in role_list %}
{%- set count = [0] %}
{%- set role_data = election_form.data.getlist(role.title) if role.title in election_form.data else [] %}
@@ -283,6 +284,22 @@ th {
{% if user.can_edit(role) and election.is_vote_editable -%}
{% trans %}Edit{% endtrans %}
{% trans %}Delete{% endtrans %}
+
+ {%- if role == role_list.last() %}
+
+
+ {%- else %}
+
+
+ {%- endif %}
+ {% if role == role_list.first() %}
+
+
+ {% else %}
+
+
+ {% endif %}
+
{%- endif -%}
{{ role.description }}
{%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %}
diff --git a/election/views.py b/election/views.py
index 445b9a5a..8b77994a 100644
--- a/election/views.py
+++ b/election/views.py
@@ -177,6 +177,23 @@ class ElectionDetailView(CanViewMixin, DetailView):
template_name = 'election/election_detail.jinja'
pk_url_kwarg = "election_id"
+ def get(self, request, *arg, **kwargs):
+ r = super(ElectionDetailView, self).get(request, *arg, **kwargs)
+ election = self.get_object()
+ if request.user.can_edit(election) and election.is_vote_editable:
+ action = request.GET.get('action', None)
+ role = request.GET.get('role', None)
+ if action and role and Role.objects.filter(id=role).exists():
+ if action == "up":
+ Role.objects.get(id=role).up()
+ elif action == "down":
+ Role.objects.get(id=role).down()
+ elif action == "bottom":
+ Role.objects.get(id=role).bottom()
+ elif action == "top":
+ Role.objects.get(id=role).top()
+ return r
+
def get_context_data(self, **kwargs):
""" Add additionnal data to the template """
kwargs = super(ElectionDetailView, self).get_context_data(**kwargs)
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 51d5023e..96bc80aa 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-06 00:40+0100\n"
+"POT-Creation-Date: 2017-12-02 19:02+0100\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia \n"
"Language-Team: AE info \n"
@@ -19,7 +19,7 @@ msgstr ""
#: accounting/models.py:61 accounting/models.py:110 accounting/models.py:138
#: accounting/models.py:197 club/models.py:47
#: core/templates/core/base.jinja:297 counter/models.py:113
-#: counter/models.py:139 counter/models.py:183 forum/models.py:49
+#: counter/models.py:140 counter/models.py:184 forum/models.py:49
#: launderette/models.py:38 launderette/models.py:84 launderette/models.py:110
#: stock/models.py:38 stock/models.py:54 stock/models.py:77 stock/models.py:97
msgid "name"
@@ -66,8 +66,8 @@ msgid "account number"
msgstr "numero de compte"
#: accounting/models.py:113 accounting/models.py:139 club/models.py:227
-#: com/models.py:67 com/models.py:178 counter/models.py:148
-#: counter/models.py:184 trombi/models.py:149
+#: com/models.py:67 com/models.py:178 counter/models.py:149
+#: counter/models.py:185 trombi/models.py:149
msgid "club"
msgstr "club"
@@ -88,13 +88,13 @@ msgstr "Compte club"
msgid "%(club_account)s on %(bank_account)s"
msgstr "%(club_account)s sur %(bank_account)s"
-#: accounting/models.py:195 club/models.py:228 counter/models.py:465
-#: election/models.py:16 launderette/models.py:148
+#: accounting/models.py:195 club/models.py:228 counter/models.py:466
+#: election/models.py:17 launderette/models.py:148
msgid "start date"
msgstr "date de début"
-#: accounting/models.py:196 club/models.py:229 counter/models.py:466
-#: election/models.py:17
+#: accounting/models.py:196 club/models.py:229 counter/models.py:467
+#: election/models.py:18
msgid "end date"
msgstr "date de fin"
@@ -107,7 +107,7 @@ msgid "club account"
msgstr "compte club"
#: accounting/models.py:200 accounting/models.py:257 counter/models.py:53
-#: counter/models.py:297
+#: counter/models.py:298
msgid "amount"
msgstr "montant"
@@ -128,18 +128,19 @@ msgid "journal"
msgstr "classeur"
#: accounting/models.py:258 core/models.py:645 core/models.py:1046
-#: core/models.py:1090 core/models.py:1117 counter/models.py:300
-#: counter/models.py:350 counter/models.py:483 eboutic/models.py:39
+#: core/models.py:1090 core/models.py:1117 counter/models.py:301
+#: counter/models.py:351 counter/models.py:484 eboutic/models.py:39
#: eboutic/models.py:73 forum/models.py:239 forum/models.py:314
#: stock/models.py:76
msgid "date"
msgstr "date"
-#: accounting/models.py:259 counter/models.py:484 stock/models.py:79
+#: accounting/models.py:259 counter/models.py:115 counter/models.py:485
+#: stock/models.py:79
msgid "comment"
msgstr "commentaire"
-#: accounting/models.py:260 counter/models.py:301 counter/models.py:351
+#: accounting/models.py:260 counter/models.py:302 counter/models.py:352
#: subscription/models.py:55
msgid "payment method"
msgstr "méthode de paiement"
@@ -165,7 +166,7 @@ msgid "accounting type"
msgstr "type comptable"
#: accounting/models.py:269 accounting/models.py:371 accounting/models.py:398
-#: accounting/models.py:422 core/models.py:1116 counter/models.py:342
+#: accounting/models.py:422 core/models.py:1116 counter/models.py:343
msgid "label"
msgstr "étiquette"
@@ -264,7 +265,7 @@ msgstr ""
"Vous devez fournir soit un type comptable simplifié ou un type comptable "
"standard"
-#: accounting/models.py:366 counter/models.py:143
+#: accounting/models.py:366 counter/models.py:144
msgid "code"
msgstr "code"
@@ -365,9 +366,10 @@ msgstr "Compte en banque : "
#: core/templates/core/user_edit.jinja:19
#: counter/templates/counter/last_ops.jinja:29
#: counter/templates/counter/last_ops.jinja:59
-#: election/templates/election/election_detail.jinja:280
-#: election/templates/election/election_detail.jinja:330
-#: election/templates/election/election_detail.jinja:378
+#: election/templates/election/election_detail.jinja:271
+#: election/templates/election/election_detail.jinja:286
+#: election/templates/election/election_detail.jinja:350
+#: election/templates/election/election_detail.jinja:401
#: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:123
#: launderette/templates/launderette/launderette_admin.jinja:16
#: launderette/views.py:182 sas/templates/sas/album.jinja:26
@@ -416,9 +418,9 @@ msgstr "Nouveau compte club"
#: counter/templates/counter/counter_list.jinja:17
#: counter/templates/counter/counter_list.jinja:33
#: counter/templates/counter/counter_list.jinja:55
-#: election/templates/election/election_detail.jinja:279
-#: election/templates/election/election_detail.jinja:327
-#: election/templates/election/election_detail.jinja:375
+#: election/templates/election/election_detail.jinja:285
+#: election/templates/election/election_detail.jinja:347
+#: election/templates/election/election_detail.jinja:398
#: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62
#: forum/templates/forum/macros.jinja:117
#: launderette/templates/launderette/launderette_list.jinja:16
@@ -926,21 +928,21 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
msgid "A club with that unix_name already exists"
msgstr "Un club avec ce nom UNIX existe déjà."
-#: club/models.py:226 counter/models.py:463 counter/models.py:481
-#: eboutic/models.py:38 eboutic/models.py:72 election/models.py:140
+#: club/models.py:226 counter/models.py:464 counter/models.py:482
+#: eboutic/models.py:38 eboutic/models.py:72 election/models.py:154
#: launderette/models.py:114 launderette/models.py:152 sas/models.py:180
#: trombi/models.py:148
msgid "user"
msgstr "nom d'utilisateur"
-#: club/models.py:230 core/models.py:180 election/models.py:139
-#: election/models.py:155 trombi/models.py:150
+#: club/models.py:230 core/models.py:180 election/models.py:153
+#: election/models.py:173 trombi/models.py:150
msgid "role"
msgstr "rôle"
#: club/models.py:232 core/models.py:66 counter/models.py:114
-#: counter/models.py:140 election/models.py:13 election/models.py:93
-#: election/models.py:141 forum/models.py:50 forum/models.py:186
+#: counter/models.py:141 election/models.py:14 election/models.py:99
+#: election/models.py:155 forum/models.py:50 forum/models.py:186
msgid "description"
msgstr "description"
@@ -1312,8 +1314,8 @@ msgstr "Hebdomadaire"
msgid "Call"
msgstr "Appel"
-#: com/models.py:63 com/models.py:127 com/models.py:175 election/models.py:12
-#: election/models.py:92 election/models.py:128 forum/models.py:189
+#: com/models.py:63 com/models.py:127 com/models.py:175 election/models.py:13
+#: election/models.py:98 election/models.py:134 forum/models.py:189
#: forum/models.py:237
msgid "title"
msgstr "titre"
@@ -2001,7 +2003,7 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/templates/core/user_detail.jinja:14
#: core/templates/core/user_detail.jinja:16
#: core/templates/core/user_edit.jinja:17
-#: election/templates/election/election_detail.jinja:317
+#: election/templates/election/election_detail.jinja:340
#: forum/templates/forum/macros.jinja:93 forum/templates/forum/macros.jinja:95
#: forum/templates/forum/reply.jinja:38 forum/templates/forum/reply.jinja:40
#: trombi/templates/trombi/user_tools.jinja:41
@@ -3273,67 +3275,67 @@ msgstr "clients"
msgid "Not enough money"
msgstr "Solde insuffisant"
-#: counter/models.py:118 counter/models.py:141
+#: counter/models.py:119 counter/models.py:142
msgid "product type"
msgstr "type du produit"
-#: counter/models.py:144
+#: counter/models.py:145
msgid "purchase price"
msgstr "prix d'achat"
-#: counter/models.py:145
+#: counter/models.py:146
msgid "selling price"
msgstr "prix de vente"
-#: counter/models.py:146
+#: counter/models.py:147
msgid "special selling price"
msgstr "prix de vente spécial"
-#: counter/models.py:147
+#: counter/models.py:148
msgid "icon"
msgstr "icône"
-#: counter/models.py:149
+#: counter/models.py:150
msgid "limit age"
msgstr "âge limite"
-#: counter/models.py:150
+#: counter/models.py:151
msgid "tray price"
msgstr "prix plateau"
-#: counter/models.py:151
+#: counter/models.py:152
msgid "parent product"
msgstr "produit parent"
-#: counter/models.py:153
+#: counter/models.py:154
msgid "buying groups"
msgstr "groupe d'achat"
-#: counter/models.py:154 election/models.py:36
+#: counter/models.py:155 election/models.py:37
msgid "archived"
msgstr "archivé"
-#: counter/models.py:157 counter/models.py:566
+#: counter/models.py:158 counter/models.py:567
msgid "product"
msgstr "produit"
-#: counter/models.py:185
+#: counter/models.py:186
msgid "products"
msgstr "produits"
-#: counter/models.py:186
+#: counter/models.py:187
msgid "counter type"
msgstr "type de comptoir"
-#: counter/models.py:188
+#: counter/models.py:189
msgid "Bar"
msgstr "Bar"
-#: counter/models.py:188
+#: counter/models.py:189
msgid "Office"
msgstr "Bureau"
-#: counter/models.py:188 counter/templates/counter/counter_list.jinja:11
+#: counter/models.py:189 counter/templates/counter/counter_list.jinja:11
#: eboutic/templates/eboutic/eboutic_main.jinja:4
#: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
@@ -3342,62 +3344,62 @@ msgstr "Bureau"
msgid "Eboutic"
msgstr "Eboutic"
-#: counter/models.py:189
+#: counter/models.py:190
msgid "sellers"
msgstr "vendeurs"
-#: counter/models.py:192 launderette/models.py:151
+#: counter/models.py:193 launderette/models.py:151
msgid "token"
msgstr "jeton"
-#: counter/models.py:195 counter/models.py:464 counter/models.py:482
+#: counter/models.py:196 counter/models.py:465 counter/models.py:483
#: launderette/models.py:39 stock/models.py:39
msgid "counter"
msgstr "comptoir"
-#: counter/models.py:303
+#: counter/models.py:304
msgid "bank"
msgstr "banque"
-#: counter/models.py:305 counter/models.py:353
+#: counter/models.py:306 counter/models.py:354
msgid "is validated"
msgstr "est validé"
-#: counter/models.py:308
+#: counter/models.py:309
msgid "refilling"
msgstr "rechargement"
-#: counter/models.py:346 eboutic/models.py:129
+#: counter/models.py:347 eboutic/models.py:129
msgid "unit price"
msgstr "prix unitaire"
-#: counter/models.py:347 counter/models.py:555 eboutic/models.py:130
+#: counter/models.py:348 counter/models.py:556 eboutic/models.py:130
msgid "quantity"
msgstr "quantité"
-#: counter/models.py:352
+#: counter/models.py:353
msgid "Sith account"
msgstr "Compte utilisateur"
-#: counter/models.py:352 sith/settings.py:368 sith/settings.py:373
+#: counter/models.py:353 sith/settings.py:368 sith/settings.py:373
#: sith/settings.py:395
msgid "Credit card"
msgstr "Carte bancaire"
-#: counter/models.py:356
+#: counter/models.py:357
msgid "selling"
msgstr "vente"
-#: counter/models.py:375
+#: counter/models.py:376
msgid "Unknown event"
msgstr "Événement inconnu"
-#: counter/models.py:376
+#: counter/models.py:377
#, python-format
msgid "Eticket bought for the event %(event)s"
msgstr "Eticket acheté pour l'événement %(event)s"
-#: counter/models.py:378 counter/models.py:390
+#: counter/models.py:379 counter/models.py:391
#, python-format
msgid ""
"You bought an eticket for the event %(event)s.\n"
@@ -3406,51 +3408,51 @@ msgstr ""
"Vous avez acheté un Eticket pour l'événement %(event)s.\n"
"Vous pouvez le télécharger sur cette page: %(url)s"
-#: counter/models.py:467
+#: counter/models.py:468
msgid "last activity date"
msgstr "dernière activité"
-#: counter/models.py:470
+#: counter/models.py:471
msgid "permanency"
msgstr "permanence"
-#: counter/models.py:485
+#: counter/models.py:486
msgid "emptied"
msgstr "coffre vidée"
-#: counter/models.py:488
+#: counter/models.py:489
msgid "cash register summary"
msgstr "relevé de caisse"
-#: counter/models.py:553
+#: counter/models.py:554
msgid "cash summary"
msgstr "relevé"
-#: counter/models.py:554
+#: counter/models.py:555
msgid "value"
msgstr "valeur"
-#: counter/models.py:556
+#: counter/models.py:557
msgid "check"
msgstr "chèque"
-#: counter/models.py:559
+#: counter/models.py:560
msgid "cash register summary item"
msgstr "élément de relevé de caisse"
-#: counter/models.py:567
+#: counter/models.py:568
msgid "banner"
msgstr "bannière"
-#: counter/models.py:568
+#: counter/models.py:569
msgid "event date"
msgstr "date de l'événement"
-#: counter/models.py:569
+#: counter/models.py:570
msgid "event title"
msgstr "titre de l'événement"
-#: counter/models.py:570
+#: counter/models.py:571
msgid "secret"
msgstr "secret"
@@ -3906,49 +3908,49 @@ msgstr "Retourner à l'eboutic"
msgid "You do not have enough money to buy the basket"
msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
-#: election/models.py:14
+#: election/models.py:15
msgid "start candidature"
msgstr "début des candidatures"
-#: election/models.py:15
+#: election/models.py:16
msgid "end candidature"
msgstr "fin des candidatures"
-#: election/models.py:21
+#: election/models.py:22
msgid "edit groups"
msgstr "groupe d'édition"
-#: election/models.py:25
+#: election/models.py:26
msgid "view groups"
msgstr "groupe de vue"
-#: election/models.py:29
+#: election/models.py:30
msgid "vote groups"
msgstr "groupe de vote"
-#: election/models.py:33
+#: election/models.py:34
msgid "candidature groups"
msgstr "groupe de candidature"
-#: election/models.py:91 election/models.py:129
+#: election/models.py:97 election/models.py:135
msgid "election"
msgstr "élection"
-#: election/models.py:94
+#: election/models.py:100
msgid "max choice"
msgstr "nombre de choix maxi"
-#: election/models.py:142
+#: election/models.py:156
msgid "election list"
msgstr "liste électorale"
-#: election/models.py:156
+#: election/models.py:174
msgid "candidature"
msgstr "candidature"
#: election/templates/election/candidate_form.jinja:4
#: election/templates/election/candidate_form.jinja:13
-#: election/templates/election/election_detail.jinja:366
+#: election/templates/election/election_detail.jinja:389
msgid "Candidate"
msgstr "Candidater"
@@ -3994,40 +3996,50 @@ msgstr "Vous avez déjà voté pour cette élection."
msgid "Blank vote"
msgstr "Vote blanc"
-#: election/templates/election/election_detail.jinja:284
+#: election/templates/election/election_detail.jinja:307
msgid "You may choose up to"
msgstr "Vous pouvez choisir jusqu'à"
-#: election/templates/election/election_detail.jinja:284
+#: election/templates/election/election_detail.jinja:307
msgid "people."
msgstr "personne(s)"
-#: election/templates/election/election_detail.jinja:298
+#: election/templates/election/election_detail.jinja:321
msgid "Choose blank vote"
msgstr "Choisir de voter blanc"
-#: election/templates/election/election_detail.jinja:305
-#: election/templates/election/election_detail.jinja:345
+#: election/templates/election/election_detail.jinja:328
+#: election/templates/election/election_detail.jinja:368
msgid "votes"
msgstr "votes"
-#: election/templates/election/election_detail.jinja:338
+#: election/templates/election/election_detail.jinja:361
#: launderette/templates/launderette/launderette_book.jinja:12
msgid "Choose"
msgstr "Choisir"
-#: election/templates/election/election_detail.jinja:361
+#: election/templates/election/election_detail.jinja:384
msgid "Submit the vote !"
msgstr "Envoyer le vote !"
-#: election/templates/election/election_detail.jinja:369
+#: election/templates/election/election_detail.jinja:392
msgid "Add a new list"
msgstr "Ajouter une nouvelle liste"
-#: election/templates/election/election_detail.jinja:373
+#: election/templates/election/election_detail.jinja:396
msgid "Add a new role"
msgstr "Ajouter un nouveau rôle"
+#: election/templates/election/election_detail.jinja:411
+#: election/templates/election/election_detail.jinja:415
+msgid "Show more"
+msgstr "Montrer plus"
+
+#: election/templates/election/election_detail.jinja:412
+#: election/templates/election/election_detail.jinja:416
+msgid "Show less"
+msgstr "Montrer moins"
+
#: election/templates/election/election_list.jinja:5
msgid "Election list"
msgstr "Liste des élections"
diff --git a/requirements.txt b/requirements.txt
index c17b56b8..b94274f4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,5 +13,6 @@ django-haystack
whoosh
django-debug-toolbar
libsass
+django-ordered-model
pygraphviz
# mysqlclient