admin.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. from django.contrib import admin
  4. from django.contrib.auth import get_user_model
  5. from django.forms import ModelChoiceField
  6. import autocomplete_light
  7. from .models import ItemType, Item, Loan, Storage
  8. import coin.members.admin
  9. User = get_user_model()
  10. admin.site.register(ItemType)
  11. class OwnerFilter(admin.SimpleListFilter):
  12. title = "Propriétaire"
  13. parameter_name = 'owner'
  14. def lookups(self, request, model_admin):
  15. owners = [
  16. (i.pk, i) for i in User.objects.filter(items__isnull=False)]
  17. return [(None, "L'association")] + owners
  18. def queryset(self, request, queryset):
  19. if self.value():
  20. return queryset.filter(owner__pk=self.value())
  21. else:
  22. return queryset
  23. class AvailabilityFilter(admin.SimpleListFilter):
  24. title = "Disponibilité"
  25. parameter_name = 'availability'
  26. def lookups(self, request, model_admin):
  27. return [
  28. ('available', 'Disponible'),
  29. ('borrowed', 'Emprunté'),
  30. ('deployed', 'Déployé'),
  31. ]
  32. def queryset(self, request, queryset):
  33. if self.value() == 'available':
  34. return queryset.available()
  35. elif self.value() == 'borrowed':
  36. return queryset.borrowed()
  37. elif self.value() == 'deployed':
  38. return queryset.deployed()
  39. else:
  40. return queryset
  41. class CurrentLoanInline(admin.TabularInline):
  42. model = Loan
  43. extra = 0
  44. fields = ('user', 'item', 'short_date', 'notes')
  45. readonly_fields = ('user', 'item', 'short_date', 'notes')
  46. verbose_name_plural = "Emprunt en cours"
  47. show_change_link = True
  48. def get_queryset(self, request):
  49. qs = super(CurrentLoanInline, self).get_queryset(request)
  50. return qs.running()
  51. def has_add_permission(self, request, obj=None):
  52. return False
  53. def has_delete_permission(self, request, obj=None):
  54. return False
  55. class LoanHistoryInline(admin.TabularInline):
  56. model = Loan
  57. extra = 0
  58. fields = ('user', 'item', 'short_date', 'short_date_end', 'notes')
  59. readonly_fields = ('user', 'item', 'short_date', 'short_date_end', 'notes')
  60. ordering = ['-loan_date_end']
  61. verbose_name_plural = "Historique de prêt de cet objet"
  62. show_change_link = True
  63. classes = ['collapse'] # Django >= 1.10-ready
  64. def get_queryset(self, request):
  65. qs = super(LoanHistoryInline, self).get_queryset(request)
  66. return qs.finished()
  67. def has_add_permission(self, request, obj=None):
  68. return False
  69. def has_delete_permission(self, request, obj=None):
  70. return False
  71. class AddLoanInline(admin.StackedInline):
  72. model = Loan
  73. extra = 1
  74. max_num = 1
  75. fields = ('user', 'item', 'loan_date', 'notes')
  76. verbose_name_plural = "Déclarer le prêt de cet objet"
  77. classes = ['collapse'] # Django >= 1.10-ready
  78. form = autocomplete_light.modelform_factory(Loan, fields='__all__')
  79. def get_queryset(self, request):
  80. qs = super(AddLoanInline, self).get_queryset(request)
  81. return qs.none()
  82. def has_delete_permission(self, request, obj=None):
  83. return False
  84. class BorrowerFilter(admin.SimpleListFilter):
  85. title = 'Adhérent emprunteur'
  86. parameter_name = 'user'
  87. def _filter_loans(self, items_queryset, user_pk=None):
  88. qs = Loan.objects.running().filter(item__in=items_queryset)
  89. if user_pk is not None:
  90. qs.filter(user=user_pk)
  91. return qs
  92. def lookups(self, request, model_admin):
  93. # Get relevant (and authorized) users only
  94. relevant_items = model_admin.get_queryset(request)
  95. users = set()
  96. for loan in self._filter_loans(relevant_items):
  97. users.add((loan.user.pk, loan.user))
  98. return users
  99. def queryset(self, request, queryset):
  100. if self.value():
  101. loans_qs = self._filter_loans(queryset).filter(
  102. user__pk=self.value(),
  103. )
  104. return queryset.filter(loans__in=loans_qs)
  105. else:
  106. return queryset
  107. @admin.register(Item)
  108. class ItemAdmin(admin.ModelAdmin):
  109. list_display = (
  110. 'designation',
  111. 'current_borrower',
  112. 'get_mac_and_serial',
  113. 'deployed', 'is_available', 'storage',
  114. 'buy_date', 'owner',
  115. )
  116. list_filter = (
  117. AvailabilityFilter, 'type', 'storage',
  118. 'buy_date', BorrowerFilter, OwnerFilter)
  119. search_fields = (
  120. 'designation', 'mac_address', 'serial',
  121. 'owner__email', 'owner__nickname',
  122. 'owner__first_name', 'owner__last_name')
  123. save_as = True
  124. actions = ['give_back']
  125. form = autocomplete_light.modelform_factory(Loan, fields='__all__')
  126. inlines = [AddLoanInline, CurrentLoanInline, LoanHistoryInline]
  127. def give_back(self, request, queryset):
  128. for item in queryset.filter(loans__loan_date_end=None):
  129. item.give_back()
  130. give_back.short_description = 'Rendre le matériel'
  131. class StatusFilter(admin.SimpleListFilter):
  132. title = 'Statut'
  133. parameter_name = 'status'
  134. def lookups(self, request, model_admin):
  135. return [
  136. ('all', 'Tout'),
  137. (None, 'En cours'),
  138. ('finished', 'Passés'),
  139. ]
  140. def choices(self, cl):
  141. for lookup, title in self.lookup_choices:
  142. yield {
  143. 'selected': self.value() == lookup,
  144. 'query_string': cl.get_query_string({
  145. self.parameter_name: lookup,
  146. }, []),
  147. 'display': title,
  148. }
  149. def queryset(self, request, queryset):
  150. v = self.value()
  151. if v in (None, 'running'):
  152. return queryset.running()
  153. elif v == 'finished':
  154. return queryset.finished()
  155. else:
  156. return queryset
  157. class BorrowerFilter(admin.SimpleListFilter):
  158. title = 'Adhérent emprunteur'
  159. parameter_name = 'user'
  160. def lookups(self, request, model_admin):
  161. users = set()
  162. for loan in model_admin.get_queryset(request):
  163. users.add((loan.user.pk, loan.user))
  164. return users
  165. def queryset(self, request, queryset):
  166. if self.value():
  167. return queryset.filter(user=self.value())
  168. else:
  169. return queryset
  170. class ItemChoiceField(ModelChoiceField):
  171. # On surcharge cette méthode pour afficher mac et n° de série dans le menu
  172. # déroulant de sélection d'un objet dans la création d'un prêt.
  173. def label_from_instance(self, obj):
  174. return obj.designation + ' ' + obj.get_mac_and_serial()
  175. @admin.register(Loan)
  176. class LoanAdmin(admin.ModelAdmin):
  177. list_display = ('item', 'get_mac_and_serial', 'user', 'loan_date', 'loan_date_end')
  178. list_filter = (StatusFilter, BorrowerFilter, 'item__designation')
  179. search_fields = (
  180. 'item__designation',
  181. 'user__nickname', 'user__username',
  182. 'user__first_name', 'user__last_name', )
  183. actions = ['end_loan']
  184. def end_loan(self, request, queryset):
  185. queryset.filter(loan_date_end=None).update(
  186. loan_date_end=datetime.now())
  187. end_loan.short_description = 'Mettre fin au prêt'
  188. form = autocomplete_light.modelform_factory(Loan, fields='__all__')
  189. def formfield_for_foreignkey(self, db_field, request, **kwargs):
  190. if db_field.name == 'item':
  191. kwargs['queryset'] = Item.objects.all()
  192. return ItemChoiceField(**kwargs)
  193. else:
  194. return super(LoanAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
  195. @admin.register(Storage)
  196. class StorageAdmin(admin.ModelAdmin):
  197. list_display = ('name', 'truncated_notes', 'items_count')
  198. def truncated_notes(self, obj):
  199. if len(obj.notes) > 50:
  200. return '{}…'.format(obj.notes[:50])
  201. else:
  202. return obj.notes
  203. truncated_notes.short_description = 'notes'
  204. class LoanInline(admin.TabularInline):
  205. model = Loan
  206. extra = 0
  207. exclude = ('notes',)
  208. readonly_fields = ('item', 'get_mac_and_serial', 'loan_date', 'loan_date_end', 'is_running')
  209. show_change_link = True
  210. def get_queryset(self, request):
  211. qs = super(LoanInline, self).get_queryset(request)
  212. return qs.order_by('-loan_date_end')
  213. def has_add_permission(self, request, obj=None):
  214. return False
  215. def has_delete_permission(self, request, obj=None):
  216. return False
  217. class MemberAdmin(coin.members.admin.MemberAdmin):
  218. inlines = coin.members.admin.MemberAdmin.inlines + [LoanInline]
  219. admin.site.unregister(coin.members.admin.Member)
  220. admin.site.register(coin.members.admin.Member, MemberAdmin)