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