admin.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. from django.contrib import admin, messages
  2. from django.core.urlresolvers import reverse
  3. from django.utils.encoding import force_text
  4. from django.utils.safestring import mark_safe
  5. from .models import (
  6. Document, Cost, Good, AbstractUse, CostUse, GoodUse, Service, ServiceUse)
  7. import markdown
  8. class GoodInline(admin.TabularInline):
  9. model = Good
  10. extra = 0
  11. exclude = ['description_html']
  12. class CostInline(admin.TabularInline):
  13. model = Cost
  14. extra = 0
  15. exclude = ['description_html']
  16. class ServiceInline(admin.TabularInline):
  17. model = Service
  18. fields = (
  19. 'name', 'subscriptions_count',
  20. 'monthly_unit_cost', 'new_subscriber_cost')
  21. readonly_fields = (
  22. 'subscriptions_count',
  23. 'monthly_unit_cost', 'new_subscriber_cost')
  24. show_change_link = True
  25. extra = 0
  26. verbose_name = 'Service proposé'
  27. verbose_name_plural = 'Services proposés'
  28. def monthly_unit_cost(self, obj):
  29. return '{:.2f}€'.format(obj.get_prices()['unit_recurring_price'])
  30. monthly_unit_cost.short_description = "Coût de revient mensuel"
  31. def new_subscriber_cost(self, obj):
  32. return '{:.2f}€'.format(obj.get_prices()['unit_goods_value_share'])
  33. new_subscriber_cost.short_description = "Coût nouv. abo"
  34. @admin.register(Document)
  35. class DocumentAdmin(admin.ModelAdmin):
  36. list_display = ('name', 'date', 'type')
  37. actions = ['copy']
  38. inlines = [ServiceInline, GoodInline, CostInline]
  39. save_on_top = True
  40. def copy(self, request, queryset):
  41. for i in queryset.all():
  42. new = i.copy()
  43. edit_url = reverse('admin:costs_document_change', args=(new.pk,))
  44. self.message_user(
  45. request, mark_safe(
  46. "{} a été créé, en tant que brouillon, pensez à <a href=\"{}\">l'éditer</a>.".format(
  47. new, edit_url)))
  48. copy.short_description = 'Copier'
  49. class AbstractUseInline(admin.TabularInline):
  50. """ An inline with some knowledge of the currently edited Document
  51. """
  52. fields = ['share', 'help', 'view_help', 'resource']
  53. readonly_fields = ['view_help']
  54. class Media:
  55. js = ("edit_help.js",)
  56. def view_help(self, obj):
  57. return mark_safe(markdown.markdown(getattr(obj, 'help', '')
  58. + ''' <a class='edit_help' title='Editer le text'><img src="/static/admin/img/icon-changelink.svg" alt="Modifier"></a>'''))
  59. def formfield_for_foreignkey(self, db_field, request, **kwargs):
  60. if db_field.name == "resource" and getattr(request, 'document', None):
  61. kwargs["queryset"] = db_field.related_model.objects.filter(
  62. document=request.document)
  63. return super().formfield_for_foreignkey(
  64. db_field, request, **kwargs)
  65. class GoodUseInline(AbstractUseInline):
  66. model = GoodUse
  67. extra = 1
  68. class CostUseInline(AbstractUseInline):
  69. model = CostUse
  70. extra = 1
  71. class ServiceUseInline(AbstractUseInline):
  72. model = ServiceUse
  73. extra = 1
  74. fk_name = 'service'
  75. class DirectDocumentFilter(admin.SimpleListFilter):
  76. title = 'Rapport'
  77. parameter_name = 'document'
  78. def queryset(self, request, queryset):
  79. document = self.value()
  80. if not document:
  81. return queryset.none()
  82. else:
  83. return queryset.filter(document=document)
  84. def lookups(self, request, model_admin):
  85. for i in Document.objects.all():
  86. yield i.pk, str(i)
  87. def choices(self, changelist):
  88. """ Same as base SimpleListFilter but do not display the "All" choice
  89. """
  90. for lookup, title in self.lookup_choices:
  91. yield {
  92. 'selected': self.value() == force_text(lookup),
  93. 'query_string': changelist.get_query_string(
  94. {self.parameter_name: lookup}, []),
  95. 'display': title,
  96. }
  97. @admin.register(Service)
  98. class ServiceAdmin(admin.ModelAdmin):
  99. list_display = (
  100. 'name', 'subscriptions_count', 'document',
  101. 'monthly_unit_cost', 'new_subscriber_cost')
  102. inlines = (CostUseInline, GoodUseInline, ServiceUseInline)
  103. list_filter = [DirectDocumentFilter]
  104. fieldsets = (
  105. (None, {
  106. 'fields': (
  107. ('name', 'document'), 'description', 'subscriptions_count'),
  108. }),
  109. ('Utilisation', {
  110. 'fields': ('reusable', 'internal')
  111. })
  112. )
  113. save_on_top = True
  114. def get_form(self, request, obj=None, **kwargs):
  115. if obj:
  116. # anotate the request with some context
  117. request.document = obj.document
  118. else:
  119. doc_pk = request.GET.get('document')
  120. if doc_pk:
  121. request.document = Document.objects.get(pk=doc_pk)
  122. else:
  123. request.document = None
  124. if request.method == 'GET':
  125. self.message_user(
  126. request,
  127. 'Il est nécessaire de faire "Enregistrer et continuer"'
  128. ' pour ajouter des ressources au service',
  129. messages.WARNING)
  130. return super().get_form(request, obj, **kwargs)
  131. def get_inline_instances(self, request, obj=None):
  132. if getattr(request, 'document', None):
  133. return super().get_inline_instances(request, obj)
  134. else:
  135. return []
  136. def monthly_unit_cost(self, obj):
  137. return '{:.2f}€'.format(obj.get_prices()['unit_recurring_price'])
  138. def new_subscriber_cost(self, obj):
  139. return '{:.2f}€'.format(obj.get_prices()['total_goods_value_share'])
  140. @admin.register(Good)
  141. class GoodAdmin(admin.ModelAdmin):
  142. list_filter = [DirectDocumentFilter]
  143. exclude = ['description_html']
  144. @admin.register(Cost)
  145. class CostAdmin(admin.ModelAdmin):
  146. list_filter = [DirectDocumentFilter]
  147. exclude = ['description_html']