admin.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. from django.contrib import admin
  2. from django.db import models
  3. from django.forms import ModelForm, BaseInlineFormSet
  4. from django.utils import timezone
  5. from django.core.urlresolvers import reverse
  6. from django.utils.html import format_html
  7. from django.core.mail import mail_managers
  8. from adhesions.models import Adhesion
  9. from djadhere.utils import get_active_filter
  10. from .models import Service, ServiceType, IPResource, Route, ResourceAllocation
  11. from .utils import notify_allocation
  12. ### Filters
  13. class ResourceInUseFilter(admin.SimpleListFilter):
  14. title = 'disponibilité'
  15. parameter_name = 'available'
  16. def lookups(self, request, model_admin):
  17. return (
  18. (1, 'Disponible'),
  19. (0, 'Non disponible'),
  20. )
  21. def queryset(self, request, queryset):
  22. now = timezone.now()
  23. active_filter = get_active_filter('allocation')
  24. if self.value() == '0': # non disponible
  25. return queryset.filter(active_filter | models.Q(reserved=True))
  26. if self.value() == '1': # disponible
  27. return queryset.exclude(reserved=True).exclude(active_filter)
  28. class AllocationStatusFilter(admin.SimpleListFilter):
  29. title = 'statut'
  30. parameter_name = 'status'
  31. def lookups(self, request, model_admin):
  32. return (
  33. (1, 'En cours'),
  34. (0, 'Terminée'),
  35. )
  36. def queryset(self, request, queryset):
  37. now = timezone.now()
  38. active_filter = get_active_filter()
  39. if self.value() == '0': # inactif
  40. return queryset.exclude(active_filter)
  41. if self.value() == '1': # actif
  42. return queryset.filter(active_filter)
  43. ### Inlines
  44. class ResourceAllocationInlineFormSet(BaseInlineFormSet):
  45. def save_new(self, form, commit=True):
  46. obj = super().save_new(form, commit)
  47. notify_allocation(self.request, obj)
  48. return obj
  49. def save_existing(self, form, instance, commit=True):
  50. old = ResourceAllocation.objects.get(pk=instance.pk)
  51. notify_allocation(self.request, instance, old)
  52. return super().save_existing(form, instance, commit)
  53. class AllocationInline(admin.TabularInline):
  54. model = ResourceAllocation
  55. formset = ResourceAllocationInlineFormSet
  56. extra = 0
  57. fields = ('id', 'service', 'resource', 'route', 'start', 'end')
  58. raw_id_fields = ('service', 'resource',)
  59. verbose_name_plural = 'Allocations'
  60. show_change_link = True
  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_max_num(self, request, obj=None, **kwargs):
  66. existing = obj.allocations.count() if obj else 0
  67. # pour simplifier la validation, on ajoute qu’une allocation à la fois
  68. # il faudrait surcharger la méthode clean du formset pour supprimer cette limite
  69. return existing + 1
  70. def has_delete_permission(self, request, obj=None):
  71. return False
  72. ### Actions
  73. def ends_resource(resource, request, queryset):
  74. now = timezone.now()
  75. queryset.exclude(start__lte=now, end__isnull=False).update(end=now)
  76. # TODO: send mail
  77. ends_resource.short_description = 'Terminer les allocations sélectionnées'
  78. ### ModelAdmin
  79. class ServiceAdmin(admin.ModelAdmin):
  80. list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
  81. list_select_related = ('adhesion',) # to reduce database requests
  82. list_filter = (
  83. 'active',
  84. ('service_type', admin.RelatedOnlyFieldListFilter),
  85. )
  86. inlines = (AllocationInline,)
  87. search_fields = ('id', 'service_type__name', 'label', 'adhesion__id',)
  88. raw_id_fields = ('adhesion',)
  89. get_adhesion_link = lambda self, service: service.adhesion.get_adhesion_link()
  90. get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
  91. get_adherent_link = lambda self, service: service.adhesion.get_adherent_link()
  92. get_adherent_link.short_description = Adhesion.get_adherent_link.short_description
  93. def get_actions(self, request):
  94. actions = super().get_actions(request)
  95. if 'delete_selected' in actions:
  96. del actions['delete_selected']
  97. return actions
  98. def has_delete_permission(self, request, obj=None):
  99. return False
  100. class IPResourceAdmin(admin.ModelAdmin):
  101. list_display = ('__str__', 'available_display')
  102. list_filter = (
  103. ResourceInUseFilter,
  104. ('prefixes', admin.RelatedOnlyFieldListFilter),
  105. )
  106. fields = ('ip', 'reserved', 'notes')
  107. readonly_fields = ('ip', 'reserved',)
  108. search_fields = ('ip',)
  109. inlines = (AllocationInline,)
  110. def available_display(self, obj):
  111. return not obj.reserved and not obj.in_use
  112. available_display.short_description = 'Disponible'
  113. available_display.boolean = True
  114. def get_actions(self, request):
  115. actions = super().get_actions(request)
  116. if 'delete_selected' in actions:
  117. del actions['delete_selected']
  118. return actions
  119. def has_add_permission(self, request, obj=None):
  120. return False
  121. def has_delete_permission(self, request, obj=None):
  122. return False
  123. class RouteAdmin(admin.ModelAdmin):
  124. fields = ('name',)
  125. readonly_fields = ('name',)
  126. def has_add_permission(self, request, obj=None):
  127. return False
  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_delete_permission(self, request, obj=None):
  134. return False
  135. class ResourceAllocationAdmin(admin.ModelAdmin):
  136. list_display = ('id', 'resource', 'service', 'start', 'end',)
  137. list_display_links = ('resource', 'service',)
  138. list_filter = (AllocationStatusFilter,)
  139. #actions = (ends_resource,)
  140. raw_id_fields = ('resource', 'service',)
  141. search_fields = ('resource__ip', 'service__id', 'service__service_type__name', 'service__label')
  142. def get_actions(self, request):
  143. actions = super().get_actions(request)
  144. if 'delete_selected' in actions:
  145. del actions['delete_selected']
  146. return actions
  147. def has_delete_permission(self, request, obj=None):
  148. return False
  149. def save_model(self, request, obj, form, change):
  150. if change:
  151. old_alloc = ResourceAllocation.objects.get(pk=obj.pk)
  152. else:
  153. old_alloc = None
  154. super().save_model(request, obj, form, change)
  155. notify_allocation(request, obj, old_alloc)
  156. class ServiceTypeAdmin(admin.ModelAdmin):
  157. fields = ('name',)
  158. readonly_fields = ('name',)
  159. def get_actions(self, request):
  160. actions = super().get_actions(request)
  161. if 'delete_selected' in actions:
  162. del actions['delete_selected']
  163. return actions
  164. def has_add_permission(self, request, obj=None):
  165. return False
  166. def has_delete_permission(self, request, obj=None):
  167. return False
  168. admin.site.register(ServiceType, ServiceTypeAdmin)
  169. admin.site.register(Service, ServiceAdmin)
  170. admin.site.register(IPResource, IPResourceAdmin)
  171. admin.site.register(Route, RouteAdmin)
  172. admin.site.register(ResourceAllocation, ResourceAllocationAdmin)