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