admin.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. from django.contrib import admin
  2. from django.db import models
  3. from django.forms import ModelForm
  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 .models import Service, ServiceType, IPResource, Route, ResourceAllocation
  10. from djadhere.utils import get_active_filter
  11. ### Filters
  12. class ResourceInUseFilter(admin.SimpleListFilter):
  13. title = 'disponibilité'
  14. parameter_name = 'available'
  15. def lookups(self, request, model_admin):
  16. return (
  17. (1, 'Disponible'),
  18. (0, 'Non disponible'),
  19. )
  20. def queryset(self, request, queryset):
  21. now = timezone.now()
  22. active_filter = get_active_filter('allocation')
  23. if self.value() == '0': # non disponible
  24. return queryset.filter(active_filter | models.Q(reserved=True))
  25. if self.value() == '1': # disponible
  26. return queryset.exclude(reserved=True).exclude(active_filter)
  27. class AllocationStatusFilter(admin.SimpleListFilter):
  28. title = 'statut'
  29. parameter_name = 'status'
  30. def lookups(self, request, model_admin):
  31. return (
  32. (1, 'En cours'),
  33. (0, 'Terminée'),
  34. )
  35. def queryset(self, request, queryset):
  36. now = timezone.now()
  37. active_filter = get_active_filter()
  38. if self.value() == '0': # inactif
  39. return queryset.exclude(active_filter)
  40. if self.value() == '1': # actif
  41. return queryset.filter(active_filter)
  42. ### Helpers
  43. def get_foreignkey_link_func(field):
  44. def foreignkey_link(self, instance):
  45. obj = getattr(instance, field)
  46. url = reverse('admin:%s_%s_change' % (obj._meta.app_label,
  47. obj._meta.model_name),
  48. args=(obj.pk,))
  49. return format_html(u'<a href="{}">{}</a>', url, str(obj))
  50. return foreignkey_link
  51. ### Inlines
  52. class AllocationInline(admin.TabularInline):
  53. model = ResourceAllocation
  54. extra = 0
  55. fields = ('id', 'service', 'resource', 'route', 'start', 'end')
  56. raw_id_fields = ('service', 'resource',)
  57. verbose_name_plural = 'Allocations'
  58. show_change_link = True
  59. def get_max_num(self, request, obj=None, **kwargs):
  60. existing = obj.allocations.count() if obj else 0
  61. # pour simplifier la validation, on ajoute qu’une allocation à la fois
  62. return existing + 1
  63. def has_delete_permission(self, request, obj=None):
  64. return False
  65. ### Actions
  66. def ends_resource(resource, request, queryset):
  67. now = timezone.now()
  68. queryset.exclude(start__lte=now, end__isnull=False).update(end=now)
  69. ends_resource.short_description = 'Terminer les allocations sélectionnées'
  70. ### ModelAdmin
  71. class ServiceAdmin(admin.ModelAdmin):
  72. list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
  73. list_filter = (
  74. 'active',
  75. ('service_type', admin.RelatedOnlyFieldListFilter),
  76. )
  77. inlines = (AllocationInline,)
  78. search_fields = ('id', 'service_type__name', 'label', 'adhesion__id',)
  79. raw_id_fields = ('adhesion',)
  80. get_adhesion_link = get_foreignkey_link_func('adhesion')
  81. get_adhesion_link.short_description = 'Numéro d’adhésion'
  82. get_adherent_link = lambda self, service: service.adhesion.get_adherent_link()
  83. get_adherent_link.short_description = Adhesion.get_adherent_link.short_description
  84. def get_actions(self, request):
  85. actions = super().get_actions(request)
  86. if 'delete_selected' in actions:
  87. del actions['delete_selected']
  88. return actions
  89. def has_delete_permission(self, request, obj=None):
  90. return False
  91. class IPResourceAdmin(admin.ModelAdmin):
  92. list_display = ('__str__', 'available_display')
  93. list_filter = (
  94. ResourceInUseFilter,
  95. ('prefixes', admin.RelatedOnlyFieldListFilter),
  96. )
  97. fields = ('ip', 'reserved',)
  98. readonly_fields = ('ip', 'reserved',)
  99. search_fields = ('ip',)
  100. inlines = (AllocationInline,)
  101. def available_display(self, obj):
  102. return not obj.reserved and not obj.in_use
  103. available_display.short_description = 'Disponible'
  104. available_display.boolean = True
  105. def get_actions(self, request):
  106. actions = super().get_actions(request)
  107. if 'delete_selected' in actions:
  108. del actions['delete_selected']
  109. return actions
  110. def has_add_permission(self, request, obj=None):
  111. return False
  112. def has_delete_permission(self, request, obj=None):
  113. return False
  114. class RouteAdmin(admin.ModelAdmin):
  115. fields = ('name',)
  116. readonly_fields = ('name',)
  117. def has_add_permission(self, request, obj=None):
  118. return False
  119. def get_actions(self, request):
  120. actions = super().get_actions(request)
  121. if 'delete_selected' in actions:
  122. del actions['delete_selected']
  123. return actions
  124. def has_delete_permission(self, request, obj=None):
  125. return False
  126. class ResourceAllocationAdmin(admin.ModelAdmin):
  127. list_display = ('id', 'resource_link', 'service_link', 'start', 'end',)
  128. list_filter = (AllocationStatusFilter,)
  129. actions = (ends_resource,)
  130. raw_id_fields = ('resource', 'service',)
  131. search_fields = ('resource__ip', 'service__id', 'service__service_type__name', 'service__label')
  132. resource_link = get_foreignkey_link_func('resource')
  133. resource_link.short_description = 'Ressource'
  134. service_link = get_foreignkey_link_func('service')
  135. service_link.short_description = 'Service'
  136. def get_actions(self, request):
  137. actions = super().get_actions(request)
  138. if 'delete_selected' in actions:
  139. del actions['delete_selected']
  140. return actions
  141. def has_delete_permission(self, request, obj=None):
  142. return False
  143. def save_model(self, request, obj, form, change):
  144. fields = ['resource', 'service', 'route', 'start', 'end', 'active', 'notes']
  145. new_alloc = obj
  146. if change:
  147. old_alloc = ResourceAllocation.objects.get(pk=new_alloc.pk)
  148. else:
  149. old_alloc = None
  150. super().save_model(request, obj, form, change)
  151. message = 'Bénévole : ' + str(request.user.profile)
  152. message += '\n\nAllocation :'
  153. diff = False
  154. for field in fields:
  155. new_attr = getattr(new_alloc, field)
  156. if new_attr == '' or new_attr is None:
  157. new_attr = '-'
  158. if old_alloc:
  159. old_attr = getattr(old_alloc, field)
  160. if old_attr == '' or old_attr is None:
  161. old_attr = '-'
  162. if change and old_attr != new_attr:
  163. message += '\n-%12s: %s\n+%12s: %s' % (field, old_attr, field, new_attr)
  164. diff = True
  165. else:
  166. message += '\n %12s: %s' % (field, new_attr)
  167. url = 'https' if request.is_secure() else 'http'
  168. url += '://' + request.get_host()
  169. url += reverse('admin:services_resourceallocation_change', args=(obj.pk,))
  170. message += '\n\nVoir : ' + url
  171. if old_alloc and diff:
  172. sujet = 'Modification d’une allocation'
  173. elif not old_alloc:
  174. sujet = 'Nouvelle allocation'
  175. else:
  176. sujet = None
  177. if sujet:
  178. mail_managers(sujet, message)
  179. class ServiceTypeAdmin(admin.ModelAdmin):
  180. fields = ('name',)
  181. readonly_fields = ('name',)
  182. def get_actions(self, request):
  183. actions = super().get_actions(request)
  184. if 'delete_selected' in actions:
  185. del actions['delete_selected']
  186. return actions
  187. def has_add_permission(self, request, obj=None):
  188. return False
  189. def has_delete_permission(self, request, obj=None):
  190. return False
  191. admin.site.register(ServiceType, ServiceTypeAdmin)
  192. admin.site.register(Service, ServiceAdmin)
  193. admin.site.register(IPResource, IPResourceAdmin)
  194. admin.site.register(Route, RouteAdmin)
  195. admin.site.register(ResourceAllocation, ResourceAllocationAdmin)