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