admin.py 6.3 KB

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