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