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