# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf.urls import url from django.shortcuts import get_object_or_404 from django.contrib import admin, messages from django.contrib.auth import get_user_model from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect import autocomplete_light from .models import ItemType, Item, Loan, Storage import coin.members.admin User = get_user_model() admin.site.register(ItemType) def give_back_loan(request, id): # could be better : could not be a POST, and could not rely on HTTP_REFERER # We could for that rely on django-inline-actions, but the version # we could use with our Django 1.9 is outdated and buggy # We could also offer an intermediate page to specify the storage redirect_url = request.META['HTTP_REFERER'] loan = get_object_or_404(Loan, pk=id) loan.item.give_back() messages.success( request, "{} a bien été marqué comme rendu".format(loan.item), ) return HttpResponseRedirect(redirect_url) class OwnerFilter(admin.SimpleListFilter): title = "Propriétaire" parameter_name = 'owner' def lookups(self, request, model_admin): owners = [ (i.pk, i) for i in User.objects.filter(items__isnull=False)] return [(None, "L'association")] + owners def queryset(self, request, queryset): if self.value(): return queryset.filter(owner__pk=self.value()) else: return queryset class AvailabilityFilter(admin.SimpleListFilter): title = "Disponibilité" parameter_name = 'availability' def lookups(self, request, model_admin): return [ ('available', 'Disponible'), ('borrowed', 'Emprunté'), ('deployed', 'Déployé'), ] def queryset(self, request, queryset): if self.value() == 'available': return queryset.available() elif self.value() == 'borrowed': return queryset.borrowed() elif self.value() == 'deployed': return queryset.deployed() else: return queryset class CurrentLoanInline(admin.TabularInline): model = Loan extra = 0 fields = ('user', 'item', 'short_date', 'notes', 'action_buttons') readonly_fields = ('user', 'item', 'short_date', 'notes', 'action_buttons') verbose_name_plural = "Emprunt en cours" show_change_link = True def get_queryset(self, request): qs = super(CurrentLoanInline, self).get_queryset(request) return qs.running() def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False def action_buttons(self, obj): if obj.is_running(): return """Déclarer rendu""".format( reverse('admin:loan-give_back', args=[obj.pk])) else: return '' action_buttons.short_description = 'Actions' action_buttons.allow_tags = True class LoanHistoryInline(admin.TabularInline): model = Loan extra = 0 fields = ('user', 'item', 'short_date', 'short_date_end', 'notes') readonly_fields = ('user', 'item', 'short_date', 'short_date_end', 'notes') ordering = ['-loan_date_end'] verbose_name_plural = "Historique de prêt de cet objet" show_change_link = True classes = ['collapse'] # Django >= 1.10-ready def get_queryset(self, request): qs = super(LoanHistoryInline, self).get_queryset(request) return qs.finished() def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False class AddLoanInline(admin.StackedInline): model = Loan extra = 1 max_num = 1 fields = ('user', 'item', 'loan_date', 'notes') verbose_name_plural = "Déclarer le prêt de cet objet" classes = ['collapse'] # Django >= 1.10-ready form = autocomplete_light.modelform_factory(Loan, fields='__all__') def get_queryset(self, request): qs = super(AddLoanInline, self).get_queryset(request) return qs.none() def has_delete_permission(self, request, obj=None): return False class BorrowerFilter(admin.SimpleListFilter): title = 'Adhérent emprunteur' parameter_name = 'user' def _filter_loans(self, items_queryset, user_pk=None): qs = Loan.objects.running().filter(item__in=items_queryset) if user_pk is not None: qs.filter(user=user_pk) return qs def lookups(self, request, model_admin): # Get relevant (and authorized) users only relevant_items = model_admin.get_queryset(request) users = set() for loan in self._filter_loans(relevant_items): users.add((loan.user.pk, loan.user)) return users def queryset(self, request, queryset): if self.value(): loans_qs = self._filter_loans(queryset).filter( user__pk=self.value(), ) return queryset.filter(loans__in=loans_qs) else: return queryset @admin.register(Item) class ItemAdmin(admin.ModelAdmin): list_display = ( 'designation', 'current_borrower', 'get_mac_and_serial', 'deployed', 'is_available', 'storage', 'buy_date', 'owner', ) list_filter = ( AvailabilityFilter, 'type', 'storage', 'buy_date', BorrowerFilter, OwnerFilter) search_fields = ( 'designation', 'mac_address', 'serial', 'owner__email', 'owner__nickname', 'owner__first_name', 'owner__last_name') save_as = True actions = ['give_back'] form = autocomplete_light.modelform_factory(Loan, fields='__all__') inlines = [AddLoanInline, CurrentLoanInline, LoanHistoryInline] def give_back(self, request, queryset): for item in queryset.filter(loans__loan_date_end=None): item.give_back() give_back.short_description = 'Rendre le matériel' def get_urls(self): urls = super(ItemAdmin, self).get_urls() my_urls = [ url( r'^give_back/(?P.+)$', self.admin_site.admin_view(give_back_loan), name='loan-give_back'), ] return my_urls + urls class StatusFilter(admin.SimpleListFilter): title = 'Statut' parameter_name = 'status' def lookups(self, request, model_admin): return [ ('all', 'Tout'), (None, 'En cours'), ('finished', 'Passés'), ] def choices(self, cl): for lookup, title in self.lookup_choices: yield { 'selected': self.value() == lookup, 'query_string': cl.get_query_string({ self.parameter_name: lookup, }, []), 'display': title, } def queryset(self, request, queryset): v = self.value() if v in (None, 'running'): return queryset.running() elif v == 'finished': return queryset.finished() else: return queryset @admin.register(Storage) class StorageAdmin(admin.ModelAdmin): list_display = ('name', 'truncated_notes', 'items_count') def truncated_notes(self, obj): if len(obj.notes) > 50: return '{}…'.format(obj.notes[:50]) else: return obj.notes truncated_notes.short_description = 'notes' class LoanInline(admin.TabularInline): model = Loan extra = 0 exclude = ('notes',) readonly_fields = ('item', 'get_mac_and_serial', 'loan_date', 'loan_date_end', 'is_running') show_change_link = True def get_queryset(self, request): qs = super(LoanInline, self).get_queryset(request) return qs.order_by('-loan_date_end') def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False class MemberAdmin(coin.members.admin.MemberAdmin): inlines = coin.members.admin.MemberAdmin.inlines + [LoanInline] admin.site.unregister(coin.members.admin.Member) admin.site.register(coin.members.admin.Member, MemberAdmin)