Modification de l'affiahce du poste et dossier dans le listing des employes
[auf_rh_dae.git] / project / rh / admin.py
1 # -*- encoding: utf-8 -*-
2
3 from collections import defaultdict
4 import datetime
5
6 from django.db import models
7 from django import forms
8 from django.core.urlresolvers import reverse
9 from django.contrib import admin
10 from django.contrib.admin.views.main import ChangeList as DjangoChangeList
11 from django.conf import settings
12 from django.db.models import Q
13 from django.template.defaultfilters import date
14 from ajax_select import make_ajax_form
15 from auf.django.metadata.admin import AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, AUF_METADATA_READONLY_FIELDS
16 from forms import ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect
17 from dae.utils import get_employe_from_user
18 from groups import grp_drh
19 import models as rh
20 import filters
21
22 ################################################################################
23 # FILTRAGE PAR DATE
24 ################################################################################
25 class DateRangeMixin(object):
26 """
27 Mixin pour que le model admin utilise le changelist trafiqué permettant de filter par range
28 non strict.
29 Par défaut, le filtrage est configuré sur aujourd'hui, soit les actifs
30 """
31 date_borne_gauche = 'date_debut'
32 date_borne_droite = 'date_fin'
33 def get_changelist(self, request, **kwargs):
34 if request.META.has_key('HTTP_REFERER'):
35 referer = request.META['HTTP_REFERER']
36 referer = "/".join(referer.split('/')[3:])
37 referer = "/%s" % referer.split('?')[0]
38 change_list_view = 'admin:%s_%s_changelist' % (self.model._meta.app_label, self.model.__name__.lower())
39 if referer != reverse(change_list_view):
40 params = request.GET.copy()
41 today = datetime.date.today()
42 params.update({'%s__gte' % self.date_borne_gauche : str(today), '%s__lte' % self.date_borne_droite : str(today) })
43 request.GET = params
44 return ChangeList
45
46 class ChangeList(DjangoChangeList):
47 PERIODE_CHOICE = ('', 'actuelle', 'passee', 'future')
48
49 def __init__(self, *args, **kwargs):
50 self.annees = {'actuelle': 'actuelle', 'passee': 'passee', 'future': 'future'}
51 super(ChangeList, self).__init__(*args, **kwargs)
52
53 def get_query_set(self):
54 old = self.params.copy()
55 periode = None
56 annee = None
57 date_debut = None
58 date_fin = None
59 today = datetime.date.today()
60 for k, v in self.params.items():
61 if 'periode' == k:
62 periode = self.params[k]
63 del self.params[k]
64 if 'annee' == k:
65 annee = self.params[k]
66 del self.params[k]
67 if 'date_debut' == k:
68 date_debut = self.params[k]
69 del self.params[k]
70 if 'date_fin' == k:
71 date_fin = self.params[k]
72 del self.params[k]
73
74 qs = super(ChangeList, self).get_query_set()
75 if periode == 'actuelle':
76 qs = qs.filter(date_fin__exact=today, date_debut__exact=today).distinct()
77 elif periode == 'passee':
78 qs = qs.filter(date_fin__lt=today)
79 elif periode == 'future':
80 qs = qs.filter(date_debut__gt=today)
81 elif annee:
82 date_debut = datetime.date(int(annee), 01, 01)
83 date_fin = datetime.date(int(annee), 12, 31)
84
85 if date_debut and date_fin:
86 prefix_debut = 'date_debut'
87 prefix_fin = 'date_fin'
88 q_left = (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__lte' % prefix_debut : date_debut})) & (Q(**{'%s__gte' % prefix_fin : date_debut}) & Q(**{'%s__lte' % prefix_fin : date_fin}))
89 q_right = (Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__gte' % prefix_fin : date_fin})) & (Q(**{'%s__gte' % prefix_debut : date_debut}) & Q(**{'%s__lte' % prefix_debut : date_fin}))
90 q_both = Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__lte' % prefix_fin : date_fin}) & (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__gte' % prefix_debut : date_debut}))
91 q_non_supprime = Q(**{'%s__exact' % prefix_debut.replace('date_debut', 'supprime') : False})
92 q = (q_left | q_right | q_both) & q_non_supprime
93 qs = qs.filter(q).distinct()
94
95 self.params = old
96 return qs
97
98 ################################################################################
99
100 # Override of the InlineModelAdmin to support the link in the tabular inline
101 class LinkedInline(admin.options.InlineModelAdmin):
102 template = "admin/linked.html"
103 admin_model_path = None
104
105 def __init__(self, *args):
106 super(LinkedInline, self).__init__(*args)
107 if self.admin_model_path is None:
108 self.admin_model_path = self.model.__name__.lower()
109
110
111 class ProtectRegionMixin(object):
112
113 def queryset(self, request):
114 from dae.workflow import grp_drh, grp_correspondants_rh
115 qs = super(ProtectRegionMixin, self).queryset(request)
116
117 if request.user.is_superuser:
118 return qs
119
120 user_groups = request.user.groups.all()
121
122 if grp_drh in user_groups:
123 return qs
124
125 if grp_correspondants_rh in user_groups:
126 employe = get_employe_from_user(request.user)
127 q = Q(**{self.model.prefix_implantation: employe.implantation.region})
128 qs = qs.filter(q).distinct()
129 return qs
130 return qs.none()
131
132 def has_change_permission(self, request, obj=None):
133 user_groups = request.user.groups.all()
134
135 # Lock pour autoriser uniquement les DRH à utiliser RH
136 if not request.user.is_superuser and not grp_drh in user_groups:
137 return False
138
139 if len(user_groups) == 0 and not request.user.is_superuser:
140 return False
141
142 if obj is None:
143 return True
144 ids = [o.id for o in self.queryset(request)]
145 return obj.id in ids
146
147
148 # Inlines
149
150 class ReadOnlyInlineMixin(object):
151 def get_readonly_fields(self, request, obj=None):
152 return [f.name for f in self.model._meta.fields if f.name not in AUF_METADATA_READONLY_FIELDS]
153
154
155 class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
156 model = rh.AyantDroit
157 form = AyantDroitForm
158 extra = 0
159
160 fieldsets = (
161 (None, {
162 'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', 'lien_parente', )
163 }),
164 )
165
166
167 class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
168 readonly_fields = ('owner', )
169 model = rh.AyantDroitCommentaire
170 extra = 1
171
172
173 class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
174 form = ContratForm
175 model = rh.Contrat
176 extra = 1
177
178
179 class DossierROInline(ReadOnlyInlineMixin, LinkedInline):
180 template = "admin/rh/dossier/linked.html"
181 exclude = AUF_METADATA_READONLY_FIELDS
182 model = rh.Dossier
183 extra = 0
184 can_delete = False
185
186 def has_add_permission(self, request=None):
187 return False
188
189 def has_change_permission(self, request, obj=None):
190 return False
191
192 def has_delete_permission(self, request, obj=None):
193 return False
194
195
196 class DossierCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
197 readonly_fields = ('owner', )
198 model = rh.DossierCommentaire
199 extra = 1
200
201
202 class DossierPieceInline(admin.TabularInline):
203 model = rh.DossierPiece
204 extra = 4
205
206
207 class EmployeInline(admin.TabularInline):
208 model = rh.Employe
209
210 class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
211 readonly_fields = ('owner', )
212 model = rh.EmployeCommentaire
213 extra = 1
214
215
216 class EmployePieceInline(admin.TabularInline):
217 model = rh.EmployePiece
218 extra = 4
219
220
221 class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
222 readonly_fields = ('owner', )
223 model = rh.PosteCommentaire
224 extra = 1
225
226
227 class PosteFinancementInline(admin.TabularInline):
228 model = rh.PosteFinancement
229
230
231 class PostePieceInline(admin.TabularInline):
232 model = rh.PostePiece
233
234
235 class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
236 model = rh.Remuneration
237 extra = 1
238
239
240 class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
241 pass
242
243
244 class TypePosteInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
245 model = rh.TypePoste
246
247
248 class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
249 model = rh.PosteComparaison
250
251
252 class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
253 list_display = ('_classement', '_date_modification', 'user_modification', )
254 fieldsets = AUFMetadataAdminMixin.fieldsets + (
255 (None, {
256 'fields': ('type', 'echelon', 'degre', 'coefficient', )
257 }),
258 )
259
260 def _classement(self, obj):
261 return unicode(obj)
262 _classement.short_description = u"Classement"
263
264 def _date_modification(self, obj):
265 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
266 _date_modification.short_description = u'date modification'
267 _date_modification.admin_order_field = 'date_modification'
268
269 class CommentaireAdmin(admin.ModelAdmin):
270 pass
271
272
273 class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
274 list_display = ('code', 'nom', '_date_modification', 'user_modification',)
275 list_filter = ('archive', )
276 fieldsets = AUFMetadataAdminMixin.fieldsets + (
277 (None, {
278 'fields': ('code', 'nom', 'archive', ),
279 }),
280 )
281
282 def _date_modification(self, obj):
283 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
284 _date_modification.short_description = u'date modification'
285 _date_modification.admin_order_field = 'date_modification'
286
287 class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
288 alphabet_filter = 'employe__nom'
289 search_fields = ('employe__nom', 'employe__prenom', 'poste__nom', 'poste__nom_feminin')
290 list_display = (
291 '_id',
292 '_apercu',
293 '_nom',
294 '_poste',
295 '_employe',
296 '_date_debut',
297 '_date_fin',
298 '_date_modification',
299 'user_modification',
300 )
301 list_display_links = ('_nom',)
302 list_filter = (
303 'poste__implantation__region',
304 'poste__implantation',
305 'poste__type_poste__famille_emploi',
306 'poste__type_poste',
307 'rh_contrats__type_contrat',
308 'date_debut',
309 'date_fin',
310 )
311 inlines = (DossierPieceInline, ContratInline,
312 RemunerationInline,
313 DossierCommentaireInline,
314 )
315 fieldsets = AUFMetadataAdminMixin.fieldsets + (
316 (None, {
317 'fields': ('employe', 'poste', 'statut', 'organisme_bstg',)
318 }),
319 ('Recrutement', {
320 'fields': ('statut_residence', 'remplacement', 'remplacement_de', )
321 }),
322 ('Rémunération', {
323 'fields': ('classement', ('regime_travail', 'regime_travail_nb_heure_semaine'),)
324 }),
325 ('Occupation du Poste par cet Employe', {
326 'fields': (('date_debut', 'date_fin'), )
327 }),
328 )
329 form = make_ajax_form(rh.Dossier, {
330 'employe' : 'employes',
331 'poste' : 'postes',
332 'remplacement_de' : 'dossiers',
333 })
334
335 def lookup_allowed(self, key, value):
336 if key in (
337 'employe__nom__istartswith',
338 'poste__implantation__region__id__exact',
339 'poste__implantation__id__exact',
340 'poste__type_poste__id__exact',
341 'poste__type_poste__famille_emploi__id__exact',
342 'rh_contrats__type_contrat__id__exact',
343 'date_debut__gte',
344 'date_debut__isnull',
345 'date_fin__lte',
346 'date_fin__isnull',
347 ):
348 return True
349
350 def _id(self, obj):
351 return obj.id
352 _id.short_description = u"#"
353 _id.admin_order_field = "id"
354
355 def _nom(self, obj):
356 return "%d : %s %s" % \
357 (obj.date_debut.year, obj.employe.nom.upper(), obj.employe.prenom)
358 _nom.allow_tags = True
359 _nom.short_description = u"Dossier"
360
361
362 def _apercu(self, d):
363 apercu_link = u"""<a title="Aperçu du dossier" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
364 (reverse('dossier_apercu', args=(d.id,)),
365 settings.STATIC_URL,
366 )
367 return apercu_link
368 _apercu.allow_tags = True
369 _apercu.short_description = u""
370
371
372 def _date_debut(self, obj):
373 return date(obj.date_debut)
374
375 _date_debut.short_description = u'Occupation début'
376 _date_debut.admin_order_field = 'date_debut'
377
378 def _date_fin(self, obj):
379 return date(obj.date_fin)
380 _date_fin.short_description = u'Occupation fin'
381 _date_fin.admin_order_field = 'date_fin'
382
383
384 def _date_modification(self, obj):
385 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
386 _date_modification.short_description = u'date modification'
387 _date_modification.admin_order_field = 'date_modification'
388
389 def _poste(self, dossier):
390 link = u"""<a title="Aperçu du poste" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a> <a href="%s" title="Modifier le poste">%s</a>""" % \
391 (reverse('poste_apercu', args=(dossier.poste.id,)),
392 settings.STATIC_URL,
393 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
394 dossier.poste,
395 )
396 return link
397 _poste.allow_tags = True
398 _poste.short_description = u'Poste'
399 _poste.admin_order_field = 'poste__nom'
400
401 def _employe(self, obj):
402 employe = obj.employe
403 view_link = reverse('employe_apercu', args=(employe.id,))
404 edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
405
406 style = ""
407 view = u"""<a href="%s" title="Aperçu l'employé" onclick="return showAddAnotherPopup(this);"><img src="%simg/loupe.png" /></a>""" % (view_link, settings.STATIC_URL,)
408 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
409 (view, edit_link, style, employe)
410 _employe.allow_tags = True
411 _employe.short_description = u"Employé"
412 _employe.admin_order_field = "employe__nom"
413
414 def save_formset(self, request, form, formset, change):
415 instances = formset.save(commit=False)
416 for instance in instances:
417 if instance.__class__ == rh.DossierCommentaire:
418 instance.owner = request.user
419 instance.date_creation = datetime.datetime.now()
420 instance.save()
421
422
423 class DossierPieceAdmin(admin.ModelAdmin):
424 pass
425
426
427 class DossierCommentaireAdmin(admin.ModelAdmin):
428 pass
429
430
431 class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin,):
432 alphabet_filter = 'nom'
433 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
434 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
435 ordering = ('nom', )
436 form = EmployeAdminForm
437 list_display = ('_id', '_apercu', '_nom', '_dossiers_postes', '_date_modification', 'user_modification', )
438 list_display_links = ('_nom',)
439 list_filter = ('rh_dossiers__poste__implantation__region', 'rh_dossiers__poste__implantation', 'nb_postes', 'rh_dossiers__date_debut', 'rh_dossiers__date_fin')
440 date_borne_gauche = 'rh_dossiers__date_debut'
441 date_borne_droite = 'rh_dossiers__date_fin'
442 inlines = (AyantDroitInline,
443 DossierROInline,
444 EmployePieceInline,
445 EmployeCommentaireInline)
446 fieldsets = AUFMetadataAdminMixin.fieldsets + (
447 ('Identification', {
448 'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', )
449 }),
450 ('Informations personnelles', {
451 'fields': ('situation_famille', 'date_entree', )
452 }),
453 ('Coordonnées', {
454 'fields': (('tel_domicile', 'tel_cellulaire'), ('adresse', 'ville'), ('code_postal', 'province'), 'pays', )
455 }),
456 )
457
458 def _apercu(self, obj):
459 return u"""<a title="Aperçu de l'employé" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
460 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
461 _apercu.allow_tags = True
462 _apercu.short_description = u""
463
464 def _nom(self, obj):
465 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
466 return u"""<a href='%s'><strong>%s</strong></a>""" % \
467 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
468 _nom.allow_tags = True
469 _nom.short_description = u"Employé"
470 _nom.admin_order_field = "nom"
471
472 def _id(self, obj):
473 return obj.id
474 _id.short_description = u"#"
475 _id.admin_order_field = "id"
476
477 def _date_modification(self, obj):
478 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
479 _date_modification.short_description = u'date modification'
480 _date_modification.admin_order_field = 'date_modification'
481
482 def _dossiers_postes(self, obj):
483 l = []
484 for d in obj.rh_dossiers.all().order_by('-date_debut'):
485 dossier = u"""<a title="Aperçu du dossier" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du dossier"><img src="%simg/loupe.png" /></a><a href="%s">Dossier</a>&nbsp;""" % \
486 ( reverse('dossier_apercu', args=(d.id,)),
487 settings.STATIC_URL,
488 reverse('admin:rh_dossier_change', args=(d.id,))
489 )
490
491 poste = u"""<a title="Aperçu du poste" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du poste"><img src="%simg/loupe.png" /></a><a href="%s">Poste</a>&nbsp;""" % \
492 ( reverse('poste_apercu', args=(d.poste.id,)),
493 settings.STATIC_URL,
494 reverse('admin:rh_poste_change', args=(d.poste.id,))
495 )
496 link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
497 (dossier, poste,
498 d.date_debut.year,
499 d.poste.id,
500 d.poste.nom,
501 )
502
503 # Dossier terminé en gris non cliquable
504 if d.date_fin is not None:
505 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
506 (d.date_debut.year,
507 d.poste.id,
508 d.poste.nom,
509 )
510
511 l.append(link)
512 return "<ul>%s</ul>" % "\n".join(l)
513 _dossiers_postes.allow_tags = True
514 _dossiers_postes.short_description = u"Dossiers et postes"
515
516 def queryset(self, request):
517 qs = super(EmployeAdmin, self).queryset(request)
518 return qs.select_related(depth=1).order_by('nom')
519
520 def save_formset(self, request, form, formset, change):
521 instances = formset.save(commit=False)
522 for instance in instances:
523 if instance.__class__ == rh.EmployeCommentaire:
524 instance.owner = request.user
525 instance.date_creation = datetime.datetime.now()
526 instance.save()
527
528
529
530 class EmployeCommentaireAdmin(admin.ModelAdmin):
531 pass
532
533
534 class EmployePieceAdmin(admin.ModelAdmin):
535 pass
536
537
538 class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
539 list_display = ('nom', '_date_modification', 'user_modification', )
540 inlines = (TypePosteInline,)
541 fieldsets = AUFMetadataAdminMixin.fieldsets + (
542 (None, {
543 'fields': ('nom', )
544 }),
545 )
546
547 def _date_modification(self, obj):
548 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
549 _date_modification.short_description = u'date modification'
550 _date_modification.admin_order_field = 'date_modification'
551
552 class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
553 search_fields = ('nom',)
554 list_display = ('nom', 'type', 'pays', '_date_modification', 'user_modification', )
555 list_filter = ('type', )
556 inlines = (DossierROInline,)
557 fieldsets = AUFMetadataAdminMixin.fieldsets + (
558 (None, {
559 'fields': ('nom', 'type', 'pays', )
560 }),
561 )
562
563 def _date_modification(self, obj):
564 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
565 _date_modification.short_description = u'date modification'
566 _date_modification.admin_order_field = 'date_modification'
567
568
569 class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
570 form = make_ajax_form(rh.Poste, {
571 'implantation' : 'implantations',
572 'type_poste' : 'typepostes',
573 'responsable' : 'postes',
574 'valeur_point_min' : 'valeurpoints',
575 'valeur_point_max' : 'valeurpoints',
576 })
577 alphabet_filter = 'nom'
578 search_fields = ('nom',
579 'implantation__code',
580 'implantation__nom',
581 'implantation__region__code',
582 'implantation__region__nom',
583 'rh_dossiers__employe__nom',
584 'rh_dossiers__employe__prenom',
585 )
586 list_display = (
587 '_id',
588 '_apercu',
589 '_nom',
590 '_occupe_par',
591 'implantation',
592 '_service',
593 'date_debut',
594 'date_fin',
595 '_date_modification',
596 'user_modification',
597 )
598 list_filter = (
599 'implantation__region',
600 'implantation',
601 'service',
602 'type_poste',
603 'type_poste__famille_emploi',
604 'date_debut',
605 'date_fin',
606 'vacant',
607 )
608 list_display_links = ('_nom',)
609 fieldsets = AUFMetadataAdminMixin.fieldsets + (
610 (None, {
611 'fields': (('nom', 'nom_feminin'), 'implantation', 'type_poste',
612 'service', 'responsable')
613 }),
614 ('Contrat', {
615 'fields': (('regime_travail', 'regime_travail_nb_heure_semaine'), )
616 }),
617 ('Recrutement', {
618 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)
619 }),
620 ('Rémunération', {
621 'fields': (('classement_min', 'valeur_point_min', 'devise_min', 'salaire_min', 'indemn_min', 'autre_min', ),
622 ('classement_max', 'valeur_point_max' ,'devise_max', 'salaire_max', 'indemn_max', 'autre_max', ),
623 )
624 }),
625 ('Comparatifs de rémunération', {
626 'fields': ('devise_comparaison',
627 ('comp_locale_min', 'comp_locale_max'),
628 ('comp_universite_min', 'comp_universite_max'),
629 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
630 ('comp_ong_min', 'comp_ong_max'),
631 ('comp_autre_min', 'comp_autre_max'))
632 }),
633 ('Justification', {
634 'fields': ('justification',)
635 }),
636 ('Autres Méta-données', {
637 'fields': ('date_debut', 'date_fin')
638 }),
639 )
640
641 inlines = (PosteFinancementInline,
642 PostePieceInline,
643 DossierROInline,
644 PosteComparaisonInline,
645 PosteCommentaireInline, )
646
647
648 def lookup_allowed(self, key, value):
649 if key in (
650 'date_debut__gte',
651 'date_debut__isnull',
652 'date_fin__lte',
653 'date_fin__isnull',
654 'implantation__region__id__exact',
655 'implantation__id__exact',
656 'type_poste__id__exact',
657 'type_poste__famille_emploi__id__exact',
658 'service__id__exact',
659 'service__isnull',
660 'vacant__exact',
661 ):
662 return True
663
664
665 def _apercu(self, poste):
666 view_link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /></a>""" % \
667 (reverse('poste_apercu', args=(poste.id,)),
668 settings.STATIC_URL,
669 )
670 return view_link
671 _apercu.allow_tags = True
672 _apercu.short_description = ''
673
674 def _id(self, obj):
675 return "%s" % obj.id
676 _id.short_description = '#'
677 _id.admin_order_field = 'id'
678
679 def _service(self, obj):
680 return obj.service
681
682 def _nom(self, poste):
683 return """<a href="%s">%s</a>""" % \
684 (reverse('admin:rh_poste_change', args=(poste.id,)),
685 poste.nom
686 )
687 _nom.allow_tags = True
688 _nom.short_description = u'Nom'
689 _nom.admin_order_field = 'nom'
690
691 def _date_modification(self, obj):
692 return date(obj.date_modification)
693 _date_modification.short_description = u'date modification'
694 _date_modification.admin_order_field = 'date_modification'
695
696 def _occupe_par(self, obj):
697 """Formatte la méthode Poste.occupe_par() pour l'admin"""
698 output = u"Vacant"
699 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
700 return u"s/o"
701 employes = obj.occupe_par()
702 if employes:
703 l = []
704 for e in employes:
705 link = "<a href='%s' title='Aperçu de l\'employer' onclick='return showAddAnotherPopup(this)'><img src='%simg/loupe.png' /></a> <a href='%s'>%s</a>" % \
706 (reverse('employe_apercu', args=(e.id,)),
707 settings.STATIC_URL,
708 reverse('admin:rh_employe_change', args=(e.id,)),
709 e
710 )
711 l.append(link)
712 output = "\n<br />".join(l)
713 return output
714 _occupe_par.allow_tags = True
715 _occupe_par.short_description = "Occupé par"
716
717 def save_formset(self, request, form, formset, change):
718 instances = formset.save(commit=False)
719 for instance in instances:
720 if instance.__class__ == rh.PosteCommentaire:
721 instance.owner = request.user
722 instance.date_creation = datetime.datetime.now()
723 instance.save()
724 formset.save_m2m()
725
726
727 class PosteCommentaireAdmin(admin.ModelAdmin):
728 pass
729
730
731 class PosteFinancementAdmin(admin.ModelAdmin):
732 pass
733
734
735 class PostePieceAdmin(admin.ModelAdmin):
736 fk_name = 'poste'
737
738
739 class RemunerationAdmin(admin.ModelAdmin):
740 pass
741
742
743 class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
744 fieldsets = AUFMetadataAdminMixin.fieldsets + (
745 (None, {
746 'fields': ('employe', 'implantation', ),
747 }),
748 )
749
750
751 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
752 list_display = ('nom', '_date_modification', 'user_modification', )
753 fieldsets = AUFMetadataAdminMixin.fieldsets + (
754 (None, {
755 'fields': ('nom', ),
756 }),
757 )
758
759 def _date_modification(self, obj):
760 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
761 _date_modification.short_description = u'date modification'
762 _date_modification.admin_order_field = 'date_modification'
763
764
765 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
766 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
767 fieldsets = AUFMetadataAdminMixin.fieldsets + (
768 (None, {
769 'fields': ('code', 'nom', ),
770 }),
771 )
772
773 def _date_modification(self, obj):
774 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
775 _date_modification.short_description = u'date modification'
776 _date_modification.admin_order_field = 'date_modification'
777
778 class TauxChangeAdmin(admin.ModelAdmin):
779 list_display = ('taux', 'devise', 'annee', '_date_modification', 'user_modification', )
780 list_filter = ('devise', )
781 fieldsets = AUFMetadataAdminMixin.fieldsets + (
782 (None, {
783 'fields': ('taux', 'devise', 'annee', ),
784 }),
785 )
786
787 def _date_modification(self, obj):
788 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
789 _date_modification.short_description = u'date modification'
790 _date_modification.admin_order_field = 'date_modification'
791
792 class TypeContratAdmin(admin.ModelAdmin):
793 list_display = ('nom', 'nom_long', '_date_modification', 'user_modification', )
794 fieldsets = AUFMetadataAdminMixin.fieldsets + (
795 (None, {
796 'fields': ('nom', 'nom_long', ),
797 }),
798 )
799
800 def _date_modification(self, obj):
801 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
802 _date_modification.short_description = u'date modification'
803 _date_modification.admin_order_field = 'date_modification'
804
805
806 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
807 search_fields = ('nom', 'nom_feminin', )
808 list_display = ('nom', 'famille_emploi', '_date_modification', 'user_modification', )
809 list_filter = ('famille_emploi', )
810 fieldsets = AUFMetadataAdminMixin.fieldsets + (
811 (None, {
812 'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi', )
813 }),
814 )
815
816 def _date_modification(self, obj):
817 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
818 _date_modification.short_description = u'date modification'
819 _date_modification.admin_order_field = 'date_modification'
820
821
822 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
823 list_display = ('nom', 'type_paiement', 'nature_remuneration', '_date_modification', 'user_modification', )
824 fieldsets = AUFMetadataAdminMixin.fieldsets + (
825 (None, {
826 'fields': ('nom', 'type_paiement', 'nature_remuneration', )
827 }),
828 )
829
830 def _date_modification(self, obj):
831 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
832 _date_modification.short_description = u'date modification'
833 _date_modification.admin_order_field = 'date_modification'
834
835
836 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
837 list_display = ('nom', '_date_modification', 'user_modification', )
838 fieldsets = AUFMetadataAdminMixin.fieldsets + (
839 (None, {
840 'fields': ('nom', )
841 }),
842 )
843
844 def _date_modification(self, obj):
845 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
846 _date_modification.short_description = u'date modification'
847 _date_modification.admin_order_field = 'date_modification'
848
849
850 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
851 list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur', '_date_modification', 'user_modification', )
852 list_filter = ('annee', 'devise', )
853 fieldsets = AUFMetadataAdminMixin.fieldsets + (
854 (None, {
855 'fields': ('valeur', 'devise', 'implantation', 'annee', )
856 }),
857 )
858
859 def _date_modification(self, obj):
860 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
861 _date_modification.short_description = u'date modification'
862 _date_modification.admin_order_field = 'date_modification'
863
864 def _devise_code(self, obj):
865 return obj.devise.code
866 _devise_code.short_description = "Code de la devise"
867
868 def _devise_nom(self, obj):
869 return obj.devise.nom
870 _devise_nom.short_description = "Nom de la devise"
871
872
873 admin.site.register(rh.Classement, ClassementAdmin)
874 admin.site.register(rh.Devise, DeviseAdmin)
875 admin.site.register(rh.Dossier, DossierAdmin)
876 admin.site.register(rh.Employe, EmployeAdmin)
877 admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
878 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
879 admin.site.register(rh.Poste, PosteAdmin)
880 admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
881 admin.site.register(rh.Service, ServiceAdmin)
882 admin.site.register(rh.Statut, StatutAdmin)
883 admin.site.register(rh.TauxChange, TauxChangeAdmin)
884 admin.site.register(rh.TypeContrat, TypeContratAdmin)
885 admin.site.register(rh.TypePoste, TypePosteAdmin)
886 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
887 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
888 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)