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