changelist
[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 lookup_allowed(self, key, value):
365 if key in (
366 'employe__nom__istartswith',
367 'poste__implantation__region__id__exact',
368 'poste__implantation__id__exact',
369 'poste__type_poste__id__exact',
370 'poste__type_poste__categorie_emploi__id__exact',
371 'rh_contrats__type_contrat__id__exact',
372 'principal__exact',
373 'principal__isnull',
374 ):
375 return True
376
377 def _id(self, obj):
378 return obj.id
379 _id.short_description = u"#"
380 _id.admin_order_field = "id"
381
382 def _nom(self, obj):
383 return "%d : %s %s" % (
384 obj.date_debut.year,
385 obj.employe.nom.upper(),
386 obj.employe.prenom)
387 _nom.allow_tags = True
388 _nom.short_description = u"Dossier"
389
390 def _apercu(self, d):
391 apercu_link = u"""<a title="Aperçu du dossier"
392 onclick="return showAddAnotherPopup(this);"
393 href='%s'>
394 <img src="%simg/loupe.png" />
395 </a>""" % \
396 (reverse('dossier_apercu', args=(d.id,)),
397 settings.STATIC_URL,
398 )
399 return apercu_link
400 _apercu.allow_tags = True
401 _apercu.short_description = u""
402
403 def _dae(self, d):
404 apercu_link = ""
405 dossiers_dae = d.dossiers_dae.all()
406 if len(dossiers_dae) > 0:
407 dossier_dae = dossiers_dae[0]
408 apercu_link = u"""<a title="Aperçu du dossier"
409 onclick="return showAddAnotherPopup(this);"
410 href='%s'>
411 <img src="%simg/loupe.png" />
412 </a>""" % \
413 (reverse('embauche_consulter', args=(dossier_dae.id,)),
414 settings.STATIC_URL,
415 )
416 return apercu_link
417 _dae.allow_tags = True
418 _dae.short_description = u"DAE"
419
420 def _date_debut(self, obj):
421 return date(obj.date_debut)
422
423 _date_debut.short_description = u'Occupation début'
424 _date_debut.admin_order_field = 'date_debut'
425
426 def _date_fin(self, obj):
427 return date(obj.date_fin)
428 _date_fin.short_description = u'Occupation fin'
429 _date_fin.admin_order_field = 'date_fin'
430
431 def _date_modification(self, obj):
432 return date(obj.date_modification) \
433 if obj.date_modification is not None else "(aucune)"
434 _date_modification.short_description = u'date modification'
435 _date_modification.admin_order_field = 'date_modification'
436
437 def _poste(self, dossier):
438 link = u"""<a title="Aperçu du poste"
439 onclick="return showAddAnotherPopup(this);"
440 href='%s'><img src="%simg/loupe.png" />
441 </a>
442 <a href="%s" title="Modifier le poste">%s</a>""" % \
443 (reverse('poste_apercu', args=(dossier.poste.id,)),
444 settings.STATIC_URL,
445 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
446 dossier.poste,
447 )
448 return link
449 _poste.allow_tags = True
450 _poste.short_description = u'Poste'
451 _poste.admin_order_field = 'poste__nom'
452
453 def _employe(self, obj):
454 employe = obj.employe
455 view_link = reverse('employe_apercu', args=(employe.id,))
456 edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
457
458 style = ""
459 view = u"""<a href="%s"
460 title="Aperçu l'employé"
461 onclick="return showAddAnotherPopup(this);">
462 <img src="%simg/loupe.png" />
463 </a>""" % (view_link, settings.STATIC_URL,)
464 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
465 (view, edit_link, style, employe)
466 _employe.allow_tags = True
467 _employe.short_description = u"Employé"
468 _employe.admin_order_field = "employe__nom"
469
470 def save_formset(self, request, form, formset, change):
471 instances = formset.save(commit=False)
472 for instance in instances:
473 if instance.__class__ == rh.DossierCommentaire:
474 instance.owner = request.user
475 instance.date_creation = datetime.datetime.now()
476 instance.save()
477
478
479 class DossierPieceAdmin(admin.ModelAdmin):
480 pass
481
482
483 class DossierCommentaireAdmin(admin.ModelAdmin):
484 pass
485
486
487 class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
488 ProtectRegionMixin, admin.ModelAdmin,):
489 prefixe_recherche_temporelle = "rh_dossiers__"
490 alphabet_filter = 'nom'
491 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
492 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
493 ordering = ('nom', )
494 form = EmployeAdminForm
495 list_display = (
496 '_id',
497 '_apercu',
498 '_nom',
499 '_dossiers_postes',
500 '_date_modification',
501 'user_modification',
502 )
503 list_display_links = ('_nom',)
504 list_filter = (
505 'rh_dossiers__poste__implantation__region',
506 'rh_dossiers__poste__implantation',
507 'nb_postes',
508 )
509 inlines = (AyantDroitInline,
510 DossierROInline,
511 EmployePieceInline,
512 EmployeCommentaireInline)
513 fieldsets = AUFMetadataAdminMixin.fieldsets + (
514 ('Identification', {
515 'fields': (
516 ('nom', 'prenom'),
517 ('nom_affichage', 'genre'),
518 'nationalite',
519 'date_naissance',
520 )}
521 ),
522 ('Informations personnelles', {
523 'fields': ('situation_famille', 'date_entree', )}
524 ),
525 ('Coordonnées', {
526 'fields': (
527 ('tel_domicile', 'tel_cellulaire'),
528 ('adresse', 'ville'),
529 ('code_postal', 'province'),
530 'pays',
531 )}
532 ),
533 )
534
535 def has_add_permission(self, request):
536 user_groups = request.user.groups.all()
537 if groups.grp_correspondants_rh in user_groups or \
538 groups.grp_administrateurs in user_groups or \
539 groups.grp_directeurs_bureau in user_groups or \
540 in_drh_or_admin(request.user):
541 return True
542 return False
543
544 def has_delete_permission(self, request, obj=None):
545 return in_drh_or_admin(request.user)
546
547 def _apercu(self, obj):
548 return u"""<a title="Aperçu de l'employé"
549 onclick="return showAddAnotherPopup(this);"
550 href='%s'>
551 <img src="%simg/loupe.png" />
552 </a>""" % \
553 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
554 _apercu.allow_tags = True
555 _apercu.short_description = u""
556
557 def _nom(self, obj):
558 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
559 return u"""<a href='%s'><strong>%s</strong></a>""" % \
560 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
561 _nom.allow_tags = True
562 _nom.short_description = u"Employé"
563 _nom.admin_order_field = "nom"
564
565 def _id(self, obj):
566 return obj.id
567 _id.short_description = u"#"
568 _id.admin_order_field = "id"
569
570 def _date_modification(self, obj):
571 return date(obj.date_modification) \
572 if obj.date_modification is not None else "(aucune)"
573 _date_modification.short_description = u'date modification'
574 _date_modification.admin_order_field = 'date_modification'
575
576 def _dossiers_postes(self, obj):
577 l = []
578 for d in obj.rh_dossiers.all().order_by('-date_debut'):
579 dossier = u"""<a title="Aperçu du dossier"
580 href="%s"
581 onclick="return showAddAnotherPopup(this);"
582 title="Aperçu du dossier">
583 <img src="%simg/loupe.png" />
584 </a>
585 <a href="%s">Dossier</a>
586 &nbsp;""" % \
587 (reverse('dossier_apercu', args=(d.id,)),
588 settings.STATIC_URL,
589 reverse('admin:rh_dossier_change', args=(d.id,)))
590
591 poste = u"""<a title="Aperçu du poste"
592 href="%s"
593 onclick="return showAddAnotherPopup(this);"
594 title="Aperçu du poste">
595 <img src="%simg/loupe.png" />
596 </a>
597 <a href="%s">Poste</a>
598 &nbsp;""" % \
599 (reverse('poste_apercu', args=(d.poste.id,)),
600 settings.STATIC_URL,
601 reverse('admin:rh_poste_change', args=(d.poste.id,)))
602 link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
603 (dossier, poste,
604 d.date_debut.year,
605 d.poste.id,
606 d.poste.nom,
607 )
608
609 # Dossier terminé en gris non cliquable
610 if d.date_fin is not None and d.date_fin < datetime.date.today():
611 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
612 (d.date_debut.year,
613 d.poste.id,
614 d.poste.nom,
615 )
616
617 l.append(link)
618 return "<ul>%s</ul>" % "\n".join(l)
619 _dossiers_postes.allow_tags = True
620 _dossiers_postes.short_description = u"Dossiers et postes"
621
622 def queryset(self, request):
623 qs = super(EmployeAdmin, self).queryset(request)
624 return qs.select_related(depth=1).order_by('nom')
625
626 def save_formset(self, request, form, formset, change):
627 instances = formset.save(commit=False)
628 for instance in instances:
629 if instance.__class__ == rh.EmployeCommentaire:
630 instance.owner = request.user
631 instance.date_creation = datetime.datetime.now()
632 instance.save()
633
634
635 class EmployeProxyAdmin(EmployeAdmin):
636 list_display = ('_id', '_apercu', '_nom', '_organigramme')
637 actions = None
638
639 def __init__(self, *args, **kwargs):
640 super(EmployeProxyAdmin, self).__init__(*args, **kwargs)
641 self.list_display_links = (None, )
642
643 def has_add_permission(self, obj):
644 return False
645
646 def _organigramme(self, obj):
647 l = []
648 for d in rh.Dossier.objects.filter(
649 Q(date_fin__gt=datetime.date.today()) | Q(date_fin=None),
650 Q(date_debut__lt=datetime.date.today()) | Q(date_debut=None),
651 employe=obj.id
652 ):
653 organigramme = \
654 u'Organigramme, niveau: ' \
655 u'<input type="text" id="level_%s" ' \
656 u'style="width:30px;height:15px;" /> ' \
657 u'<input type="button" value="Générer" ' \
658 u"""onclick="window.location='%s' + """ \
659 u"""document.getElementById('level_%s').value" />""" % (
660 d.poste.id,
661 reverse('rho_employe_sans_niveau', args=(d.poste.id,)),
662 d.poste.id
663 )
664 link = u"""<li>%s - [%s] %s : %s</li>""" % (
665 d.date_debut.year,
666 d.poste.id,
667 d.poste.nom,
668 organigramme
669 )
670 l.append(link)
671 return "<ul>%s</ul>" % "\n".join(l)
672
673 _organigramme.allow_tags = True
674 _organigramme.short_description = "Organigramme"
675
676
677 class EmployeCommentaireAdmin(admin.ModelAdmin):
678 pass
679
680
681 class EmployePieceAdmin(admin.ModelAdmin):
682 pass
683
684
685 class CategorieEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
686 list_display = ('nom', '_date_modification', 'user_modification', )
687 inlines = (TypePosteInline,)
688 fieldsets = AUFMetadataAdminMixin.fieldsets + (
689 (None, {'fields': ('nom', )}),)
690
691 def _date_modification(self, obj):
692 return date(obj.date_modification) \
693 if obj.date_modification is not None else "(aucune)"
694 _date_modification.short_description = u'date modification'
695 _date_modification.admin_order_field = 'date_modification'
696
697
698 class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
699 search_fields = ('nom',)
700 list_display = (
701 'nom',
702 'type',
703 'pays',
704 '_date_modification',
705 'user_modification',
706 )
707 list_filter = ('type', )
708 inlines = (DossierROInline,)
709 fieldsets = AUFMetadataAdminMixin.fieldsets + (
710 (None, {'fields': ('nom', 'type', 'pays',)}),
711 )
712
713 def _date_modification(self, obj):
714 return date(obj.date_modification) \
715 if obj.date_modification is not None else "(aucune)"
716 _date_modification.short_description = u'date modification'
717 _date_modification.admin_order_field = 'date_modification'
718
719
720 class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
721 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
722 form = make_ajax_form(rh.Poste, {
723 'implantation': 'implantations',
724 'type_poste': 'typepostes',
725 'responsable': 'postes',
726 'valeur_point_min': 'valeurpoints',
727 'valeur_point_max': 'valeurpoints',
728 })
729 alphabet_filter = 'nom'
730 search_fields = (
731 'id',
732 'nom',
733 'implantation__nom',
734 'implantation__region__code',
735 'implantation__region__nom',
736 'rh_dossiers__employe__nom',
737 'rh_dossiers__employe__prenom',
738 )
739 list_display = (
740 '_id',
741 '_apercu',
742 '_nom',
743 '_occupe_par',
744 'implantation',
745 '_service',
746 '_responsable',
747 'date_debut',
748 'date_fin',
749 '_date_modification',
750 'user_modification',
751 '_dae',
752 )
753 list_filter = (
754 'implantation__region',
755 'implantation',
756 'service',
757 'type_poste',
758 'type_poste__categorie_emploi',
759 'type_poste__famille_professionnelle',
760 'vacant',
761 )
762 list_display_links = ('_nom',)
763 fieldsets = AUFMetadataAdminMixin.fieldsets + (
764 (None, {'fields': (
765 ('nom', 'nom_feminin'),
766 'implantation',
767 'type_poste',
768 'service',
769 'responsable',
770 )}
771 ),
772 ('Contrat', {
773 'fields': ((
774 'regime_travail',
775 'regime_travail_nb_heure_semaine'),
776 )}
777 ),
778 ('Recrutement', {
779 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
780 ),
781 ('Rémunération', {
782 'fields': (('classement_min',
783 'valeur_point_min',
784 'devise_min',
785 'salaire_min',
786 'indemn_min',
787 'autre_min',),
788 ('classement_max',
789 'valeur_point_max',
790 'devise_max',
791 'salaire_max',
792 'indemn_max',
793 'autre_max',),
794 )}),
795 ('Comparatifs de rémunération', {
796 'fields': ('devise_comparaison',
797 ('comp_locale_min', 'comp_locale_max'),
798 ('comp_universite_min', 'comp_universite_max'),
799 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
800 ('comp_ong_min', 'comp_ong_max'),
801 ('comp_autre_min', 'comp_autre_max'))}
802 ),
803 ('Justification', {
804 'fields': ('justification',)}
805 ),
806 ('Autres Méta-données', {
807 'fields': ('date_debut', 'date_fin')}
808 ),
809 )
810
811 inlines = (PosteFinancementInline,
812 PostePieceInline,
813 DossierROInline,
814 PosteComparaisonInline,
815 PosteCommentaireInline, )
816
817 def lookup_allowed(self, key, value):
818 return key in (
819 'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
820 'date_fin__isnull', 'implantation__region__id__exact',
821 'implantation__id__exact', 'type_poste__id__exact',
822 'type_poste__categorie_emploi__id__exact', 'service__id__exact',
823 'service__isnull', 'vacant__exact', 'vacant__isnull',
824 ) or super(PosteAdmin, self).lookup_allowed(key, value)
825
826 def _apercu(self, poste):
827 view_link = u"""<a onclick="return showAddAnotherPopup(this);"
828 title="Aperçu du poste"
829 href='%s'>
830 <img src="%simg/loupe.png" />
831 </a>""" % \
832 (reverse('poste_apercu', args=(poste.id,)),
833 settings.STATIC_URL,)
834 return view_link
835 _apercu.allow_tags = True
836 _apercu.short_description = ''
837
838 def _dae(self, poste):
839 apercu_link = ""
840 postes_dae = poste.postes_dae.all()
841 if len(postes_dae) > 0:
842 poste_dae = postes_dae[0]
843 apercu_link = \
844 u'<a title="Aperçu du dossier" href="%s" ' \
845 u'onclick="return showAddAnotherPopup(this);">' \
846 u'<img src="%simg/loupe.png" /></a>' % (reverse(
847 'poste_consulter', args=("dae-%s" % poste_dae.id,)
848 ), settings.STATIC_URL)
849 return apercu_link
850 _dae.allow_tags = True
851 _dae.short_description = u"DAE"
852
853 def _id(self, obj):
854 return "%s" % obj.id
855 _id.short_description = '#'
856 _id.admin_order_field = 'id'
857
858 def _service(self, obj):
859 if obj.service.supprime:
860 return """<span style="color:red">%s</span>""" % obj.service
861 else:
862 return obj.service
863 _service.short_description = 'Service'
864 _service.allow_tags = True
865
866 def _responsable(self, obj):
867 try:
868 responsable = u"""<a href="%s"
869 onclick="return showAddAnotherPopup(this)">
870 <img src="%simg/loupe.png"
871 title="Aperçu du poste" />
872 </a>
873 <a href="%s">%s</a>
874 <br />""" % \
875 (reverse('poste_apercu', args=(obj.responsable.id,)),
876 settings.STATIC_URL,
877 reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
878 obj.responsable.nom)
879 except:
880 responsable = ''
881
882 try:
883 employe = obj.responsable.rh_dossiers.all()[0]
884 employe_id = obj.responsable.rh_dossiers.all()[0].id
885 employe_html = u"""<br />
886 <a href="%s"
887 onclick="return showAddAnotherPopup(this)">
888 <img src="%simg/loupe.png"
889 title="Aperçu de l'employé">
890 </a>
891 <a href="%s">%s</a>""" % \
892 (reverse('employe_apercu', args=(employe_id,)),
893 settings.STATIC_URL,
894 reverse('admin:rh_employe_change', args=(employe_id,)),
895 employe)
896 except:
897 employe_html = ""
898
899 return "%s %s" % (responsable, employe_html)
900 _responsable.short_description = 'Responsable'
901 _responsable.allow_tags = True
902
903 def _nom(self, poste):
904 return """<a href="%s">%s</a>""" % \
905 (reverse('admin:rh_poste_change', args=(poste.id,)),
906 poste.nom)
907 _nom.allow_tags = True
908 _nom.short_description = u'Nom'
909 _nom.admin_order_field = 'nom'
910
911 def _date_modification(self, obj):
912 return date(obj.date_modification)
913 _date_modification.short_description = u'date modification'
914 _date_modification.admin_order_field = 'date_modification'
915
916 def _occupe_par(self, obj):
917 """Formatte la méthode Poste.occupe_par() pour l'admin"""
918 output = u"Vacant"
919 if obj.date_fin is not None and obj.date_fin < datetime.date.today():
920 return u"s/o"
921 employes = obj.occupe_par()
922 if employes:
923 l = []
924 for e in employes:
925 link = u"""<a href='%s'
926 title='Aperçu de l\'employer'
927 onclick='return showAddAnotherPopup(this)'>
928 <img src='%simg/loupe.png' />
929 </a>
930 <a href='%s'>%s</a>""" % \
931 (reverse('employe_apercu', args=(e.id,)),
932 settings.STATIC_URL,
933 reverse('admin:rh_employe_change', args=(e.id,)),
934 e)
935 l.append(link)
936 output = "\n<br />".join(l)
937 return output
938 _occupe_par.allow_tags = True
939 _occupe_par.short_description = "Occupé par"
940
941 def save_formset(self, request, form, formset, change):
942 instances = formset.save(commit=False)
943 for instance in instances:
944 if instance.__class__ == rh.PosteCommentaire:
945 instance.owner = request.user
946 instance.date_creation = datetime.datetime.now()
947 instance.save()
948 formset.save_m2m()
949
950
951 class PosteCommentaireAdmin(admin.ModelAdmin):
952 pass
953
954
955 class PosteFinancementAdmin(admin.ModelAdmin):
956 pass
957
958
959 class PostePieceAdmin(admin.ModelAdmin):
960 fk_name = 'poste'
961
962
963 class RemunerationAdmin(admin.ModelAdmin):
964 pass
965
966
967 class ResponsableInline(admin.TabularInline):
968 model = rh.ResponsableImplantation
969 extra = 0
970 fk_name = "implantation"
971
972
973 class ResponsableImplantationAdmin(admin.ModelAdmin):
974 actions = None
975 list_filter = ('region', 'statut', )
976 list_display = ('nom', 'statut', '_responsable', )
977 readonly_fields = ('nom', )
978 fields = ('nom', )
979 inlines = (ResponsableInline, )
980
981 def _responsable(self, obj):
982 try:
983 employe = obj.responsable.employe
984 dossiers = employe.dossiers_encours()
985 if len(dossiers) == 0:
986 return u"<span style='color: red;'>%s %s </span>" % (
987 employe, u"sans dossier actif")
988 else:
989 return employe
990 except Exception:
991 if obj.statut in (1, 2): # ouverte, ouverture imminente
992 css = "style='color: red;'"
993 else:
994 css = ""
995 return u"<span %s>Pas de responsable</span>" % css
996 _responsable.allow_tags = True
997 _responsable.short_description = u"Responsable"
998
999 def has_add_permission(self, request=None):
1000 return False
1001
1002 def has_change_permission(self, request, obj=None):
1003 return in_drh_or_admin(request.user)
1004
1005 def has_delete_permission(self, request, obj=None):
1006 return False
1007
1008
1009 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
1010 list_display = (
1011 'nom',
1012 '_archive',
1013 '_date_modification',
1014 'user_modification',
1015 )
1016 list_filter = ('archive', )
1017 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1018 (None, {
1019 'fields': ('nom', 'archive', ),
1020 }),
1021 )
1022
1023 def _date_modification(self, obj):
1024 return date(obj.date_modification) \
1025 if obj.date_modification is not None else "(aucune)"
1026 _date_modification.short_description = u'date modification'
1027 _date_modification.admin_order_field = 'date_modification'
1028
1029
1030 class ServiceProxyAdmin(ServiceAdmin):
1031 list_display = ('nom', '_organigramme', '_archive', )
1032 actions = None
1033
1034 def __init__(self, *args, **kwargs):
1035 super(ServiceProxyAdmin, self).__init__(*args, **kwargs)
1036 self.list_display_links = (None, )
1037
1038 def has_add_permission(self, obj):
1039 return False
1040
1041 def has_change_permission(self, request, obj=None):
1042 return in_drh_or_admin(request.user)
1043
1044 def _organigramme(self, obj):
1045 return """<a href="%s"><strong>Organigramme</strong></a>""" % \
1046 (reverse('rho_service', args=(obj.id,)))
1047 _organigramme.allow_tags = True
1048 _organigramme.short_description = "Organigramme"
1049
1050
1051 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1052 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
1053 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1054 (None, {
1055 'fields': ('code', 'nom', ),
1056 }),
1057 )
1058
1059 def _date_modification(self, obj):
1060 return date(obj.date_modification) \
1061 if obj.date_modification is not None else "(aucune)"
1062 _date_modification.short_description = u'date modification'
1063 _date_modification.admin_order_field = 'date_modification'
1064
1065
1066 class TauxChangeAdmin(admin.ModelAdmin):
1067 list_display = (
1068 'taux',
1069 'devise',
1070 'annee',
1071 '_date_modification',
1072 'user_modification',
1073 )
1074 list_filter = ('devise', )
1075 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1076 (None, {
1077 'fields': ('taux', 'devise', 'annee', ),
1078 }),
1079 )
1080
1081 def _date_modification(self, obj):
1082 return date(obj.date_modification) \
1083 if obj.date_modification is not None else "(aucune)"
1084 _date_modification.short_description = u'date modification'
1085 _date_modification.admin_order_field = 'date_modification'
1086
1087
1088 class TypeContratAdmin(admin.ModelAdmin):
1089 list_display = (
1090 'nom',
1091 'nom_long',
1092 '_date_modification',
1093 'user_modification',
1094 )
1095 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1096 (None, {
1097 'fields': ('nom', 'nom_long', ),
1098 }),
1099 )
1100
1101 def _date_modification(self, obj):
1102 return date(obj.date_modification) \
1103 if obj.date_modification is not None else "(aucune)"
1104 _date_modification.short_description = u'date modification'
1105 _date_modification.admin_order_field = 'date_modification'
1106
1107
1108 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1109 search_fields = ('nom', 'nom_feminin', )
1110 list_display = (
1111 'nom',
1112 'categorie_emploi',
1113 '_date_modification',
1114 'user_modification',
1115 )
1116 list_filter = ('categorie_emploi', 'famille_professionnelle')
1117 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1118 (None, {
1119 'fields': (
1120 'nom',
1121 'nom_feminin',
1122 'is_responsable',
1123 'categorie_emploi',
1124 'famille_professionnelle',
1125 )}
1126 ),
1127 )
1128
1129 def _date_modification(self, obj):
1130 return date(obj.date_modification) \
1131 if obj.date_modification is not None else "(aucune)"
1132 _date_modification.short_description = u'date modification'
1133 _date_modification.admin_order_field = 'date_modification'
1134
1135
1136 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin,
1137 ArchiveMixin):
1138 list_display = (
1139 'nom',
1140 'type_paiement',
1141 'nature_remuneration',
1142 '_archive',
1143 '_date_modification',
1144 'user_modification',)
1145 list_filter = ('archive', )
1146 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1147 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1148 'archive')}),
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 TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1159 list_display = ('nom', '_date_modification', 'user_modification', )
1160 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1161 (None, {'fields': ('nom', )}),
1162 )
1163
1164 def _date_modification(self, obj):
1165 return date(obj.date_modification) \
1166 if obj.date_modification is not None else "(aucune)"
1167 _date_modification.short_description = u'date modification'
1168 _date_modification.admin_order_field = 'date_modification'
1169
1170
1171 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1172 list_display = (
1173 '_devise_code',
1174 '_devise_nom',
1175 'annee',
1176 'implantation',
1177 'valeur',
1178 '_date_modification',
1179 'user_modification',
1180 )
1181 list_filter = ('annee', 'devise', 'implantation__region', )
1182 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1183 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
1184 )
1185
1186 def _date_modification(self, obj):
1187 return date(obj.date_modification) \
1188 if obj.date_modification is not None else "(aucune)"
1189 _date_modification.short_description = u'date modification'
1190 _date_modification.admin_order_field = 'date_modification'
1191
1192 def _devise_code(self, obj):
1193 return obj.devise.code
1194 _devise_code.short_description = "Code de la devise"
1195
1196 def _devise_nom(self, obj):
1197 return obj.devise.nom
1198 _devise_nom.short_description = "Nom de la devise"
1199
1200
1201 class ImplantationProxyAdmin(admin.ModelAdmin):
1202 list_display = ('nom', '_organigramme')
1203 actions = None
1204
1205 def __init__(self, *args, **kwargs):
1206 super(ImplantationProxyAdmin, self).__init__(*args, **kwargs)
1207 self.list_display_links = (None, )
1208
1209 def has_add_permission(self, obj):
1210 return False
1211
1212 def has_change_permission(self, request, obj=None):
1213 return in_drh_or_admin(request.user)
1214
1215 def _organigramme(self, obj):
1216 return '<a href="%s"><strong>Organigramme</strong></a>' % (
1217 reverse('rho_implantation', args=(obj.id,))
1218 )
1219 _organigramme.allow_tags = True
1220 _organigramme.short_description = "Organigramme"
1221
1222
1223 class RegionProxyAdmin(admin.ModelAdmin):
1224 list_display = ('nom', '_organigramme')
1225 actions = None
1226
1227 def __init__(self, *args, **kwargs):
1228 super(RegionProxyAdmin, self).__init__(*args, **kwargs)
1229 self.list_display_links = (None, )
1230
1231 def has_add_permission(self, obj):
1232 return False
1233
1234 def has_change_permission(self, request, obj=None):
1235 return in_drh_or_admin(request.user)
1236
1237 def _organigramme(self, obj):
1238 return """<a href="%s"><strong>Organigramme</strong></a>""" % (
1239 reverse('rho_region', args=(obj.id,))
1240 )
1241 _organigramme.allow_tags = True
1242 _organigramme.short_description = "Organigramme"
1243
1244
1245 admin.site.register(rh.Classement, ClassementAdmin)
1246 admin.site.register(rh.Devise, DeviseAdmin)
1247 admin.site.register(rh.Dossier, DossierAdmin)
1248 admin.site.register(EmployeProxy, EmployeProxyAdmin)
1249 admin.site.register(ServiceProxy, ServiceProxyAdmin)
1250 admin.site.register(rh.Employe, EmployeAdmin)
1251 admin.site.register(rh.CategorieEmploi, CategorieEmploiAdmin)
1252 admin.site.register(rh.FamilleProfessionnelle)
1253 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1254 admin.site.register(rh.Poste, PosteAdmin)
1255 admin.site.register(
1256 rh.ResponsableImplantationProxy, ResponsableImplantationAdmin
1257 )
1258 admin.site.register(rh.Service, ServiceAdmin)
1259 admin.site.register(rh.Statut, StatutAdmin)
1260 admin.site.register(rh.TauxChange, TauxChangeAdmin)
1261 admin.site.register(rh.TypeContrat, TypeContratAdmin)
1262 admin.site.register(rh.TypePoste, TypePosteAdmin)
1263 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1264 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1265 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
1266 admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
1267 admin.site.register(RegionProxy, RegionProxyAdmin)