|
@@ -19,23 +19,6 @@ 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 PaymentMethodFilter(admin.SimpleListFilter):
|
|
|
title = 'méthode de paiement'
|
|
|
parameter_name = 'method'
|
|
@@ -46,24 +29,74 @@ class PaymentMethodFilter(admin.SimpleListFilter):
|
|
|
def queryset(self, request, queryset):
|
|
|
if self.value() is not None:
|
|
|
return queryset.filter(payment_method=self.value())
|
|
|
+ else:
|
|
|
+ return queryset.exclude(payment_method=PaymentUpdate.STOP)
|
|
|
|
|
|
|
|
|
class PendingPaymentFilter(admin.SimpleListFilter):
|
|
|
- title = 'opérations en attente'
|
|
|
- parameter_name = 'pending'
|
|
|
+ title = 'statut'
|
|
|
+ parameter_name = 'status'
|
|
|
|
|
|
def lookups(self, request, model_admin):
|
|
|
return (
|
|
|
- (0, 'À jour'),
|
|
|
- (1, 'En attente'),
|
|
|
+ ('up-to-date', 'À jour'),
|
|
|
+ ('pending', '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)
|
|
|
+ if self.value() == 'up-to-date':
|
|
|
+ queryset = queryset.filter(last=True)
|
|
|
+ if self.value() == 'pending':
|
|
|
+ queryset = queryset.filter(last=False)
|
|
|
+ return queryset
|
|
|
+ payments = RecurringPayment.objects.annotate(
|
|
|
+ validated=models.Subquery(
|
|
|
+ PaymentUpdate.objects.filter(payment=models.OuterRef('pk'))
|
|
|
+ .filter(validated=True)
|
|
|
+ .order_by('-start')
|
|
|
+ .values('pk')[:1]
|
|
|
+ ),
|
|
|
+ pending=models.Subquery(
|
|
|
+ PaymentUpdate.objects.filter(payment=models.OuterRef('pk'))
|
|
|
+ .filter(validated=False)
|
|
|
+ .order_by('-start')
|
|
|
+ .values('pk')[:1]
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ up_to_date = payments.filter(pending__isnull=True)
|
|
|
+ pending = payments.exclude(pending__isnull=True)
|
|
|
+ if self.value() == 'up-to-date':
|
|
|
+ p = up_to_date
|
|
|
+ elif self.value() == 'pending':
|
|
|
+ p = pending
|
|
|
+ else:
|
|
|
+ p = payments
|
|
|
+ queryset = queryset.filter(pk__in=p.values_list('validated', flat=True))
|
|
|
+ queryset = queryset.annotate(
|
|
|
+ last=models.Case(
|
|
|
+ models.When(pk__in=up_to_date.values_list('validated', flat=True), then=True),
|
|
|
+ default=False,
|
|
|
+ output_field=models.BooleanField(),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ return queryset
|
|
|
+
|
|
|
+
|
|
|
+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(payment__adhesion__isnull=False)
|
|
|
+ if self.value() == 'service':
|
|
|
+ return queryset.filter(payment__service__isnull=False)
|
|
|
|
|
|
|
|
|
### Inlines
|
|
@@ -86,7 +119,8 @@ class PendingPaymentUpdateInline(admin.TabularInline):
|
|
|
model = PaymentUpdate
|
|
|
formset = PendingPaymentUpdateFormSet
|
|
|
extra = 1
|
|
|
- verbose_name_plural = 'En attente de saisie bancaire'
|
|
|
+ max_num = 1
|
|
|
+ verbose_name_plural = 'Demande de saisie bancaire'
|
|
|
|
|
|
def get_formset(self, request, obj=None, **kwargs):
|
|
|
formset = super().get_formset(request, obj, **kwargs)
|
|
@@ -123,36 +157,9 @@ def prefix_search_field(prefix, field):
|
|
|
### ModelAdmin
|
|
|
|
|
|
class RecurringPaymentAdmin(admin.ModelAdmin):
|
|
|
- list_display = ('id', 'payment_type', 'payment_object_link', 'get_active',)# 'get_pending',)
|
|
|
- list_select_related = ('adhesion', 'service', 'service__service_type',)
|
|
|
inlines = (PendingPaymentUpdateInline, ValidatedPaymentUpdateInline,)
|
|
|
- list_filter = (PaymentTypeFilter, PaymentMethodFilter, ActiveFilter, PendingPaymentFilter,)
|
|
|
fields = ('payment_type', 'payment_object_link', 'debtor_link',)
|
|
|
readonly_fields = ('payment_type', 'payment_object_link', 'debtor_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 get_active(self, obj):
|
|
|
- return obj.active
|
|
|
- get_active.short_description = 'Actif'
|
|
|
- get_active.boolean = True
|
|
|
|
|
|
def payment_object_link(self, obj):
|
|
|
obj = obj.payment_object()
|
|
@@ -173,6 +180,9 @@ class RecurringPaymentAdmin(admin.ModelAdmin):
|
|
|
def has_add_permission(self, request, obj=None):
|
|
|
return False
|
|
|
|
|
|
+ def has_change_permission(self, request, obj=None):
|
|
|
+ return obj
|
|
|
+
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
|
return False
|
|
|
|
|
@@ -201,4 +211,75 @@ class RecurringPaymentAdmin(admin.ModelAdmin):
|
|
|
return TemplateResponse(request, 'banking/debtor.html', context)
|
|
|
|
|
|
|
|
|
+class PaymentUpdateAdmin(admin.ModelAdmin):
|
|
|
+ list_display = ('payment_type', 'payment_object_link', 'payment_link', 'last',)
|
|
|
+ list_select_related = ('payment', 'payment__adhesion', 'payment__service', 'payment__service__service_type',)
|
|
|
+ list_filter = (PaymentTypeFilter, PaymentMethodFilter, PendingPaymentFilter,)
|
|
|
+ list_display_links = None
|
|
|
+ search_fields = \
|
|
|
+ tuple([prefix_search_field('payment__adhesion', f) for f in AdhesionAdmin.search_fields]) \
|
|
|
+ + tuple([prefix_search_field('payment__service', f) for f in ServiceAdmin.search_fields])
|
|
|
+
|
|
|
+ def last(self, obj):
|
|
|
+ return obj.last
|
|
|
+ last.boolean = True
|
|
|
+ last.short_description = 'À jour'
|
|
|
+
|
|
|
+ def payment_type(self, update):
|
|
|
+ return update.payment.payment_type()
|
|
|
+ payment_type.short_description = 'Type'
|
|
|
+
|
|
|
+ def payment_object_link(self, update):
|
|
|
+ obj = update.payment.payment_object()
|
|
|
+ return format_html(u'<a href="{}">{}</a>', obj.get_absolute_url(), obj)
|
|
|
+ payment_object_link.short_description = 'Objet'
|
|
|
+
|
|
|
+ def payment_link(self, update):
|
|
|
+ payment = update.payment
|
|
|
+ return format_html(u'<a href="{}">{}</a>', payment.get_absolute_url(), update)
|
|
|
+ payment_link.short_description = 'Paiement'
|
|
|
+
|
|
|
+ def get_queryset(self, request):
|
|
|
+ qs = super().get_queryset(request)
|
|
|
+ payments = RecurringPayment.objects.annotate(
|
|
|
+ validated=models.Subquery(
|
|
|
+ PaymentUpdate.objects.filter(payment=models.OuterRef('pk'))
|
|
|
+ .filter(validated=True)
|
|
|
+ .order_by('-start')
|
|
|
+ .values('pk')[:1]
|
|
|
+ ),
|
|
|
+ pending=models.Subquery(
|
|
|
+ PaymentUpdate.objects.filter(payment=models.OuterRef('pk'))
|
|
|
+ .filter(validated=False)
|
|
|
+ .order_by('-start')
|
|
|
+ .values('pk')[:1]
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ qs = qs.filter(pk__in=payments.values_list('validated', flat=True))
|
|
|
+ qs = qs.annotate(
|
|
|
+ last=models.Case(
|
|
|
+ models.When(pk__in=payments.filter(pending__isnull=True).values_list('validated', flat=True), then=True),
|
|
|
+ default=False,
|
|
|
+ output_field=models.BooleanField(),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ return qs
|
|
|
+
|
|
|
+ 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_change_permission(self, request, obj=None):
|
|
|
+ return not obj
|
|
|
+
|
|
|
+ def has_delete_permission(self, request, obj=None):
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
admin.site.register(RecurringPayment, RecurringPaymentAdmin)
|
|
|
+admin.site.register(PaymentUpdate, PaymentUpdateAdmin)
|