1 from django.contrib import admin
 
   2 from django.contrib.admin.filters import FieldListFilter, SimpleListFilter
 
   3 from django.contrib import messages
 
   4 from django.db.models import Q
 
   5 from django.shortcuts import get_object_or_404, redirect
 
   6 from django.urls import path, reverse
 
   7 from django.utils.safestring import mark_safe
 
   8 from django.utils.translation import gettext_lazy as _
 
   9 from django.utils.timezone import now
 
  10 from fnpdjango.actions import export_as_csv_action
 
  15 admin.site.register(models.Fundraiser)
 
  16 admin.site.register(models.Campaign)
 
  19 # Backport from Django 3.1.
 
  20 class EmptyFieldListFilter(FieldListFilter):
 
  21     def __init__(self, field, request, params, model, model_admin, field_path):
 
  22         self.lookup_kwarg = '%s__isempty' % field_path
 
  23         self.lookup_val = params.get(self.lookup_kwarg)
 
  24         super().__init__(field, request, params, model, model_admin, field_path)
 
  26     def queryset(self, request, queryset):
 
  27         if self.lookup_kwarg not in self.used_parameters:
 
  29         if self.lookup_val not in ('0', '1'):
 
  30             raise IncorrectLookupParameters
 
  32         lookup_condition = Q(**{'%s__isnull' % self.field_path: True})
 
  33         if self.lookup_val == '1':
 
  34             return queryset.filter(lookup_condition)
 
  35         return queryset.exclude(lookup_condition)
 
  37     def expected_parameters(self):
 
  38         return [self.lookup_kwarg]
 
  40     def choices(self, changelist):
 
  41         for lookup, title in (
 
  44             ('0', _('Not empty')),
 
  47                 'selected': self.lookup_val == lookup,
 
  48                 'query_string': changelist.get_query_string({self.lookup_kwarg: lookup}),
 
  53 class PayedListFilter(SimpleListFilter):
 
  55     parameter_name = 'payed'
 
  56     def lookups(self, request, model_admin):
 
  62     def queryset(self, request, queryset):
 
  63         if self.value() == 'yes':
 
  64             return queryset.filter(payment__is_dd=True, payment__realised=True).distinct()
 
  65         if self.value() == 'no':
 
  66             return queryset.exclude(payment__is_dd=True, payment__realised=True).distinct()
 
  70 class BankExportFeedbackLineInline(admin.TabularInline):
 
  71     model = models.BankExportFeedbackLine
 
  74 class BankPaymentInline(admin.TabularInline):
 
  75     model = models.Payment
 
  78 @admin.register(models.DirectDebit)
 
  79 class DirectDebitAdmin(admin.ModelAdmin):
 
  81         'payment_id', 'acquisition_date',
 
  84         'bank_submission_date',
 
  85         'bank_acceptance_date',
 
  86         'amount', 'first_name', 'last_name',
 
  88     date_hierarchy = 'acquisition_date'
 
  90         'payment_id', 'first_name', 'last_name', 'street', 'building', 'town', 'flat',
 
  91         'phone', 'email', 'iban',
 
 101         ('cancelled_at', EmptyFieldListFilter),
 
 108         ('fundraiser_commission', EmptyFieldListFilter),
 
 109         ('fundraiser_bonus', EmptyFieldListFilter),
 
 115                 ('first_name', 'sex', 'date_of_birth'),
 
 117                 ('street', 'building'),
 
 119                 ('postal_code', 'phone'),
 
 121                 ('iban', 'iban_valid', 'iban_warning'),
 
 122                 ('payment_id', 'latest_status'),
 
 126                 ('acquisition_date', 'amount'),
 
 132         (_('Processing'), {"fields": [
 
 133             ('cancelled_at', 'needs_redo', 'optout'),
 
 135             'fundraiser_commission',
 
 138             'bank_submission_date',
 
 139             'bank_acceptance_date',
 
 144     readonly_fields = ['agree_contact', 'iban_valid', 'iban_warning', 'latest_status']
 
 145     inlines = [BankExportFeedbackLineInline, BankPaymentInline]
 
 147     def set_bank_submission(m, r, q):
 
 148         q.update(bank_submission_date=now())
 
 150     def create_bank_order(m, request, queryset):
 
 151         bo = models.BankOrder.objects.create()
 
 152         bo.debits.set(queryset)
 
 153         messages.info(request, mark_safe(
 
 154             '<a href="{}">Bank order</a> created.'.format(
 
 155                 reverse('admin:pz_bankorder_change', args=[bo.pk])
 
 164         export_as_csv_action(),
 
 167     def agree_contact(self, obj):
 
 168         return _('obligatory')
 
 169     agree_contact.short_description = _('agree contact')
 
 171     def get_changeform_initial_data(self, request):
 
 173             'payment_id': models.DirectDebit.get_next_payment_id(),
 
 177 @admin.register(models.BankExportFeedback)
 
 178 class BankExportFeedbackAdmin(admin.ModelAdmin):
 
 179     inlines = [BankExportFeedbackLineInline, BankPaymentInline]
 
 183 @admin.register(models.BankOrder)
 
 184 class BankOrderAdmin(admin.ModelAdmin):
 
 185     fields = ['payment_date', 'debits', 'sent', 'download']
 
 186     filter_horizontal = ['debits']
 
 188     def get_readonly_fields(self, request, obj=None):
 
 189         fields = ['download']
 
 190         if obj is not None and obj.sent:
 
 191             fields += ['debits', 'payment_date']
 
 194     def download(self, obj):
 
 195         if obj is not None and obj.pk:
 
 196             return mark_safe('<a href="{}">Download</a>'.format(
 
 197                 reverse('admin:pz_bankorder_download', args=[obj.pk])
 
 203         urls = super().get_urls()
 
 206                 '<int:pk>/download/',
 
 207                 self.admin_site.admin_view(self.download_view),
 
 208                 name='pz_bankorder_download',
 
 211         return my_urls + urls
 
 213     def download_view(self, request, pk):
 
 214         order = get_object_or_404(
 
 215             models.BankOrder, pk=pk)
 
 217             return bank.bank_order(
 
 222         except Exception as e:
 
 223             messages.error(request, str(e))
 
 224             return redirect('admin:pz_bankorder_change', pk)