admin.py 7.38 KB
Newer Older
1
"""Registers admin interfaces for the activemembers module"""
2
3
4
5
import csv
import datetime

from django import forms
6
from django.contrib import admin, messages
7
from django.db.models import Q
8
9
10
from django.http import HttpResponse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
11

12
from activemembers import models
13
from activemembers.forms import MemberGroupMembershipForm, MemberGroupForm
14
from utils.snippets import datetime_to_lectureyear
15
from utils.translation import TranslatedModelAdmin
Thom Wiggers's avatar
Thom Wiggers committed
16

17

18
class MemberGroupMembershipInlineFormSet(forms.BaseInlineFormSet):
19
20
21
    """
    Solely here for performance reasons.

22
    Needed because the `__str__()` of `MemberGroupMembership` (which is displayed
23
    above each inline form) uses the username, name of the member and name of
24
    the group.
25
26
27
28
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
29
        self.queryset = self.queryset.select_related(
30
            'member', 'group').filter(until=None)
31
32


33
34
35
36
class MemberGroupMembershipInline(admin.StackedInline):
    """Inline for group memberships"""
    model = models.MemberGroupMembership
    formset = MemberGroupMembershipInlineFormSet
37
38
39
    can_delete = False
    ordering = ('since',)
    extra = 0
40
    autocomplete_fields = ('member',)
41
42


Thom Wiggers's avatar
Thom Wiggers committed
43
@admin.register(models.Committee)
44
class CommitteeAdmin(TranslatedModelAdmin):
45
    """Manage the committees"""
46
    inlines = (MemberGroupMembershipInline,)
47
    form = MemberGroupForm
48
49
    list_display = ('name', 'since', 'until', 'active', 'email')
    list_filter = ('until', 'active',)
Joren Vrancken's avatar
Joren Vrancken committed
50
    search_fields = ('name', 'description')
51
    filter_horizontal = ('permissions',)
Thom Wiggers's avatar
Thom Wiggers committed
52

53
    fields = ('name', 'description', 'photo', 'permissions', 'since',
54
55
              'until', 'contact_mailinglist', 'contact_email',
              'wiki_namespace', 'active')
56

57
58
59
60
61
62
63
    def email(self, instance):
        if instance.contact_email:
            return instance.contact_email
        elif instance.contact_mailinglist:
            return instance.contact_mailinglist.name + '@thalia.nu'
        return None

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

@admin.register(models.Society)
class CommitteeAdmin(TranslatedModelAdmin):
    """Manage the societies"""
    inlines = (MemberGroupMembershipInline,)
    form = MemberGroupForm
    list_display = ('name', 'since', 'until', 'active', 'email')
    list_filter = ('until', 'active',)
    search_fields = ('name', 'description')
    filter_horizontal = ('permissions',)

    fields = ('name', 'description', 'photo', 'permissions', 'since',
              'until', 'contact_mailinglist', 'contact_email', 'active')

    def email(self, instance):
        if instance.contact_email:
            return instance.contact_email
        elif instance.contact_mailinglist:
            return instance.contact_mailinglist.name + '@thalia.nu'
        return None
Thom Wiggers's avatar
Thom Wiggers committed
84
85
86


@admin.register(models.Board)
87
class BoardAdmin(TranslatedModelAdmin):
88
    """Manage the board"""
89
    inlines = (MemberGroupMembershipInline,)
90
    form = MemberGroupForm
Thom Wiggers's avatar
Thom Wiggers committed
91
    exclude = ('is_board',)
92
    filter_horizontal = ('permissions',)
Thom Wiggers's avatar
Thom Wiggers committed
93

94
95
    fields = ('name', 'description', 'photo', 'permissions',
              'contact_mailinglist', 'contact_email', 'since', 'until',)
96

Thom Wiggers's avatar
Thom Wiggers committed
97

98
class TypeFilter(admin.SimpleListFilter):
99
    """Filter memberships on board-only"""
100
101
    title = _('group memberships')
    parameter_name = 'group_type'
102
103
104

    def lookups(self, request, model_admin):
        return [
105
106
107
            ('boards', _('Only boards')),
            ('committees', _('Only committees')),
            ('societies', _('Only societies')),
108
109
110
        ]

    def queryset(self, request, queryset):
111
        if self.value() == 'boards':
112
            return queryset.exclude(group__board=None)
113
114
115
116
        elif self.value() == 'committees':
            return queryset.exclude(group__committee=None)
        elif self.value() == 'societies':
            return queryset.exclude(group__society=None)
117
118
119
120
121

        return queryset


class LectureYearFilter(admin.SimpleListFilter):
122
    """Filter the memberships on those started or ended in a lecture year"""
123
124
125
126
127
128
    title = _('lecture year')
    parameter_name = 'lecture_year'

    def lookups(self, request, model_admin):
        current_year = datetime_to_lectureyear(timezone.now())
        first_year = datetime_to_lectureyear(
129
                models.MemberGroupMembership.objects.earliest('since').since
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
        )

        return [(year, '{}-{}'.format(year, year+1))
                for year in range(first_year, current_year+1)]

    def queryset(self, request, queryset):
        if not self.value():
            return queryset

        year = int(self.value())
        first_of_september = datetime.date(year=year, month=9, day=1)

        return queryset.exclude(until__lt=first_of_september)


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
class ActiveMembershipsFilter(admin.SimpleListFilter):
    """Filter the memberships by whether they are active or not"""
    title = _('active memberships')
    parameter_name = 'active'

    def lookups(self, request, model_name):
        return (
            ('active', _('Active')),
            ('inactive', _('Inactive')),
        )

    def queryset(self, request, queryset):
        now = timezone.now()

        if self.value() == 'active':
            return queryset.filter(Q(until__isnull=True) |
                                   Q(until__gte=now))

        if self.value() == 'inactive':
            return queryset.filter(until__lt=now)


167
168
169
170
171
@admin.register(models.MemberGroupMembership)
class MemberGroupMembershipAdmin(TranslatedModelAdmin):
    """Manage the group memberships"""
    form = MemberGroupMembershipForm
    list_display = ('member', 'group', 'since', 'until', 'chair', 'role')
172
    list_filter = ('group', TypeFilter, LectureYearFilter,
173
                   ActiveMembershipsFilter)
174
    list_select_related = ('member', 'group',)
175
176
    search_fields = ('member__first_name', 'member__last_name',
                     'member__email')
177

178
179
    actions = ('export',)

180
181
    def changelist_view(self, request, extra_context=None):
        self.message_user(request, _('Do not edit existing memberships if the '
182
183
                                     'chair of a group has changed, add a '
                                     'new membership instead.'),
184
185
186
                          messages.WARNING)
        return super().changelist_view(request, extra_context)

187
188
189
190
    def export(self, request, queryset):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = ('attachment;'
                                           'filename='
191
                                           '"group_memberships.csv"')
192
193
194
195
196
        writer = csv.writer(response)
        writer.writerow([
            _('First name'),
            _('Last name'),
            _('Email'),
197
198
199
200
            _('Group'),
            _('Member since'),
            _('Member until'),
            _('Chair of the group'),
201
202
203
204
205
206
207
208
            _('Role'),
        ])

        for membership in queryset:
            writer.writerow([
                membership.member.first_name,
                membership.member.last_name,
                membership.member.email,
209
                membership.group,
210
211
212
213
214
215
216
217
218
                membership.since,
                membership.until,
                membership.chair,
                membership.role,
            ])

        return response
    export.short_description = _('Export selected memberships')

219
220

@admin.register(models.Mentorship)
221
class MentorshipAdmin(admin.ModelAdmin):
222
    """Manage the mentorships"""
223
    list_select_related = ('member',)