admin.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. from django.contrib import admin
  2. from django.db import models
  3. from django.urls import reverse
  4. from django.forms import BaseInlineFormSet
  5. from django.utils.html import format_html
  6. from django.conf.urls import url
  7. from django.shortcuts import get_object_or_404
  8. from django.template.response import TemplateResponse
  9. from functools import update_wrapper
  10. from services.models import ServiceType
  11. from services.admin import ServiceAdmin
  12. from adhesions.admin import AdhesionAdmin
  13. from djadhere.utils import ActiveFilter
  14. from .models import RecurringPayment, PaymentUpdate
  15. from .utils import notify_payment_update
  16. ### Inlines
  17. class PaymentTypeFilter(admin.SimpleListFilter):
  18. title = 'type'
  19. parameter_name = 'type'
  20. def lookups(self, request, model_admin):
  21. return (
  22. ('adhesion', 'Adhésion'),
  23. ('service', 'Service'),
  24. )
  25. def queryset(self, request, queryset):
  26. if self.value() == 'adhesion':
  27. return queryset.filter(adhesion__isnull=False)
  28. if self.value() == 'service':
  29. return queryset.filter(service__isnull=False)
  30. class PaymentMethodFilter(admin.SimpleListFilter):
  31. title = 'méthode de paiement'
  32. parameter_name = 'method'
  33. def lookups(self, request, model_admin):
  34. return PaymentUpdate.PAYMENT_CHOICES
  35. def queryset(self, request, queryset):
  36. if self.value() is not None:
  37. return queryset.filter(payment_method=self.value())
  38. class PendingPaymentFilter(admin.SimpleListFilter):
  39. title = 'opérations en attente'
  40. parameter_name = 'pending'
  41. def lookups(self, request, model_admin):
  42. return (
  43. (0, 'À jour'),
  44. (1, 'En attente'),
  45. )
  46. def queryset(self, request, queryset):
  47. pending = PaymentUpdate.objects.filter(validated=False).values_list('payment__pk', flat=True)
  48. if self.value() == '0':
  49. return queryset.exclude(pk__in=pending)
  50. if self.value() == '1':
  51. return queryset.filter(pk__in=pending)
  52. ### Inlines
  53. class PendingPaymentUpdateFormSet(BaseInlineFormSet):
  54. def save_new(self, form, commit=True):
  55. obj = super().save_new(form, commit)
  56. if not obj.validated:
  57. notify_payment_update(self.request, obj)
  58. return obj
  59. def save_existing(self, form, instance, commit=True):
  60. old = PaymentUpdate.objects.get(pk=instance.pk)
  61. if not instance.validated:
  62. notify_payment_update(self.request, instance, old)
  63. return super().save_existing(form, instance, commit)
  64. class PendingPaymentUpdateInline(admin.TabularInline):
  65. model = PaymentUpdate
  66. formset = PendingPaymentUpdateFormSet
  67. extra = 1
  68. verbose_name_plural = 'En attente de saisie bancaire'
  69. def get_formset(self, request, obj=None, **kwargs):
  70. formset = super().get_formset(request, obj, **kwargs)
  71. formset.request = request
  72. return formset
  73. def get_queryset(self, request):
  74. return super().get_queryset(request).filter(validated=False)
  75. class ValidatedPaymentUpdateInline(admin.TabularInline):
  76. model = PaymentUpdate
  77. verbose_name_plural = 'Historique'
  78. max_num = 0
  79. fields = ('amount', 'period', 'payment_method', 'start',)
  80. readonly_fields = ('amount', 'period', 'payment_method', 'start',)
  81. def has_delete_permission(self, request, obj=None):
  82. return False
  83. def get_queryset(self, request):
  84. return super().get_queryset(request).filter(validated=True)
  85. ### Helpers
  86. def prefix_search_field(prefix, field):
  87. if field[0] == '=':
  88. return '=' + prefix + '__' + field[1:]
  89. else:
  90. return prefix + '__' + field
  91. ### ModelAdmin
  92. class RecurringPaymentAdmin(admin.ModelAdmin):
  93. list_display = ('id', 'payment_type', 'payment_object_link', 'get_active',)# 'get_pending',)
  94. list_select_related = ('adhesion', 'service', 'service__service_type',)
  95. inlines = (PendingPaymentUpdateInline, ValidatedPaymentUpdateInline,)
  96. list_filter = (PaymentTypeFilter, PaymentMethodFilter, ActiveFilter, PendingPaymentFilter,)
  97. fields = ('payment_type', 'payment_object_link', 'debtor_link',)
  98. readonly_fields = ('payment_type', 'payment_object_link', 'debtor_link',)
  99. search_fields = \
  100. tuple([prefix_search_field('adhesion', f) for f in AdhesionAdmin.search_fields]) \
  101. + tuple([prefix_search_field('service', f) for f in ServiceAdmin.search_fields])
  102. #def get_queryset(self, request):
  103. # qs = super().get_queryset(request)
  104. # qs = qs.prefetch_related('updates')
  105. # qs = qs.prefetch_related(
  106. # models.Prefetch(
  107. # 'updates',
  108. # queryset=PaymentUpdate.objects.filter(validated=False),
  109. # to_attr='pending_updates'
  110. # )
  111. # )
  112. # return qs
  113. #def get_pending(self, obj):
  114. # return len(obj.pending_updates)
  115. #get_pending.short_description = 'Opérations en attente'
  116. def get_active(self, obj):
  117. return obj.active
  118. get_active.short_description = 'Actif'
  119. get_active.boolean = True
  120. def payment_object_link(self, obj):
  121. obj = obj.payment_object()
  122. return format_html(u'<a href="{}">{}</a>', obj.get_absolute_url(), obj)
  123. payment_object_link.short_description = 'Objet'
  124. def debtor_link(self, obj):
  125. url = reverse(viewname='admin:%s_%s_debtor' % (obj._meta.app_label, obj._meta.model_name), args=[obj.pk])
  126. return format_html(u'<a href="{}">{}</a>', url, obj.debtor)
  127. debtor_link.short_description = 'Débiteur'
  128. def get_actions(self, request):
  129. actions = super().get_actions(request)
  130. if 'delete_selected' in actions:
  131. del actions['delete_selected']
  132. return actions
  133. def has_add_permission(self, request, obj=None):
  134. return False
  135. def has_delete_permission(self, request, obj=None):
  136. return False
  137. def get_urls(self):
  138. info = self.model._meta.app_label, self.model._meta.model_name
  139. urls = [
  140. url(r'^(.*)/debtor/$', self.admin_site.admin_view(self.debtor_view), name='%s_%s_debtor' % info),
  141. ]
  142. return urls + super().get_urls()
  143. def debtor_view(self, request, payment_pk):
  144. payment = get_object_or_404(RecurringPayment, pk=payment_pk)
  145. adhesion = payment.debtor
  146. if adhesion.is_physical():
  147. profile = adhesion.user.profile
  148. else:
  149. profile = adhesion.corporation
  150. context = dict(
  151. self.admin_site.each_context(request),
  152. opts=self.model._meta,
  153. payment=payment,
  154. adhesion=adhesion,
  155. adherent=adhesion.adherent,
  156. profile=profile,
  157. )
  158. return TemplateResponse(request, 'banking/debtor.html', context)
  159. admin.site.register(RecurringPayment, RecurringPaymentAdmin)