from django.contrib import admin from django.db import models from django.forms import ModelForm, BaseInlineFormSet 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 djadhere.utils import get_active_filter from .models import Service, ServiceType, IPResource, Route, ResourceAllocation from .utils import notify_allocation ### 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) ### Inlines class ResourceAllocationInlineFormSet(BaseInlineFormSet): def save_new(self, form, commit=True): obj = super().save_new(form, commit) notify_allocation(self.request, obj) return obj def save_existing(self, form, instance, commit=True): old = ResourceAllocation.objects.get(pk=instance.pk) notify_allocation(self.request, instance, old) return super().save_existing(form, instance, commit) class AllocationInline(admin.TabularInline): model = ResourceAllocation formset = ResourceAllocationInlineFormSet extra = 0 fields = ('id', 'service', 'resource', 'route', 'start', 'end') raw_id_fields = ('service', 'resource',) verbose_name_plural = 'Allocations' show_change_link = True def get_formset(self, request, obj=None, **kwargs): formset = super().get_formset(request, obj, **kwargs) formset.request = request return formset 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 # il faudrait surcharger la méthode clean du formset pour supprimer cette limite 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) # TODO: send mail ends_resource.short_description = 'Terminer les allocations sélectionnées' ### ModelAdmin class ServiceAdmin(admin.ModelAdmin): list_display = ('id', 'adhesion', 'get_adherent_link', 'service_type', 'label', 'active') list_display_links = ('adhesion',) list_select_related = ('adhesion',) # to reduce database requests list_filter = ( 'active', ('service_type', admin.RelatedOnlyFieldListFilter), ) inlines = (AllocationInline,) search_fields = ('id', 'service_type__name', 'label', 'adhesion__id',) raw_id_fields = ('adhesion',) 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', 'notes') 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', 'service', 'start', 'end',) list_display_links = ('resource', 'service',) list_filter = (AllocationStatusFilter,) #actions = (ends_resource,) raw_id_fields = ('resource', 'service',) search_fields = ('resource__ip', 'service__id', 'service__service_type__name', 'service__label') 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): if change: old_alloc = ResourceAllocation.objects.get(pk=obj.pk) else: old_alloc = None super().save_model(request, obj, form, change) notify_allocation(request, obj, old_alloc) 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)