# -*- 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)