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