poste import + liens dans RH
[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 output = u"Vacant"
892 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
893 return u"s/o"
894 employes = obj.occupe_par()
895 if employes:
896 l = []
897 for e in employes:
898 link = u"""<a href='%s'
899 title='Aperçu de l\'employer'
900 onclick='return showAddAnotherPopup(this)'>
901 <img src='%simg/loupe.png' />
902 </a>
903 <a href='%s'>%s</a>""" % \
904 (reverse('employe_apercu', args=(e.id,)),
905 settings.STATIC_URL,
906 reverse('admin:rh_employe_change', args=(e.id,)),
907 e)
908 l.append(link)
909 output = "\n<br />".join(l)
910 return output
911 _occupe_par.allow_tags = True
912 _occupe_par.short_description = "Occupé par"
913
914 def save_formset(self, request, form, formset, change):
915 instances = formset.save(commit=False)
916 for instance in instances:
917 if instance.__class__ == rh.PosteCommentaire:
918 instance.owner = request.user
919 instance.date_creation = datetime.datetime.now()
920 instance.save()
921 formset.save_m2m()
922
923
924 class PosteCommentaireAdmin(admin.ModelAdmin):
925 pass
926
927
928 class PosteFinancementAdmin(admin.ModelAdmin):
929 pass
930
931
932 class PostePieceAdmin(admin.ModelAdmin):
933 fk_name = 'poste'
934
935
936 class RemunerationAdmin(admin.ModelAdmin):
937 pass
938
939
940 class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
941 fieldsets = AUFMetadataAdminMixin.fieldsets + (
942 (None, {
943 'fields': ('employe', 'implantation', ),
944 }),
945 )
946
947
948 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
949 list_display = (
950 'nom',
951 '_archive',
952 '_date_modification',
953 'user_modification',
954 )
955 list_filter = ('archive', )
956 fieldsets = AUFMetadataAdminMixin.fieldsets + (
957 (None, {
958 'fields': ('nom', 'archive', ),
959 }),
960 )
961
962 def _date_modification(self, obj):
963 return date(obj.date_modification) \
964 if obj.date_modification is not None else "(aucune)"
965 _date_modification.short_description = u'date modification'
966 _date_modification.admin_order_field = 'date_modification'
967
968
969 class ServiceProxyAdmin(ServiceAdmin):
970 list_display = ('nom', '_organigramme')
971 list_display_links = ('nom',)
972
973 def has_add_permission(self, obj):
974 return False
975
976 def _organigramme(self, obj):
977 return """<a href="%s">Organigramme</a>""" % (reverse('rho_service', args=(obj.id,)))
978 _organigramme.allow_tags = True
979 _organigramme.short_description = "Organigramme"
980
981 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
982 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
983 fieldsets = AUFMetadataAdminMixin.fieldsets + (
984 (None, {
985 'fields': ('code', 'nom', ),
986 }),
987 )
988
989 def _date_modification(self, obj):
990 return date(obj.date_modification) \
991 if obj.date_modification is not None else "(aucune)"
992 _date_modification.short_description = u'date modification'
993 _date_modification.admin_order_field = 'date_modification'
994
995
996 class TauxChangeAdmin(admin.ModelAdmin):
997 list_display = (
998 'taux',
999 'devise',
1000 'annee',
1001 '_date_modification',
1002 'user_modification',
1003 )
1004 list_filter = ('devise', )
1005 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1006 (None, {
1007 'fields': ('taux', 'devise', 'annee', ),
1008 }),
1009 )
1010
1011 def _date_modification(self, obj):
1012 return date(obj.date_modification) \
1013 if obj.date_modification is not None else "(aucune)"
1014 _date_modification.short_description = u'date modification'
1015 _date_modification.admin_order_field = 'date_modification'
1016
1017
1018 class TypeContratAdmin(admin.ModelAdmin):
1019 list_display = (
1020 'nom',
1021 'nom_long',
1022 '_date_modification',
1023 'user_modification',
1024 )
1025 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1026 (None, {
1027 'fields': ('nom', 'nom_long', ),
1028 }),
1029 )
1030
1031 def _date_modification(self, obj):
1032 return date(obj.date_modification) \
1033 if obj.date_modification is not None else "(aucune)"
1034 _date_modification.short_description = u'date modification'
1035 _date_modification.admin_order_field = 'date_modification'
1036
1037
1038 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1039 search_fields = ('nom', 'nom_feminin', )
1040 list_display = (
1041 'nom',
1042 'famille_emploi',
1043 '_date_modification',
1044 'user_modification',
1045 )
1046 list_filter = ('famille_emploi', )
1047 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1048 (None, {
1049 'fields': (
1050 'nom',
1051 'nom_feminin',
1052 'is_responsable',
1053 'famille_emploi',
1054 )}
1055 ),
1056 )
1057
1058 def _date_modification(self, obj):
1059 return date(obj.date_modification) \
1060 if obj.date_modification is not None else "(aucune)"
1061 _date_modification.short_description = u'date modification'
1062 _date_modification.admin_order_field = 'date_modification'
1063
1064
1065 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
1066 list_display = (
1067 'nom',
1068 'type_paiement',
1069 'nature_remuneration',
1070 '_archive',
1071 '_date_modification',
1072 'user_modification',)
1073 list_filter = ('archive', )
1074 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1075 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1076 'archive')}),
1077 )
1078
1079 def _date_modification(self, obj):
1080 return date(obj.date_modification) \
1081 if obj.date_modification is not None else "(aucune)"
1082 _date_modification.short_description = u'date modification'
1083 _date_modification.admin_order_field = 'date_modification'
1084
1085
1086 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1087 list_display = ('nom', '_date_modification', 'user_modification', )
1088 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1089 (None, {'fields': ('nom', )}),
1090 )
1091
1092 def _date_modification(self, obj):
1093 return date(obj.date_modification) \
1094 if obj.date_modification is not None else "(aucune)"
1095 _date_modification.short_description = u'date modification'
1096 _date_modification.admin_order_field = 'date_modification'
1097
1098
1099 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1100 list_display = (
1101 '_devise_code',
1102 '_devise_nom',
1103 'annee',
1104 'valeur',
1105 '_date_modification',
1106 'user_modification',
1107 )
1108 list_filter = ('annee', 'devise', )
1109 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1110 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
1111 )
1112
1113 def _date_modification(self, obj):
1114 return date(obj.date_modification) \
1115 if obj.date_modification is not None else "(aucune)"
1116 _date_modification.short_description = u'date modification'
1117 _date_modification.admin_order_field = 'date_modification'
1118
1119 def _devise_code(self, obj):
1120 return obj.devise.code
1121 _devise_code.short_description = "Code de la devise"
1122
1123 def _devise_nom(self, obj):
1124 return obj.devise.nom
1125 _devise_nom.short_description = "Nom de la devise"
1126
1127 class ImplantationProxyAdmin(admin.ModelAdmin):
1128 list_display = ('nom', '_organigramme')
1129 list_display_links = ('nom',)
1130
1131 def has_add_permission(self, obj):
1132 return False
1133
1134 def _organigramme(self, obj):
1135 return """<a href="%s">Organigramme</a>""" % (reverse('rho_implantation', args=(obj.id,)))
1136 _organigramme.allow_tags = True
1137 _organigramme.short_description = "Organigramme"
1138
1139 class RegionProxyAdmin(admin.ModelAdmin):
1140 list_display = ('nom', '_organigramme')
1141 list_display_links = ('nom',)
1142
1143 def has_add_permission(self, obj):
1144 return False
1145
1146 def _organigramme(self, obj):
1147 return """<a href="%s">Organigramme</a>""" % (reverse('rho_region', args=(obj.id,)))
1148 _organigramme.allow_tags = True
1149 _organigramme.short_description = "Organigramme"
1150
1151
1152
1153
1154 admin.site.register(rh.Classement, ClassementAdmin)
1155 admin.site.register(rh.Devise, DeviseAdmin)
1156 admin.site.register(rh.Dossier, DossierAdmin)
1157 admin.site.register(EmployeProxy, EmployeProxyAdmin)
1158 admin.site.register(ServiceProxy, ServiceProxyAdmin)
1159 admin.site.register(rh.Employe, EmployeAdmin)
1160 admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
1161 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1162 admin.site.register(rh.Poste, PosteAdmin)
1163 admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
1164 admin.site.register(rh.Service, ServiceAdmin)
1165 admin.site.register(rh.Statut, StatutAdmin)
1166 admin.site.register(rh.TauxChange, TauxChangeAdmin)
1167 admin.site.register(rh.TypeContrat, TypeContratAdmin)
1168 admin.site.register(rh.TypePoste, TypePosteAdmin)
1169 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1170 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1171 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
1172 admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
1173 admin.site.register(RegionProxy, RegionProxyAdmin)