Unverified Commit 6e1495a7 authored by Joost Rijneveld's avatar Joost Rijneveld
Browse files

Allow for storage of membership history

parent 60b10f8f
......@@ -4,22 +4,50 @@ This module registers admin pages for the models
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from . import models
class MembershipInline(admin.StackedInline):
model = models.Membership
extra = 0
class MemberInline(admin.StackedInline):
model = models.Member
can_delete = False
class MembershipTypeListFilter(admin.SimpleListFilter):
title = _('membership type')
parameter_name = 'membership'
def lookups(self, request, model_admin):
return models.Membership.MEMBERSHIP_TYPES
def queryset(self, request, queryset):
if not self.value():
return queryset
queryset.prefetch_related('user__memberships')
users = set()
for user in queryset:
try:
if user.member.current_membership:
if user.member.current_membership.type == self.value():
users.add(user.pk)
except models.Member.DoesNotExist:
# The superuser does not have a .member object attached.
pass
return queryset.filter(pk__in=users)
class UserAdmin(BaseUserAdmin):
inlines = (MemberInline,)
inlines = (MemberInline, MembershipInline)
# FIXME include proper filter for expiration
# https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
list_filter = ('member__type',
'member__membership_expiration',
'is_superuser')
list_filter = (MembershipTypeListFilter,
'is_superuser',)
# FIXME use nicer form
# form = forms.AdminForm (base on ModelForm, reorder elements, etc).
......
......@@ -60,9 +60,6 @@
"user": 1,
"programme": null,
"student_number": "",
"type": "member",
"registration_year": 2011,
"membership_expiration": null,
"address_street": "Heyendaalseweg 135",
"address_street2": "",
"address_postal_code": "1245 TG",
......@@ -89,9 +86,6 @@
"user": 2,
"programme": null,
"student_number": "",
"type": "member",
"registration_year": 2011,
"membership_expiration": null,
"address_street": "testuserv 2",
"address_street2": "",
"address_postal_code": "2545 TG",
......@@ -118,9 +112,6 @@
"user": 3,
"programme": null,
"student_number": "",
"type": "member",
"registration_year": 1999,
"membership_expiration": null,
"address_street": "testuser 2",
"address_street2": "",
"address_postal_code": "6525 TE",
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-05 12:35
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('members', '0003_merge_20160727_2333'),
]
operations = [
migrations.CreateModel(
name='Membership',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[('member', 'Member'), ('supporter', 'Supporter'), ('honorary', 'Honorary Member')], max_length=40, verbose_name='Membership type')),
('since', models.DateField(default=django.utils.timezone.now, help_text='The date the member started holding this membership.', verbose_name='Membership since')),
('until', models.DateField(blank=True, help_text='The date the member stops holding this membership.', null=True, verbose_name='Membership until')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
),
migrations.RemoveField(
model_name='member',
name='membership_expiration',
),
migrations.RemoveField(
model_name='member',
name='registration_year',
),
migrations.RemoveField(
model_name='member',
name='type',
),
migrations.AddField(
model_name='member',
name='starting_year',
field=models.IntegerField(blank=True, help_text='The year this member started studying.', null=True, verbose_name='Starting year'),
),
]
......@@ -14,11 +14,6 @@ class Member(models.Model):
"""This class describes a member"""
# No longer yearly membership as a type, use expiration date instead.
MEMBERSHIP_TYPES = (
('benefactor', _('Benefactor')),
('member', _('Member')),
('honorary', _('Honorary Member')))
PROGRAMME_CHOICES = (
('computingscience', _('Computing Science')),
('informationscience', _('Information Sciences')))
......@@ -47,23 +42,39 @@ class Member(models.Model):
null=True,
)
type = models.CharField(
max_length=40,
choices=MEMBERSHIP_TYPES,
verbose_name=_('Membership type'),
starting_year = models.IntegerField(
verbose_name=_('Starting year'),
help_text=_('The year this member started studying.'),
blank=True,
null=True,
)
registration_year = models.IntegerField(
verbose_name=_('Registration year'),
help_text=_('The year this member first became a part of Thalia'),
)
@property
def current_membership(self):
membership = self.latest_membership
if membership and not membership.is_active():
return None
return membership
membership_expiration = models.DateField(
verbose_name=_('Expiration date of membership'),
help_text=_('Let the membership expire after this time'),
null=True,
blank=True,
)
@property
def latest_membership(self):
if not self.membership_set.exists():
return None
return self.membership_set.latest('since')
@property
def membership_set(self):
return self.user.membership_set
def is_active(self):
"""Is this member currently active
Tested by checking if the expiration date has passed.
"""
return self.current_membership is not None
# Special properties for admin site
is_active.boolean = True
is_active.short_description = _('Is this user currently active')
# ---- Address information -----
......@@ -221,16 +232,6 @@ class Member(models.Model):
blank=True,
)
def is_active(self):
"""Is this member currently active
Tested by checking if the expiration date has passed.
"""
return self.membership_expiration > timezone.now()
# Special properties for admin site
is_active.boolean = True
is_active.short_description = _('Is this user currently active')
def display_name(self):
pref = self.display_name_preference
if pref == 'nickname':
......@@ -252,6 +253,49 @@ class Member(models.Model):
return self.display_name()
class Membership(models.Model):
MEMBERSHIP_TYPES = (
('member', _('Member')),
('supporter', _('Supporter')),
('honorary', _('Honorary Member')))
type = models.CharField(
max_length=40,
choices=MEMBERSHIP_TYPES,
verbose_name=_('Membership type'),
)
# Preferably this would have been a foreign key to Member instead,
# but Django currently does not support nested inlines in the Admin UI.
# This is necessary to create an inline in the User form.
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
verbose_name=_('User'),
)
since = models.DateField(
verbose_name=_("Membership since"),
help_text=_("The date the member started holding this membership."),
default=timezone.now
)
until = models.DateField(
verbose_name=_("Membership until"),
help_text=_("The date the member stops holding this membership."),
blank=True,
null=True,
)
@property
def member(self):
return self.user.member
def is_active(self):
return not self.until or self.until > timezone.now()
class BecomeAMemberDocument(models.Model):
name = models.CharField(max_length=200)
file = models.FileField(
......
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