diff --git a/openslides/agenda/templates/agenda/overview.html b/openslides/agenda/templates/agenda/overview.html
index 67c81d835..8eefd1212 100644
--- a/openslides/agenda/templates/agenda/overview.html
+++ b/openslides/agenda/templates/agenda/overview.html
@@ -137,29 +137,7 @@
{% if perms.agenda.can_manage_agenda %}
- {% ifequal item.type 'ItemApplication' %}
- {% trans "Application" %} {{ item.cast.application.number }}
- {% endifequal %}
-
- {% ifequal item.type 'ItemPoll' %}
- {% if item.cast.poll.application %}
- {% trans "Poll of Application" %}
- {% endif %}
- {% if item.cast.poll.assignment %}
- {% trans "Poll of Election" %}
- {% endif %}
- {% endifequal %}
-
- {% ifequal item.type 'ItemAssignment' %}
- {% trans "Election" %}
- {% endifequal %}
-
- {% ifequal item.type 'ItemText' %}
- Text
- {% endifequal %}
- {% if item.hidden %}
- ({% trans 'hidden' %})
- {% endif %}
+ Text
|
{% endif %}
diff --git a/openslides/application/models.py b/openslides/application/models.py
index cf09f713e..c2b07c2c2 100644
--- a/openslides/application/models.py
+++ b/openslides/application/models.py
@@ -23,6 +23,8 @@ from projector.models import Slide
from participant.models import Profile
from system.api import config_get
from utils.utils import _propper_unicode
+from poll import ChoicePoll
+from poll.models import BaseOption, BasePoll
class Application(models.Model, Slide):
@@ -410,24 +412,28 @@ class Application(models.Model, Slide):
"""
Generates a poll object for the application
"""
- from poll.models import Poll
- poll = Poll(optiondecision=True, \
- application=self)
+ poll = ApplicationPoll()
poll.save()
- poll.add_option(self)
+ poll.set_options([{'application': self}])
self.writelog(_("Poll created"), user)
return poll
+ @property
+ def polls(self):
+ #todo: return an query_set
+ return [option.poll for option in self.applicationoption_set.all()]
+
@property
def results(self):
"""
Return a list of voting results
"""
+ # TODO: This will propably not work
results = []
- for poll in self.poll_set.all():
- for option in poll.options:
- if poll.votesinvalid != None and poll.votescast != None:
- results.append([option.yes, option.no, option.undesided, poll.votesinvalidf, poll.votescastf])
+ for poll in self.polls:
+ for option in poll.get_options():
+ #if poll.votesinvalid != None and poll.votescast != None:
+ results.append([option.yes, option.no, option.undesided, poll.votesinvalidf, poll.votescastf])
return results
def slide(self):
@@ -484,3 +490,14 @@ class AVersion(models.Model):
return self._aid
register_slidemodel(Application)
+
+
+class ApplicationOption(BaseOption):
+ application = models.ForeignKey(Application)
+
+ def __unicode__(self):
+ return unicode(self.application)
+
+
+class ApplicationPoll(BasePoll):
+ option_class = ApplicationOption
diff --git a/openslides/application/templates/application/poll_view.html b/openslides/application/templates/application/poll_view.html
index ab83ab86c..a2ba6ac2b 100644
--- a/openslides/application/templates/application/poll_view.html
+++ b/openslides/application/templates/application/poll_view.html
@@ -6,60 +6,45 @@
{% if perms.application.can_manage_application %}
{% block submenu %}
-{{ block.super }}
-
-{%trans "Application No." %} {{ poll.application.number }}
-
+ {{ block.super }}
+
+ {%trans "Application No." %} {{ poll.application.number }}
+
{% endblock %}
{% endif %}
{% block content %}
- {%trans "Application No." %} {{ poll.application.number }} - {%trans "Vote" %}
- {{ poll.application.title }}
+ {%trans "Application No." %} {{ application.number }} - {%trans "Vote" %}
+ {{ application.title }}
{%trans "Results of" %} {{ ballot }}. {%trans "Vote" %}
-1 := {% trans 'majority' %}, -2 := {% trans 'undocumented' %}
{% endblock %}
diff --git a/openslides/application/templates/application/view.html b/openslides/application/templates/application/view.html
index f8b40b979..4fedb25b4 100644
--- a/openslides/application/templates/application/view.html
+++ b/openslides/application/templates/application/view.html
@@ -47,7 +47,7 @@
{% endfor %}
{% trans "Vote results" %}:
- {% with application.poll_set.all as polls %}
+ {% with application.polls as polls %}
{% if polls|length == 0 %}
{% if perms.application.can_manage_application %}
{% if "genpoll" in actions %}
diff --git a/openslides/application/urls.py b/openslides/application/urls.py
index d87e8474f..64f1fb3d2 100644
--- a/openslides/application/urls.py
+++ b/openslides/application/urls.py
@@ -11,6 +11,10 @@
"""
from django.conf.urls.defaults import *
+from django.utils.translation import ugettext as _
+
+from application.views import ViewPoll
+
urlpatterns = patterns('application.views',
url(r'^application/$', 'overview', \
@@ -77,8 +81,10 @@ urlpatterns = patterns('application.views',
url(r'^application/poll/(?P\d+)/print$', 'print_application_poll', \
name='print_application_poll'),
- url(r'^application/poll/(?P\d+)$', 'view_poll', \
- name='application_poll_view'),
+ url(r'^application/poll/(?P\d+)$',
+ ViewPoll.as_view(),
+ name='application_poll_view'
+ ),
url(r'^application/poll/(?P\d+)/del$', 'delete_poll', \
name='application_poll_delete'),
diff --git a/openslides/application/views.py b/openslides/application/views.py
index c0f98b0a6..52c2868de 100644
--- a/openslides/application/views.py
+++ b/openslides/application/views.py
@@ -23,14 +23,15 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.db import transaction
-from openslides.agenda.models import Item
-from openslides.application.models import Application, AVersion
-from openslides.application.forms import ApplicationForm, \
+from agenda.models import Item
+from application.models import Application, AVersion, ApplicationPoll
+from application.forms import ApplicationForm, \
ApplicationManagerForm, \
ApplicationImportForm
from openslides.participant.models import Profile
-from openslides.poll.models import Poll
-from openslides.poll.forms import OptionResultForm, PollForm
+
+from poll.models import PollFormView
+
from openslides.utils.utils import template, permission_required, \
render_to_forbitten, del_confirm_form, gen_confirm_form
from openslides.utils.pdf import print_application, print_application_poll
@@ -92,7 +93,7 @@ def view(request, application_id, newest=False):
'actions': actions,
'min_supporters': int(config_get('application_min_supporters')),
'version': version,
- 'results': application.results
+ #'results': application.results
}
@@ -347,7 +348,7 @@ def gen_poll(request, application_id):
poll = Application.objects.get(pk=application_id).gen_poll(user=request.user)
messages.success(request, _("New vote was successfully created.") )
except Application.DoesNotExist:
- pass
+ pass # TODO: do not call poll after this excaption
return redirect(reverse('application_poll_view', args=[poll.id]))
@@ -373,9 +374,9 @@ 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
+ poll = ApplicationPoll.objects.get(pk=poll_id)
+ #ballot = poll.ballot
+ options = poll.get_options()
if request.user.has_perm('application.can_manage_application'):
if request.method == 'POST':
form = PollForm(request.POST, prefix="poll")
@@ -408,9 +409,27 @@ def view_poll(request, poll_id):
'poll': poll,
'form': form,
'options': options,
- 'ballot': ballot,
+ #'ballot': ballot,
}
+
+class ViewPoll(PollFormView):
+ poll_class = ApplicationPoll
+ vote_values = [_('yes'), _('no'), _('contained')]
+ template_name = 'application/poll_view.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(ViewPoll, self).get_context_data()
+ self.application = self.poll.get_options()[0].application
+ context['application'] = self.application
+ return context
+
+ def get_success_url(self):
+ if not 'apply' in self.request.POST:
+ return reverse('application_view', args=[self.application.id])
+ return ''
+
+
@permission_required('application.can_manage_application')
def permit_version(request, aversion_id):
aversion = AVersion.objects.get(pk=aversion_id)
diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py
index 70e7394e7..14c32e648 100644
--- a/openslides/assignment/views.py
+++ b/openslides/assignment/views.py
@@ -17,8 +17,8 @@ from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from openslides.agenda.models import Item
-from poll.models import Poll, Option
-from poll.forms import OptionResultForm, PollForm
+#from poll.models import Poll, Option
+#from poll.forms import OptionResultForm, PollForm
from assignment.models import Assignment
from assignment.forms import AssignmentForm, AssignmentRunForm
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
diff --git a/openslides/participant/models.py b/openslides/participant/models.py
index 32c06d3a3..d1f20bfcb 100644
--- a/openslides/participant/models.py
+++ b/openslides/participant/models.py
@@ -52,3 +52,4 @@ class Profile(models.Model):
('can_see_participant', "Can see participant"),
('can_manage_participant', "Can manage participant"),
)
+
diff --git a/openslides/poll/__init__.py b/openslides/poll/__init__.py
index e69de29bb..53035f305 100644
--- a/openslides/poll/__init__.py
+++ b/openslides/poll/__init__.py
@@ -0,0 +1,12 @@
+from django.utils.translation import ugettext as _
+
+from models import PollFormView, BasePoll
+
+
+class DesicionPoll(PollFormView):
+ vote_values = [_('yes'), _('no'), _('contained')]
+ poll_class = BasePoll
+
+
+class ChoicePoll(PollFormView):
+ poll_class = BasePoll
diff --git a/openslides/poll/models.py b/openslides/poll/models.py
index 0f03c8e86..0ba4b299f 100644
--- a/openslides/poll/models.py
+++ b/openslides/poll/models.py
@@ -12,185 +12,142 @@
from django.db import models
from django.utils.translation import ugettext as _
-
-from application.models import Application
-from assignment.models import Assignment
-from participant.models import Profile
+from django import forms
+from django.views.generic import TemplateView
+from django.http import HttpResponseRedirect
-class Poll(models.Model):
- 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"))
+class OptionForm(forms.Form):
+ def __init__(self, *args, **kwargs):
+ extra = kwargs.pop('extra')
+ formid = kwargs.pop('formid')
+ kwargs['prefix'] = "option-%s" % formid
+ super(OptionForm, self).__init__(*args, **kwargs)
+
+ for key, value in extra:
+ self.fields[key] = forms.IntegerField(
+ widget=forms.TextInput(attrs={'class': 'small-input'}),
+ label=_(key),
+ initial=value,
+ )
+
+class BaseOption(models.Model):
+ poll = models.ForeignKey('BasePoll')
+
+ @property
+ def votes(self):
+ count = 0
+ for vote in Vote.objects.filter(option=self):
+ count += vote.weight
+ return weight
+
+
+class TextOption(BaseOption):
+ text = models.CharField(max_length=255)
+
+ def __unicode__(self):
+ return self.text
+
+
+class Vote(models.Model):
+ option = models.ForeignKey(BaseOption)
+ #profile = models.ForeignKey(Profile) # TODO: we need a person+ here
+ weight = models.IntegerField(default=1)
+ value = models.CharField(max_length=255, null=True)
+
+
+class BasePoll(models.Model):
description = models.TextField(null=True, blank=True, verbose_name = _("Description"))
votescast = models.IntegerField(null=True, blank=True, verbose_name = _("Votes cast"))
votesinvalid = models.IntegerField(null=True, blank=True, verbose_name = _("Votes invalid"))
- published = models.BooleanField(default=False)
- def add_option(self, option):
- self.save()
- optionc = Option()
- optionc.poll = self
- if isinstance(option, Application):
- optionc.application = option
- elif isinstance(option, Profile):
- optionc.user = option
- else:
- optionc.text = str(option)
- optionc.save()
- return optionc
+ option_class = TextOption
+ vote_values = [_('votes')]
- @property
- def votescastf(self):
- if self.votescast == -2:
- return _('undocumented')
- elif self.votescast:
- return self.votescast
- return '0'
-
- @property
- def votesinvalidf(self):
- if self.votesinvalid == -2:
- return _('undocumented')
- elif self.votesinvalid:
- if self.votescast > 0:
- percentage = round(float(self.votesinvalid) / float(self.votescast) * 100,1)
- invalid = "%s (%s %%)" % (str(self.votesinvalid), str(percentage))
- return invalid
- return self.votesinvalid
- return '0'
-
- def has_vote(self):
- for option in self.options:
- if option.voteyes or option.voteno or option.voteundesided:
- return True
- return False
+ def set_options(self, options_data):
+ for option_data in options_data:
+ option = self.option_class(**option_data)
+ option.poll = self
+ option.save()
def get_options(self):
- return self.option_set.all()
+ return self.get_option_class().objects.filter(poll=self)
- @property
- def options(self):
- return self.option_set.all()
+ def get_option_class(self):
+ return self.option_class
- @property
- def options_values(self):
- return [option.value for option in self.options]
+ def get_vote_values(self):
+ return self.vote_values
- def set_published(self, published=True):
- """
- Changes the published-status of the poll.
- """
- self.published = published
- self.save()
-
- @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:
- if link == 'view':
- return ('application_poll_view', [str(self.id), 0])
- if link == 'delete':
- return ('application_poll_delete', [str(self.id)])
- if self.assignment:
- if link == 'view':
- return ('assignment_poll_view', [str(self.id), 0])
- if link == 'delete':
- return ('assignment_poll_delete', [str(self.id)])
- if link == 'view':
- return ('poll_view', [str(self.id)])
- if link == 'delete':
- return ('poll_delete', [str(self.id)])
-
- def __unicode__(self):
- if self.application:
- return self.application.title
- if self.assignment:
- return self.assignment.name
+ def set_form_values(self, option, data):
+ for value in self.get_vote_values():
+ try:
+ vote = Vote.objects.filter(option=option).get(value=value)
+ except Vote.DoesNotExist:
+ vote = Vote(option=option, value=value)
+ vote.weight = data[value]
+ vote.save()
-class Option(models.Model):
- text = models.CharField(max_length=100, null=True, blank=True, verbose_name = _("Text"))
- user = models.ForeignKey(Profile, null=True, blank=True, verbose_name = _("Participant"))
- application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application"))
- poll = models.ForeignKey(Poll, verbose_name = _("Poll"))
- voteyes = models.IntegerField(null=True, blank=True)
- voteno = models.IntegerField(null=True, blank=True)
- voteundesided = models.IntegerField(null=True, blank=True)
+ def get_form_values(self, option_id):
+ values = []
+ for value in self.get_vote_values():
+ try:
+ vote = Vote.objects.filter(option=option_id).get(value=value)
+ weight = vote.weight
+ except Vote.DoesNotExist:
+ weight = None
+ values.append((value, weight))
+ return values
- @property
- def yes(self):
- if self.voteyes == -1:
- return _('majority')
- if self.voteyes == -2:
- return _('undocumented')
- if self.voteyes:
- if self.poll.votescast > 0 and self.voteyes > 0:
- percentage = round(float(self.voteyes) / float(self.poll.votescast) * 100,1)
- return "%s (%s %%)" % (str(self.voteyes), str(percentage))
- return self.voteyes
- return '0'
+ def get_vote_form(self, **kwargs):
+ return OptionForm(extra=self.get_form_values(kwargs['formid']), **kwargs)
- @property
- def no(self):
- if self.voteno == -1:
- return _('majority')
- if self.voteno == -2:
- return _('undocumented')
- if self.voteno:
- if self.poll.votescast > 0 and self.voteno > 0:
- percentage = round(float(self.voteno) / float(self.poll.votescast) * 100,1)
- return "%s (%s %%)" % (str(self.voteno), str(percentage))
- return self.voteno
- return '0'
+ def get_vote_forms(self, **kwargs):
+ forms = []
+ for option in self.get_options():
+ form = self.get_vote_form(formid=option.id, **kwargs)
+ form.option = option
+ forms.append(form)
- @property
- def undesided(self):
- if self.voteundesided == -1:
- return _('majority')
- if self.voteundesided == -2:
- return _('undocumented')
- if self.voteundesided:
- if self.poll.votescast > 0 and self.voteundesided > 0:
- percentage = round(float(self.voteundesided) / float(self.poll.votescast) * 100,1)
- return "%s (%s %%)" % (str(self.voteundesided), str(percentage))
- return self.voteundesided
- return '0'
+ return forms
- @property
- def value(self):
- if self.text != "" and self.text is not None:
- return self.text
- if self.user is not None:
- return self.user
- if self.application is not None:
- return self.application
- return None
- def __unicode__(self):
- if self.value:
- return unicode(self.value)
- return _("No options")
+class PollFormView(TemplateView):
+ template_name = 'poll/poll.html'
+ poll_argument = 'poll_id'
+
+ def set_poll(self, poll_id):
+ poll_id = poll_id
+ self.poll = self.poll_class.objects.get(pk=poll_id)
+ self.poll.vote_values = self.vote_values
+
+ def get_context_data(self, **kwargs):
+ context = super(PollFormView, self).get_context_data(**kwargs)
+ self.set_poll(self.kwargs['poll_id'])
+ context['poll'] = self.poll
+ if not 'forms' in context:
+ context['forms'] = context['poll'].get_vote_forms()
+ return context
+
+ def get_success_url(self):
+ return self.success_url
+
+ def post(self, request, *args, **kwargs):
+ context = self.get_context_data(**kwargs)
+ forms = self.poll.get_vote_forms(data=self.request.POST)
+ error = False
+ for form in forms:
+ if not form.is_valid():
+ error = True
+ if error:
+ return self.render_to_response(self.get_context_data(forms=forms))
+
+ for form in forms:
+ data = {}
+ for value in self.poll.vote_values:
+ data[value] = form.cleaned_data[value]
+ print data
+ self.poll.set_form_values(form.option, data)
+ return HttpResponseRedirect(self.get_success_url())
+
diff --git a/openslides/utils/pdf.py b/openslides/utils/pdf.py
index 4a1c1b6cd..86e093a5e 100755
--- a/openslides/utils/pdf.py
+++ b/openslides/utils/pdf.py
@@ -36,7 +36,7 @@ from openslides.agenda.models import Item
from openslides.agenda.api import children_list
from openslides.application.models import Application
from openslides.assignment.models import Assignment
-from openslides.poll.models import Poll, Option
+#from openslides.poll.models import Poll, Option
from openslides.participant.models import Profile
from openslides.system.api import config_get
from openslides.settings import SITE_ROOT
@@ -343,7 +343,7 @@ def get_application(application, story):
else:
story.append(Paragraph(_("Application No."), stylesheet['Heading1']))
-
+
# submitter
cell1a = []
cell1a.append(Spacer(0,0.2*cm))
@@ -357,7 +357,7 @@ def get_application(application, story):
cell1b.append(Spacer(0,0.2*cm))
else:
cell1b.append(Paragraph(unicode(application.submitter.profile), stylesheet['Normal']))
-
+
# supporters
cell2a = []
cell2a.append(Paragraph("%s:" % _("Supporters"), stylesheet['Heading4']))
@@ -368,7 +368,7 @@ def get_application(application, story):
for x in range(0,application.missing_supporters):
cell2b.append(Paragraph(". __________________________________________",stylesheet['Signaturefield']))
cell2b.append(Spacer(0,0.2*cm))
-
+
# status
note = ""
for n in application.notes:
@@ -389,7 +389,7 @@ def get_application(application, story):
data.append([cell1a,cell1b])
data.append([cell2a,cell2b])
data.append([cell3a,cell3b])
-
+
# voting results
if len(application.results) > 0:
cell4a = []
@@ -412,7 +412,7 @@ def get_application(application, story):
]))
story.append(t)
story.append(Spacer(0,1*cm))
-
+
# title
story.append(Paragraph(application.title, stylesheet['Heading3']))
# text
@@ -431,7 +431,7 @@ def print_application(request, application_id=None):
doc = SimpleDocTemplate(response)
doc.title = None
story = []
-
+
if application_id is None: #print all applications
title = config_get("application_pdf_title")
story.append(Paragraph(title, stylesheet['Heading1']))
@@ -614,7 +614,7 @@ def get_assignment(assignment, story):
('LINEBELOW',(0,-1),(-1,-1),2,colors.black),
('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9))),
]))
-
+
# table
data = []
data.append([cell1a,cell1b])
@@ -635,7 +635,7 @@ def get_assignment(assignment, story):
# text
story.append(Paragraph("%s" % assignment.description.replace('\r\n',' '), stylesheet['Paragraph']))
return story
-
+
@permission_required('application.can_see_application')
def print_assignment(request, assignment_id=None):
response = HttpResponse(mimetype='application/pdf')
@@ -644,7 +644,7 @@ def print_assignment(request, assignment_id=None):
doc = SimpleDocTemplate(response)
doc.title = None
story = []
-
+
if assignment_id is None: #print all applications
title = config_get("assignment_pdf_title")
story.append(Paragraph(title, stylesheet['Heading1']))
@@ -667,7 +667,7 @@ def print_assignment(request, assignment_id=None):
doc.build(story, onFirstPage=firstPage, onLaterPages=firstPage)
return response
-
+
@permission_required('application.can_manage_application')
def print_assignment_poll(request, poll_id=None):
poll = Poll.objects.get(id=poll_id)
@@ -714,7 +714,7 @@ def print_assignment_poll(request, poll_id=None):
rest = number % 2
if rest:
data.append([cell,''])
-
+
if len(options) <= 2:
t=Table(data, 10.5*cm, 7.42*cm)
elif len(options) <= 5:
@@ -742,7 +742,7 @@ def print_assignment_poll(request, poll_id=None):
rest = number % 2
if rest:
data.append([cell,''])
-
+
if len(options) <= 4:
t=Table(data, 10.5*cm, 7.42*cm)
elif len(options) <= 8:
|