admin.py 8.32 KB
Newer Older
1
"""Registers admin interfaces for the registrations module"""
2
3
from django.contrib import admin, messages
from django.contrib.admin.utils import model_ngettext
4
from django.forms import Field
5
6
7
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _

8
from payments.widgets import PaymentWidget
Thom Wiggers's avatar
Thom Wiggers committed
9
from . import services
10
11
12
13
14
15
from .models import Entry, Registration, Renewal, Reference


class ReferenceInline(admin.StackedInline):
    model = Reference
    extra = 0
16
17
18


def _show_message(admin, request, n, message, error):
19
    """Show a message in the Django Admin"""
20
21
22
23
24
25
26
27
28
29
30
    if n == 0:
        admin.message_user(request, error, messages.ERROR)
    else:
        admin.message_user(request, message % {
            "count": n,
            "items": model_ngettext(admin.opts, n)
        }, messages.SUCCESS)


@admin.register(Registration)
class RegistrationAdmin(admin.ModelAdmin):
31
32
    """Manage the registrations"""

33
34
35
36
37
    list_display = ('name', 'email', 'status', 'membership_type',
                    'created_at', 'payment_status', 'no_references',
                    'reference_count')
    list_filter = ('status', 'programme', 'membership_type', 'no_references',
                   'payment__type', 'payment__amount')
38
    inlines = (ReferenceInline,)
39
40
41
42
43
44
45
46
47
    search_fields = ('first_name', 'last_name', 'email', 'phone_number',
                     'student_number',)
    date_hierarchy = 'created_at'
    fieldsets = (
        (_('Application information'), {
            'fields': ('created_at',
                       'updated_at',
                       'username',
                       'length',
48
                       'contribution',
49
50
                       'membership_type',
                       'status',
51
52
                       'payment',
                       'remarks')
53
54
55
56
57
        }),
        (_('Personal information'), {
            'fields': ('first_name',
                       'last_name',
                       'birthday',
58
                       'optin_birthday',
59
                       'email',
60
                       'optin_mailinglist',
61
62
63
64
65
66
                       'phone_number',)
        }),
        (_('Address'), {
            'fields': ('address_street',
                       'address_street2',
                       'address_postal_code',
67
68
                       'address_city',
                       'address_country',)
69
70
71
72
73
74
75
76
77
        }),
        (_('University information'), {
            'fields': ('student_number',
                       'programme',
                       'starting_year',)
        }),
    )
    actions = ['accept_selected', 'reject_selected']

78
79
80
81
    def reference_count(self, obj):
        return obj.reference_set.count()
    reference_count.short_description = _('references')

82
83
84
85
86
87
88
89
    def formfield_for_dbfield(self, db_field, request, **kwargs):
        field = super().formfield_for_dbfield(db_field, request, **kwargs)
        if db_field.name == 'payment':
            return Field(widget=PaymentWidget,
                         initial=field.initial,
                         required=False)
        return field

90
91
    def changeform_view(self, request, object_id=None, form_url='',
                        extra_context=None):
92
93
94
95
        """
        Renders the change formview
        Only allow when the entry has not been processed yet
        """
96
        obj = None
97
98
        can_review = False
        can_resend = False
99
        can_revert = False
100
101
102
        if (object_id is not None and
                request.user.has_perm('registrations.review_entries')):
            obj = Entry.objects.get(id=object_id)
103
            can_review = obj.status == Entry.STATUS_REVIEW
Thom Wiggers's avatar
Thom Wiggers committed
104
105
            can_revert = obj.status in [
                    Entry.STATUS_ACCEPTED, Entry.STATUS_REJECTED]
106
107
108
109
            try:
                can_resend = obj.registration.status == Entry.STATUS_CONFIRM
            except Registration.DoesNotExist:
                pass
110
        return super().changeform_view(
111
112
113
114
            request, object_id, form_url, {
                'entry': obj,
                'can_review': can_review,
                'can_resend': can_resend,
115
                'can_revert': can_revert,
116
            })
117
118
119

    def get_readonly_fields(self, request, obj=None):
        if obj is None or not (obj.status == Entry.STATUS_REJECTED or
120
121
                               obj.status == Entry.STATUS_ACCEPTED or
                               obj.status == Entry.STATUS_COMPLETED):
122
            return ['status', 'created_at', 'updated_at']
123
        else:
124
125
126
127
128
            return [
                field.name for field in self.model._meta.get_fields()
                if not field.name in['payment', 'no_references']
                and field.editable
            ]
129
130
131
132
133
134
135

    @staticmethod
    def name(obj):
        return obj.get_full_name()

    @staticmethod
    def payment_status(obj):
136
137
        payment = obj.payment
        if payment:
138
139
140
141
142
            processed_str = (_('Processed') if payment.processed else
                             _('Unprocessed'))
            return format_html('<a href="{link}">{title}</a>'
                               .format(link=payment.get_admin_url(),
                                       title=processed_str))
143
        return '-'
144
145

    def reject_selected(self, request, queryset):
146
        """Reject the selected entries"""
147
        if request.user.has_perm('registrations.review_entries'):
148
            rows_updated = services.reject_entries(request.user.pk, queryset)
149
150
151
152
153
154
            _show_message(
                self, request, rows_updated,
                message=_("Successfully rejected %(count)d %(items)s."),
                error=_('The selected registration(s) could not be rejected.')
            )
    reject_selected.short_description = _('Reject selected registrations')
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
155
    reject_selected.allowed_permissions = ('review',)
156
157

    def accept_selected(self, request, queryset):
158
        """Accept the selected entries"""
159
        if request.user.has_perm('registrations.review_entries'):
160
            rows_updated = services.accept_entries(request.user.pk, queryset)
161
162
163
164
165
166
            _show_message(
                self, request, rows_updated,
                message=_("Successfully accepted %(count)d %(items)s."),
                error=_('The selected registration(s) could not be accepted.')
            )
    accept_selected.short_description = _('Accept selected registrations')
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
167
168
169
170
171
    accept_selected.allowed_permissions = ('review',)

    def has_review_permission(self, request):
        """Does the user have the review permission?"""
        return request.user.has_perm('registrations.review_entries')
172

173
174
175
176
177
    def save_model(self, request, obj, form, change):
        if not (obj.status == Entry.STATUS_REJECTED or
                obj.status == Entry.STATUS_ACCEPTED or
                obj.status == Entry.STATUS_COMPLETED):
            super().save_model(request, obj, form, change)
178

179
180
181

@admin.register(Renewal)
class RenewalAdmin(RegistrationAdmin):
182
183
    """Manage the renewals"""

184
185
186
187
188
    list_display = ('name', 'email', 'status', 'membership_type',
                    'created_at', 'payment_status', 'no_references',
                    'reference_count')
    list_filter = ('status', 'membership_type', 'no_references',
                   'payment__type', 'payment__amount')
189
190
191
192
193
194
195
196
197
198
    search_fields = ('member__first_name', 'member__last_name',
                     'member__email', 'member__profile__phone_number',
                     'member__profile__student_number',)
    date_hierarchy = 'created_at'
    fieldsets = (
                    (_('Application information'), {
                        'fields': (
                            'created_at',
                            'updated_at',
                            'length',
199
                            'contribution',
200
201
                            'membership_type',
                            'status',
202
                            'payment',
203
204
205
206
                            'remarks',
                            'member',)
                    }),
    )
207
    actions = RegistrationAdmin.actions
208
209

    def get_readonly_fields(self, request, obj=None):
210
        """Make all fields read-only and add member if needed"""
211
212
213
214
215
216
217
218
        fields = super().get_readonly_fields(request, obj)
        if 'member' not in fields and obj is not None:
            return fields + ['member']
        return fields

    @staticmethod
    def name(obj):
        return obj.member.get_full_name()
219
    name.short_description = _('name')
220
221
222
223

    @staticmethod
    def email(obj):
        return obj.member.email