1 # -*- encoding: utf-8 -*-
6 from ajax_select
import make_ajax_form
7 from auf
.django
.metadata
.admin
import \
8 AUFMetadataAdminMixin
, AUFMetadataInlineAdminMixin
, \
9 AUF_METADATA_READONLY_FIELDS
10 from auf
.django
.references
import models
as ref
11 from django
.core
.urlresolvers
import reverse
12 from django
.contrib
import admin
13 from django
.conf
import settings
14 from django
.db
.models
import Q
, Count
15 from django
.template
.defaultfilters
import date
17 from project
.decorators
import in_drh_or_admin
18 from project
.groups
import grp_correspondants_rh
19 from project
.groups
import get_employe_from_user
20 from project
.rh
.forms
import ContratForm
, AyantDroitForm
, EmployeAdminForm
, \
21 AjaxSelect
, DossierForm
, ResponsableInlineForm
22 from project
.rh
import models
as rh
23 from project
.rh
.change_list
import ChangeList
26 class BaseAdmin(admin
.ModelAdmin
):
30 'css/admin_custom.css',
31 'jquery-autocomplete/jquery.autocomplete.css',
34 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
35 'jquery-autocomplete/jquery.autocomplete.min.js',
39 class ArchiveMixin(object):
41 Archive Mixin pour gérer le queryset et le display
42 NON COMPRIS : list_filter, et list_display, field à setter dans la classe.
45 def queryset(self
, request
):
46 return self
.model
._base_manager
48 def _archive(self
, obj
):
53 _archive
.short_description
= u
'Archivé'
54 _archive
.admin_order_field
= 'archive'
57 class RegionProxy(ref
.Region
):
58 """ Proxy utilisé pour les organigrammes par région """
61 verbose_name
= u
"Organigramme par région"
62 verbose_name_plural
= u
"Organigramme par région"
65 class ImplantationProxy(ref
.Implantation
):
66 """ Proxy utilisé pour les organigrammes par implantation """
69 verbose_name
= u
"Organigramme par implantations"
70 verbose_name_plural
= u
"Organigramme par implantations"
73 class ServiceProxy(rh
.Service
):
74 """ Proxy utilisé pour les organigrammes opar service """
78 verbose_name
= u
"Organigramme par services"
79 verbose_name_plural
= u
"Organigramme par services"
82 class EmployeProxy(rh
.Employe
):
83 """ Proxy utilisé pour les organigrammes des employés """
86 verbose_name
= u
"Organigramme des employés"
87 verbose_name_plural
= u
"Organigramme des employés"
90 class DateRangeMixin(object):
91 prefixe_recherche_temporelle
= ""
93 def get_changelist(self
, request
, **kwargs
):
94 if 'HTTP_REFERER' in request
.META
.keys():
95 referer
= request
.META
['HTTP_REFERER']
96 referer
= "/".join(referer
.split('/')[3:])
97 referer
= "/%s" % referer
.split('?')[0]
98 change_list_view
= 'admin:%s_%s_changelist' % (
99 self
.model
._meta
.app_label
,
100 self
.model
.__name__
.lower(),)
101 if referer
!= reverse(change_list_view
):
102 params
= request
.GET
.copy()
103 params
.update({'statut': 'Actif'})
108 # Override of the InlineModelAdmin to support the link in the tabular inline
109 class LinkedInline(admin
.options
.InlineModelAdmin
):
110 template
= "admin/linked.html"
111 admin_model_path
= None
113 def __init__(self
, *args
):
114 super(LinkedInline
, self
).__init__(*args
)
115 if self
.admin_model_path
is None:
116 self
.admin_model_path
= self
.model
.__name__
.lower()
119 class ProtectRegionMixin(object):
121 def queryset(self
, request
):
122 qs
= super(ProtectRegionMixin
, self
).queryset(request
)
124 user_groups
= request
.user
.groups
.all()
125 if in_drh_or_admin(request
.user
):
128 if grp_correspondants_rh
in user_groups
:
129 employe
= get_employe_from_user(request
.user
)
130 q
= Q(**{self
.model
.prefix_implantation
: \
131 employe
.implantation
.region
})
132 qs
= qs
.filter(q
).distinct()
136 def has_add_permission(self
, request
):
137 if not in_drh_or_admin(request
.user
):
142 def has_change_permission(self
, request
, obj
=None):
143 user_groups
= request
.user
.groups
.all()
145 # Lock pour autoriser uniquement les DRH à utiliser RH
146 if not in_drh_or_admin(request
.user
):
149 if len(user_groups
) == 0 and not request
.user
.is_superuser
:
154 ids
= [o
.id for o
in self
.queryset(request
)]
160 class ReadOnlyInlineMixin(object):
162 def get_readonly_fields(self
, request
, obj
=None):
163 return [f
.name
for f
in self
.model
._meta
.fields \
164 if f
.name
not in AUF_METADATA_READONLY_FIELDS
]
167 class AyantDroitInline(AUFMetadataInlineAdminMixin
, admin
.StackedInline
):
168 model
= rh
.AyantDroit
169 form
= AyantDroitForm
176 ('nom_affichage', 'genre'),
184 class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin
, \
185 admin
.TabularInline
):
186 readonly_fields
= ('owner', )
187 model
= rh
.AyantDroitCommentaire
191 class ContratInline(AUFMetadataInlineAdminMixin
, admin
.TabularInline
):
197 class DossierROInline(ReadOnlyInlineMixin
, LinkedInline
):
198 template
= "admin/rh/dossier/linked.html"
199 exclude
= AUF_METADATA_READONLY_FIELDS
204 def has_add_permission(self
, request
=None):
207 def has_change_permission(self
, request
, obj
=None):
210 def has_delete_permission(self
, request
, obj
=None):
214 class DossierCommentaireInline(AUFMetadataInlineAdminMixin
, \
215 admin
.TabularInline
):
216 readonly_fields
= ('owner', )
217 model
= rh
.DossierCommentaire
221 class DossierPieceInline(admin
.TabularInline
):
222 model
= rh
.DossierPiece
226 class EmployeInline(admin
.TabularInline
):
230 class EmployeCommentaireInline(AUFMetadataInlineAdminMixin
, \
231 admin
.TabularInline
):
232 readonly_fields
= ('owner', )
233 model
= rh
.EmployeCommentaire
237 class EmployePieceInline(admin
.TabularInline
):
238 model
= rh
.EmployePiece
242 class PosteCommentaireInline(AUFMetadataInlineAdminMixin
, admin
.TabularInline
):
243 readonly_fields
= ('owner', )
244 model
= rh
.PosteCommentaire
248 class PosteFinancementInline(admin
.TabularInline
):
249 model
= rh
.PosteFinancement
252 class PostePieceInline(admin
.TabularInline
):
253 model
= rh
.PostePiece
256 class RemunerationInline(AUFMetadataInlineAdminMixin
, admin
.TabularInline
):
257 model
= rh
.Remuneration
261 class RemunerationROInline(ReadOnlyInlineMixin
, RemunerationInline
):
265 class TypePosteInline(AUFMetadataInlineAdminMixin
, admin
.TabularInline
):
269 class PosteComparaisonInline(AUFMetadataInlineAdminMixin
, admin
.TabularInline
):
270 model
= rh
.PosteComparaison
273 class ClassementAdmin(AUFMetadataAdminMixin
, BaseAdmin
,
274 reversion
.VersionAdmin
):
275 list_display
= ('_classement', '_date_modification', 'user_modification', )
276 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
278 'fields': ('type', 'echelon', 'degre', 'coefficient',)}),
281 def _classement(self
, obj
):
283 _classement
.short_description
= u
"Classement"
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'
292 class CommentaireAdmin(reversion
.VersionAdmin
, BaseAdmin
):
296 class DeviseAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
297 ArchiveMixin
, BaseAdmin
):
302 '_date_modification',
305 list_filter
= ('archive', )
306 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
308 'fields': ('code', 'nom', 'archive', ),
312 def _date_modification(self
, obj
):
313 return date(obj
.date_modification
) \
314 if obj
.date_modification
is not None else "(aucune)"
315 _date_modification
.short_description
= u
'date modification'
316 _date_modification
.admin_order_field
= 'date_modification'
319 class DossierAdmin(DateRangeMixin
, AUFMetadataAdminMixin
,
320 ProtectRegionMixin
, BaseAdmin
, AjaxSelect
,
321 reversion
.VersionAdmin
):
322 alphabet_filter
= 'employe__nom'
330 'poste__nom_feminin',
331 'poste__implantation__nom',
341 '_date_modification',
345 list_display_links
= ('_nom',)
347 'poste__implantation__region',
348 'poste__implantation',
349 'poste__type_poste__categorie_emploi',
351 'rh_contrats__type_contrat',
354 inlines
= (DossierPieceInline
, ContratInline
,
356 DossierCommentaireInline
,
358 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
365 'organisme_bstg',)}),
370 'remplacement_de', )}),
374 ('regime_travail', 'regime_travail_nb_heure_semaine'),)}),
375 ('Occupation du Poste par cet Employe', {
376 'fields': (('date_debut', 'date_fin'), )}
379 form
= make_ajax_form(rh
.Dossier
, {
380 'employe': 'employes',
382 'remplacement_de': 'dossiers',
383 }, superclass
=DossierForm
)
385 def lookup_allowed(self
, key
, value
):
387 'employe__nom__istartswith',
388 'poste__implantation__region__id__exact',
389 'poste__implantation__id__exact',
390 'poste__type_poste__id__exact',
391 'poste__type_poste__categorie_emploi__id__exact',
392 'rh_contrats__type_contrat__id__exact',
400 _id
.short_description
= u
"#"
401 _id
.admin_order_field
= "id"
404 return "%d : %s %s" % (
406 obj
.employe
.nom
.upper(),
408 _nom
.allow_tags
= True
409 _nom
.short_description
= u
"Dossier"
411 def _apercu(self
, d
):
412 apercu_link
= u
"""<a title="Aperçu du dossier"
413 onclick="return showAddAnotherPopup(this);"
415 <img src="%simg/dossier-apercu.png" />
417 (reverse('dossier_apercu', args
=(d
.id,)),
421 _apercu
.allow_tags
= True
422 _apercu
.short_description
= u
""
426 dossiers_dae
= d
.dossiers_dae
.all()
427 if len(dossiers_dae
) > 0:
428 dossier_dae
= dossiers_dae
[0]
429 apercu_link
= u
"""<a title="Aperçu du dossier"
430 onclick="return showAddAnotherPopup(this);"
432 <img src="%simg/loupe.png" />
434 (reverse('embauche_consulter', args
=(dossier_dae
.id,)),
438 _dae
.allow_tags
= True
439 _dae
.short_description
= u
"DAE"
441 def _date_debut(self
, obj
):
442 return date(obj
.date_debut
)
444 _date_debut
.short_description
= u
'Occupation début'
445 _date_debut
.admin_order_field
= 'date_debut'
447 def _date_fin(self
, obj
):
448 return date(obj
.date_fin
)
449 _date_fin
.short_description
= u
'Occupation fin'
450 _date_fin
.admin_order_field
= 'date_fin'
452 def _date_modification(self
, obj
):
453 return date(obj
.date_modification
) \
454 if obj
.date_modification
is not None else "(aucune)"
455 _date_modification
.short_description
= u
'date modification'
456 _date_modification
.admin_order_field
= 'date_modification'
458 def _poste(self
, dossier
):
459 link
= u
"""<a title="Aperçu du poste"
460 onclick="return showAddAnotherPopup(this);"
461 href='%s'><img src="%simg/poste-apercu.png" />
463 <a href="%s" title="Modifier le poste">%s</a>""" % \
464 (reverse('poste_apercu', args
=(dossier
.poste
.id,)),
466 reverse('admin:rh_poste_change', args
=(dossier
.poste
.id,)),
470 _poste
.allow_tags
= True
471 _poste
.short_description
= u
'Poste'
472 _poste
.admin_order_field
= 'poste__nom'
474 def _employe(self
, obj
):
475 employe
= obj
.employe
476 view_link
= reverse('employe_apercu', args
=(employe
.id,))
477 edit_link
= reverse('admin:rh_employe_change', args
=(employe
.id,))
480 view
= u
"""<a href="%s"
481 title="Aperçu l'employé"
482 onclick="return showAddAnotherPopup(this);">
483 <img src="%simg/employe-apercu.png" />
484 </a>""" % (view_link
, settings
.STATIC_URL
,)
485 return u
"""%s<a href='%s' style="%s;">%s</a>""" % \
486 (view
, edit_link
, style
, employe
)
487 _employe
.allow_tags
= True
488 _employe
.short_description
= u
"Employé"
489 _employe
.admin_order_field
= "employe__nom"
491 def save_formset(self
, request
, form
, formset
, change
):
492 instances
= formset
.save(commit
=False)
493 for instance
in instances
:
494 if instance
.__class__
== rh
.DossierCommentaire
:
495 instance
.owner
= request
.user
496 instance
.date_creation
= datetime
.datetime
.now()
500 class EmployeAdminMixin(DateRangeMixin
, AUFMetadataAdminMixin
,
501 ProtectRegionMixin
, BaseAdmin
):
502 prefixe_recherche_temporelle
= "rh_dossiers__"
503 alphabet_filter
= 'nom'
504 DEFAULT_ALPHABET
= u
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
506 'id', 'nom', 'prenom', 'nom_affichage',
507 'rh_dossiers__poste__nom',
508 'rh_dossiers__poste__nom_feminin'
511 form
= EmployeAdminForm
518 '_date_modification',
521 list_display_links
= ('_nom',)
523 'rh_dossiers__poste__implantation__region',
524 'rh_dossiers__poste__implantation',
527 inlines
= (AyantDroitInline
,
530 EmployeCommentaireInline
)
531 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
535 ('nom_affichage', 'genre'),
540 ('Informations personnelles', {
541 'fields': ('situation_famille', 'date_entree', )}
543 ('Coordonnées personnelles', {
545 ('tel_domicile', 'tel_cellulaire'),
546 ('adresse', 'ville'),
547 ('code_postal', 'province'),
554 def _apercu(self
, obj
):
555 return u
"""<a title="Aperçu de l'employé"
556 onclick="return showAddAnotherPopup(this);"
558 <img src="%simg/employe-apercu.png" />
560 (reverse('employe_apercu', args
=(obj
.id,)), settings
.STATIC_URL
)
561 _apercu
.allow_tags
= True
562 _apercu
.short_description
= u
""
565 edit_link
= reverse('admin:rh_employe_change', args
=(obj
.id,))
566 return u
"""<a href='%s'><strong>%s</strong></a>""" % \
567 (edit_link
, "%s %s" % (obj
.nom
.upper(), obj
.prenom
))
568 _nom
.allow_tags
= True
569 _nom
.short_description
= u
"Employé"
570 _nom
.admin_order_field
= "nom"
574 _id
.short_description
= u
"#"
575 _id
.admin_order_field
= "id"
577 def _date_modification(self
, obj
):
578 return date(obj
.date_modification
) \
579 if obj
.date_modification
is not None else "(aucune)"
580 _date_modification
.short_description
= u
'date modification'
581 _date_modification
.admin_order_field
= 'date_modification'
583 def _dossiers_postes(self
, obj
):
585 for d
in obj
.rh_dossiers
.all().order_by('-date_debut'):
586 dossier
= u
"""<a title="Aperçu du dossier"
588 onclick="return showAddAnotherPopup(this);"
589 title="Aperçu du dossier">
590 <img src="%simg/dossier-apercu.png" />
592 <a href="%s">Dossier</a>
594 (reverse('dossier_apercu', args
=(d
.id,)),
596 reverse('admin:rh_dossier_change', args
=(d
.id,)))
598 poste
= u
"""<a title="Aperçu du poste"
600 onclick="return showAddAnotherPopup(this);"
601 title="Aperçu du poste">
602 <img src="%simg/poste-apercu.png" />
604 <a href="%s">Poste</a>
606 (reverse('poste_apercu', args
=(d
.poste
.id,)),
608 reverse('admin:rh_poste_change', args
=(d
.poste
.id,)))
609 link
= u
"""<li>%s %s - %s : [%s] %s</li>""" % \
616 # Dossier terminé en gris non cliquable
617 if d
.date_fin
is not None and d
.date_fin
< datetime
.date
.today():
618 link
= u
"""<li style="color: grey">%s : [%s] %s</li>""" % \
625 return "<ul>%s</ul>" % "\n".join(l
)
626 _dossiers_postes
.allow_tags
= True
627 _dossiers_postes
.short_description
= u
"Dossiers et postes"
629 def queryset(self
, request
):
630 qs
= super(EmployeAdmin
, self
).queryset(request
)
631 return qs
.select_related(depth
=1).order_by('nom')
633 def save_formset(self
, request
, form
, formset
, change
):
634 instances
= formset
.save(commit
=False)
635 for instance
in instances
:
636 if instance
.__class__
== rh
.EmployeCommentaire
:
637 instance
.owner
= request
.user
638 instance
.date_creation
= datetime
.datetime
.now()
642 class EmployeAdmin(reversion
.VersionAdmin
, EmployeAdminMixin
):
646 class EmployeProxyAdmin(admin
.ModelAdmin
, EmployeAdminMixin
):
647 list_display
= ('_id', '_apercu', '_nom', '_organigramme')
650 def __init__(self
, *args
, **kwargs
):
651 super(EmployeProxyAdmin
, self
).__init__(*args
, **kwargs
)
652 self
.list_display_links
= (None, )
654 def has_add_permission(self
, obj
):
657 def _organigramme(self
, obj
):
659 for d
in rh
.Dossier
.objects
.filter(
660 Q(date_fin__gt
=datetime
.date
.today()) |
Q(date_fin
=None),
661 Q(date_debut__lt
=datetime
.date
.today()) |
Q(date_debut
=None),
665 u
'Organigramme, niveau: ' \
666 u
'<input type="text" id="level_%s" ' \
667 u
'style="width:30px;height:15px;" /> ' \
668 u
'<input type="button" value="Générer" ' \
669 u
"""onclick="window.location='%s' + """ \
670 u
"""document.getElementById('level_%s').value" />""" % (
672 reverse('rho_employe_sans_niveau', args
=(d
.poste
.id,)),
675 link
= u
"""<li>%s - [%s] %s : %s</li>""" % (
682 return "<ul>%s</ul>" % "\n".join(l
)
684 _organigramme
.allow_tags
= True
685 _organigramme
.short_description
= "Organigramme"
688 class CategorieEmploiAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
690 list_display
= ('nom', '_date_modification', 'user_modification', )
691 inlines
= (TypePosteInline
,)
692 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
693 (None, {'fields': ('nom', )}),)
695 def _date_modification(self
, obj
):
696 return date(obj
.date_modification
) \
697 if obj
.date_modification
is not None else "(aucune)"
698 _date_modification
.short_description
= u
'date modification'
699 _date_modification
.admin_order_field
= 'date_modification'
702 class OrganismeBstgAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
704 search_fields
= ('nom',)
709 '_date_modification',
712 list_filter
= ('type', )
713 inlines
= (DossierROInline
,)
714 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
715 (None, {'fields': ('nom', 'type', 'pays',)}),
718 def _date_modification(self
, obj
):
719 return date(obj
.date_modification
) \
720 if obj
.date_modification
is not None else "(aucune)"
721 _date_modification
.short_description
= u
'date modification'
722 _date_modification
.admin_order_field
= 'date_modification'
725 class PosteAdmin(DateRangeMixin
, AUFMetadataAdminMixin
, ProtectRegionMixin
,
726 reversion
.VersionAdmin
, AjaxSelect
, BaseAdmin
):
727 form
= make_ajax_form(rh
.Poste
, {
728 'implantation': 'implantations',
729 'type_poste': 'typepostes',
730 'responsable': 'postes',
731 'valeur_point_min': 'valeurpoints',
732 'valeur_point_max': 'valeurpoints',
734 alphabet_filter
= 'nom'
739 'implantation__region__code',
740 'implantation__region__nom',
741 'rh_dossiers__employe__id',
742 'rh_dossiers__employe__nom',
743 'rh_dossiers__employe__prenom',
755 '_date_modification',
760 'implantation__region',
764 'type_poste__categorie_emploi',
765 'type_poste__famille_professionnelle',
768 list_display_links
= ('_nom',)
769 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
771 ('nom', 'nom_feminin'),
781 'regime_travail_nb_heure_semaine'),
785 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
788 'fields': (('classement_min',
801 ('Comparatifs de rémunération', {
802 'fields': ('devise_comparaison',
803 ('comp_locale_min', 'comp_locale_max'),
804 ('comp_universite_min', 'comp_universite_max'),
805 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
806 ('comp_ong_min', 'comp_ong_max'),
807 ('comp_autre_min', 'comp_autre_max'))}
810 'fields': ('justification',)}
812 ('Autres Méta-données', {
813 'fields': ('date_debut', 'date_fin')}
817 inlines
= (PosteFinancementInline
,
820 PosteComparaisonInline
,
821 PosteCommentaireInline
, )
823 def lookup_allowed(self
, key
, value
):
825 'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
826 'date_fin__isnull', 'implantation__region__id__exact',
827 'implantation__id__exact', 'type_poste__id__exact',
828 'type_poste__categorie_emploi__id__exact', 'service__id__exact',
829 'service__isnull', 'vacant__exact', 'vacant__isnull',
830 ) or super(PosteAdmin
, self
).lookup_allowed(key
, value
)
832 def _apercu(self
, poste
):
833 view_link
= u
"""<a onclick="return showAddAnotherPopup(this);"
834 title="Aperçu du poste"
836 <img src="%simg/poste-apercu.png" />
838 (reverse('poste_apercu', args
=(poste
.id,)),
839 settings
.STATIC_URL
,)
841 _apercu
.allow_tags
= True
842 _apercu
.short_description
= ''
844 def _dae(self
, poste
):
846 postes_dae
= poste
.postes_dae
.all()
847 if len(postes_dae
) > 0:
848 poste_dae
= postes_dae
[0]
850 u
'<a title="Aperçu du dossier" href="%s" ' \
851 u
'onclick="return showAddAnotherPopup(this);">' \
852 u
'<img src="%simg/loupe.png" /></a>' % (reverse(
853 'poste_consulter', args
=("dae-%s" % poste_dae
.id,)
854 ), settings
.STATIC_URL
)
856 _dae
.allow_tags
= True
857 _dae
.short_description
= u
"DAE"
861 _id
.short_description
= '#'
862 _id
.admin_order_field
= 'id'
864 def _service(self
, obj
):
865 if obj
.service
.supprime
:
866 return """<span style="color:red">%s</span>""" % obj
.service
869 _service
.short_description
= 'Service'
870 _service
.allow_tags
= True
872 def _responsable(self
, obj
):
874 responsable
= u
"""<a href="%s"
875 onclick="return showAddAnotherPopup(this)">
876 <img src="%simg/poste-apercu.png"
877 title="Aperçu du poste" />
881 (reverse('poste_apercu', args
=(obj
.responsable
.id,)),
883 reverse('admin:rh_poste_change', args
=(obj
.responsable
.id,)),
889 dossier
= obj
.responsable
.rh_dossiers
.all() \
890 .order_by('-date_debut')[0]
891 employe_id
= dossier
.employe
.id
892 employe_html
= u
"""<br />
894 onclick="return showAddAnotherPopup(this)">
895 <img src="%simg/employe-apercu.png"
896 title="Aperçu de l'employé">
898 <a href="%s">%s</a>""" % \
899 (reverse('employe_apercu', args
=(employe_id
,)),
901 reverse('admin:rh_employe_change', args
=(employe_id
,)),
906 return "%s %s" % (responsable
, employe_html
)
907 _responsable
.short_description
= 'Responsable'
908 _responsable
.allow_tags
= True
910 def _implantation(self
, poste
):
911 return poste
.implantation
.nom
912 _implantation
.short_description
= 'Implantation'
913 _implantation
.admin_order_field
= 'implantation'
915 def _nom(self
, poste
):
916 return """<a href="%s">%s</a>""" % \
917 (reverse('admin:rh_poste_change', args
=(poste
.id,)),
919 _nom
.allow_tags
= True
920 _nom
.short_description
= u
'Poste'
921 _nom
.admin_order_field
= 'nom'
923 def _date_modification(self
, obj
):
924 return date(obj
.date_modification
)
925 _date_modification
.short_description
= u
'date modification'
926 _date_modification
.admin_order_field
= 'date_modification'
928 def _occupe_par(self
, obj
):
929 """Formatte la méthode Poste.occupe_par() pour l'admin"""
931 if obj
.date_fin
is not None and obj
.date_fin
< datetime
.date
.today():
933 employes
= obj
.occupe_par()
937 link
= u
"""<a href='%s'
938 title='Aperçu de l\'employé'
939 onclick='return showAddAnotherPopup(this)'>
940 <img src='%simg/employe-apercu.png' />
942 <a href='%s'>%s</a>""" % \
943 (reverse('employe_apercu', args
=(e
.id,)),
945 reverse('admin:rh_employe_change', args
=(e
.id,)),
948 output
= "\n<br />".join(l
)
950 _occupe_par
.allow_tags
= True
951 _occupe_par
.short_description
= "Occupé par"
953 def save_formset(self
, request
, form
, formset
, change
):
954 instances
= formset
.save(commit
=False)
955 for instance
in instances
:
956 if instance
.__class__
== rh
.PosteCommentaire
:
957 instance
.owner
= request
.user
958 instance
.date_creation
= datetime
.datetime
.now()
963 class ResponsableInline(admin
.TabularInline
):
964 model
= rh
.ResponsableImplantation
966 fk_name
= "implantation"
967 form
= ResponsableInlineForm
970 class ResponsableImplantationAdmin(BaseAdmin
):
973 inlines
= (ResponsableInline
, )
974 list_filter
= ('region', 'statut', )
975 list_display
= ('_region', '_nom', 'statut', '_responsable', )
976 list_display_links
= ('_nom',)
977 readonly_fields
= ('nom', )
980 'responsable__employe__id',
981 'responsable__employe__nom',
982 'responsable__employe__prenom',
986 def _region(self
, obj
):
987 return obj
.region
.code
988 _region
.short_description
= u
"Région"
989 _region
.admin_order_field
= 'region__code'
993 _nom
.short_description
= u
"Implantation"
994 _nom
.admin_order_field
= 'nom'
996 def _responsable(self
, obj
):
998 employe
= obj
.responsable
.employe
999 dossiers
= employe
.dossiers_encours()
1000 if len(dossiers
) == 0:
1001 return u
"<span style='color: red;'>%s %s </span>" % (
1002 employe
, u
"sans dossier actif")
1006 if obj
.statut
in (1, 2): # ouverte, ouverture imminente
1007 css
= "style='color: red;'"
1010 return u
"<span %s>Pas de responsable</span>" % css
1011 _responsable
.allow_tags
= True
1012 _responsable
.short_description
= u
"Responsable"
1013 _responsable
.admin_order_field
= 'responsable__employe__nom'
1015 def has_add_permission(self
, request
=None):
1018 def has_change_permission(self
, request
, obj
=None):
1019 return in_drh_or_admin(request
.user
)
1021 def has_delete_permission(self
, request
, obj
=None):
1025 class ServiceAdminMixin(AUFMetadataAdminMixin
, ArchiveMixin
, BaseAdmin
):
1029 '_date_modification',
1030 'user_modification',
1032 list_filter
= ('archive', )
1033 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1035 'fields': ('nom', 'archive', ),
1039 def _date_modification(self
, obj
):
1040 return date(obj
.date_modification
) \
1041 if obj
.date_modification
is not None else "(aucune)"
1042 _date_modification
.short_description
= u
'date modification'
1043 _date_modification
.admin_order_field
= 'date_modification'
1046 class ServiceAdmin(reversion
.VersionAdmin
, ServiceAdminMixin
):
1050 class ServiceProxyAdmin(admin
.ModelAdmin
, ServiceAdminMixin
):
1051 list_display
= ('nom', '_organigramme', '_archive', )
1054 def __init__(self
, *args
, **kwargs
):
1055 super(ServiceProxyAdmin
, self
).__init__(*args
, **kwargs
)
1056 self
.list_display_links
= (None, )
1058 def queryset(self
, request
):
1059 return super(ServiceProxyAdmin
, self
).queryset(request
) \
1060 .annotate(num_postes
=Count('rh_postes')) \
1061 .filter(num_postes__gt
=0)
1063 def has_add_permission(self
, obj
):
1066 def has_change_permission(self
, request
, obj
=None):
1067 return in_drh_or_admin(request
.user
)
1069 def _organigramme(self
, obj
):
1070 return """<a href="%s"><strong>Organigramme</strong></a>""" % \
1071 (reverse('rho_service', args
=(obj
.id,)))
1072 _organigramme
.allow_tags
= True
1073 _organigramme
.short_description
= "Organigramme"
1076 class StatutAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
, BaseAdmin
):
1077 list_display
= ('code', 'nom', '_date_modification', 'user_modification', )
1078 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1080 'fields': ('code', 'nom', ),
1084 def _date_modification(self
, obj
):
1085 return date(obj
.date_modification
) \
1086 if obj
.date_modification
is not None else "(aucune)"
1087 _date_modification
.short_description
= u
'date modification'
1088 _date_modification
.admin_order_field
= 'date_modification'
1091 class TauxChangeAdmin(reversion
.VersionAdmin
, BaseAdmin
):
1096 '_date_modification',
1097 'user_modification',
1099 list_filter
= ('devise', )
1100 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1102 'fields': ('taux', 'devise', 'annee', ),
1106 def _date_modification(self
, obj
):
1107 return date(obj
.date_modification
) \
1108 if obj
.date_modification
is not None else "(aucune)"
1109 _date_modification
.short_description
= u
'date modification'
1110 _date_modification
.admin_order_field
= 'date_modification'
1113 class TypeContratAdmin(reversion
.VersionAdmin
, BaseAdmin
):
1117 '_date_modification',
1118 'user_modification',
1120 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1122 'fields': ('nom', 'nom_long', ),
1126 def _date_modification(self
, obj
):
1127 return date(obj
.date_modification
) \
1128 if obj
.date_modification
is not None else "(aucune)"
1129 _date_modification
.short_description
= u
'date modification'
1130 _date_modification
.admin_order_field
= 'date_modification'
1133 class TypePosteAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
1135 search_fields
= ('nom', 'nom_feminin', )
1139 '_date_modification',
1140 'user_modification',
1142 list_filter
= ('categorie_emploi', 'famille_professionnelle')
1143 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1150 'famille_professionnelle',
1155 def _date_modification(self
, obj
):
1156 return date(obj
.date_modification
) \
1157 if obj
.date_modification
is not None else "(aucune)"
1158 _date_modification
.short_description
= u
'date modification'
1159 _date_modification
.admin_order_field
= 'date_modification'
1162 class TypeRemunerationAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
1163 ArchiveMixin
, BaseAdmin
):
1167 'nature_remuneration',
1169 '_date_modification',
1170 'user_modification',)
1171 list_filter
= ('archive', )
1172 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1173 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1177 def _date_modification(self
, obj
):
1178 return date(obj
.date_modification
) \
1179 if obj
.date_modification
is not None else "(aucune)"
1180 _date_modification
.short_description
= u
'date modification'
1181 _date_modification
.admin_order_field
= 'date_modification'
1184 class TypeRevalorisationAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
1186 list_display
= ('nom', '_date_modification', 'user_modification', )
1187 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1188 (None, {'fields': ('nom', )}),
1191 def _date_modification(self
, obj
):
1192 return date(obj
.date_modification
) \
1193 if obj
.date_modification
is not None else "(aucune)"
1194 _date_modification
.short_description
= u
'date modification'
1195 _date_modification
.admin_order_field
= 'date_modification'
1198 class ValeurPointAdmin(AUFMetadataAdminMixin
, reversion
.VersionAdmin
,
1206 '_date_modification',
1207 'user_modification',
1209 list_filter
= ('annee', 'devise', 'implantation__region', )
1210 fieldsets
= AUFMetadataAdminMixin
.fieldsets
+ (
1211 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
1214 def _date_modification(self
, obj
):
1215 return date(obj
.date_modification
) \
1216 if obj
.date_modification
is not None else "(aucune)"
1217 _date_modification
.short_description
= u
'date modification'
1218 _date_modification
.admin_order_field
= 'date_modification'
1220 def _devise_code(self
, obj
):
1221 return obj
.devise
.code
1222 _devise_code
.short_description
= "Code de la devise"
1224 def _devise_nom(self
, obj
):
1225 return obj
.devise
.nom
1226 _devise_nom
.short_description
= "Nom de la devise"
1229 class ImplantationProxyAdmin(BaseAdmin
):
1230 list_display
= ('nom', '_organigramme')
1233 def __init__(self
, *args
, **kwargs
):
1234 super(ImplantationProxyAdmin
, self
).__init__(*args
, **kwargs
)
1235 self
.list_display_links
= (None, )
1237 def has_add_permission(self
, obj
):
1240 def has_change_permission(self
, request
, obj
=None):
1241 return in_drh_or_admin(request
.user
)
1243 def _organigramme(self
, obj
):
1244 return '<a href="%s"><strong>Organigramme</strong></a>' % (
1245 reverse('rho_implantation', args
=(obj
.id,))
1247 _organigramme
.allow_tags
= True
1248 _organigramme
.short_description
= "Organigramme"
1251 class RegionProxyAdmin(BaseAdmin
):
1252 list_display
= ('nom', '_organigramme')
1255 def __init__(self
, *args
, **kwargs
):
1256 super(RegionProxyAdmin
, self
).__init__(*args
, **kwargs
)
1257 self
.list_display_links
= (None, )
1259 def has_add_permission(self
, obj
):
1262 def has_change_permission(self
, request
, obj
=None):
1263 return in_drh_or_admin(request
.user
)
1265 def _organigramme(self
, obj
):
1266 return """<a href="%s"><strong>Organigramme</strong></a>""" % (
1267 reverse('rho_region', args
=(obj
.id,))
1269 _organigramme
.allow_tags
= True
1270 _organigramme
.short_description
= "Organigramme"
1273 admin
.site
.register(rh
.Classement
, ClassementAdmin
)
1274 admin
.site
.register(rh
.Devise
, DeviseAdmin
)
1275 admin
.site
.register(rh
.Dossier
, DossierAdmin
)
1276 admin
.site
.register(EmployeProxy
, EmployeProxyAdmin
)
1277 admin
.site
.register(ServiceProxy
, ServiceProxyAdmin
)
1278 admin
.site
.register(rh
.Employe
, EmployeAdmin
)
1279 admin
.site
.register(rh
.CategorieEmploi
, CategorieEmploiAdmin
)
1280 admin
.site
.register(rh
.FamilleProfessionnelle
)
1281 admin
.site
.register(rh
.OrganismeBstg
, OrganismeBstgAdmin
)
1282 admin
.site
.register(rh
.Poste
, PosteAdmin
)
1283 admin
.site
.register(
1284 rh
.ResponsableImplantationProxy
, ResponsableImplantationAdmin
1286 admin
.site
.register(rh
.Service
, ServiceAdmin
)
1287 admin
.site
.register(rh
.Statut
, StatutAdmin
)
1288 admin
.site
.register(rh
.TauxChange
, TauxChangeAdmin
)
1289 admin
.site
.register(rh
.TypeContrat
, TypeContratAdmin
)
1290 admin
.site
.register(rh
.TypePoste
, TypePosteAdmin
)
1291 admin
.site
.register(rh
.TypeRemuneration
, TypeRemunerationAdmin
)
1292 admin
.site
.register(rh
.TypeRevalorisation
, TypeRevalorisationAdmin
)
1293 admin
.site
.register(rh
.ValeurPoint
, ValeurPointAdmin
)
1294 admin
.site
.register(ImplantationProxy
, ImplantationProxyAdmin
)
1295 admin
.site
.register(RegionProxy
, RegionProxyAdmin
)