from django.contrib import admin from django.db import models from django.forms import ModelForm from django.utils import timezone from django.core.urlresolvers import reverse from django.utils.html import format_html from django.core.mail import mail_managers from adhesions.models import Adhesion from .models import Service, ServiceType, IPResource, Route, ResourceAllocation from djadhere.utils import get_active_filter ### Filters class ResourceInUseFilter(admin.SimpleListFilter): title = 'disponibilité' parameter_name = 'available' def lookups(self, request, model_admin): return ( (1, 'Disponible'), (0, 'Non disponible'), ) def queryset(self, request, queryset): now = timezone.now() active_filter = get_active_filter('allocation') if self.value() == '0': # non disponible return queryset.filter(active_filter | models.Q(reserved=True)) if self.value() == '1': # disponible return queryset.exclude(reserved=True).exclude(active_filter) class AllocationStatusFilter(admin.SimpleListFilter): title = 'statut' parameter_name = 'status' def lookups(self, request, model_admin): return ( (1, 'En cours'), (0, 'Terminée'), ) def queryset(self, request, queryset): now = timezone.now() active_filter = get_active_filter() if self.value() == '0': # inactif return queryset.exclude(active_filter) if self.value() == '1': # actif return queryset.filter(active_filter) ### Helpers def get_foreignkey_link_func(field): def foreignkey_link(self, instance): obj = getattr(instance, field) url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.model_name), args=(obj.pk,)) return format_html(u'{}', url, str(obj)) return foreignkey_link ### Inlines class AllocationInline(admin.TabularInline): model = ResourceAllocation extra = 0 fields = ('id', 'service', 'resource', 'route', 'start', 'end') raw_id_fields = ('service', 'resource',) verbose_name_plural = 'Allocations' show_change_link = True def get_max_num(self, request, obj=None, **kwargs): existing = obj.allocations.count() if obj else 0 # pour simplifier la validation, on ajoute qu’une allocation à la fois return existing + 1 def has_delete_permission(self, request, obj=None): return False ### Actions def ends_resource(resource, request, queryset): now = timezone.now() queryset.exclude(start__lte=now, end__isnull=False).update(end=now) ends_resource.short_description = 'Terminer les allocations sélectionnées' ### ModelAdmin class ServiceAdmin(admin.ModelAdmin): list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active') list_filter = ( 'active', ('service_type', admin.RelatedOnlyFieldListFilter), ) inlines = (AllocationInline,) search_fields = ('id', 'service_type__name', 'label', 'adhesion__id',) raw_id_fields = ('adhesion',) get_adhesion_link = get_foreignkey_link_func('adhesion') get_adhesion_link.short_description = 'Numéro d’adhésion' get_adherent_link = lambda self, service: service.adhesion.get_adherent_link() get_adherent_link.short_description = Adhesion.get_adherent_link.short_description def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_delete_permission(self, request, obj=None): return False class IPResourceAdmin(admin.ModelAdmin): list_display = ('__str__', 'available_display') list_filter = ( ResourceInUseFilter, ('prefixes', admin.RelatedOnlyFieldListFilter), ) fields = ('ip', 'reserved',) readonly_fields = ('ip', 'reserved',) search_fields = ('ip',) inlines = (AllocationInline,) def available_display(self, obj): return not obj.reserved and not obj.in_use available_display.short_description = 'Disponible' available_display.boolean = True def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False class RouteAdmin(admin.ModelAdmin): fields = ('name',) readonly_fields = ('name',) def has_add_permission(self, request, obj=None): return False def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_delete_permission(self, request, obj=None): return False class ResourceAllocationAdmin(admin.ModelAdmin): list_display = ('id', 'resource_link', 'service_link', 'start', 'end',) list_filter = (AllocationStatusFilter,) actions = (ends_resource,) raw_id_fields = ('resource', 'service',) search_fields = ('resource__ip', 'service__id', 'service__service_type__name', 'service__label') resource_link = get_foreignkey_link_func('resource') resource_link.short_description = 'Ressource' service_link = get_foreignkey_link_func('service') service_link.short_description = 'Service' def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_delete_permission(self, request, obj=None): return False def save_model(self, request, obj, form, change): fields = ['resource', 'service', 'route', 'start', 'end', 'active', 'notes'] new_alloc = obj if change: old_alloc = ResourceAllocation.objects.get(pk=new_alloc.pk) else: old_alloc = None super().save_model(request, obj, form, change) message = 'Bénévole : ' + str(request.user.profile) message += '\n\nAllocation :' diff = False for field in fields: new_attr = getattr(new_alloc, field) if new_attr == '' or new_attr is None: new_attr = '-' if old_alloc: old_attr = getattr(old_alloc, field) if old_attr == '' or old_attr is None: old_attr = '-' if change and old_attr != new_attr: message += '\n-%12s: %s\n+%12s: %s' % (field, old_attr, field, new_attr) diff = True else: message += '\n %12s: %s' % (field, new_attr) url = 'https' if request.is_secure() else 'http' url += '://' + request.get_host() url += reverse('admin:services_resourceallocation_change', args=(obj.pk,)) message += '\n\nVoir : ' + url if old_alloc and diff: sujet = 'Modification d’une allocation' elif not old_alloc: sujet = 'Nouvelle allocation' else: sujet = None if sujet: mail_managers(sujet, message) class ServiceTypeAdmin(admin.ModelAdmin): fields = ('name',) readonly_fields = ('name',) def get_actions(self, request): actions = super().get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] return actions def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False admin.site.register(ServiceType, ServiceTypeAdmin) admin.site.register(Service, ServiceAdmin) admin.site.register(IPResource, IPResourceAdmin) admin.site.register(Route, RouteAdmin) admin.site.register(ResourceAllocation, ResourceAllocationAdmin)