2011-07-31 10:46:29 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
openslides.assignment.models
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Models for the assignment app.
|
|
|
|
|
|
|
|
:copyright: 2011 by the OpenSlides team, see AUTHORS.
|
|
|
|
:license: GNU GPL, see LICENSE for more details.
|
|
|
|
"""
|
|
|
|
|
|
|
|
from django.db import models
|
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
|
|
|
|
from participant.models import Profile
|
|
|
|
|
2012-02-06 22:22:16 +01:00
|
|
|
from projector.models import Slide
|
|
|
|
from projector.api import register_slidemodel
|
2011-07-31 10:46:29 +02:00
|
|
|
|
2012-02-03 23:12:28 +01:00
|
|
|
|
2012-02-06 22:22:16 +01:00
|
|
|
class Assignment(models.Model, Slide):
|
2012-02-03 23:12:28 +01:00
|
|
|
prefix = 'assignment'
|
2011-07-31 10:46:29 +02:00
|
|
|
STATUS = (
|
|
|
|
('sea', _('Searching for candidates')),
|
|
|
|
('vot', _('Voting')),
|
|
|
|
('fin', _('Finished')),
|
|
|
|
)
|
|
|
|
|
|
|
|
name = models.CharField(max_length=100, verbose_name = _("Name"))
|
|
|
|
description = models.TextField(null=True, blank=True, verbose_name = _("Description"))
|
2011-09-03 10:52:29 +02:00
|
|
|
posts = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts"))
|
2011-09-03 23:38:14 +02:00
|
|
|
polldescription = models.CharField(max_length=100, null=True, blank=True, verbose_name = _("Short description (for ballot paper)"))
|
2011-07-31 10:46:29 +02:00
|
|
|
profile = models.ManyToManyField(Profile, null=True, blank=True)
|
2011-09-03 11:42:44 +02:00
|
|
|
elected = models.ManyToManyField(Profile, null=True, blank=True, related_name='elected_set')
|
2011-07-31 10:46:29 +02:00
|
|
|
status = models.CharField(max_length=1, choices=STATUS, default='sea')
|
|
|
|
|
|
|
|
def set_status(self, status):
|
|
|
|
error = True
|
|
|
|
for a, b in Assignment.STATUS:
|
|
|
|
if status == a:
|
|
|
|
error = False
|
|
|
|
break
|
|
|
|
if error:
|
|
|
|
raise NameError(_('%s is not a valid status.') % status)
|
|
|
|
if self.status == status:
|
|
|
|
raise NameError(_('The assignment status is already %s.') % self.status)
|
|
|
|
self.status = status
|
|
|
|
self.save()
|
|
|
|
|
|
|
|
def run(self, profile):
|
|
|
|
"""
|
|
|
|
run for a vote
|
|
|
|
"""
|
|
|
|
if self.is_candidate(profile):
|
|
|
|
raise NameError(_('<b>%s</b> is already a candidate.') % profile)
|
|
|
|
self.profile.add(profile)
|
|
|
|
|
|
|
|
def delrun(self, profile):
|
|
|
|
"""
|
|
|
|
stop running for a vote
|
|
|
|
"""
|
|
|
|
if self.is_candidate(profile):
|
|
|
|
self.profile.remove(profile)
|
|
|
|
else:
|
|
|
|
raise NameError(_('%s is no candidate') % profile)
|
|
|
|
|
|
|
|
def is_candidate(self, profile):
|
|
|
|
if profile in self.profile.get_query_set():
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2011-09-03 11:42:44 +02:00
|
|
|
@property
|
|
|
|
def candidates(self):
|
2011-09-06 10:07:51 +02:00
|
|
|
return Profile.objects.filter(option__poll__assignment=self).order_by('user__first_name').distinct()
|
2011-09-03 11:42:44 +02:00
|
|
|
|
|
|
|
def set_elected(self, profile, value=True):
|
|
|
|
if profile in self.candidates:
|
|
|
|
if value and not self.is_elected(profile):
|
|
|
|
self.elected.add(profile)
|
|
|
|
elif not value:
|
|
|
|
self.elected.remove(profile)
|
|
|
|
|
|
|
|
def is_elected(self, profile):
|
|
|
|
if profile in self.elected.all():
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
def gen_poll(self):
|
|
|
|
from poll.models import Poll
|
|
|
|
poll = Poll()
|
2011-09-03 11:56:35 +02:00
|
|
|
|
2011-09-03 11:42:44 +02:00
|
|
|
candidates = list(self.profile.all())
|
|
|
|
for elected in self.elected.all():
|
|
|
|
try:
|
|
|
|
candidates.remove(elected)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
# Option A: candidates <= available posts -> yes/no/abstention
|
2011-09-03 11:46:22 +02:00
|
|
|
if len(candidates) <= self.posts - self.elected.count():
|
2011-07-31 10:46:29 +02:00
|
|
|
poll.optiondecision = True
|
|
|
|
else:
|
|
|
|
poll.optiondecision = False
|
2011-09-03 11:56:35 +02:00
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
# Option B: candidates == 1 -> yes/no/abstention
|
|
|
|
#if self.profile.count() == 1:
|
|
|
|
# poll.optiondecision = True
|
|
|
|
#else:
|
|
|
|
# poll.optiondecision = False
|
2011-09-03 11:56:35 +02:00
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
poll.assignment = self
|
|
|
|
poll.description = self.polldescription
|
|
|
|
poll.save()
|
2011-09-03 11:56:35 +02:00
|
|
|
for candidate in candidates:
|
2011-09-03 11:42:44 +02:00
|
|
|
poll.add_option(candidate)
|
2011-07-31 10:46:29 +02:00
|
|
|
return poll
|
|
|
|
|
2012-02-06 22:08:08 +01:00
|
|
|
def slide(self):
|
2012-02-03 23:12:28 +01:00
|
|
|
"""
|
2012-02-06 22:08:08 +01:00
|
|
|
return the slide dict
|
2012-02-03 23:12:28 +01:00
|
|
|
"""
|
2012-02-06 22:08:08 +01:00
|
|
|
data = super(Assignment, self).slide()
|
2012-02-03 23:12:28 +01:00
|
|
|
data['assignment'] = self
|
|
|
|
data['title'] = self.name
|
2012-02-06 22:08:08 +01:00
|
|
|
data['template'] = 'projector/Assignment.html'
|
2012-02-03 23:12:28 +01:00
|
|
|
return data
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
@models.permalink
|
|
|
|
def get_absolute_url(self, link='view'):
|
|
|
|
if link == 'view':
|
|
|
|
return ('assignment_view', [str(self.id)])
|
|
|
|
if link == 'delete':
|
|
|
|
return ('assignment_delete', [str(self.id)])
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
permissions = (
|
2011-09-04 12:21:58 +02:00
|
|
|
('can_see_assignment', "Can see assignment"),
|
|
|
|
('can_nominate_other', "Can nominate another person"),
|
|
|
|
('can_nominate_self', "Can nominate themselves"),
|
|
|
|
('can_manage_assignment', "Can manage assignment"),
|
2011-07-31 10:46:29 +02:00
|
|
|
)
|
2012-02-03 23:12:28 +01:00
|
|
|
|
2012-02-06 22:22:16 +01:00
|
|
|
register_slidemodel(Assignment)
|