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