Many improvements for application and assignment poll system.
This commit is contained in:
parent
b1b5d9cb70
commit
ca0c50caef
@ -10,7 +10,7 @@
|
||||
<h4>{% trans "Status" %}:</h4>
|
||||
{% trans item.assignment.get_status_display %}
|
||||
<h4>{% trans "Number of available posts" %}:</h4>
|
||||
{{ item.assignment.assignment_number }}
|
||||
{{ item.assignment.posts }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -351,14 +351,8 @@ class Application(models.Model):
|
||||
Generates a poll object for the application
|
||||
"""
|
||||
from poll.models import Poll
|
||||
if pollcount > 1:
|
||||
description = _("%s. poll") % pollcount
|
||||
else:
|
||||
description = _("Poll")
|
||||
poll = Poll(title=_("Application #%s") % self.number, \
|
||||
optiondecision=True, \
|
||||
application=self,
|
||||
description=description)
|
||||
poll = Poll(optiondecision=True, \
|
||||
application=self)
|
||||
poll.save()
|
||||
poll.add_option(self)
|
||||
self.writelog(_("Poll created"), user)
|
||||
|
@ -1,25 +1,25 @@
|
||||
{% extends 'application/base_application.html' %}
|
||||
{% block title %}{{ block.super }} - {{ poll.title }}{% endblock %}
|
||||
{% block title %}{{ block.super }} - {{ poll }}{% endblock %}
|
||||
|
||||
{% if perms.poll.can_manage_poll %}
|
||||
{% if perms.application.can_manage_application %}
|
||||
{% block submenu %}
|
||||
{{ block.super }}
|
||||
<br>
|
||||
<h3>{%trans "Application" %} #{{ poll.application.number }}</h3>
|
||||
<ul>
|
||||
<li><a href="{% url print_application_poll poll.id %}"><img src="/static/images/icons/application-pdf.png"> {%trans 'Print Poll' %}</a></li>
|
||||
<li><a href="{% url print_application_poll poll.id %}"><img src="/static/images/icons/application-pdf.png"> {%trans 'Print vote' %}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ poll.title }}</h1>
|
||||
<h4>Title: "{{ poll.application.title }}"</h4>
|
||||
<h1>{%trans "Application" %} #{{ poll.application.number }} - {%trans "Vote" %}</h1>
|
||||
<h4>{{ poll.application.title }}</h4>
|
||||
|
||||
{% if perms.poll.can_manage_poll %}
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{{ poll.description }}</legend>
|
||||
<legend>{%trans "Results" %}: {{ ballot }}. {%trans "Vote" %}</legend>
|
||||
<p><nobr><label>{%trans "Votes in favour" %}:</label></nobr>
|
||||
{{ options.0.form.yes.errors }}{{ options.0.form.yes }}
|
||||
</p>
|
||||
|
@ -149,7 +149,7 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url application_poll_view poll.id %}">{% trans "Enter vote result!" %}</a>
|
||||
<a href="{% url application_poll_view poll.id %}">{% trans "Enter vote results!" %}</a>
|
||||
{% endif %}
|
||||
{% if not forloop.last %}<br>{% endif %}
|
||||
{% empty %}
|
||||
@ -206,13 +206,13 @@
|
||||
|
||||
|
||||
<div>
|
||||
<p>{% trans "Application" %}
|
||||
<h1>{% trans "Application" %}
|
||||
{% if application.number != None %}
|
||||
#{{ application.number }}
|
||||
{% else %}
|
||||
<i>[no number]</i>
|
||||
{% endif %}</p>
|
||||
<h1>{{ application.title }}</h1>
|
||||
{% endif %}</h1>
|
||||
<h2>{{ application.title }}</h2>
|
||||
|
||||
|
||||
{{ application.text|linebreaks }}
|
||||
|
@ -318,6 +318,7 @@ def view_poll(request, poll_id):
|
||||
view a poll for this application.
|
||||
"""
|
||||
poll = Poll.objects.get(pk=poll_id)
|
||||
ballot = poll.ballot
|
||||
options = poll.options
|
||||
if request.user.has_perm('application.can_manage_applications'):
|
||||
if request.method == 'POST':
|
||||
@ -347,4 +348,5 @@ def view_poll(request, poll_id):
|
||||
'poll': poll,
|
||||
'form': form,
|
||||
'options': options,
|
||||
'ballot': ballot,
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ from participant.models import Profile
|
||||
from assignment.models import Assignment
|
||||
|
||||
|
||||
class AssigmentForm(ModelForm):
|
||||
class AssignmentForm(ModelForm):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
|
||||
@ -26,7 +26,7 @@ class AssigmentForm(ModelForm):
|
||||
exclude = ('status', 'profile')
|
||||
|
||||
|
||||
class AssigmentRunForm(Form):
|
||||
class AssignmentRunForm(Form):
|
||||
error_css_class = 'error'
|
||||
|
||||
candidate = ModelChoiceField(
|
||||
|
@ -25,7 +25,7 @@ class Assignment(models.Model):
|
||||
|
||||
name = models.CharField(max_length=100, verbose_name = _("Name"))
|
||||
description = models.TextField(null=True, blank=True, verbose_name = _("Description"))
|
||||
assignment_number = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts"))
|
||||
posts = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts"))
|
||||
polldescription = models.CharField(max_length=50, null=True, blank=True, verbose_name = _("Short description (for ballot paper)"))
|
||||
profile = models.ManyToManyField(Profile, null=True, blank=True)
|
||||
status = models.CharField(max_length=1, choices=STATUS, default='sea')
|
||||
@ -69,10 +69,9 @@ class Assignment(models.Model):
|
||||
def gen_poll(self):
|
||||
from poll.models import Poll
|
||||
poll = Poll()
|
||||
poll.title = _("Election for %s") % self.name
|
||||
|
||||
# Option A: candidates <= available posts -> yes/no/abstention
|
||||
if self.profile.count() <= self.assignment_number:
|
||||
if self.profile.count() <= self.posts:
|
||||
poll.optiondecision = True
|
||||
else:
|
||||
poll.optiondecision = False
|
||||
|
@ -27,7 +27,7 @@
|
||||
{% for assignment in assignments %}
|
||||
<tr class="{% cycle '' 'odd' %}">
|
||||
<td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td>
|
||||
<td>{{ assignment.profile.count }} / {{ assignment.assignment_number }}</td>
|
||||
<td>{{ assignment.profile.count }} / {{ assignment.posts }}</td>
|
||||
<td>{{ assignment.get_status_display }}</td>
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
<td><a href="{% url assignment_edit assignment.id %}"><img src="/static/images/icons/document-edit.png" title="{%trans 'Edit assignment' %}"></a>
|
||||
|
@ -1,8 +1,8 @@
|
||||
{% extends 'assignment/base_assignment.html' %}
|
||||
{% block title %}{{ block.super }} - {%trans "Poll" %} "{{ poll.title }}"{% endblock %}
|
||||
{% block title %}{{ block.super }} - {%trans "Poll" %} "{{ poll }}"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ poll.title }}</h1>
|
||||
<h1>{{ poll }}</h1>
|
||||
<p>{{ ballotnumber }}. {%trans "ballot" %}: {{options.count}}
|
||||
{% blocktrans count counter=options|length %}candidate{% plural %}candidates{% endblocktrans %}
|
||||
</p>
|
||||
@ -46,7 +46,7 @@
|
||||
<span class="icon previous">{%trans 'Back to election' %}</span>
|
||||
</button>
|
||||
</a>
|
||||
<a href='{% url print_assignment_poll poll.id ballotnumber poll.assignment.assignment_number %}'>
|
||||
<a href='{% url print_assignment_poll poll.id %}'>
|
||||
<button type="button">
|
||||
<span class="icon pdf">{%trans 'Print ballot' %}</span>
|
||||
</button>
|
||||
|
@ -9,7 +9,7 @@
|
||||
{% trans assignment.get_status_display %}
|
||||
|
||||
<h4>{% trans "Number of available posts" %}:</h4>
|
||||
{{ assignment.assignment_number }}
|
||||
{{ assignment.posts }}
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
@ -122,7 +122,7 @@
|
||||
<tr>
|
||||
<th>{% trans "Candidates" %}</th>
|
||||
{% for poll in assignment.poll_set.all %}
|
||||
<th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id forloop.counter %}">{% endif %}
|
||||
<th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id %}">{% endif %}
|
||||
{{forloop.counter}}.
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
</a>
|
||||
@ -132,13 +132,11 @@
|
||||
{% endfor %}
|
||||
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
<th>
|
||||
{% with ballotnumber=assignment.poll_set.all.count %}
|
||||
<a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
|
||||
<a href='{% url assignment_gen_poll assignment.id %}'>
|
||||
<button type="button">
|
||||
<span class="icon poll">{%trans 'New ballot' %}</span>
|
||||
</button>
|
||||
</a>
|
||||
{% endwith %}
|
||||
</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
@ -169,13 +167,11 @@
|
||||
<i>{% trans "No ballots available." %}</i>
|
||||
|
||||
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
{% with ballotnumber=assignment.poll_set.all.count %}
|
||||
<p><a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
|
||||
<p><a href='{% url assignment_gen_poll assignment.id %}'>
|
||||
<button type="button">
|
||||
<span class="icon poll">{%trans 'New ballot' %}</span>
|
||||
</button>
|
||||
</a></p>
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
@ -40,13 +40,13 @@ urlpatterns = patterns('assignment.views',
|
||||
url(r'^assignment/(?P<assignment_id>\d+)/delother/(?P<profile_id>\d+)$', 'delother', \
|
||||
name='assignment_delother'),
|
||||
|
||||
url(r'^assignment/poll/(?P<poll_id>\d+)/print/(?P<ballotnumber>\d+)/(?P<posts>\d+)$', 'print_assignment_poll', \
|
||||
url(r'^assignment/poll/(?P<poll_id>\d+)/print$', 'print_assignment_poll', \
|
||||
name='print_assignment_poll'),
|
||||
|
||||
url(r'^assignment/(?P<assignment_id>\d+)/gen_poll/(?P<ballotnumber>\d+)$', 'gen_poll', \
|
||||
url(r'^assignment/(?P<assignment_id>\d+)/gen_poll$', 'gen_poll', \
|
||||
name='assignment_gen_poll'),
|
||||
|
||||
url(r'^assignment/poll/(?P<poll_id>\d+)/(?P<ballotnumber>\d+)$', 'poll_view', \
|
||||
url(r'^assignment/poll/(?P<poll_id>\d+)$', 'poll_view', \
|
||||
name='assignment_poll_view'),
|
||||
|
||||
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
|
||||
|
@ -19,7 +19,7 @@ from django.utils.translation import ugettext as _
|
||||
from poll.models import Poll, Option
|
||||
from poll.forms import OptionResultForm, PollInvalidForm
|
||||
from assignment.models import Assignment
|
||||
from assignment.forms import AssigmentForm, AssigmentRunForm
|
||||
from assignment.forms import AssignmentForm, AssignmentRunForm
|
||||
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form
|
||||
from utils.pdf import print_assignment_poll
|
||||
from participant.models import Profile
|
||||
@ -53,7 +53,7 @@ def view(request, assignment_id=None):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
if request.method == 'POST':
|
||||
if request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = AssigmentRunForm(request.POST)
|
||||
form = AssignmentRunForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.cleaned_data['candidate']
|
||||
try:
|
||||
@ -63,7 +63,7 @@ def view(request, assignment_id=None):
|
||||
messages.error(request, e)
|
||||
else:
|
||||
if request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = AssigmentRunForm()
|
||||
form = AssignmentRunForm()
|
||||
|
||||
# list of candidates
|
||||
candidates = set()
|
||||
@ -102,7 +102,7 @@ def edit(request, assignment_id=None):
|
||||
assignment = None
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AssigmentForm(request.POST, instance=assignment)
|
||||
form = AssignmentForm(request.POST, instance=assignment)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if assignment_id is None:
|
||||
@ -111,7 +111,7 @@ def edit(request, assignment_id=None):
|
||||
messages.success(request, _('Election was successfully modified.'))
|
||||
return redirect(reverse("assignment_overview"))
|
||||
else:
|
||||
form = AssigmentForm(instance=assignment)
|
||||
form = AssignmentForm(instance=assignment)
|
||||
return {
|
||||
'form': form,
|
||||
'assignment': assignment,
|
||||
@ -180,19 +180,20 @@ def delother(request, assignment_id, profile_id):
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def gen_poll(request, assignment_id, ballotnumber):
|
||||
def gen_poll(request, assignment_id):
|
||||
try:
|
||||
poll = Assignment.objects.get(pk=assignment_id).gen_poll()
|
||||
messages.success(request, _("New ballot was successfully created.") )
|
||||
except Assignment.DoesNotExist:
|
||||
pass
|
||||
return redirect(reverse('assignment_poll_view', args=[poll.id, ballotnumber]))
|
||||
return redirect(reverse('assignment_poll_view', args=[poll.id]))
|
||||
|
||||
|
||||
@permission_required('assignment.can_view_assignment')
|
||||
@template('assignment/poll_view.html')
|
||||
def poll_view(request, poll_id, ballotnumber=1):
|
||||
def poll_view(request, poll_id):
|
||||
poll = Poll.objects.get(pk=poll_id)
|
||||
ballotnumber = poll.ballot
|
||||
options = poll.options.order_by('user__user__first_name')
|
||||
assignment = poll.assignment
|
||||
if request.user.has_perm('assignment.can_manage_assignment'):
|
||||
|
@ -19,8 +19,6 @@ from participant.models import Profile
|
||||
|
||||
|
||||
class Poll(models.Model):
|
||||
#TODO: Mehrheit in den Zahlen festmachen
|
||||
title = models.CharField(max_length=100, verbose_name = _("Title"))
|
||||
optiondecision = models.BooleanField(default=True, verbose_name = _("Poll of decision (yes, no, abstention)"))
|
||||
application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application"))
|
||||
assignment = models.ForeignKey(Assignment, null=True, blank=True, verbose_name = _("Election"))
|
||||
@ -58,6 +56,30 @@ class Poll(models.Model):
|
||||
def options_values(self):
|
||||
return [option.value for option in self.options]
|
||||
|
||||
@property
|
||||
def count_ballots(self):
|
||||
if self.application:
|
||||
return Poll.objects.filter(application=self.application).count()
|
||||
if self.assignment:
|
||||
return Poll.objects.filter(assignment=self.assignment).count()
|
||||
return None
|
||||
|
||||
@property
|
||||
def ballot(self):
|
||||
if self.application:
|
||||
counter = 0
|
||||
for poll in Poll.objects.filter(application=self.application):
|
||||
counter = counter + 1
|
||||
if self == poll:
|
||||
return counter
|
||||
if self.assignment:
|
||||
counter = 0
|
||||
for poll in Poll.objects.filter(assignment=self.assignment):
|
||||
counter = counter + 1
|
||||
if self == poll:
|
||||
return counter
|
||||
return None
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self, link='view'):
|
||||
if self.application:
|
||||
@ -76,7 +98,10 @@ class Poll(models.Model):
|
||||
return ('poll_delete', [str(self.id)])
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
if self.application:
|
||||
return self.application.title
|
||||
if self.assignment:
|
||||
return self.assignment.name
|
||||
|
||||
|
||||
class Option(models.Model):
|
||||
|
@ -320,10 +320,10 @@ def print_application_poll(request, poll_id=None):
|
||||
circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/> "
|
||||
cell = []
|
||||
cell.append(Spacer(0,0.8*cm))
|
||||
cell.append(Paragraph(poll.title, stylesheet['Ballot_title']))
|
||||
cell.append(Paragraph(_("Title")+": "+poll.application.title, stylesheet['Ballot_subtitle']))
|
||||
if poll.description:
|
||||
cell.append(Paragraph(poll.description, stylesheet['Ballot_description']))
|
||||
cell.append(Paragraph(_("Application")+" #"+str(poll.application.number), stylesheet['Ballot_title']))
|
||||
cell.append(Paragraph(poll.application.title, stylesheet['Ballot_subtitle']))
|
||||
#if poll.description:
|
||||
cell.append(Paragraph(str(poll.ballot)+". "+_("Vote"), stylesheet['Ballot_description']))
|
||||
cell.append(Spacer(0,0.5*cm))
|
||||
cell.append(Paragraph(circle+_("Yes"), stylesheet['Ballot_option']))
|
||||
cell.append(Paragraph(circle+_("No"), stylesheet['Ballot_option']))
|
||||
@ -340,10 +340,10 @@ def print_application_poll(request, poll_id=None):
|
||||
doc.build(story)
|
||||
return response
|
||||
|
||||
def print_assignment_poll(request, poll_id=None, ballotnumber=1, posts=None):
|
||||
def print_assignment_poll(request, poll_id=None):
|
||||
poll = Poll.objects.get(id=poll_id)
|
||||
response = HttpResponse(mimetype='application/pdf')
|
||||
filename = u'filename=%s-%s-#%s.pdf;' % (_("Election"), poll.title.replace(' ','_'), ballotnumber)
|
||||
filename = u'filename=%s-%s-#%s.pdf;' % (_("Election"), poll.assignment.name.replace(' ','_'), poll.ballot)
|
||||
response['Content-Disposition'] = filename.encode('utf-8')
|
||||
doc = SimpleDocTemplate(response, pagesize=A4, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0, showBoundary=False)
|
||||
story = [Spacer(0,0*cm)]
|
||||
@ -351,18 +351,13 @@ def print_assignment_poll(request, poll_id=None, ballotnumber=1, posts=None):
|
||||
circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/> "
|
||||
cell = []
|
||||
cell.append(Spacer(0,0.8*cm))
|
||||
cell.append(Paragraph(poll.title, stylesheet['Ballot_title']))
|
||||
cell.append(Paragraph(_("Election") + ": " + poll.assignment.name, stylesheet['Ballot_title']))
|
||||
cell.append(Paragraph(poll.description, stylesheet['Ballot_subtitle']))
|
||||
options = poll.get_options().order_by('user__user__first_name')
|
||||
cell.append(Paragraph(ballotnumber+". "+_("ballot")+", "+str(len(options))+" "+ ungettext("candidate", "candidates", len(options))+", "+posts+" "+_("available posts"), stylesheet['Ballot_description']))
|
||||
cell.append(Paragraph(str(poll.ballot)+". "+_("ballot")+", "+str(len(options))+" "+ ungettext("candidate", "candidates", len(options))+", "+str(poll.assignment.posts)+" "+_("available posts"), stylesheet['Ballot_description']))
|
||||
cell.append(Spacer(0,0.4*cm))
|
||||
|
||||
if len(options) <= int(posts):
|
||||
optiondecision = True
|
||||
else:
|
||||
optiondecision = False
|
||||
|
||||
if optiondecision:
|
||||
if poll.optiondecision:
|
||||
for option in options:
|
||||
o = str(option).rsplit("(",1)
|
||||
cell.append(Paragraph(o[0], stylesheet['Ballot_option_name']))
|
||||
|
Loading…
Reference in New Issue
Block a user