[#2593] Ajouter le champ courriel perso au modèle des employés
[auf_rh_dae.git] / project / rh / admin.py
1 # -*- encoding: utf-8 -*-
2
3 import datetime
4
5 from ajax_select import make_ajax_form
6 from auf.django.metadata.admin import \
7 AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, \
8 AUF_METADATA_READONLY_FIELDS
9 from django.core.urlresolvers import reverse
10 from django.contrib import admin
11 from django.conf import settings
12 from django.db.models import Q
13 from django.template.defaultfilters import date
14
15 import auf.django.references.models as ref
16 import models as rh
17 from forms import \
18 ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect, DossierForm
19 from dae.utils import get_employe_from_user
20 from change_list import ChangeList
21 from groups import grp_correspondants_rh
22 from decorators import in_drh_or_admin
23
24
25 class ArchiveMixin(object):
26 """
27 Archive Mixin pour gérer le queryset et le display
28 NON COMPRIS : list_filter, et list_display, field à setter dans la classe.
29 """
30
31 def queryset(self, request):
32 return self.model._base_manager
33
34 def _archive(self, obj):
35 if obj.archive:
36 return "oui"
37 else:
38 return "non"
39 _archive.short_description = u'Archivé'
40 _archive.admin_order_field = 'archive'
41
42
43 class RegionProxy(ref.Region):
44 """ Proxy utilisé pour les organigrammes par région """
45 class Meta:
46 proxy = True
47 verbose_name = u"Organigramme par région"
48 verbose_name_plural = u"Organigramme par région"
49
50
51 class ImplantationProxy(ref.Implantation):
52 """ Proxy utilisé pour les organigrammes par implantation """
53 class Meta:
54 proxy = True
55 verbose_name = u"Organigramme par implantations"
56 verbose_name_plural = u"Organigramme par implantations"
57
58
59 class ServiceProxy(rh.Service):
60 """ Proxy utilisé pour les organigrammes opar service """
61 class Meta:
62 proxy = True
63 verbose_name = u"Organigramme par services"
64 verbose_name_plural = u"Organigramme par services"
65
66
67 class EmployeProxy(rh.Employe):
68 """ Proxy utilisé pour les organigrammes des employés """
69 class Meta:
70 proxy = True
71 verbose_name = u"Organigramme des employés"
72 verbose_name_plural = u"Organigramme des employés"
73
74
75 class DateRangeMixin(object):
76 prefixe_recherche_temporelle = ""
77
78 def get_changelist(self, request, **kwargs):
79 if 'HTTP_REFERER' in request.META.keys():
80 referer = request.META['HTTP_REFERER']
81 referer = "/".join(referer.split('/')[3:])
82 referer = "/%s" % referer.split('?')[0]
83 change_list_view = 'admin:%s_%s_changelist' % (
84 self.model._meta.app_label,
85 self.model.__name__.lower(),)
86 if referer != reverse(change_list_view):
87 params = request.GET.copy()
88 params.update({'statut': 'Actif'})
89 request.GET = params
90 return ChangeList
91
92
93 # Override of the InlineModelAdmin to support the link in the tabular inline
94 class LinkedInline(admin.options.InlineModelAdmin):
95 template = "admin/linked.html"
96 admin_model_path = None
97
98 def __init__(self, *args):
99 super(LinkedInline, self).__init__(*args)
100 if self.admin_model_path is None:
101 self.admin_model_path = self.model.__name__.lower()
102
103
104 class ProtectRegionMixin(object):
105
106 def queryset(self, request):
107 qs = super(ProtectRegionMixin, self).queryset(request)
108
109 user_groups = request.user.groups.all()
110 if in_drh_or_admin(request.user):
111 return qs
112
113 if grp_correspondants_rh in user_groups:
114 employe = get_employe_from_user(request.user)
115 q = Q(**{self.model.prefix_implantation: \
116 employe.implantation.region})
117 qs = qs.filter(q).distinct()
118 return qs
119 return qs.none()
120
121 def has_add_permission(self, request):
122 if not in_drh_or_admin(request.user):
123 return False
124 else:
125 return True
126
127 def has_change_permission(self, request, obj=None):
128 user_groups = request.user.groups.all()
129
130 # Lock pour autoriser uniquement les DRH à utiliser RH
131 if not in_drh_or_admin(request.user):
132 return False
133
134 if len(user_groups) == 0 and not request.user.is_superuser:
135 return False
136
137 if obj is None:
138 return True
139 ids = [o.id for o in self.queryset(request)]
140 return obj.id in ids
141
142
143 # Inlines
144
145 class ReadOnlyInlineMixin(object):
146
147 def get_readonly_fields(self, request, obj=None):
148 return [f.name for f in self.model._meta.fields \
149 if f.name not in AUF_METADATA_READONLY_FIELDS]
150
151
152 class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
153 model = rh.AyantDroit
154 form = AyantDroitForm
155 extra = 0
156
157 fieldsets = (
158 (None, {
159 'fields': (
160 ('nom', 'prenom'),
161 ('nom_affichage', 'genre'),
162 'nationalite',
163 'date_naissance',
164 'lien_parente',
165 )}),
166 )
167
168
169 class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, \
170 admin.TabularInline):
171 readonly_fields = ('owner', )
172 model = rh.AyantDroitCommentaire
173 extra = 1
174
175
176 class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
177 form = ContratForm
178 model = rh.Contrat
179 extra = 1
180
181
182 class DossierROInline(ReadOnlyInlineMixin, LinkedInline):
183 template = "admin/rh/dossier/linked.html"
184 exclude = AUF_METADATA_READONLY_FIELDS
185 model = rh.Dossier
186 extra = 0
187 can_delete = False
188
189 def has_add_permission(self, request=None):
190 return False
191
192 def has_change_permission(self, request, obj=None):
193 return False
194
195 def has_delete_permission(self, request, obj=None):
196 return False
197
198
199 class DossierCommentaireInline(AUFMetadataInlineAdminMixin, \
200 admin.TabularInline):
201 readonly_fields = ('owner', )
202 model = rh.DossierCommentaire
203 extra = 1
204
205
206 class DossierPieceInline(admin.TabularInline):
207 model = rh.DossierPiece
208 extra = 4
209
210
211 class EmployeInline(admin.TabularInline):
212 model = rh.Employe
213
214
215 class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, \
216 admin.TabularInline):
217 readonly_fields = ('owner', )
218 model = rh.EmployeCommentaire
219 extra = 1
220
221
222 class EmployePieceInline(admin.TabularInline):
223 model = rh.EmployePiece
224 extra = 4
225
226
227 class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
228 readonly_fields = ('owner', )
229 model = rh.PosteCommentaire
230 extra = 1
231
232
233 class PosteFinancementInline(admin.TabularInline):
234 model = rh.PosteFinancement
235
236
237 class PostePieceInline(admin.TabularInline):
238 model = rh.PostePiece
239
240
241 class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
242 model = rh.Remuneration
243 extra = 1
244
245
246 class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
247 pass
248
249
250 class TypePosteInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
251 model = rh.TypePoste
252
253
254 class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
255 model = rh.PosteComparaison
256
257
258 class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
259 list_display = ('_classement', '_date_modification', 'user_modification', )
260 fieldsets = AUFMetadataAdminMixin.fieldsets + (
261 (None, {
262 'fields': ('type', 'echelon', 'degre', 'coefficient',)}),
263 )
264
265 def _classement(self, obj):
266 return unicode(obj)
267 _classement.short_description = u"Classement"
268
269 def _date_modification(self, obj):
270 return date(obj.date_modification) \
271 if obj.date_modification is not None else "(aucune)"
272 _date_modification.short_description = u'date modification'
273 _date_modification.admin_order_field = 'date_modification'
274
275
276 class CommentaireAdmin(admin.ModelAdmin):
277 pass
278
279
280 class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
281 list_display = (
282 'code',
283 'nom',
284 '_archive',
285 '_date_modification',
286 'user_modification',
287 )
288 list_filter = ('archive', )
289 fieldsets = AUFMetadataAdminMixin.fieldsets + (
290 (None, {
291 'fields': ('code', 'nom', 'archive', ),
292 }),
293 )
294
295 def _date_modification(self, obj):
296 return date(obj.date_modification) \
297 if obj.date_modification is not None else "(aucune)"
298 _date_modification.short_description = u'date modification'
299 _date_modification.admin_order_field = 'date_modification'
300
301
302 class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
303 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
304 alphabet_filter = 'employe__nom'
305 search_fields = (
306 'employe__nom',
307 'employe__prenom',
308 'poste__nom',
309 'poste__nom_feminin')
310 list_display = (
311 '_id',
312 '_apercu',
313 '_nom',
314 '_poste',
315 '_employe',
316 '_date_debut',
317 '_date_fin',
318 '_date_modification',
319 'user_modification',
320 '_dae',
321 )
322 list_display_links = ('_nom',)
323 list_filter = (
324 'poste__implantation__region',
325 'poste__implantation',
326 'poste__type_poste__categorie_emploi',
327 'poste__type_poste',
328 'rh_contrats__type_contrat',
329 'principal',
330 )
331 inlines = (DossierPieceInline, ContratInline,
332 RemunerationInline,
333 DossierCommentaireInline,
334 )
335 fieldsets = AUFMetadataAdminMixin.fieldsets + (
336 (None, {
337 'fields': (
338 'employe',
339 'poste',
340 'principal',
341 'statut',
342 'organisme_bstg',)}),
343 ('Recrutement', {
344 'fields': (
345 'statut_residence',
346 'remplacement',
347 'remplacement_de', )}),
348 ('Rémunération', {
349 'fields': (
350 'classement',
351 ('regime_travail', 'regime_travail_nb_heure_semaine'),)}),
352 ('Occupation du Poste par cet Employe', {
353 'fields': (('date_debut', 'date_fin'), )}
354 ),
355 )
356 form = make_ajax_form(rh.Dossier, {
357 'employe': 'employes',
358 'poste': 'postes',
359 'remplacement_de': 'dossiers',
360 }, superclass=DossierForm)
361
362 def lookup_allowed(self, key, value):
363 if key in (
364 'employe__nom__istartswith',
365 'poste__implantation__region__id__exact',
366 'poste__implantation__id__exact',
367 'poste__type_poste__id__exact',
368 'poste__type_poste__categorie_emploi__id__exact',
369 'rh_contrats__type_contrat__id__exact',
370 'principal__exact',
371 'principal__isnull',
372 ):
373 return True
374
375 def _id(self, obj):
376 return obj.id
377 _id.short_description = u"#"
378 _id.admin_order_field = "id"
379
380 def _nom(self, obj):
381 return "%d : %s %s" % (
382 obj.date_debut.year,
383 obj.employe.nom.upper(),
384 obj.employe.prenom)
385 _nom.allow_tags = True
386 _nom.short_description = u"Dossier"
387
388 def _apercu(self, d):
389 apercu_link = u"""<a title="Aperçu du dossier"
390 onclick="return showAddAnotherPopup(this);"
391 href='%s'>
392 <img src="%simg/loupe.png" />
393 </a>""" % \
394 (reverse('dossier_apercu', args=(d.id,)),
395 settings.STATIC_URL,
396 )
397 return apercu_link
398 _apercu.allow_tags = True
399 _apercu.short_description = u""
400
401 def _dae(self, d):
402 apercu_link = ""
403 dossiers_dae = d.dossiers_dae.all()
404 if len(dossiers_dae) > 0:
405 dossier_dae = dossiers_dae[0]
406 apercu_link = u"""<a title="Aperçu du dossier"
407 onclick="return showAddAnotherPopup(this);"
408 href='%s'>
409 <img src="%simg/loupe.png" />
410 </a>""" % \
411 (reverse('embauche_consulter', args=(dossier_dae.id,)),
412 settings.STATIC_URL,
413 )
414 return apercu_link
415 _dae.allow_tags = True
416 _dae.short_description = u"DAE"
417
418 def _date_debut(self, obj):
419 return date(obj.date_debut)
420
421 _date_debut.short_description = u'Occupation début'
422 _date_debut.admin_order_field = 'date_debut'
423
424 def _date_fin(self, obj):
425 return date(obj.date_fin)
426 _date_fin.short_description = u'Occupation fin'
427 _date_fin.admin_order_field = 'date_fin'
428
429 def _date_modification(self, obj):
430 return date(obj.date_modification) \
431 if obj.date_modification is not None else "(aucune)"
432 _date_modification.short_description = u'date modification'
433 _date_modification.admin_order_field = 'date_modification'
434
435 def _poste(self, dossier):
436 link = u"""<a title="Aperçu du poste"
437 onclick="return showAddAnotherPopup(this);"
438 href='%s'><img src="%simg/loupe.png" />
439 </a>
440 <a href="%s" title="Modifier le poste">%s</a>""" % \
441 (reverse('poste_apercu', args=(dossier.poste.id,)),
442 settings.STATIC_URL,
443 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
444 dossier.poste,
445 )
446 return link
447 _poste.allow_tags = True
448 _poste.short_description = u'Poste'
449 _poste.admin_order_field = 'poste__nom'
450
451 def _employe(self, obj):
452 employe = obj.employe
453 view_link = reverse('employe_apercu', args=(employe.id,))
454 edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
455
456 style = ""
457 view = u"""<a href="%s"
458 title="Aperçu l'employé"
459 onclick="return showAddAnotherPopup(this);">
460 <img src="%simg/loupe.png" />
461 </a>""" % (view_link, settings.STATIC_URL,)
462 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
463 (view, edit_link, style, employe)
464 _employe.allow_tags = True
465 _employe.short_description = u"Employé"
466 _employe.admin_order_field = "employe__nom"
467
468 def save_formset(self, request, form, formset, change):
469 instances = formset.save(commit=False)
470 for instance in instances:
471 if instance.__class__ == rh.DossierCommentaire:
472 instance.owner = request.user
473 instance.date_creation = datetime.datetime.now()
474 instance.save()
475
476
477 class DossierPieceAdmin(admin.ModelAdmin):
478 pass
479
480
481 class DossierCommentaireAdmin(admin.ModelAdmin):
482 pass
483
484
485 class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
486 ProtectRegionMixin, admin.ModelAdmin,):
487 prefixe_recherche_temporelle = "rh_dossiers__"
488 alphabet_filter = 'nom'
489 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
490 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
491 ordering = ('nom', )
492 form = EmployeAdminForm
493 list_display = (
494 '_id',
495 '_apercu',
496 '_nom',
497 '_dossiers_postes',
498 '_date_modification',
499 'user_modification',
500 )
501 list_display_links = ('_nom',)
502 list_filter = (
503 'rh_dossiers__poste__implantation__region',
504 'rh_dossiers__poste__implantation',
505 'nb_postes',
506 )
507 inlines = (AyantDroitInline,
508 DossierROInline,
509 EmployePieceInline,
510 EmployeCommentaireInline)
511 fieldsets = AUFMetadataAdminMixin.fieldsets + (
512 ('Identification', {
513 'fields': (
514 ('nom', 'prenom'),
515 ('nom_affichage', 'genre'),
516 'nationalite',
517 'date_naissance',
518 )}
519 ),
520 ('Informations personnelles', {
521 'fields': ('situation_famille', 'date_entree', )}
522 ),
523 ('Coordonnées personnelles', {
524 'fields': (
525 ('tel_domicile', 'tel_cellulaire'),
526 ('adresse', 'ville'),
527 ('code_postal', 'province'),
528 'pays',
529 'courriel_perso'
530 )}
531 ),
532 )
533
534 def _apercu(self, obj):
535 return u"""<a title="Aperçu de l'employé"
536 onclick="return showAddAnotherPopup(this);"
537 href='%s'>
538 <img src="%simg/loupe.png" />
539 </a>""" % \
540 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
541 _apercu.allow_tags = True
542 _apercu.short_description = u""
543
544 def _nom(self, obj):
545 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
546 return u"""<a href='%s'><strong>%s</strong></a>""" % \
547 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
548 _nom.allow_tags = True
549 _nom.short_description = u"Employé"
550 _nom.admin_order_field = "nom"
551
552 def _id(self, obj):
553 return obj.id
554 _id.short_description = u"#"
555 _id.admin_order_field = "id"
556
557 def _date_modification(self, obj):
558 return date(obj.date_modification) \
559 if obj.date_modification is not None else "(aucune)"
560 _date_modification.short_description = u'date modification'
561 _date_modification.admin_order_field = 'date_modification'
562
563 def _dossiers_postes(self, obj):
564 l = []
565 for d in obj.rh_dossiers.all().order_by('-date_debut'):
566 dossier = u"""<a title="Aperçu du dossier"
567 href="%s"
568 onclick="return showAddAnotherPopup(this);"
569 title="Aperçu du dossier">
570 <img src="%simg/loupe.png" />
571 </a>
572 <a href="%s">Dossier</a>
573 &nbsp;""" % \
574 (reverse('dossier_apercu', args=(d.id,)),
575 settings.STATIC_URL,
576 reverse('admin:rh_dossier_change', args=(d.id,)))
577
578 poste = u"""<a title="Aperçu du poste"
579 href="%s"
580 onclick="return showAddAnotherPopup(this);"
581 title="Aperçu du poste">
582 <img src="%simg/loupe.png" />
583 </a>
584 <a href="%s">Poste</a>
585 &nbsp;""" % \
586 (reverse('poste_apercu', args=(d.poste.id,)),
587 settings.STATIC_URL,
588 reverse('admin:rh_poste_change', args=(d.poste.id,)))
589 link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
590 (dossier, poste,
591 d.date_debut.year,
592 d.poste.id,
593 d.poste.nom,
594 )
595
596 # Dossier terminé en gris non cliquable
597 if d.date_fin is not None and d.date_fin < datetime.date.today():
598 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
599 (d.date_debut.year,
600 d.poste.id,
601 d.poste.nom,
602 )
603
604 l.append(link)
605 return "<ul>%s</ul>" % "\n".join(l)
606 _dossiers_postes.allow_tags = True
607 _dossiers_postes.short_description = u"Dossiers et postes"
608
609 def queryset(self, request):
610 qs = super(EmployeAdmin, self).queryset(request)
611 return qs.select_related(depth=1).order_by('nom')
612
613 def save_formset(self, request, form, formset, change):
614 instances = formset.save(commit=False)
615 for instance in instances:
616 if instance.__class__ == rh.EmployeCommentaire:
617 instance.owner = request.user
618 instance.date_creation = datetime.datetime.now()
619 instance.save()
620
621
622 class EmployeProxyAdmin(EmployeAdmin):
623 list_display = ('_id', '_apercu', '_nom', '_organigramme')
624 actions = None
625
626 def __init__(self, *args, **kwargs):
627 super(EmployeProxyAdmin, self).__init__(*args, **kwargs)
628 self.list_display_links = (None, )
629
630 def has_add_permission(self, obj):
631 return False
632
633 def _organigramme(self, obj):
634 l = []
635 for d in rh.Dossier.objects.filter(
636 Q(date_fin__gt=datetime.date.today()) | Q(date_fin=None),
637 Q(date_debut__lt=datetime.date.today()) | Q(date_debut=None),
638 employe=obj.id
639 ):
640 organigramme = \
641 u'Organigramme, niveau: ' \
642 u'<input type="text" id="level_%s" ' \
643 u'style="width:30px;height:15px;" /> ' \
644 u'<input type="button" value="Générer" ' \
645 u"""onclick="window.location='%s' + """ \
646 u"""document.getElementById('level_%s').value" />""" % (
647 d.poste.id,
648 reverse('rho_employe_sans_niveau', args=(d.poste.id,)),
649 d.poste.id
650 )
651 link = u"""<li>%s - [%s] %s : %s</li>""" % (
652 d.date_debut.year,
653 d.poste.id,
654 d.poste.nom,
655 organigramme
656 )
657 l.append(link)
658 return "<ul>%s</ul>" % "\n".join(l)
659
660 _organigramme.allow_tags = True
661 _organigramme.short_description = "Organigramme"
662
663
664 class EmployeCommentaireAdmin(admin.ModelAdmin):
665 pass
666
667
668 class EmployePieceAdmin(admin.ModelAdmin):
669 pass
670
671
672 class CategorieEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
673 list_display = ('nom', '_date_modification', 'user_modification', )
674 inlines = (TypePosteInline,)
675 fieldsets = AUFMetadataAdminMixin.fieldsets + (
676 (None, {'fields': ('nom', )}),)
677
678 def _date_modification(self, obj):
679 return date(obj.date_modification) \
680 if obj.date_modification is not None else "(aucune)"
681 _date_modification.short_description = u'date modification'
682 _date_modification.admin_order_field = 'date_modification'
683
684
685 class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
686 search_fields = ('nom',)
687 list_display = (
688 'nom',
689 'type',
690 'pays',
691 '_date_modification',
692 'user_modification',
693 )
694 list_filter = ('type', )
695 inlines = (DossierROInline,)
696 fieldsets = AUFMetadataAdminMixin.fieldsets + (
697 (None, {'fields': ('nom', 'type', 'pays',)}),
698 )
699
700 def _date_modification(self, obj):
701 return date(obj.date_modification) \
702 if obj.date_modification is not None else "(aucune)"
703 _date_modification.short_description = u'date modification'
704 _date_modification.admin_order_field = 'date_modification'
705
706
707 class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
708 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
709 form = make_ajax_form(rh.Poste, {
710 'implantation': 'implantations',
711 'type_poste': 'typepostes',
712 'responsable': 'postes',
713 'valeur_point_min': 'valeurpoints',
714 'valeur_point_max': 'valeurpoints',
715 })
716 alphabet_filter = 'nom'
717 search_fields = (
718 'id',
719 'nom',
720 'implantation__nom',
721 'implantation__region__code',
722 'implantation__region__nom',
723 'rh_dossiers__employe__nom',
724 'rh_dossiers__employe__prenom',
725 )
726 list_display = (
727 '_id',
728 '_apercu',
729 '_nom',
730 '_occupe_par',
731 'implantation',
732 '_service',
733 '_responsable',
734 'date_debut',
735 'date_fin',
736 '_date_modification',
737 'user_modification',
738 '_dae',
739 )
740 list_filter = (
741 'implantation__region',
742 'implantation',
743 'service',
744 'type_poste',
745 'type_poste__categorie_emploi',
746 'type_poste__famille_professionnelle',
747 'vacant',
748 )
749 list_display_links = ('_nom',)
750 fieldsets = AUFMetadataAdminMixin.fieldsets + (
751 (None, {'fields': (
752 ('nom', 'nom_feminin'),
753 'implantation',
754 'type_poste',
755 'service',
756 'responsable',
757 )}
758 ),
759 ('Contrat', {
760 'fields': ((
761 'regime_travail',
762 'regime_travail_nb_heure_semaine'),
763 )}
764 ),
765 ('Recrutement', {
766 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
767 ),
768 ('Rémunération', {
769 'fields': (('classement_min',
770 'valeur_point_min',
771 'devise_min',
772 'salaire_min',
773 'indemn_min',
774 'autre_min',),
775 ('classement_max',
776 'valeur_point_max',
777 'devise_max',
778 'salaire_max',
779 'indemn_max',
780 'autre_max',),
781 )}),
782 ('Comparatifs de rémunération', {
783 'fields': ('devise_comparaison',
784 ('comp_locale_min', 'comp_locale_max'),
785 ('comp_universite_min', 'comp_universite_max'),
786 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
787 ('comp_ong_min', 'comp_ong_max'),
788 ('comp_autre_min', 'comp_autre_max'))}
789 ),
790 ('Justification', {
791 'fields': ('justification',)}
792 ),
793 ('Autres Méta-données', {
794 'fields': ('date_debut', 'date_fin')}
795 ),
796 )
797
798 inlines = (PosteFinancementInline,
799 PostePieceInline,
800 DossierROInline,
801 PosteComparaisonInline,
802 PosteCommentaireInline, )
803
804 def lookup_allowed(self, key, value):
805 return key in (
806 'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
807 'date_fin__isnull', 'implantation__region__id__exact',
808 'implantation__id__exact', 'type_poste__id__exact',
809 'type_poste__categorie_emploi__id__exact', 'service__id__exact',
810 'service__isnull', 'vacant__exact', 'vacant__isnull',
811 ) or super(PosteAdmin, self).lookup_allowed(key, value)
812
813 def _apercu(self, poste):
814 view_link = u"""<a onclick="return showAddAnotherPopup(this);"
815 title="Aperçu du poste"
816 href='%s'>
817 <img src="%simg/loupe.png" />
818 </a>""" % \
819 (reverse('poste_apercu', args=(poste.id,)),
820 settings.STATIC_URL,)
821 return view_link
822 _apercu.allow_tags = True
823 _apercu.short_description = ''
824
825 def _dae(self, poste):
826 apercu_link = ""
827 postes_dae = poste.postes_dae.all()
828 if len(postes_dae) > 0:
829 poste_dae = postes_dae[0]
830 apercu_link = \
831 u'<a title="Aperçu du dossier" href="%s" ' \
832 u'onclick="return showAddAnotherPopup(this);">' \
833 u'<img src="%simg/loupe.png" /></a>' % (reverse(
834 'poste_consulter', args=("dae-%s" % poste_dae.id,)
835 ), settings.STATIC_URL)
836 return apercu_link
837 _dae.allow_tags = True
838 _dae.short_description = u"DAE"
839
840 def _id(self, obj):
841 return "%s" % obj.id
842 _id.short_description = '#'
843 _id.admin_order_field = 'id'
844
845 def _service(self, obj):
846 if obj.service.supprime:
847 return """<span style="color:red">%s</span>""" % obj.service
848 else:
849 return obj.service
850 _service.short_description = 'Service'
851 _service.allow_tags = True
852
853 def _responsable(self, obj):
854 try:
855 responsable = u"""<a href="%s"
856 onclick="return showAddAnotherPopup(this)">
857 <img src="%simg/loupe.png"
858 title="Aperçu du poste" />
859 </a>
860 <a href="%s">%s</a>
861 <br />""" % \
862 (reverse('poste_apercu', args=(obj.responsable.id,)),
863 settings.STATIC_URL,
864 reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
865 obj.responsable.nom)
866 except:
867 responsable = ''
868
869 try:
870 employe = obj.responsable.rh_dossiers.all()[0]
871 employe_id = obj.responsable.rh_dossiers.all()[0].id
872 employe_html = u"""<br />
873 <a href="%s"
874 onclick="return showAddAnotherPopup(this)">
875 <img src="%simg/loupe.png"
876 title="Aperçu de l'employé">
877 </a>
878 <a href="%s">%s</a>""" % \
879 (reverse('employe_apercu', args=(employe_id,)),
880 settings.STATIC_URL,
881 reverse('admin:rh_employe_change', args=(employe_id,)),
882 employe)
883 except:
884 employe_html = ""
885
886 return "%s %s" % (responsable, employe_html)
887 _responsable.short_description = 'Responsable'
888 _responsable.allow_tags = True
889
890 def _nom(self, poste):
891 return """<a href="%s">%s</a>""" % \
892 (reverse('admin:rh_poste_change', args=(poste.id,)),
893 poste.nom)
894 _nom.allow_tags = True
895 _nom.short_description = u'Nom'
896 _nom.admin_order_field = 'nom'
897
898 def _date_modification(self, obj):
899 return date(obj.date_modification)
900 _date_modification.short_description = u'date modification'
901 _date_modification.admin_order_field = 'date_modification'
902
903 def _occupe_par(self, obj):
904 """Formatte la méthode Poste.occupe_par() pour l'admin"""
905 output = u"Vacant"
906 if obj.date_fin is not None and obj.date_fin < datetime.date.today():
907 return u"s/o"
908 employes = obj.occupe_par()
909 if employes:
910 l = []
911 for e in employes:
912 link = u"""<a href='%s'
913 title='Aperçu de l\'employer'
914 onclick='return showAddAnotherPopup(this)'>
915 <img src='%simg/loupe.png' />
916 </a>
917 <a href='%s'>%s</a>""" % \
918 (reverse('employe_apercu', args=(e.id,)),
919 settings.STATIC_URL,
920 reverse('admin:rh_employe_change', args=(e.id,)),
921 e)
922 l.append(link)
923 output = "\n<br />".join(l)
924 return output
925 _occupe_par.allow_tags = True
926 _occupe_par.short_description = "Occupé par"
927
928 def save_formset(self, request, form, formset, change):
929 instances = formset.save(commit=False)
930 for instance in instances:
931 if instance.__class__ == rh.PosteCommentaire:
932 instance.owner = request.user
933 instance.date_creation = datetime.datetime.now()
934 instance.save()
935 formset.save_m2m()
936
937
938 class PosteCommentaireAdmin(admin.ModelAdmin):
939 pass
940
941
942 class PosteFinancementAdmin(admin.ModelAdmin):
943 pass
944
945
946 class PostePieceAdmin(admin.ModelAdmin):
947 fk_name = 'poste'
948
949
950 class RemunerationAdmin(admin.ModelAdmin):
951 pass
952
953
954 class ResponsableInline(admin.TabularInline):
955 model = rh.ResponsableImplantation
956 extra = 0
957 fk_name = "implantation"
958
959
960 class ResponsableImplantationAdmin(admin.ModelAdmin):
961 actions = None
962 list_filter = ('region', 'statut', )
963 list_display = ('nom', 'statut', '_responsable', )
964 readonly_fields = ('nom', )
965 fields = ('nom', )
966 inlines = (ResponsableInline, )
967
968 def _responsable(self, obj):
969 try:
970 employe = obj.responsable.employe
971 dossiers = employe.dossiers_encours()
972 if len(dossiers) == 0:
973 return u"<span style='color: red;'>%s %s </span>" % (
974 employe, u"sans dossier actif")
975 else:
976 return employe
977 except Exception:
978 if obj.statut in (1, 2): # ouverte, ouverture imminente
979 css = "style='color: red;'"
980 else:
981 css = ""
982 return u"<span %s>Pas de responsable</span>" % css
983 _responsable.allow_tags = True
984 _responsable.short_description = u"Responsable"
985
986 def has_add_permission(self, request=None):
987 return False
988
989 def has_change_permission(self, request, obj=None):
990 return in_drh_or_admin(request.user)
991
992 def has_delete_permission(self, request, obj=None):
993 return False
994
995
996 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
997 list_display = (
998 'nom',
999 '_archive',
1000 '_date_modification',
1001 'user_modification',
1002 )
1003 list_filter = ('archive', )
1004 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1005 (None, {
1006 'fields': ('nom', 'archive', ),
1007 }),
1008 )
1009
1010 def _date_modification(self, obj):
1011 return date(obj.date_modification) \
1012 if obj.date_modification is not None else "(aucune)"
1013 _date_modification.short_description = u'date modification'
1014 _date_modification.admin_order_field = 'date_modification'
1015
1016
1017 class ServiceProxyAdmin(ServiceAdmin):
1018 list_display = ('nom', '_organigramme', '_archive', )
1019 actions = None
1020
1021 def __init__(self, *args, **kwargs):
1022 super(ServiceProxyAdmin, self).__init__(*args, **kwargs)
1023 self.list_display_links = (None, )
1024
1025 def has_add_permission(self, obj):
1026 return False
1027
1028 def has_change_permission(self, request, obj=None):
1029 return in_drh_or_admin(request.user)
1030
1031 def _organigramme(self, obj):
1032 return """<a href="%s"><strong>Organigramme</strong></a>""" % \
1033 (reverse('rho_service', args=(obj.id,)))
1034 _organigramme.allow_tags = True
1035 _organigramme.short_description = "Organigramme"
1036
1037
1038 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1039 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
1040 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1041 (None, {
1042 'fields': ('code', 'nom', ),
1043 }),
1044 )
1045
1046 def _date_modification(self, obj):
1047 return date(obj.date_modification) \
1048 if obj.date_modification is not None else "(aucune)"
1049 _date_modification.short_description = u'date modification'
1050 _date_modification.admin_order_field = 'date_modification'
1051
1052
1053 class TauxChangeAdmin(admin.ModelAdmin):
1054 list_display = (
1055 'taux',
1056 'devise',
1057 'annee',
1058 '_date_modification',
1059 'user_modification',
1060 )
1061 list_filter = ('devise', )
1062 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1063 (None, {
1064 'fields': ('taux', 'devise', 'annee', ),
1065 }),
1066 )
1067
1068 def _date_modification(self, obj):
1069 return date(obj.date_modification) \
1070 if obj.date_modification is not None else "(aucune)"
1071 _date_modification.short_description = u'date modification'
1072 _date_modification.admin_order_field = 'date_modification'
1073
1074
1075 class TypeContratAdmin(admin.ModelAdmin):
1076 list_display = (
1077 'nom',
1078 'nom_long',
1079 '_date_modification',
1080 'user_modification',
1081 )
1082 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1083 (None, {
1084 'fields': ('nom', 'nom_long', ),
1085 }),
1086 )
1087
1088 def _date_modification(self, obj):
1089 return date(obj.date_modification) \
1090 if obj.date_modification is not None else "(aucune)"
1091 _date_modification.short_description = u'date modification'
1092 _date_modification.admin_order_field = 'date_modification'
1093
1094
1095 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1096 search_fields = ('nom', 'nom_feminin', )
1097 list_display = (
1098 'nom',
1099 'categorie_emploi',
1100 '_date_modification',
1101 'user_modification',
1102 )
1103 list_filter = ('categorie_emploi', 'famille_professionnelle')
1104 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1105 (None, {
1106 'fields': (
1107 'nom',
1108 'nom_feminin',
1109 'is_responsable',
1110 'categorie_emploi',
1111 'famille_professionnelle',
1112 )}
1113 ),
1114 )
1115
1116 def _date_modification(self, obj):
1117 return date(obj.date_modification) \
1118 if obj.date_modification is not None else "(aucune)"
1119 _date_modification.short_description = u'date modification'
1120 _date_modification.admin_order_field = 'date_modification'
1121
1122
1123 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin,
1124 ArchiveMixin):
1125 list_display = (
1126 'nom',
1127 'type_paiement',
1128 'nature_remuneration',
1129 '_archive',
1130 '_date_modification',
1131 'user_modification',)
1132 list_filter = ('archive', )
1133 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1134 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1135 'archive')}),
1136 )
1137
1138 def _date_modification(self, obj):
1139 return date(obj.date_modification) \
1140 if obj.date_modification is not None else "(aucune)"
1141 _date_modification.short_description = u'date modification'
1142 _date_modification.admin_order_field = 'date_modification'
1143
1144
1145 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1146 list_display = ('nom', '_date_modification', 'user_modification', )
1147 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1148 (None, {'fields': ('nom', )}),
1149 )
1150
1151 def _date_modification(self, obj):
1152 return date(obj.date_modification) \
1153 if obj.date_modification is not None else "(aucune)"
1154 _date_modification.short_description = u'date modification'
1155 _date_modification.admin_order_field = 'date_modification'
1156
1157
1158 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1159 list_display = (
1160 '_devise_code',
1161 '_devise_nom',
1162 'annee',
1163 'implantation',
1164 'valeur',
1165 '_date_modification',
1166 'user_modification',
1167 )
1168 list_filter = ('annee', 'devise', 'implantation__region', )
1169 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1170 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
1171 )
1172
1173 def _date_modification(self, obj):
1174 return date(obj.date_modification) \
1175 if obj.date_modification is not None else "(aucune)"
1176 _date_modification.short_description = u'date modification'
1177 _date_modification.admin_order_field = 'date_modification'
1178
1179 def _devise_code(self, obj):
1180 return obj.devise.code
1181 _devise_code.short_description = "Code de la devise"
1182
1183 def _devise_nom(self, obj):
1184 return obj.devise.nom
1185 _devise_nom.short_description = "Nom de la devise"
1186
1187
1188 class ImplantationProxyAdmin(admin.ModelAdmin):
1189 list_display = ('nom', '_organigramme')
1190 actions = None
1191
1192 def __init__(self, *args, **kwargs):
1193 super(ImplantationProxyAdmin, self).__init__(*args, **kwargs)
1194 self.list_display_links = (None, )
1195
1196 def has_add_permission(self, obj):
1197 return False
1198
1199 def has_change_permission(self, request, obj=None):
1200 return in_drh_or_admin(request.user)
1201
1202 def _organigramme(self, obj):
1203 return '<a href="%s"><strong>Organigramme</strong></a>' % (
1204 reverse('rho_implantation', args=(obj.id,))
1205 )
1206 _organigramme.allow_tags = True
1207 _organigramme.short_description = "Organigramme"
1208
1209
1210 class RegionProxyAdmin(admin.ModelAdmin):
1211 list_display = ('nom', '_organigramme')
1212 actions = None
1213
1214 def __init__(self, *args, **kwargs):
1215 super(RegionProxyAdmin, self).__init__(*args, **kwargs)
1216 self.list_display_links = (None, )
1217
1218 def has_add_permission(self, obj):
1219 return False
1220
1221 def has_change_permission(self, request, obj=None):
1222 return in_drh_or_admin(request.user)
1223
1224 def _organigramme(self, obj):
1225 return """<a href="%s"><strong>Organigramme</strong></a>""" % (
1226 reverse('rho_region', args=(obj.id,))
1227 )
1228 _organigramme.allow_tags = True
1229 _organigramme.short_description = "Organigramme"
1230
1231
1232 admin.site.register(rh.Classement, ClassementAdmin)
1233 admin.site.register(rh.Devise, DeviseAdmin)
1234 admin.site.register(rh.Dossier, DossierAdmin)
1235 admin.site.register(EmployeProxy, EmployeProxyAdmin)
1236 admin.site.register(ServiceProxy, ServiceProxyAdmin)
1237 admin.site.register(rh.Employe, EmployeAdmin)
1238 admin.site.register(rh.CategorieEmploi, CategorieEmploiAdmin)
1239 admin.site.register(rh.FamilleProfessionnelle)
1240 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1241 admin.site.register(rh.Poste, PosteAdmin)
1242 admin.site.register(
1243 rh.ResponsableImplantationProxy, ResponsableImplantationAdmin
1244 )
1245 admin.site.register(rh.Service, ServiceAdmin)
1246 admin.site.register(rh.Statut, StatutAdmin)
1247 admin.site.register(rh.TauxChange, TauxChangeAdmin)
1248 admin.site.register(rh.TypeContrat, TypeContratAdmin)
1249 admin.site.register(rh.TypePoste, TypePosteAdmin)
1250 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1251 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1252 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
1253 admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
1254 admin.site.register(RegionProxy, RegionProxyAdmin)