Many improvements for application and assignment poll system.

This commit is contained in:
Emanuel Schuetze 2011-09-03 10:52:29 +02:00
parent b1b5d9cb70
commit ca0c50caef
14 changed files with 77 additions and 65 deletions

View File

@ -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 %}

View File

@ -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)

View File

@ -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>
<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>

View File

@ -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 }}

View File

@ -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,
}

View File

@ -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(

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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 %}

View File

@ -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', \

View File

@ -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'):

View File

@ -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):

View File

@ -320,10 +320,10 @@ def print_application_poll(request, poll_id=None):
circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/>&nbsp;&nbsp;"
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'/>&nbsp;"
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']))