admin.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. from django import forms
  4. from django.contrib import admin
  5. from django.contrib import messages
  6. from django.http import HttpResponseRedirect
  7. from django.conf.urls import url
  8. from django.contrib.admin.util import flatten_fieldsets
  9. from coin.filtering_queryset import LimitedAdminInlineMixin
  10. from coin.billing.models import Invoice, InvoiceDetail, Payment
  11. from coin.billing.utils import get_invoice_from_id_or_number
  12. from coin.offers.models import OfferSubscription
  13. import autocomplete_light
  14. class InvoiceDetailInline(LimitedAdminInlineMixin, admin.StackedInline):
  15. model = InvoiceDetail
  16. extra = 0
  17. fields = (('label', 'amount', 'quantity', 'tax'),
  18. ('offersubscription','period_from', 'period_to'))
  19. def get_filters(self, obj):
  20. """
  21. Le champ "Abonnement" est filtré afin de n'afficher que les abonnements
  22. du membre choisi dans la facture. Si pas de membre alors renvoi
  23. une liste vide
  24. """
  25. if obj and obj.member:
  26. return (('offersubscription', {'member':obj.member}),)
  27. else:
  28. return (('offersubscription', None),)
  29. def get_readonly_fields(self, request, obj=None):
  30. if not obj or not obj.member:
  31. return self.readonly_fields + ('offersubscription',)
  32. return self.readonly_fields
  33. class InvoiceDetailInlineReadOnly(admin.StackedInline):
  34. """
  35. Lorsque la facture est validée, il n'est plus possible de la modifier
  36. Ce inline est donc identique à InvoiceDetailInline, mais tous
  37. les champs sont en lecture seule
  38. """
  39. model = InvoiceDetail
  40. extra = 0
  41. fields = InvoiceDetailInline.fields
  42. can_delete = False
  43. def has_add_permission(self, request):
  44. return False
  45. def get_readonly_fields(self, request, obj=None):
  46. if self.declared_fieldsets:
  47. result = flatten_fieldsets(self.declared_fieldsets)
  48. else:
  49. result = list(set(
  50. [field.name for field in self.opts.local_fields] +
  51. [field.name for field in self.opts.local_many_to_many]
  52. ))
  53. result.remove('id')
  54. return result
  55. class PaymentInline(admin.StackedInline):
  56. model = Payment
  57. extra = 0
  58. fields = (('date', 'payment_mean', 'amount'),)
  59. class InvoiceAdmin(admin.ModelAdmin):
  60. list_display = ('number', 'date', 'status', 'amount', 'member', 'validated')
  61. list_display_links = ('number', 'date')
  62. fields = (('number', 'date', 'status'),
  63. ('date_due'),
  64. ('member'),
  65. ('amount','amount_paid'),
  66. ('validated', 'pdf'))
  67. readonly_fields = ('amount','amount_paid','validated','pdf')
  68. form = autocomplete_light.modelform_factory(Invoice)
  69. def get_readonly_fields(self, request, obj=None):
  70. """
  71. Si la facture est validée, passe tous les champs en readonly
  72. """
  73. if obj and obj.validated:
  74. if self.declared_fieldsets:
  75. return flatten_fieldsets(self.declared_fieldsets)
  76. else:
  77. return list(set(
  78. [field.name for field in self.opts.local_fields] +
  79. [field.name for field in self.opts.local_many_to_many]
  80. ))
  81. return self.readonly_fields
  82. def get_inline_instances(self, request, obj=None):
  83. """
  84. Renvoi les inlines selon le context :
  85. * Si création, alors ne renvoi aucun inline
  86. * Si modification, renvoi InvoiceDetail et PaymentInline
  87. * Si facture validée, renvoi InvoiceDetail en ReadOnly et PaymentInline
  88. """
  89. inlines = []
  90. inline_instances = []
  91. if obj is not None:
  92. if obj.validated:
  93. inlines = [InvoiceDetailInlineReadOnly]
  94. else:
  95. inlines = [InvoiceDetailInline]
  96. inlines += [PaymentInline]
  97. for inline_class in inlines:
  98. inline = inline_class(self.model, self.admin_site)
  99. if request:
  100. if not (inline.has_add_permission(request) or
  101. inline.has_change_permission(request) or
  102. inline.has_delete_permission(request)):
  103. continue
  104. if not inline.has_add_permission(request):
  105. inline.max_num = 0
  106. inline_instances.append(inline)
  107. return inline_instances
  108. def get_urls(self):
  109. """
  110. Custom admin urls
  111. """
  112. urls = super(InvoiceAdmin, self).get_urls()
  113. my_urls = [
  114. url(r'^validate/(?P<id>.+)$', self.admin_site.admin_view(self.validate_view),
  115. name='invoice_validate'),
  116. ]
  117. return my_urls + urls
  118. def validate_view(self, request, id):
  119. """
  120. Vue appelée lorsque l'admin souhaite valider une facture (et générer le pdf)
  121. """
  122. #TODO : Add better perm here
  123. if request.user.is_superuser:
  124. invoice = get_invoice_from_id_or_number(id)
  125. invoice.validate()
  126. messages.success(request, 'La facture a été validée.')
  127. else:
  128. messages.error(request, 'Vous n\'avez pas l\'autorisation de valider une facture.')
  129. return HttpResponseRedirect(request.META["HTTP_REFERER"])
  130. admin.site.register(Invoice, InvoiceAdmin)