Merge branch 'hotfix' into olivier
[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.now():
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
934 class ServiceProxyAdmin(ServiceAdmin):
935 list_display = ('nom', '_organigramme')
936 list_display_links = ('nom',)
937
938 def has_add_permission(self, obj):
939 return False
940
941 def _organigramme(self, obj):
942 return """<a href="%s">Organigramme</a>""" % (reverse('rho_service', args=(obj.id,)))
943 _organigramme.allow_tags = True
944 _organigramme.short_description = "Organigramme"
945
946 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
947 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
948 fieldsets = AUFMetadataAdminMixin.fieldsets + (
949 (None, {
950 'fields': ('code', 'nom', ),
951 }),
952 )
953
954 def _date_modification(self, obj):
955 return date(obj.date_modification) \
956 if obj.date_modification is not None else "(aucune)"
957 _date_modification.short_description = u'date modification'
958 _date_modification.admin_order_field = 'date_modification'
959
960
961 class TauxChangeAdmin(admin.ModelAdmin):
962 list_display = (
963 'taux',
964 'devise',
965 'annee',
966 '_date_modification',
967 'user_modification',
968 )
969 list_filter = ('devise', )
970 fieldsets = AUFMetadataAdminMixin.fieldsets + (
971 (None, {
972 'fields': ('taux', 'devise', 'annee', ),
973 }),
974 )
975
976 def _date_modification(self, obj):
977 return date(obj.date_modification) \
978 if obj.date_modification is not None else "(aucune)"
979 _date_modification.short_description = u'date modification'
980 _date_modification.admin_order_field = 'date_modification'
981
982
983 class TypeContratAdmin(admin.ModelAdmin):
984 list_display = (
985 'nom',
986 'nom_long',
987 '_date_modification',
988 'user_modification',
989 )
990 fieldsets = AUFMetadataAdminMixin.fieldsets + (
991 (None, {
992 'fields': ('nom', 'nom_long', ),
993 }),
994 )
995
996 def _date_modification(self, obj):
997 return date(obj.date_modification) \
998 if obj.date_modification is not None else "(aucune)"
999 _date_modification.short_description = u'date modification'
1000 _date_modification.admin_order_field = 'date_modification'
1001
1002
1003 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1004 search_fields = ('nom', 'nom_feminin', )
1005 list_display = (
1006 'nom',
1007 'famille_emploi',
1008 '_date_modification',
1009 'user_modification',
1010 )
1011 list_filter = ('famille_emploi', )
1012 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1013 (None, {
1014 'fields': (
1015 'nom',
1016 'nom_feminin',
1017 'is_responsable',
1018 'famille_emploi',
1019 )}
1020 ),
1021 )
1022
1023 def _date_modification(self, obj):
1024 return date(obj.date_modification) \
1025 if obj.date_modification is not None else "(aucune)"
1026 _date_modification.short_description = u'date modification'
1027 _date_modification.admin_order_field = 'date_modification'
1028
1029
1030 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
1031 list_display = (
1032 'nom',
1033 'type_paiement',
1034 'nature_remuneration',
1035 '_archive',
1036 '_date_modification',
1037 'user_modification',)
1038 list_filter = ('archive', )
1039 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1040 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1041 'archive')}),
1042 )
1043
1044 def _date_modification(self, obj):
1045 return date(obj.date_modification) \
1046 if obj.date_modification is not None else "(aucune)"
1047 _date_modification.short_description = u'date modification'
1048 _date_modification.admin_order_field = 'date_modification'
1049
1050
1051 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1052 list_display = ('nom', '_date_modification', 'user_modification', )
1053 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1054 (None, {'fields': ('nom', )}),
1055 )
1056
1057 def _date_modification(self, obj):
1058 return date(obj.date_modification) \
1059 if obj.date_modification is not None else "(aucune)"
1060 _date_modification.short_description = u'date modification'
1061 _date_modification.admin_order_field = 'date_modification'
1062
1063
1064 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1065 list_display = (
1066 '_devise_code',
1067 '_devise_nom',
1068 'annee',
1069 'valeur',
1070 '_date_modification',
1071 'user_modification',
1072 )
1073 list_filter = ('annee', 'devise', )
1074 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1075 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
1076 )
1077
1078 def _date_modification(self, obj):
1079 return date(obj.date_modification) \
1080 if obj.date_modification is not None else "(aucune)"
1081 _date_modification.short_description = u'date modification'
1082 _date_modification.admin_order_field = 'date_modification'
1083
1084 def _devise_code(self, obj):
1085 return obj.devise.code
1086 _devise_code.short_description = "Code de la devise"
1087
1088 def _devise_nom(self, obj):
1089 return obj.devise.nom
1090 _devise_nom.short_description = "Nom de la devise"
1091
1092 class ImplantationProxyAdmin(admin.ModelAdmin):
1093 list_display = ('nom', '_organigramme')
1094 list_display_links = ('nom',)
1095
1096 def has_add_permission(self, obj):
1097 return False
1098
1099 def _organigramme(self, obj):
1100 return """<a href="%s">Organigramme</a>""" % (reverse('rho_implantation', args=(obj.id,)))
1101 _organigramme.allow_tags = True
1102 _organigramme.short_description = "Organigramme"
1103
1104 class RegionProxyAdmin(admin.ModelAdmin):
1105 list_display = ('nom', '_organigramme')
1106 list_display_links = ('nom',)
1107
1108 def has_add_permission(self, obj):
1109 return False
1110
1111 def _organigramme(self, obj):
1112 return """<a href="%s">Organigramme</a>""" % (reverse('rho_region', args=(obj.id,)))
1113 _organigramme.allow_tags = True
1114 _organigramme.short_description = "Organigramme"
1115
1116
1117
1118
1119 admin.site.register(rh.Classement, ClassementAdmin)
1120 admin.site.register(rh.Devise, DeviseAdmin)
1121 admin.site.register(rh.Dossier, DossierAdmin)
1122 admin.site.register(EmployeProxy, EmployeProxyAdmin)
1123 admin.site.register(ServiceProxy, ServiceProxyAdmin)
1124 admin.site.register(rh.Employe, EmployeAdmin)
1125 admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
1126 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1127 admin.site.register(rh.Poste, PosteAdmin)
1128 admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
1129 admin.site.register(rh.Service, ServiceAdmin)
1130 admin.site.register(rh.Statut, StatutAdmin)
1131 admin.site.register(rh.TauxChange, TauxChangeAdmin)
1132 admin.site.register(rh.TypeContrat, TypeContratAdmin)
1133 admin.site.register(rh.TypePoste, TypePosteAdmin)
1134 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1135 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1136 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
1137 admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
1138 admin.site.register(RegionProxy, RegionProxyAdmin)