from django.contrib import admin
from django.contrib.contenttypes.admin import GenericStackedInline, GenericTabularInline
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User as AuthUser
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from django.http import HttpResponseRedirect
from django.utils.html import format_html, mark_safe
from django.urls import reverse
from django.utils import timezone
from django.conf.urls import url
from django.template.response import TemplateResponse
from .forms import UserCreationForm
from .models import User, Corporation, Adhesion
from accounts.models import Profile
from services.models import Service
from djadhere.utils import ActiveFilter, get_active_filter
from banking.models import PaymentUpdate
from datetime import timedelta
### Inlines
class ProfileInline(admin.StackedInline):
model = Profile
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
class AdhesionInline(admin.StackedInline):
model = Adhesion
fields = ('id', 'notes',)
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
class ServiceInline(admin.StackedInline):
model = Service
extra = 0
show_change_link = True
fields = ('service_type', 'label',)
readonly_fields = ('service_type', 'label',)
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
class ActiveServiceInline(ServiceInline):
verbose_name_plural = 'Services actifs'
def get_queryset(self, request):
return super().get_queryset(request).filter(active=True)
class InactiveServiceInline(ServiceInline):
verbose_name_plural = 'Anciens services'
def get_queryset(self, request):
return super().get_queryset(request).filter(active=False)
### Filters
class AdherentTypeFilter(admin.SimpleListFilter):
title = 'type d’adhérent·e'
parameter_name = 'type'
def lookups(self, request, model_admin):
return (
('physique', 'Personne physique'),
('morale', 'Personne morale'),
)
def queryset(self, request, queryset):
if self.value() == 'physique':
return queryset.filter(user__isnull=False)
if self.value() == 'morale':
return queryset.filter(corporation__isnull=False)
### Mixins
class AdtSearchMixin:
adhesion_search_field = 'id'
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
if search_term[:3] == 'ADT':
try:
adh_id = int(search_term[3:])
except ValueError:
pass
else:
queryset |= self.model.objects.filter(**{self.adhesion_search_field: adh_id})
return queryset, use_distinct
### ModelAdmin
class UserAdmin(AdtSearchMixin, AuthUserAdmin):
list_display = AuthUserAdmin.list_display + ('get_adhesion_link',)
list_select_related = ('profile', 'adhesion',)
ordering = ('adhesion__id',)
search_fields = AuthUserAdmin.search_fields \
+ ('profile__phone_number', 'profile__address', 'profile__notes',) \
+ ('=adhesion__id', 'adhesion__notes',)
readonly_fields = ('get_adhesion_link',)
adhesion_search_field = 'adhesion__id'
get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
get_adhesion_link.admin_order_field = 'adhesion__id'
def get_inline_instances(self, request, obj=None):
if obj:
inlines = (ProfileInline, AdhesionInline,)
else:
inlines = ()
return [inline(self.model, self.admin_site) for inline in inlines]
def get_form(self, request, obj=None, **kwargs):
if obj:
return super().get_form(request, obj, **kwargs)
else:
return UserCreationForm
def get_fieldsets(self, request, obj=None):
if obj:
fieldsets = (
(AuthUserAdmin.fieldsets[1][0], {
'fields': ('get_adhesion_link',) + AuthUserAdmin.fieldsets[1][1]['fields'],
}),
('Nom d’utilisateur et mot de passe', {
'classes': ('collapse',),
'fields': AuthUserAdmin.fieldsets[0][1]['fields'],
}),
(AuthUserAdmin.fieldsets[2][0], {
'classes': ('collapse',),
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups',), # removing user_permissions
}),
(AuthUserAdmin.fieldsets[3][0], {
'classes': ('collapse',),
'fields': AuthUserAdmin.fieldsets[3][1]['fields'],
}),
)
else:
fieldsets = (
(None, {
'fields': ('first_name', 'last_name', 'username', 'email',),
}),
)
return fieldsets
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 obj and not obj.adhesion
class CorporationAdmin(AdtSearchMixin, admin.ModelAdmin):
list_display = ('social_reason', 'get_adhesion_link',)
list_select_related = ('adhesion',)
ordering = ('adhesion__id',)
search_fields = ('social_reason', 'description', 'email', 'phone_number', 'address', 'notes', 'adhesion__id', 'adhesion__notes',)
readonly_fields = ('get_adhesion_link',)
filter_horizontal = ('members',)
adhesion_search_field = 'adhesion__id'
get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
get_adhesion_link.admin_order_field = 'adhesion__id'
def get_inline_instances(self, request, obj=None):
if obj:
inlines = (AdhesionInline,)
else:
inlines = ()
return [inline(self.model, self.admin_site) for inline in inlines]
def get_actions(self, request):
actions = super().get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
# put adhesion id on top
if obj:
fields = fieldsets[0][1]['fields']
fields.remove('get_adhesion_link')
fieldsets = (
(None, {
'fields': ['get_adhesion_link'] + fields,
}),
)
return fieldsets
def has_delete_permission(self, request, obj=None):
return False
class AdhesionAdmin(AdtSearchMixin, admin.ModelAdmin):
list_display = ('get_id', 'type', 'get_adherent_link', 'is_active')
list_filter = (AdherentTypeFilter, ActiveFilter)
list_select_related = ('user', 'user__profile', 'corporation',)
fields = ('id', 'type', 'get_adherent_link', 'get_membership_link', 'get_antennas_link',)
readonly_fields = ('id', 'type', 'get_adherent_link', 'get_membership_link', 'get_antennas_link',)
search_fields = ('=id', 'notes',) \
+ tuple(['user__%s' % f for f in UserAdmin.search_fields if 'adhesion' not in f]) \
+ tuple(['corporation__%s' % f for f in CorporationAdmin.search_fields if 'adhesion' not in f])
inlines = (ActiveServiceInline, InactiveServiceInline,)
def get_id(self, obj):
return 'ADT%d' % obj.id
get_id.short_description = 'Numéro d’adhérent·e'
get_id.admin_order_field = 'id'
def get_membership_link(self, obj):
return format_html(u'{}', obj.membership.get_absolute_url(), obj.membership.get_current_payment_display())
get_membership_link.short_description = 'Cotisation'
def get_antennas_link(self, obj):
return mark_safe('
'.join(map(lambda antenna: antenna.get_absolute_link(), obj.antenna_set.all())))
get_antennas_link.short_description = 'Antennes'
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):
return False
def has_delete_permission(self, request, obj=None):
if not obj:
return False
one_year_ago = timezone.now() - timedelta(days=365)
membership = obj.membership.updates.filter(validated=True).first()
# si l’adhésion n’a pas été résilié il y a plus d’un an
if not membership or membership.payment_method != PaymentUpdate.STOP or membership.start > one_year_ago:
return False
# si l’adhérent·e est référent pour une antenne
if obj.antenna_set.exists():
return False
# si l’adherent a un service
if obj.services.exists():
return False
return True
def contact_view(self, request):
adhesions = request.GET.get('pk').split(',')
adhesions = Adhesion.objects.filter(pk__in=adhesions)
user_email = filter(lambda x: x, adhesions.values_list('user__email', flat=True))
corp_email = filter(lambda x: x, adhesions.values_list('corporation__email', flat=True))
user_tel = filter(lambda x: x, adhesions.values_list('user__profile__phone_number', flat=True))
corp_tel = filter(lambda x: x, adhesions.values_list('corporation__phone_number', flat=True))
sms_filter = lambda x: x[:2] == '06' or x[:2] == '07' or x[:3] == '+336' or x[:3] == '+337'
return TemplateResponse(request, 'adhesions/contact.html', dict(
adhesions = adhesions,
emails = set(user_email) | set(corp_email),
sms = filter(sms_filter, set(user_tel) | set(corp_tel))
))
def get_urls(self):
my_urls = [
url(r'^contact/$', self.admin_site.admin_view(self.contact_view, cacheable=True), name='contact-adherents'),
]
return my_urls + super().get_urls()
admin.site.unregister(AuthUser)
admin.site.register(User, UserAdmin)
admin.site.register(Corporation, CorporationAdmin)
admin.site.register(Adhesion, AdhesionAdmin)