diff --git a/openslides/motion/__init__.py b/openslides/motion/__init__.py
index ea23517a7..e296be3ce 100644
--- a/openslides/motion/__init__.py
+++ b/openslides/motion/__init__.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.motion
diff --git a/openslides/motion/models.py b/openslides/motion/models.py
index 023326f2a..0e61d9b09 100644
--- a/openslides/motion/models.py
+++ b/openslides/motion/models.py
@@ -16,7 +16,7 @@
from datetime import datetime
from django.core.urlresolvers import reverse
-from django.db import models
+from django.db import models, IntegrityError
from django.db.models import Max
from django.dispatch import receiver
from django.utils import formats
@@ -65,6 +65,12 @@ class Motion(SlideMixin, models.Model):
unique=True)
"""A string as human readable identifier for the motion."""
+ identifier_number = models.IntegerField(null=True)
+ """Counts the number of the motion in one category.
+
+ Needed to find the next free motion-identifier.
+ """
+
category = models.ForeignKey('Category', null=True, blank=True)
"""ForeignKey to one category of motions."""
@@ -170,6 +176,29 @@ class Motion(SlideMixin, models.Model):
if link == 'delete':
return reverse('motion_delete', args=[str(self.id)])
+ def set_identifier(self):
+ # TODO: into the config-tab
+ config['motion_identifier'] = ('manuell', 'category', 'all')[0]
+
+ number = Motion.objects.all().aggregate(Max('identifier_number'))['identifier_number__max'] or 0
+ if self.category is not None:
+ prefix = self.category.prefix + ' '
+ else:
+ prefix = ''
+
+ while True:
+ number += 1
+ self.identifier = '%s%d' % (prefix, number)
+ try:
+ self.save()
+ except IntegrityError:
+ continue
+ else:
+ self.number = number
+ self.save()
+ break
+
+
def get_title(self):
"""Get the title of the motion.
@@ -346,6 +375,18 @@ class Motion(SlideMixin, models.Model):
else:
raise WorkflowError('You can not create a poll in state %s.' % self.state.name)
+ def set_state(self, state):
+ """Set the state of the motion.
+
+ State can be the id of a state object or a state object.
+ """
+ if type(state) is int:
+ state = State.objects.get(pk=state)
+
+ if state.set_identifier:
+ self.set_identifier()
+ self.state = state
+
def reset_state(self):
"""Set the state to the default state. If the motion is new, it chooses the default workflow from config."""
if self.state:
@@ -692,6 +733,9 @@ class State(models.Model):
dont_set_new_version_active = models.BooleanField(default=False)
"""If true, new versions are not automaticly set active."""
+ set_identifier = models.BooleanField(default=False)
+ """If true, the motion get a identifier if the state change to this one."""
+
def __unicode__(self):
"""Returns the name of the state."""
return self.name
diff --git a/openslides/motion/templates/motion/motion_detail.html b/openslides/motion/templates/motion/motion_detail.html
index a9de961b6..c9a8b63aa 100644
--- a/openslides/motion/templates/motion/motion_detail.html
+++ b/openslides/motion/templates/motion/motion_detail.html
@@ -11,8 +11,8 @@
{{ motion.title }}
- {% if motion.number != None %}
- {% trans "Motion" %} {{ motion.number }},
+ {% if motion.identifier != None %}
+ {% trans "Motion" %} {{ motion.identifier }},
{% else %}
[{% trans "no number" %}],
{% endif %}
diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py
index 1fd507ad1..577073c38 100644
--- a/openslides/motion/urls.py
+++ b/openslides/motion/urls.py
@@ -40,6 +40,11 @@ urlpatterns = patterns('openslides.motion.views',
name='motion_delete',
),
+ url(r'^(?P\d+)/set_identifier',
+ 'set_identifier',
+ name='motion_set_identifier',
+ ),
+
url(r'^(?P\d+)/version/(?P\d+)/$',
'motion_detail',
name='motion_version_detail',
diff --git a/openslides/motion/views.py b/openslides/motion/views.py
index d7a760855..6d4d40cc8 100644
--- a/openslides/motion/views.py
+++ b/openslides/motion/views.py
@@ -230,6 +230,30 @@ class VersionRejectView(GetVersionMixin, SingleObjectMixin, QuestionMixin, Redir
version_reject = VersionRejectView.as_view()
+class SetIdentifierView(SingleObjectMixin, RedirectView):
+ """Set the identifier of the motion.
+
+ See motion.set_identifier for more informations
+ """
+ permission_required = 'motion.can_manage_motion'
+ model = Motion
+ url_name = 'motion_detail'
+
+ def get(self, request, *args, **kwargs):
+ """Set self.object to a motion."""
+ self.object = self.get_object()
+ return super(SetIdentifierView, self).get(request, *args, **kwargs)
+
+ def pre_redirect(self, request, *args, **kwargs):
+ """Set the identifier."""
+ self.object.set_identifier()
+
+ def get_url_name_args(self):
+ return [self.object.id]
+
+set_identifier = SetIdentifierView.as_view()
+
+
class SupportView(SingleObjectMixin, QuestionMixin, RedirectView):
"""View to support or unsupport a motion.
@@ -401,7 +425,7 @@ class MotionSetStateView(SingleObjectMixin, RedirectView):
if self.reset:
self.object.reset_state()
else:
- self.object.state = State.objects.get(pk=kwargs['state'])
+ self.object.set_state(int(kwargs['state']))
except WorkflowError, e: # TODO: Is a WorkflowError still possible here?
messages.error(request, e)
else: