admin.py 6.72 KB
Newer Older
1
"""Registers admin interfaces for the payments module"""
2
3
import csv

4
5
from django.contrib import admin, messages
from django.contrib.admin.utils import model_ngettext
6
from django.http import HttpResponse
7
from django.urls import path
8
9
from django.utils.html import format_html
from django.utils.text import capfirst
10
11
from django.utils.translation import ugettext_lazy as _

12
from payments import services, admin_views
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from .models import Payment


def _show_message(admin, request, n, message, error):
    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(Payment)
class PaymentAdmin(admin.ModelAdmin):
28
29
    """Manage the payments"""

30
31
32
33
    list_display = ('created_at', 'amount',  'processing_date', 'type',
                    'paid_by_link', 'processed_by_link', 'notes')
    list_filter = ('type',)
    list_select_related = ('paid_by', 'processed_by',)
34
    date_hierarchy = 'created_at'
35
36
37
38
39
    fields = ('created_at', 'amount', 'type', 'processing_date',
              'paid_by', 'processed_by', 'notes')
    readonly_fields = ('created_at', 'amount', 'type',
                       'processing_date', 'paid_by', 'processed_by',
                       'notes')
40
41
42
43
    search_fields = ('notes', 'paid_by__username', 'paid_by__first_name',
                     'paid_by__last_name', 'processed_by__username',
                     'processed_by__first_name', 'processed_by__last_name',
                     'amount')
44
45
    ordering = ('-created_at', 'processing_date')
    autocomplete_fields = ('paid_by', 'processed_by')
46
47
48
49
50
    actions = ['process_cash_selected', 'process_card_selected',
               'process_wire_selected', 'export_csv']

    @staticmethod
    def _member_link(member):
51
52
53
54
55
56
        if member:
            return format_html("<a href='{}'>{}</a>",
                               member.get_absolute_url(),
                               member.get_full_name())
        else:
            return "-"
57
58
59
60

    def paid_by_link(self, obj):
        return self._member_link(obj.paid_by)
    paid_by_link.admin_order_field = 'paid_by'
61
    paid_by_link.short_description = _('paid by')
62
63
64
65

    def processed_by_link(self, obj):
        return self._member_link(obj.processed_by)
    processed_by_link.admin_order_field = 'processed_by'
66
    processed_by_link.short_description = _('processed by')
67
68
69

    def changeform_view(self, request, object_id=None, form_url='',
                        extra_context=None):
70
71
72
73
        """
        Renders the change formview
        Only allow when the payment has not been processed yet
        """
74
75
76
77
78
79
80
81
82
        obj = None
        if (object_id is not None and
                request.user.has_perm('payments.process_payments')):
            obj = Payment.objects.get(id=object_id)
            if obj.processed:
                obj = None
        return super().changeform_view(
            request, object_id, form_url, {'payment': obj})

83
84
    def get_readonly_fields(self, request, obj=None):
        if not obj:
85
            return 'created_at', 'type', 'processing_date', 'processed_by'
86
87
        return super().get_readonly_fields(request, obj)

88
    def get_actions(self, request):
89
90
        """Get the actions for the payments"""
        """Hide the processing actions if the right permissions are missing"""
91
92
93
94
        actions = super().get_actions(request)
        if not request.user.has_perm('payments.process_payments'):
            del(actions['process_cash_selected'])
            del(actions['process_card_selected'])
95
            del(actions['process_wire_selected'])
96
97
98
        return actions

    def process_cash_selected(self, request, queryset):
99
        """Process the selected payment as cash"""
100
101
        if request.user.has_perm('payments.process_payments'):
            updated_payments = services.process_payment(
102
                queryset, request.member, Payment.CASH
103
104
105
106
107
108
            )
            self._process_feedback(request, updated_payments)
    process_cash_selected.short_description = _(
        'Process selected payments (cash)')

    def process_card_selected(self, request, queryset):
109
        """Process the selected payment as card"""
110
111
        if request.user.has_perm('payments.process_payments'):
            updated_payments = services.process_payment(
112
                queryset, request.member, Payment.CARD
113
114
115
116
117
            )
            self._process_feedback(request, updated_payments)
    process_card_selected.short_description = _(
        'Process selected payments (card)')

118
119
120
121
122
123
124
125
126
127
    def process_wire_selected(self, request, queryset):
        """Process the selected payment as wire"""
        if request.user.has_perm('payments.process_payments'):
            updated_payments = services.process_payment(
                queryset, request.member, Payment.WIRE
            )
            self._process_feedback(request, updated_payments)
    process_wire_selected.short_description = _(
        'Process selected payments (wire)')

128
    def _process_feedback(self, request, updated_payments):
129
        """Show a feedback message for the processing result"""
130
131
132
133
134
135
        rows_updated = len(updated_payments)
        _show_message(
            self, request, rows_updated,
            message=_("Successfully processed %(count)d %(items)s."),
            error=_('The selected payment(s) could not be processed.')
        )
136
137
138
139
140
141
142
143
144
145

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('<uuid:pk>/process/',
                 self.admin_site.admin_view(
                     admin_views.PaymentAdminView.as_view()),
                 name='payments_payment_process'),
        ]
        return custom_urls + urls
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

    def export_csv(self, request, queryset):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment;\
                                           filename="payments.csv"'
        writer = csv.writer(response)
        headers = [_('created'), _('processed'), _('amount'), _('type'),
                   _('processor'), _('payer id'), _('payer name'),
                   _('notes')]
        writer.writerow([capfirst(x) for x in headers])
        for payment in queryset:
            writer.writerow([
                payment.created_at,
                payment.processing_date,
                payment.amount,
                payment.get_type_display(),
162
163
164
165
166
167
                payment.processed_by.get_full_name()
                if payment.processed_by else '-',
                payment.paid_by.pk
                if payment.paid_by else '-',
                payment.paid_by.get_full_name()
                if payment.paid_by else '-',
168
169
170
171
                payment.notes
            ])
        return response
    export_csv.short_description = _('Export')