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