from django.contrib import admin from django.db import models from django.core.urlresolvers import reverse from django.forms import BaseInlineFormSet from django.utils.html import format_html from services.models import ServiceType from services.admin import ServiceAdmin from adhesions.admin import AdhesionAdmin from .models import RecurringPayment, PaymentUpdate from .utils import notify_payment_update ### Inlines class PaymentTypeFilter(admin.SimpleListFilter): title = 'type' parameter_name = 'type' def lookups(self, request, model_admin): return ( ('adhesion', 'Adhésion'), ('service', 'Service'), ) def queryset(self, request, queryset): if self.value() == 'adhesion': return queryset.filter(adhesion__isnull=False) if self.value() == 'service': return queryset.filter(service__isnull=False) class PaymentStatusFilter(admin.SimpleListFilter): title = 'actif' parameter_name = 'active' def lookups(self, request, model_admin): return ( (0, 'Inactif'), (1, 'Actif'), ) def queryset(self, request, queryset): actives = PaymentUpdate.objects.filter(validated=True).order_by('payment', '-start') \ .distinct('payment').exclude(payment_method=PaymentUpdate.STOP) \ .values_list('payment__pk', flat=True) if self.value() == '0': return queryset.exclude(pk__in=actives) if self.value() == '1': return queryset.filter(pk__in=actives) class PendingPaymentFilter(admin.SimpleListFilter): title = 'opérations en attente' parameter_name = 'pending' def lookups(self, request, model_admin): return ( (0, 'À jour'), (1, 'En attente'), ) def queryset(self, request, queryset): pending = PaymentUpdate.objects.filter(validated=False).values_list('payment__pk', flat=True) if self.value() == '0': return queryset.exclude(pk__in=pending) if self.value() == '1': return queryset.filter(pk__in=pending) ### Inlines class PendingPaymentUpdateFormSet(BaseInlineFormSet): def save_new(self, form, commit=True): obj = super().save_new(form, commit) notify_payment_update(self.request, obj) return obj def save_existing(self, form, instance, commit=True): old = PaymentUpdate.objects.get(pk=instance.pk) notify_payment_update(self.request, instance, old) return super().save_existing(form, instance, commit) class PendingPaymentUpdateInline(admin.TabularInline): model = PaymentUpdate formset = PendingPaymentUpdateFormSet extra = 1 verbose_name_plural = 'En attente de saisie bancaire' def get_formset(self, request, obj=None, **kwargs): formset = super().get_formset(request, obj, **kwargs) formset.request = request return formset def get_queryset(self, request): return super().get_queryset(request).filter(validated=False) class ValidatedPaymentUpdateInline(admin.TabularInline): model = PaymentUpdate verbose_name_plural = 'Historique' max_num = 0 fields = ('amount', 'period', 'payment_method', 'start',) readonly_fields = ('amount', 'period', 'payment_method', 'start',) def has_delete_permission(self, request, obj=None): return False def get_queryset(self, request): return super().get_queryset(request).filter(validated=True) ### Helpers def prefix_search_field(prefix, field): if field[0] == '=': return '=' + prefix + '__' + field[1:] else: return prefix + '__' + field ### ModelAdmin class RecurringPaymentAdmin(admin.ModelAdmin): list_display = ('id', 'payment_type', 'payment_object_link', 'get_status', 'get_last_validated_update', 'get_pending',) list_select_related = ('adhesion', 'service', 'service__service_type',) inlines = (PendingPaymentUpdateInline, ValidatedPaymentUpdateInline,) list_filter = (PaymentTypeFilter, PaymentStatusFilter, PendingPaymentFilter,) fields = ('payment_type', 'payment_object_link',) readonly_fields = ('payment_type', 'payment_object_link',) search_fields = \ tuple([prefix_search_field('adhesion', f) for f in AdhesionAdmin.search_fields]) \ + tuple([prefix_search_field('service', f) for f in ServiceAdmin.search_fields]) def get_queryset(self, request): qs = super().get_queryset(request) qs = qs.prefetch_related('updates') qs = qs.prefetch_related( models.Prefetch( 'updates', queryset=PaymentUpdate.objects.filter(validated=False), to_attr='pending_updates' ) ) return qs def get_pending(self, obj): return len(obj.pending_updates) get_pending.short_description = 'Opérations en attente' def payment_object_link(self, obj): obj = obj.payment_object() return format_html(u'{}', obj.get_absolute_url(), obj) payment_object_link.short_description = 'Objet' def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False admin.site.register(RecurringPayment, RecurringPaymentAdmin)