diff --git a/openslides/motion/models.py b/openslides/motion/models.py
index 510d481ac..0be499419 100644
--- a/openslides/motion/models.py
+++ b/openslides/motion/models.py
@@ -267,6 +267,13 @@ class Motion(SlideMixin, models.Model):
#else:
#self.writelog(_("Supporter: -%s") % (person))
+ def create_poll(self):
+ # TODO: auto increment the poll_number in the Database
+ poll_number = self.polls.aggregate(Max('poll_number'))['poll_number__max'] or 0
+ poll = MotionPoll.objects.create(motion=self, poll_number=poll_number + 1)
+ poll.set_options()
+ return poll
+
class MotionVersion(models.Model):
title = models.CharField(max_length=255, verbose_name=ugettext_lazy("Title"))
@@ -307,3 +314,42 @@ class Comment(models.Model):
text = models.TextField()
author = PersonField()
creation_time = models.DateTimeField(auto_now=True)
+
+
+class MotionVote(BaseVote):
+ option = models.ForeignKey('MotionOption')
+
+
+class MotionOption(BaseOption):
+ poll = models.ForeignKey('MotionPoll')
+ vote_class = MotionVote
+
+
+class MotionPoll(CountInvalid, CountVotesCast, BasePoll):
+ option_class = MotionOption
+ vote_values = [
+ ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')]
+
+ motion = models.ForeignKey(Motion, related_name='polls')
+ poll_number = models.PositiveIntegerField(default=1)
+
+ class Meta:
+ unique_together = ("motion", "poll_number")
+
+ def get_absolute_url(self, link='edit'):
+ return reverse('motion_poll_edit', args=[str(self.motion.pk),
+ str(self.poll_number)])
+
+ def get_motion(self):
+ return self.motion
+
+ def set_options(self):
+ #TODO: maybe it is possible with .create() to call this without poll=self
+ self.get_option_class()(poll=self).save()
+
+ def append_pollform_fields(self, fields):
+ CountInvalid.append_pollform_fields(self, fields)
+ CountVotesCast.append_pollform_fields(self, fields)
+
+ def get_ballot(self):
+ return self.motion.motionpoll_set.filter(id__lte=self.id).count()
diff --git a/openslides/motion/templates/motion/motion_detail.html b/openslides/motion/templates/motion/motion_detail.html
index fd5880ada..86c27502e 100644
--- a/openslides/motion/templates/motion/motion_detail.html
+++ b/openslides/motion/templates/motion/motion_detail.html
@@ -22,4 +22,64 @@
{% endif %}
{% endfor %}
+
+
+
{% trans "Vote results" %}:
+ {% with motion.polls.all as polls %}
+ {% if not polls.exists %}
+ {% if perms.motion.can_manage_motion %}
+
+
+ {% trans 'New vote' %}
+
+
+ {% else %}
+ -
+ {% endif %}
+ {% endif %}
+
+ {% endwith %}
{% endblock %}
diff --git a/openslides/motion/templates/motion/poll_form.html b/openslides/motion/templates/motion/poll_form.html
new file mode 100644
index 000000000..f7cd3635a
--- /dev/null
+++ b/openslides/motion/templates/motion/poll_form.html
@@ -0,0 +1,48 @@
+{% extends 'base.html' %}
+
+{% load i18n %}
+{% load staticfiles %}
+{% load tags %}
+
+{% block content %}
+ {{ motion }}
+ {% trans "Special values" %}: -1 = {% trans 'majority' %}; -2 = {% trans 'undocumented' %}
+
+{% endblock %}
diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py
index ebc1c2155..bdd7575a6 100644
--- a/openslides/motion/urls.py
+++ b/openslides/motion/urls.py
@@ -47,4 +47,19 @@ urlpatterns = patterns('openslides.motion.views',
'motion_unsupport',
name='motion_unsupport',
),
+
+ url(r'^(?P\d+)/create_poll/$',
+ 'poll_create',
+ name='motion_poll_create',
+ ),
+
+ url(r'^(?P\d+)/poll/(?P\d+)/edit$',
+ 'poll_edit',
+ name='motion_poll_edit',
+ ),
+
+ ## url(r'^poll/(?P\d+)/del/$',
+ ## 'delete_poll',
+ ## name='motion_poll_delete',
+ ## ),
)
diff --git a/openslides/motion/views.py b/openslides/motion/views.py
index 4875dae36..c0cada64d 100644
--- a/openslides/motion/views.py
+++ b/openslides/motion/views.py
@@ -22,13 +22,14 @@ from django.http import Http404
from openslides.utils.pdf import stylesheet
from openslides.utils.views import (
TemplateView, RedirectView, UpdateView, CreateView, DeleteView, PDFView,
- DetailView, ListView, FormView, QuestionMixin)
+ DetailView, ListView, FormView, QuestionMixin, SingleObjectMixin)
from openslides.utils.template import Tab
from openslides.utils.utils import html_strong
+from openslides.poll.views import PollFormView
from openslides.projector.api import get_active_slide
from openslides.projector.projector import Widget, SLIDE
from openslides.config.models import config
-from .models import Motion, MotionSubmitter, MotionSupporter
+from .models import Motion, MotionSubmitter, MotionSupporter, MotionPoll
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
MotionCreateNewVersionMixin, ConfigForm)
@@ -81,14 +82,16 @@ class MotionMixin(object):
def post_save(self, form):
super(MotionMixin, self).post_save(form)
# TODO: only delete and save neccessary submitters and supporter
- self.object.submitter.all().delete()
- self.object.supporter.all().delete()
- MotionSubmitter.objects.bulk_create(
- [MotionSubmitter(motion=self.object, person=person)
- for person in form.cleaned_data['submitter']])
- MotionSupporter.objects.bulk_create(
- [MotionSupporter(motion=self.object, person=person)
- for person in form.cleaned_data['supporter']])
+ if 'submitter' in form.cleaned_data:
+ self.object.submitter.all().delete()
+ MotionSubmitter.objects.bulk_create(
+ [MotionSubmitter(motion=self.object, person=person)
+ for person in form.cleaned_data['submitter']])
+ if 'supporter' in form.cleaned_data:
+ self.object.supporter.all().delete()
+ MotionSupporter.objects.bulk_create(
+ [MotionSupporter(motion=self.object, person=person)
+ for person in form.cleaned_data['supporter']])
def get_form_class(self):
form_classes = [BaseMotionForm]
@@ -180,6 +183,47 @@ motion_support = SupportView.as_view(support=True)
motion_unsupport = SupportView.as_view(support=False)
+class PollCreateView(SingleObjectMixin, RedirectView):
+ permission_required = 'motion.can_manage_motion'
+ model = Motion
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ return super(PollCreateView, self).get(request, *args, **kwargs)
+
+ def pre_redirect(self, request, *args, **kwargs):
+ self.poll = self.object.create_poll()
+ messages.success(request, _("New vote was successfully created."))
+
+ def get_redirect_url(self, **kwargs):
+ return reverse('motion_poll_edit', args=[self.object.pk, self.poll.poll_number])
+
+poll_create = PollCreateView.as_view()
+
+
+class PollUpdateView(PollFormView):
+ permission_required = 'motion.can_manage_motion'
+ poll_class = MotionPoll
+ template_name = 'motion/poll_form.html'
+ success_url_name = 'motion_detail'
+
+ def get_object(self):
+ return MotionPoll.objects.filter(
+ motion=self.kwargs['pk'],
+ poll_number=self.kwargs['poll_number']).get()
+
+ def get_context_data(self, **kwargs):
+ context = super(PollUpdateView, self).get_context_data(**kwargs)
+ context.update({
+ 'motion': self.poll.motion})
+ return context
+
+ def get_url_name_args(self):
+ return [self.poll.motion.pk]
+
+poll_edit = PollUpdateView.as_view()
+
+
class Config(FormView):
permission_required = 'config.can_manage_config'
form_class = ConfigForm