# -*- encoding: utf-8 -*-
import textwrap
from auf.django.emploi.models import OffreEmploi, Candidat, CandidatPiece
from auf.django.references.models import Region, Bureau
from django.conf import settings
from django.contrib import admin
from django.core.urlresolvers import reverse
from django.db.models import Avg
from django.forms.models import BaseInlineFormSet
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from reversion.admin import VersionAdmin
from project import groups
from project.rh import models as rh
from project.recrutement.forms import OffreEmploiForm
from project.recrutement.models import \
Evaluateur, CandidatEvaluation, \
ProxyOffreEmploi, ProxyCandidat, MesCandidatEvaluation, \
CourrielTemplate
### CONSTANTES
IMPLANTATIONS_CENTRALES = [15, 19]
class BaseAdmin(admin.ModelAdmin):
class Media:
css = {'screen': (
'css/admin_custom.css',
'jquery-autocomplete/jquery.autocomplete.css',
)}
js = (
'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
'jquery-autocomplete/jquery.autocomplete.min.js',
)
class OrderedChangeList(admin.views.main.ChangeList):
"""
Surcharge pour appliquer le order_by d'un annotate
"""
def get_query_set(self):
qs = super(OrderedChangeList, self).get_query_set()
qs = qs.order_by('-moyenne')
return qs
class OffreEmploiAdminMixin(BaseAdmin):
date_hierarchy = 'date_creation'
list_display = (
'nom', 'date_limite', 'region', 'statut', 'est_affiche',
'_candidatsList'
)
exclude = ('actif', 'poste_nom', 'resume',)
list_filter = ('statut',)
actions = ['affecter_evaluateurs_offre_emploi', ]
form = OffreEmploiForm
### Actions à afficher
def get_actions(self, request):
actions = super(OffreEmploiAdminMixin, self).get_actions(request)
del actions['delete_selected']
return actions
### Affecter un évaluateurs à des offres d'emploi
def affecter_evaluateurs_offre_emploi(modeladmin, obj, candidats):
selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
return HttpResponseRedirect(
reverse('affecter_evaluateurs_offre_emploi') +
"?ids=%s" % (",".join(selected))
)
affecter_evaluateurs_offre_emploi.short_description = \
u'Affecter évaluateur(s)'
### Afficher la liste des candidats pour l'offre d'emploi
def _candidatsList(self, obj):
return "Voir les candidats \
" % (reverse('admin:recrutement_proxycandidat_changelist'), obj.id)
_candidatsList.allow_tags = True
_candidatsList.short_description = "Afficher la liste des candidats"
### Formulaire
def get_form(self, request, obj=None, **kwargs):
form = super(OffreEmploiAdminMixin, self).get_form(request, obj, **kwargs)
employe = groups.get_employe_from_user(request.user)
user_groupes = [g.name for g in request.user.groups.all()]
# Region
if 'region' in form.declared_fields:
region_field = form.declared_fields['region']
read_only = False
elif 'region' in form.base_fields:
region_field = form.base_fields['region']
read_only = False
else:
read_only = True
if not read_only:
if groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
region_field.queryset = Region.objects.all()
else:
region_field.queryset = Region.objects.\
filter(id=employe.implantation.region.id)
# Poste
if 'poste' in form.declared_fields:
poste_field = form.declared_fields['poste']
read_only = False
elif 'poste' in form.base_fields:
poste_field = form.base_fields['poste']
read_only = False
else:
read_only = True
if not read_only:
if groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
poste_field.queryset = rh.Poste.objects.all()
else:
poste_field.queryset = rh.Poste.objects.\
filter(implantation__region=employe.implantation.region).\
exclude(implantation__in=IMPLANTATIONS_CENTRALES)
# Bureau
if 'bureau' in form.declared_fields:
bureau_field = form.declared_fields['bureau']
read_only = False
elif 'bureau' in form.base_fields:
bureau_field = form.base_fields['bureau']
read_only = False
else:
read_only = True
if not read_only:
if groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
bureau_field.queryset = Bureau.objects.all()
else:
bureau_field.queryset = \
Bureau.objects.filter(region=employe.implantation.region)
return form
### Queryset
def queryset(self, request):
qs = self.model._default_manager.get_query_set() \
.select_related('offre_emploi')
user_groupes = [g.name for g in request.user.groups.all()]
if groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
return qs
if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.CORRESPONDANT_RH in user_groupes or \
groups.ADMINISTRATEURS in user_groupes:
employe = groups.get_employe_from_user(request.user)
return qs.filter(region=employe.implantation.region)
if Evaluateur.objects.filter(user=request.user).exists():
evaluateur = Evaluateur.objects.get(user=request.user)
offre_ids = [
e.candidat.offre_emploi_id
for e in CandidatEvaluation.objects
.select_related('candidat')
.filter(evaluateur=evaluateur)
]
return qs.filter(id__in=offre_ids)
return qs.none()
### Permission add, delete, change
def has_add_permission(self, request):
user_groupes = [g.name for g in request.user.groups.all()]
if request.user.is_superuser is True or \
groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.ADMINISTRATEURS in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
return True
return False
def has_delete_permission(self, request, obj=None):
user_groupes = [g.name for g in request.user.groups.all()]
if request.user.is_superuser is True or \
groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
return True
if obj is not None:
employe = groups.get_employe_from_user(request.user)
if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.ADMINISTRATEURS in user_groupes) and (
employe.implantation.region == obj.lieu_affectation.region):
return True
return False
def has_change_permission(self, request, obj=None):
user_groupes = [g.name for g in request.user.groups.all()]
if request.user.is_superuser is True or \
groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
return True
if obj is not None:
employe = groups.get_employe_from_user(request.user)
if (groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.ADMINISTRATEURS in user_groupes) and (
employe.implantation.region == obj.lieu_affectation.region):
return True
else:
if groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.ADMINISTRATEURS in user_groupes:
return True
return False
class OffreEmploiAdmin(VersionAdmin, OffreEmploiAdminMixin):
pass
class ProxyOffreEmploiAdmin(OffreEmploiAdminMixin):
list_display = (
'nom', 'date_limite', 'region', 'statut', 'est_affiche'
)
readonly_fields = (
'description', 'bureau', 'duree_affectation', 'renumeration',
'debut_affectation', 'lieu_affectation', 'nom', 'resume',
'date_limite', 'region', 'poste'
)
fieldsets = (
('Nom', {
'fields': ('nom',)
}),
('Description générale', {
'fields': ('description', 'date_limite',)
}),
('Coordonnées', {
'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
}),
('Autre', {
'fields': (
'debut_affectation', 'duree_affectation', 'renumeration',
)
}),
)
inlines = []
### Lieu de redirection après le change
def response_change(self, request, obj):
return redirect('admin:recrutement_proxyoffreemploi_changelist')
### Formulaire
def get_form(self, request, obj=None, **kwargs):
form = super(ProxyOffreEmploiAdmin, self).get_form(request, obj, **kwargs)
return form
### Permissions add, delete, change
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
def has_change_permission(self, request, obj=None):
user_groupes = [g.name for g in request.user.groups.all()]
if request.user.is_superuser is True or \
groups.CORRESPONDANT_RH in user_groupes or \
groups.DRH_NIVEAU_1 in user_groupes or \
groups.DRH_NIVEAU_2 in user_groupes or \
groups.DIRECTEUR_DE_BUREAU in user_groupes or \
groups.ADMINISTRATEURS in user_groupes or \
groups.HAUTE_DIRECTION in user_groupes:
return True
if obj is not None:
return True
return False
class CandidatPieceInline(admin.TabularInline):
model = CandidatPiece
fields = ('candidat', 'nom', 'path',)
extra = 1
max_num = 3
class ReadOnlyCandidatPieceInline(CandidatPieceInline):
readonly_fields = ('candidat', 'nom', 'path', )
cand_delete = False
class CandidatEvaluationInlineFormSet(BaseInlineFormSet):
"""
Empêche la suppression d'une évaluation pour le CandidatEvaluationInline
"""
def __init__(self, *args, **kwargs):
super(CandidatEvaluationInlineFormSet, self).__init__(*args, **kwargs)
self.can_delete = False
class CandidatEvaluationInline(admin.TabularInline):
model = CandidatEvaluation
fields = ('evaluateur', 'note', 'commentaire')
max_num = 0
extra = 0
formset = CandidatEvaluationInlineFormSet
### Fields readonly
def get_readonly_fields(self, request, obj=None):
"""
Empêche la modification des évaluations
"""
if obj:
return self.readonly_fields + ('evaluateur', 'note', 'commentaire')
return self.readonly_fields
class CandidatAdminMixin(BaseAdmin):
search_fields = ('nom', 'prenom')
exclude = ('actif', )
list_editable = ('statut', )
list_display = ('_candidat', 'offre_emploi',
'voir_offre_emploi', 'calculer_moyenne',
'afficher_candidat', '_date_creation', 'statut', )
list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
fieldsets = (
("Offre d'emploi", {
'fields': ('offre_emploi', )
}),
('Informations personnelles', {
'fields': (
'prenom', 'nom', 'genre', 'nationalite',
'situation_famille', 'nombre_dependant'
)
}),
('Coordonnées', {
'fields': (
'telephone', 'email', 'adresse', 'ville', 'etat_province',
'code_postal', 'pays'
)
}),
('Informations professionnelles', {
'fields': (
'niveau_diplome', 'employeur_actuel', 'poste_actuel',
'domaine_professionnel'
)
}),
('Traitement', {
'fields': ('statut', )
}),
)
inlines = [
CandidatPieceInline,
CandidatEvaluationInline,
]
actions = ['envoyer_courriel_candidats']
def _candidat(self, obj):
txt = u"%s %s (%s)" % (obj.nom.upper(), obj.prenom, obj.genre)
txt = textwrap.wrap(txt, 30)
return "
".join(txt)
_candidat.short_description = "Candidat"
_candidat.admin_order_field = "nom"
_candidat.allow_tags = True
def _date_creation(self, obj):
return obj.date_creation
_date_creation.admin_order_field = "date_creation"
_date_creation.short_description = "Date de réception"
### Actions à afficher
def get_actions(self, request):
actions = super(CandidatAdminMixin, self).get_actions(request)
del actions['delete_selected']
return actions
### Envoyer un courriel à des candidats
def envoyer_courriel_candidats(modeladmin, obj, candidats):
selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
return HttpResponseRedirect(
reverse('selectionner_template') + "?ids=%s" % (",".join(selected))
)
envoyer_courriel_candidats.short_description = u'Envoyer courriel'
### Évaluer un candidat
def evaluer_candidat(self, obj):
return "" \
"Évaluer le candidat" % (
reverse('admin:recrutement_candidatevaluation_changelist'),
obj.id
)
evaluer_candidat.allow_tags = True
evaluer_candidat.short_description = 'Évaluation'
### Afficher un candidat
def afficher_candidat(self, obj):
items = [u"