Commit 78f2f657 authored by Thom Wiggers's avatar Thom Wiggers 📐
Browse files

Merge branch 'committees/manipulate' into 'master'

Manipulate committees

 Implements: manipulatie memberships fixen
*  if voorzitter verandert moet het een nieuw membership worden en het oude deactiveren.
 *  Verlaten van een commissie moet niet het deleten, maar het inactive maken (misschien maar gewoon met de hand doen though)



See issue #11

See merge request !4
parents e40e9753 9c7f490b
from django.utils import timezone
import logging
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
from django.contrib.auth.models import Permission
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from members.models import Member
logger = logging.getLogger(__name__)
class Committee(models.Model):
"""A committee"""
......@@ -48,7 +52,7 @@ class ActiveMembershipManager(models.Manager):
"""Get only active memberships"""
def get_queryset(self):
"""Get the currently active committee memberships"""
return super().get_queryset().exclude(until__lt=timezone.now())
return super().get_queryset().exclude(until__lt=timezone.now().date())
class CommitteeMembership(models.Model):
......@@ -87,14 +91,22 @@ class CommitteeMembership(models.Model):
default=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.pk is None:
self._was_chair = bool(self.chair)
else:
self._was_chair = False
@property
def is_active(self):
"""Is this membership currently active"""
return self.until is None or self.until > timezone.now()
return self.until is None or self.until > timezone.now().date()
def clean(self):
"""Validation"""
if self.until and self.until > timezone.now():
if self.until and self.until > timezone.now().date():
raise ValidationError({
'until': _("Membership expiration date can't be in the future:"
" '{}'").format(self.until)
......@@ -110,6 +122,7 @@ class CommitteeMembership(models.Model):
# Check if a committee has more than one chair
chairs = (CommitteeMembership.active_memberships
.filter(committee=self.committee)
.exclude(member=self.member)
.filter(chair=True)
.count())
if chairs >= 1 and self.chair:
......@@ -118,6 +131,7 @@ class CommitteeMembership(models.Model):
_('This committee already has a chair')})
# check if this member is already in the committee
if self.pk is None:
members = (self.committee.members
.filter(pk=self.member.pk)
.count())
......@@ -125,6 +139,28 @@ class CommitteeMembership(models.Model):
raise ValidationError({
'member': _('This member is already in the committee')})
def save(self, *args, **kwargs):
"""Save the instance"""
# If the chair changed and we're still active, we create a new instance
# Inactive instances should be handled manually
if (self.pk is not None and self._was_chair != self.chair and
not self.until):
logger.info("Creating new membership instance")
self.until = timezone.now().date()
super().save(*args, **kwargs)
self.pk = None # forces INSERT
self.since = self.until # Set since date to older expiration
self.until = None
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
"""Deactivates active memberships, deletes inactive ones"""
if self.is_active:
self.until = timezone.now().date()
self.save()
else:
super().delete(*args, **kwargs)
def __str__(self):
return "{} membership of {} since {}".format(self.member,
self.committee,
......
......@@ -11,15 +11,14 @@ from members.models import Member
class CommitteeMembersTest(TestCase):
fixtures = ['members.json', 'committees.json']
@classmethod
def setUpTestData(cls):
cls.testcie = Committee.objects.get(name='testcie1')
cls.testuser = Member.objects.get(pk=1)
cls.m = CommitteeMembership(committee=cls.testcie,
member=cls.testuser,
def setUp(self):
# Don't use setUpTestData because delete() will cause problems
self.testcie = Committee.objects.get(name='testcie1')
self.testuser = Member.objects.get(pk=1)
self.m = CommitteeMembership(committee=self.testcie,
member=self.testuser,
chair=False)
cls.m.save()
self.m.save()
def test_unique(self):
with self.assertRaises(IntegrityError):
......@@ -43,56 +42,80 @@ class CommitteeMembersTest(TestCase):
def test_until_date(self):
m = CommitteeMembership(committee=self.testcie,
member=self.testuser,
until=timezone.now().replace(year=2000),
until=timezone.now().date().replace(year=2000),
chair=False)
with self.assertRaises(ValidationError):
m.clean()
m.since = timezone.now().replace(year=1900)
m.since = timezone.now().date().replace(year=1900)
m.clean()
def test_inactive(self):
self.assertTrue(self.m.is_active)
self.m.until = timezone.now().replace(year=1900)
self.m.until = timezone.now().date().replace(year=1900)
self.assertFalse(self.m.is_active)
def test_delete(self):
self.m.delete()
self.assertIsNotNone(self.m.until)
self.assertIsNotNone(self.m.pk)
self.m.delete()
self.assertIsNone(self.m.pk)
class CommitteeMembersChairTest(TestCase):
fixtures = ['members.json', 'committees.json']
@classmethod
def setUpTestData(cls):
testcie = Committee.objects.get(name='testcie1')
testuser = Member.objects.get(pk=1)
cls.m1 = CommitteeMembership(committee=testcie,
member=testuser,
chair=True)
cls.m1.full_clean()
cls.m1.save()
def setUp(self):
self.testcie = Committee.objects.get(name='testcie1')
self.testuser = Member.objects.get(pk=1)
self.testuser2 = Member.objects.get(pk=2)
self.m1 = CommitteeMembership(committee=self.testcie,
member=self.testuser,
chair=True)
self.m1.full_clean()
self.m1.save()
def test_second_chair_fails(self):
testuser2 = Member.objects.get(pk=2)
m = CommitteeMembership(committee=self.testcie,
member=testuser2,
member=self.testuser2,
chair=True)
with self.assertRaises(ValidationError):
m.full_clean()
def test_inactive_chair(self):
testuser2 = Member.objects.get(pk=2)
self.m1.until = timezone.now().replace(year=1900)
self.m1.until = timezone.now().date().replace(year=1900)
self.m1.save()
m = CommitteeMembership(committee=self.testcie,
member=testuser2,
member=self.testuser2,
chair=True)
m.full_clean()
def test_clean_self_chair(self):
self.m1.chair = True
self.m1.full_clean()
def test_change_chair(self):
pk = self.m1.pk
original_chair = self.m1.chair
self.m1.save()
self.assertEqual(self.m1.pk, pk, "new object created")
self.m1.chair = not original_chair
self.m1.save()
self.assertNotEqual(self.m1.pk, pk, "No new object created")
def test_change_chair_inactive(self):
pk = self.m1.pk
original_chair = self.m1.chair
self.m1.until = timezone.now().date()
self.m1.save()
self.assertEqual(self.m1.pk, pk, "new object created")
self.m1.chair = not original_chair
self.m1.save()
self.assertEqual(self.m1.pk, pk, "No new object created")
class BackendTest(TestCase):
class PermissionsBackendTest(TestCase):
fixtures = ['members.json', 'committees.json']
@classmethod
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment