admin.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. from django.contrib import admin
  2. from django.contrib.contenttypes.admin import GenericStackedInline, GenericTabularInline
  3. from django.db.models import Q
  4. from django.contrib.contenttypes.models import ContentType
  5. from django.contrib.auth.models import User as AuthUser
  6. from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
  7. from django.http import HttpResponseRedirect
  8. from django.utils.html import format_html, mark_safe
  9. from django.urls import reverse
  10. from django.utils import timezone
  11. from django.conf.urls import url
  12. from django.template.response import TemplateResponse
  13. from .forms import UserCreationForm
  14. from .models import User, Corporation, Adhesion
  15. from accounts.models import Profile
  16. from services.models import Service
  17. from djadhere.utils import ActiveFilter, get_active_filter
  18. from banking.models import PaymentUpdate
  19. from datetime import timedelta
  20. ### Inlines
  21. class ProfileInline(admin.StackedInline):
  22. model = Profile
  23. def has_add_permission(self, request):
  24. return False
  25. def has_delete_permission(self, request, obj=None):
  26. return False
  27. class AdhesionInline(admin.StackedInline):
  28. model = Adhesion
  29. fields = ('id', 'notes',)
  30. def has_add_permission(self, request):
  31. return False
  32. def has_delete_permission(self, request, obj=None):
  33. return False
  34. class ServiceInline(admin.StackedInline):
  35. model = Service
  36. extra = 0
  37. show_change_link = True
  38. fields = ('service_type', 'label',)
  39. readonly_fields = ('service_type', 'label',)
  40. def has_add_permission(self, request):
  41. return False
  42. def has_delete_permission(self, request, obj=None):
  43. return False
  44. class ActiveServiceInline(ServiceInline):
  45. verbose_name_plural = 'Services actifs'
  46. def get_queryset(self, request):
  47. return super().get_queryset(request).filter(active=True)
  48. class InactiveServiceInline(ServiceInline):
  49. verbose_name_plural = 'Anciens services'
  50. def get_queryset(self, request):
  51. return super().get_queryset(request).filter(active=False)
  52. ### Filters
  53. class AdherentTypeFilter(admin.SimpleListFilter):
  54. title = 'type d’adhérent·e'
  55. parameter_name = 'type'
  56. def lookups(self, request, model_admin):
  57. return (
  58. ('physique', 'Personne physique'),
  59. ('morale', 'Personne morale'),
  60. )
  61. def queryset(self, request, queryset):
  62. if self.value() == 'physique':
  63. return queryset.filter(user__isnull=False)
  64. if self.value() == 'morale':
  65. return queryset.filter(corporation__isnull=False)
  66. ### Mixins
  67. class AdtSearchMixin:
  68. adhesion_search_field = 'id'
  69. def get_search_results(self, request, queryset, search_term):
  70. queryset, use_distinct = super().get_search_results(request, queryset, search_term)
  71. if search_term[:3] == 'ADT':
  72. try:
  73. adh_id = int(search_term[3:])
  74. except ValueError:
  75. pass
  76. else:
  77. queryset |= self.model.objects.filter(**{self.adhesion_search_field: adh_id})
  78. return queryset, use_distinct
  79. ### ModelAdmin
  80. class UserAdmin(AdtSearchMixin, AuthUserAdmin):
  81. list_display = AuthUserAdmin.list_display + ('get_adhesion_link',)
  82. list_select_related = ('profile', 'adhesion',)
  83. ordering = ('adhesion__id',)
  84. search_fields = AuthUserAdmin.search_fields \
  85. + ('profile__phone_number', 'profile__address', 'profile__notes',) \
  86. + ('=adhesion__id', 'adhesion__notes',)
  87. readonly_fields = ('get_adhesion_link',)
  88. adhesion_search_field = 'adhesion__id'
  89. def get_adhesion_id(self, user):
  90. return user.adhesion
  91. get_adhesion_id.short_description = 'Numéro d’adhérent·e'
  92. get_adhesion_id.admin_order_field = 'adhesion__id'
  93. get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
  94. get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
  95. def get_inline_instances(self, request, obj=None):
  96. if obj:
  97. inlines = (ProfileInline, AdhesionInline,)
  98. else:
  99. inlines = ()
  100. return [inline(self.model, self.admin_site) for inline in inlines]
  101. def get_form(self, request, obj=None, **kwargs):
  102. if obj:
  103. return super().get_form(request, obj, **kwargs)
  104. else:
  105. return UserCreationForm
  106. def get_fieldsets(self, request, obj=None):
  107. if obj:
  108. fieldsets = (
  109. (AuthUserAdmin.fieldsets[1][0], {
  110. 'fields': ('get_adhesion_link',) + AuthUserAdmin.fieldsets[1][1]['fields'],
  111. }),
  112. ('Nom d’utilisateur et mot de passe', {
  113. 'classes': ('collapse',),
  114. 'fields': AuthUserAdmin.fieldsets[0][1]['fields'],
  115. }),
  116. (AuthUserAdmin.fieldsets[2][0], {
  117. 'classes': ('collapse',),
  118. 'fields': ('is_active', 'is_staff', 'is_superuser', 'groups',), # removing user_permissions
  119. }),
  120. (AuthUserAdmin.fieldsets[3][0], {
  121. 'classes': ('collapse',),
  122. 'fields': AuthUserAdmin.fieldsets[3][1]['fields'],
  123. }),
  124. )
  125. else:
  126. fieldsets = (
  127. (None, {
  128. 'fields': ('first_name', 'last_name', 'username', 'email',),
  129. }),
  130. )
  131. return fieldsets
  132. def get_actions(self, request):
  133. actions = super().get_actions(request)
  134. if 'delete_selected' in actions:
  135. del actions['delete_selected']
  136. return actions
  137. def has_delete_permission(self, request, obj=None):
  138. return obj and not obj.adhesion
  139. class CorporationAdmin(AdtSearchMixin, admin.ModelAdmin):
  140. list_display = ('social_reason', 'get_adhesion_link',)
  141. list_select_related = ('adhesion',)
  142. ordering = ('adhesion__id',)
  143. search_fields = ('social_reason', 'description', 'email', 'phone_number', 'address', 'notes', 'adhesion__id', 'adhesion__notes',)
  144. readonly_fields = ('get_adhesion_link',)
  145. filter_horizontal = ('members',)
  146. adhesion_search_field = 'adhesion__id'
  147. def get_adhesion_id(self, corp):
  148. return corp.adhesion
  149. get_adhesion_id.short_description = 'Numéro d’adhérent·e'
  150. get_adhesion_id.admin_order_field = 'adhesion__id'
  151. get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
  152. get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
  153. def get_inline_instances(self, request, obj=None):
  154. if obj:
  155. inlines = (AdhesionInline,)
  156. else:
  157. inlines = ()
  158. return [inline(self.model, self.admin_site) for inline in inlines]
  159. def get_actions(self, request):
  160. actions = super().get_actions(request)
  161. if 'delete_selected' in actions:
  162. del actions['delete_selected']
  163. return actions
  164. def get_fieldsets(self, request, obj=None):
  165. fieldsets = super().get_fieldsets(request, obj)
  166. # put adhesion id on top
  167. if obj:
  168. fields = fieldsets[0][1]['fields']
  169. fields.remove('get_adhesion_link')
  170. fieldsets = (
  171. (None, {
  172. 'fields': ['get_adhesion_link'] + fields,
  173. }),
  174. )
  175. return fieldsets
  176. def has_delete_permission(self, request, obj=None):
  177. return False
  178. class AdhesionAdmin(AdtSearchMixin, admin.ModelAdmin):
  179. list_display = ('get_id', 'type', 'get_adherent_link', 'is_active')
  180. list_filter = (AdherentTypeFilter, ActiveFilter)
  181. list_select_related = ('user', 'user__profile', 'corporation',)
  182. fields = ('id', 'type', 'get_adherent_link', 'get_membership_link', 'get_antennas_link',)
  183. readonly_fields = ('id', 'type', 'get_adherent_link', 'get_membership_link', 'get_antennas_link',)
  184. search_fields = ('=id', 'notes',) \
  185. + tuple(['user__%s' % f for f in UserAdmin.search_fields if 'adhesion' not in f]) \
  186. + tuple(['corporation__%s' % f for f in CorporationAdmin.search_fields if 'adhesion' not in f])
  187. inlines = (ActiveServiceInline, InactiveServiceInline,)
  188. def get_id(self, obj):
  189. return 'ADT%d' % obj.id
  190. get_id.short_description = 'Numéro d’adhérent·e'
  191. get_id.admin_order_field = 'id'
  192. def get_membership_link(self, obj):
  193. return format_html(u'<a href="{}">{}</a>', obj.membership.get_absolute_url(), obj.membership.get_current_payment_display())
  194. get_membership_link.short_description = 'Cotisation'
  195. def get_antennas_link(self, obj):
  196. return mark_safe('<br />'.join(map(lambda antenna: antenna.get_absolute_link(), obj.antenna_set.all())))
  197. get_antennas_link.short_description = 'Antennes'
  198. def get_actions(self, request):
  199. actions = super().get_actions(request)
  200. if 'delete_selected' in actions:
  201. del actions['delete_selected']
  202. return actions
  203. def has_add_permission(self, request):
  204. return False
  205. def has_delete_permission(self, request, obj=None):
  206. if not obj:
  207. return False
  208. one_year_ago = timezone.now() - timedelta(days=365)
  209. membership = obj.membership.updates.filter(validated=True).first()
  210. # si l’adhésion n’a pas été résilié il y a plus d’un an
  211. if not membership or membership.payment_method != PaymentUpdate.STOP or membership.start > one_year_ago:
  212. return False
  213. # si l’adhérent·e est référent pour une antenne
  214. if obj.antenna_set.exists():
  215. return False
  216. # si l’adherent a un service
  217. if obj.services.exists():
  218. return False
  219. return True
  220. def contact_view(self, request):
  221. adhesions = request.GET.get('pk').split(',')
  222. adhesions = Adhesion.objects.filter(pk__in=adhesions)
  223. user_email = filter(lambda x: x, adhesions.values_list('user__email', flat=True))
  224. corp_email = filter(lambda x: x, adhesions.values_list('corporation__email', flat=True))
  225. user_tel = filter(lambda x: x, adhesions.values_list('user__profile__phone_number', flat=True))
  226. corp_tel = filter(lambda x: x, adhesions.values_list('corporation__phone_number', flat=True))
  227. sms_filter = lambda x: x[:2] == '06' or x[:2] == '07' or x[:3] == '+336' or x[:3] == '+337'
  228. return TemplateResponse(request, 'adhesions/contact.html', dict(
  229. adhesions = adhesions,
  230. emails = set(user_email) | set(corp_email),
  231. sms = filter(sms_filter, set(user_tel) | set(corp_tel))
  232. ))
  233. def get_urls(self):
  234. my_urls = [
  235. url(r'^contact/$', self.admin_site.admin_view(self.contact_view, cacheable=True), name='contact-adherents'),
  236. ]
  237. return my_urls + super().get_urls()
  238. admin.site.unregister(AuthUser)
  239. admin.site.register(User, UserAdmin)
  240. admin.site.register(Corporation, CorporationAdmin)
  241. admin.site.register(Adhesion, AdhesionAdmin)