admin.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 services.models import ServiceType
  7. from services.admin import ServiceAdmin
  8. from adhesions.admin import AdhesionAdmin
  9. from .models import RecurringPayment, PaymentUpdate
  10. from .utils import notify_payment_update
  11. ### Inlines
  12. class PaymentTypeFilter(admin.SimpleListFilter):
  13. title = 'type'
  14. parameter_name = 'type'
  15. def lookups(self, request, model_admin):
  16. return (
  17. ('adhesion', 'Adhésion'),
  18. ('service', 'Service'),
  19. )
  20. def queryset(self, request, queryset):
  21. if self.value() == 'adhesion':
  22. return queryset.filter(adhesion__isnull=False)
  23. if self.value() == 'service':
  24. return queryset.filter(service__isnull=False)
  25. class PaymentStatusFilter(admin.SimpleListFilter):
  26. title = 'actif'
  27. parameter_name = 'active'
  28. def lookups(self, request, model_admin):
  29. return (
  30. (0, 'Inactif'),
  31. (1, 'Actif'),
  32. )
  33. def queryset(self, request, queryset):
  34. payments = PaymentUpdate.objects.filter(validated=True).order_by('payment', '-start')\
  35. .distinct('payment').values('payment_method', 'payment__pk')
  36. actives = filter(lambda p: p['payment_method'] != PaymentUpdate.STOP, payments)
  37. actives = map(lambda p: p['payment__pk'], actives)
  38. if self.value() == '0':
  39. return queryset.exclude(pk__in=actives)
  40. if self.value() == '1':
  41. return queryset.filter(pk__in=actives)
  42. class PendingPaymentFilter(admin.SimpleListFilter):
  43. title = 'opérations en attente'
  44. parameter_name = 'pending'
  45. def lookups(self, request, model_admin):
  46. return (
  47. (0, 'À jour'),
  48. (1, 'En attente'),
  49. )
  50. def queryset(self, request, queryset):
  51. pending = PaymentUpdate.objects.filter(validated=False).values_list('payment__pk', flat=True)
  52. if self.value() == '0':
  53. return queryset.exclude(pk__in=pending)
  54. if self.value() == '1':
  55. return queryset.filter(pk__in=pending)
  56. ### Inlines
  57. class PendingPaymentUpdateFormSet(BaseInlineFormSet):
  58. def save_new(self, form, commit=True):
  59. obj = super().save_new(form, commit)
  60. if not obj.validated:
  61. notify_payment_update(self.request, obj)
  62. return obj
  63. def save_existing(self, form, instance, commit=True):
  64. old = PaymentUpdate.objects.get(pk=instance.pk)
  65. if not obj.validated:
  66. notify_payment_update(self.request, instance, old)
  67. return super().save_existing(form, instance, commit)
  68. class PendingPaymentUpdateInline(admin.TabularInline):
  69. model = PaymentUpdate
  70. formset = PendingPaymentUpdateFormSet
  71. extra = 1
  72. verbose_name_plural = 'En attente de saisie bancaire'
  73. def get_formset(self, request, obj=None, **kwargs):
  74. formset = super().get_formset(request, obj, **kwargs)
  75. formset.request = request
  76. return formset
  77. def get_queryset(self, request):
  78. return super().get_queryset(request).filter(validated=False)
  79. class ValidatedPaymentUpdateInline(admin.TabularInline):
  80. model = PaymentUpdate
  81. verbose_name_plural = 'Historique'
  82. max_num = 0
  83. fields = ('amount', 'period', 'payment_method', 'start',)
  84. readonly_fields = ('amount', 'period', 'payment_method', 'start',)
  85. def has_delete_permission(self, request, obj=None):
  86. return False
  87. def get_queryset(self, request):
  88. return super().get_queryset(request).filter(validated=True)
  89. ### Helpers
  90. def prefix_search_field(prefix, field):
  91. if field[0] == '=':
  92. return '=' + prefix + '__' + field[1:]
  93. else:
  94. return prefix + '__' + field
  95. ### ModelAdmin
  96. class RecurringPaymentAdmin(admin.ModelAdmin):
  97. list_display = ('id', 'payment_type', 'payment_object_link', 'get_status', 'get_last_validated_update', 'get_pending',)
  98. list_select_related = ('adhesion', 'service', 'service__service_type',)
  99. inlines = (PendingPaymentUpdateInline, ValidatedPaymentUpdateInline,)
  100. list_filter = (PaymentTypeFilter, PaymentStatusFilter, PendingPaymentFilter,)
  101. fields = ('payment_type', 'payment_object_link',)
  102. readonly_fields = ('payment_type', 'payment_object_link',)
  103. search_fields = \
  104. tuple([prefix_search_field('adhesion', f) for f in AdhesionAdmin.search_fields]) \
  105. + tuple([prefix_search_field('service', f) for f in ServiceAdmin.search_fields])
  106. def get_queryset(self, request):
  107. qs = super().get_queryset(request)
  108. qs = qs.prefetch_related('updates')
  109. qs = qs.prefetch_related(
  110. models.Prefetch(
  111. 'updates',
  112. queryset=PaymentUpdate.objects.filter(validated=False),
  113. to_attr='pending_updates'
  114. )
  115. )
  116. return qs
  117. def get_pending(self, obj):
  118. return len(obj.pending_updates)
  119. get_pending.short_description = 'Opérations en attente'
  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 get_actions(self, request):
  125. actions = super().get_actions(request)
  126. if 'delete_selected' in actions:
  127. del actions['delete_selected']
  128. return actions
  129. def has_add_permission(self, request, obj=None):
  130. return False
  131. def has_delete_permission(self, request, obj=None):
  132. return False
  133. admin.site.register(RecurringPayment, RecurringPaymentAdmin)