X-Git-Url: http://git.auf.org/?p=auf_rh_dae.git;a=blobdiff_plain;f=project%2Frecrutement%2Fadmin.py;h=c2b14aa4bafe9a16b1b7d9cb753bb335fb29a484;hp=50b711e87e6784bcd27601e4eb48d62852fb9e30;hb=bad00d312daf1bf886ca1d5b2708c1d3e4e91650;hpb=783ee3f67909ddf543b34dbab6f899c830f55e88
diff --git a/project/recrutement/admin.py b/project/recrutement/admin.py
index 50b711e..c2b14aa 100644
--- a/project/recrutement/admin.py
+++ b/project/recrutement/admin.py
@@ -1,26 +1,51 @@
# -*- encoding: utf-8 -*-
-from django.core.urlresolvers import reverse
-from django.http import HttpResponseRedirect
+import textwrap
+
+from auf.django.emploi.models import CandidatPiece, Candidat, OffreEmploi
+from auf.django.references.models import Region, Bureau, Implantation
+from django.conf import settings
from django.contrib import admin
-from django.forms.models import BaseInlineFormSet
+from django.core.urlresolvers import reverse
from django.db.models import Avg
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from auf.django.export.admin import ExportAdmin
+from auf.django.emploi.models import STATUT_CHOICES
+from django.forms.models import BaseInlineFormSet
+from django.http import HttpResponseRedirect
+from django.shortcuts import redirect
from reversion.admin import VersionAdmin
-from datamaster_modeles.models import Region, Bureau
-from project.rh import models as rh
-from project.dae.utils import get_employe_from_user as get_emp
-from recrutement.models import *
-from recrutement.workflow import grp_drh_recrutement, grp_directeurs_bureau_recrutement, \
- grp_administrateurs_recrutement, \
- grp_correspondants_rh_recrutement
+from project import groups
+from project.permissions import get_user_groupnames
+
+from project.rh import models as rh
+from project.recrutement.forms import OffreEmploiForm
+from project.recrutement.models import \
+ Evaluateur, CandidatEvaluation, \
+ ProxyOffreEmploi, ProxyCandidat, MesCandidatEvaluation, \
+ CourrielTemplate, OffreEmploiEvaluateur
-from recrutement.forms import *
### 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
@@ -30,164 +55,241 @@ class OrderedChangeList(admin.views.main.ChangeList):
qs = qs.order_by('-moyenne')
return qs
-class OffreEmploiAdmin(VersionAdmin):
+
+class OffreEmploiAdminMixin(BaseAdmin):
date_hierarchy = 'date_creation'
- list_display = ('nom', 'date_limite', 'region', 'statut',
- 'est_affiche', '_candidatsList', )
+ 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
+ fieldsets = (
+ (None, {
+ 'fields': (
+ 'est_affiche',
+ 'statut',
+ 'date_limite',
+ 'nom',
+ 'description',
+ 'poste',
+ 'region',
+ 'lieu_affectation',
+ 'bureau',
+ 'debut_affectation',
+ 'duree_affectation',
+ 'renumeration',
+ )
+ }),
+ )
### Actions à afficher
def get_actions(self, request):
- actions = super(OffreEmploiAdmin, self).get_actions(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):
+ 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)'
+ 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):
+ def _candidatsList(self, obj):
return "Voir les candidats \
- " % (reverse('admin:recrutement_candidat_changelist'), obj.id)
- _candidatsList.allow_tags = True
+ " % (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(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
- employe = get_emp(request.user)
- user_groupes = request.user.groups.all()
-
-
+ form = super(OffreEmploiAdminMixin, self).get_form(request, obj, **kwargs)
+ employe = groups.get_employe_from_user(request.user)
+ user_groupes = get_user_groupnames(request.user)
+
# Region
- if form.declared_fields.has_key('region'):
+ region_field = None
+ if 'region' in form.declared_fields.keys():
region_field = form.declared_fields['region']
- else:
+ if 'region' in form.base_fields.keys():
region_field = form.base_fields['region']
-
- if grp_drh_recrutement in user_groupes:
- region_field.queryset = Region.objects.all()
- else:
- region_field.queryset = Region.objects.\
+ if region_field:
+ 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 form.declared_fields.has_key('poste'):
+ poste_field = None
+ if 'poste' in form.declared_fields.keys():
poste_field = form.declared_fields['poste']
- else:
+ if 'poste' in form.base_fields.keys():
poste_field = form.base_fields['poste']
+ if poste_field:
+ 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)
- if grp_drh_recrutement 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 form.declared_fields.has_key('bureau'):
+ bureau_field = None
+ if 'bureau' in form.declared_fields.keys():
bureau_field = form.declared_fields['bureau']
- else:
+ if 'bureau' in form.base_fields.keys():
bureau_field = form.base_fields['bureau']
+ if bureau_field:
+ 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)
- if grp_drh_recrutement 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 = request.user.groups.all()
- if grp_drh_recrutement in user_groupes:
+ qs = self.model._default_manager.get_query_set() \
+ .select_related('offre_emploi')
+ user_groupes = get_user_groupnames(request.user)
+ 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 grp_directeurs_bureau_recrutement in user_groupes or \
- grp_correspondants_rh_recrutement in user_groupes or \
- grp_administrateurs_recrutement in user_groupes:
- employe = get_emp(request.user)
+ 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)]
+ 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 = request.user.groups.all()
+ user_groupes = get_user_groupnames(request.user)
if request.user.is_superuser is True or \
- grp_drh_recrutement in user_groupes or \
- grp_directeurs_bureau_recrutement in user_groupes or \
- grp_administrateurs_recrutement in user_groupes:
+ 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
+ return False
def has_delete_permission(self, request, obj=None):
- user_groupes = request.user.groups.all()
+ user_groupes = get_user_groupnames(request.user)
if request.user.is_superuser is True or \
- grp_drh_recrutement in user_groupes or \
- grp_directeurs_bureau_recrutement in user_groupes or \
- grp_administrateurs_recrutement in user_groupes:
+ groups.DRH_NIVEAU_1 in user_groupes or \
+ groups.DRH_NIVEAU_2 in user_groupes or \
+ groups.HAUTE_DIRECTION in user_groupes:
return True
- return False
+
+ 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 = request.user.groups.all()
+ user_groupes = get_user_groupnames(request.user)
if request.user.is_superuser is True or \
- grp_drh_recrutement in user_groupes or \
- grp_directeurs_bureau_recrutement in user_groupes or \
- grp_administrateurs_recrutement in user_groupes:
+ groups.DRH_NIVEAU_1 in user_groupes or \
+ groups.DRH_NIVEAU_2 in user_groupes or \
+ groups.HAUTE_DIRECTION in user_groupes:
return True
- return False
-
-class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
- 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')
+
+ 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
+
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
+ if db_field.name == 'lieu_affectation':
+ user_groupes = [g.name for g in request.user.groups.all()]
+ if not (request.user.is_superuser is True or \
+ groups.DRH_NIVEAU_1 in user_groupes or \
+ groups.DRH_NIVEAU_2 in user_groupes):
+ employe = groups.get_employe_from_user(request.user)
+ kwargs["queryset"] = Implantation.objects.filter(region=employe.implantation.region)
+ return db_field.formfield(**kwargs)
+ return super(OffreEmploiAdminMixin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+
+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', )
+ 'fields': ('nom',)
}),
('Description générale', {
- 'fields': ('description', 'date_limite', )
+ 'fields': ('description', 'date_limite',)
}),
('Coordonnées', {
'fields': ('lieu_affectation', 'bureau', 'region', 'poste',)
}),
('Autre', {
- 'fields': ('debut_affectation', 'duree_affectation',
- 'renumeration', )
+ 'fields': (
+ 'debut_affectation', 'duree_affectation', 'renumeration',
+ )
}),
- )
+ )
inlines = []
-
- ### Lieu de redirection après le change
+ ### Lieu de redirection après le change
def response_change(self, request, obj):
- return HttpResponseRedirect(reverse\
- ('admin:recrutement_proxyoffreemploi_changelist'))
-
- ### Formulaire
- def get_form(self, request, obj=None, **kwargs):
- form = super(OffreEmploiAdmin, self).get_form(request, obj, **kwargs)
- return form
+ return redirect('admin:recrutement_proxyoffreemploi_changelist')
### Permissions add, delete, change
def has_add_permission(self, request):
@@ -197,7 +299,11 @@ class ProxyOffreEmploiAdmin(OffreEmploiAdmin):
return False
def has_change_permission(self, request, obj=None):
- return True
+ if obj is not None:
+ return True
+
+ return not super(ProxyOffreEmploiAdmin, self).has_change_permission(request, obj)
+
class CandidatPieceInline(admin.TabularInline):
model = CandidatPiece
@@ -205,6 +311,7 @@ class CandidatPieceInline(admin.TabularInline):
extra = 1
max_num = 3
+
class ReadOnlyCandidatPieceInline(CandidatPieceInline):
readonly_fields = ('candidat', 'nom', 'path', )
cand_delete = False
@@ -216,7 +323,8 @@ class CandidatEvaluationInlineFormSet(BaseInlineFormSet):
"""
def __init__(self, *args, **kwargs):
super(CandidatEvaluationInlineFormSet, self).__init__(*args, **kwargs)
- self.can_delete = False
+ self.can_delete = False
+
class CandidatEvaluationInline(admin.TabularInline):
model = CandidatEvaluation
@@ -225,40 +333,47 @@ class CandidatEvaluationInline(admin.TabularInline):
extra = 0
formset = CandidatEvaluationInlineFormSet
- ### Fields readonly
+ ### 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 + ('evaluateur', 'note', 'commentaire')
return self.readonly_fields
-class CandidatAdmin(VersionAdmin):
- search_fields = ('nom', 'prenom' )
+
+class CandidatAdminMixin(BaseAdmin, ExportAdmin):
+ search_fields = ('nom', 'prenom')
exclude = ('actif', )
list_editable = ('statut', )
- list_display = ('nom', 'prenom', 'offre_emploi',
+ list_display = ('_candidat', 'offre_emploi',
'voir_offre_emploi', 'calculer_moyenne',
'afficher_candidat', '_date_creation', 'statut', )
- list_filter = ('offre_emploi', 'offre_emploi__region', 'statut', )
+ list_filter = ('offre_emploi__nom', 'offre_emploi__region', 'statut', )
fieldsets = (
("Offre d'emploi", {
'fields': ('offre_emploi', )
}),
('Informations personnelles', {
- 'fields': ('prenom','nom','genre', 'nationalite',
- 'situation_famille', 'nombre_dependant',)
+ 'fields': (
+ 'nom', 'prenom', 'genre', 'nationalite',
+ 'situation_famille', 'nombre_dependant'
+ )
}),
('Coordonnées', {
- 'fields': ('telephone', 'email', 'adresse', 'ville',
- 'etat_province', 'code_postal', 'pays', )
+ 'fields': (
+ 'telephone', 'email', 'adresse', 'ville', 'etat_province',
+ 'code_postal', 'pays'
+ )
}),
('Informations professionnelles', {
- 'fields': ('niveau_diplome','employeur_actuel',
- 'poste_actuel', 'domaine_professionnel',)
- }),
+ 'fields': (
+ 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+ 'domaine_professionnel'
+ )
+ }),
('Traitement', {
'fields': ('statut', )
}),
@@ -267,48 +382,87 @@ class CandidatAdmin(VersionAdmin):
CandidatPieceInline,
CandidatEvaluationInline,
]
+ actions = ['envoyer_courriel_candidats', 'changer_statut']
- actions = ['envoyer_courriel_candidats']
+ export_fields = ['statut', 'offre_emploi', 'prenom', 'nom', 'genre',
+ 'nationalite', 'situation_famille', 'nombre_dependant',
+ 'niveau_diplome', 'employeur_actuel', 'poste_actuel',
+ 'domaine_professionnel', 'telephone', 'email', 'adresse',
+ 'ville', 'etat_province', 'code_postal', 'pays']
+
+ 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.order_field = "date_creation"
- _date_creation.short_description = "Date de création"
+ _date_creation.admin_order_field = "date_creation"
+ _date_creation.short_description = "Date de réception"
### Actions à afficher
def get_actions(self, request):
- actions = super(CandidatAdmin, self).get_actions(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):
+ def envoyer_courriel_candidats(modeladmin, obj, candidats):
selected = obj.POST.getlist(admin.ACTION_CHECKBOX_NAME)
- return HttpResponseRedirect(reverse('selectionner_template')+
- "?ids=%s" % (",".join(selected)))
+ return HttpResponseRedirect(
+ reverse('selectionner_template') + "?ids=%s" % (",".join(selected))
+ )
envoyer_courriel_candidats.short_description = u'Envoyer courriel'
+ ### Changer le statut à des candidats
+ def changer_statut(modeladmin, request, queryset):
+ if request.POST.get('post'):
+ queryset.update(statut=request.POST.get('statut'))
+ return None
+
+ context = {
+ 'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
+ 'queryset': queryset,
+ 'status': STATUT_CHOICES,
+ }
+
+ return render_to_response("recrutement/selectionner_statut.html",
+ context, context_instance = RequestContext(request))
+
+ changer_statut.short_description = u'Changer statut'
+
### Ãvaluer un candidat
def evaluer_candidat(self, obj):
- return "Ãvaluer le candidat" % \
- (reverse('admin:recrutement_candidatevaluation_changelist'),
- obj.id)
- evaluer_candidat.allow_tags = True
+ 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):
- return "Voir le candidat" % \
- (reverse('admin:recrutement_proxycandidat_change', args=(obj.id,)))
- afficher_candidat.allow_tags = True
+ items = [u"