1 # -*- encoding: utf-8 -*-
6 from ajax_select
import make_ajax_form
7 from auf
.django
.references
import models
as ref
8 from django
import forms
9 from django
.core
.urlresolvers
import reverse
10 from django
.contrib
import admin
11 from django
.contrib
.contenttypes
.models
import ContentType
12 from django
.conf
import settings
13 from django
.db
.models
import Q
, Count
14 from django
.template
.defaultfilters
import date
15 from django
.utils
.formats
import date_format
17 from project
import groups
18 from project
.decorators
import in_drh_or_admin
19 from project
.rh
import models
as rh
20 from project
.permissions
import user_gere_obj_de_sa_region
, \
22 user_can_change_obj
, \
23 user_can_delete_obj
, \
26 from project
.rh
.forms
import ContratForm
, AyantDroitForm
, EmployeAdminForm
, \
27 AjaxSelect
, DossierForm
, ResponsableInlineForm
28 from project
.rh
.change_list
import ChangeList
31 class BaseAdmin(admin
.ModelAdmin
):
35 'css/admin_custom.css',
36 'jquery-autocomplete/jquery.autocomplete.css',
39 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
40 'jquery-autocomplete/jquery.autocomplete.min.js',
43 # Admin pour reversion
45 class ArchivableAdmin(admin
.ModelAdmin
):
47 Admin pour les modèles archivables
49 list_filter
= ('archive', )
51 def queryset(self
, request
):
52 return self
.model
.avec_archives
.all()
54 def _archive(self
, obj
):
59 _archive
.short_description
= u
'Archivé'
60 _archive
.admin_order_field
= 'archive'
63 class RegionProxy(ref
.Region
):
64 """ Proxy utilisé pour les organigrammes par région """
68 verbose_name
= u
"Organigramme par région"
69 verbose_name_plural
= u
"Organigramme par région"
72 class ImplantationProxy(ref
.Implantation
):
73 """ Proxy utilisé pour les organigrammes par implantation """
77 verbose_name
= u
"Organigramme par implantations"
78 verbose_name_plural
= u
"Organigramme par implantations"
81 class ServiceProxy(rh
.Service
):
82 """ Proxy utilisé pour les organigrammes par service """
87 verbose_name
= u
"Organigramme par services"
88 verbose_name_plural
= u
"Organigramme par services"
91 class EmployeProxy(rh
.Employe
):
92 """ Proxy utilisé pour les organigrammes des employés """
96 verbose_name
= u
"Organigramme des employés"
97 verbose_name_plural
= u
"Organigramme des employés"
100 class DateRangeMixin(object):
101 prefixe_recherche_temporelle
= ""
103 def get_changelist(self
, request
, **kwargs
):
104 if 'HTTP_REFERER' in request
.META
.keys():
105 referer
= request
.META
['HTTP_REFERER']
106 referer
= "/".join(referer
.split('/')[3:])
107 referer
= "/%s" % referer
.split('?')[0]
108 change_list_view
= 'admin:%s_%s_changelist' % (
109 self
.model
._meta
.app_label
,
110 self
.model
.__name__
.lower(),)
111 if referer
!= reverse(change_list_view
):
112 params
= request
.GET
.copy()
113 params
.update({'statut': 'Actif'})
118 # Override of the InlineModelAdmin to support the link in the tabular inline
119 class LinkedInline(admin
.options
.InlineModelAdmin
):
120 template
= "admin/linked.html"
121 admin_model_path
= None
123 def __init__(self
, *args
):
124 super(LinkedInline
, self
).__init__(*args
)
125 if self
.admin_model_path
is None:
126 self
.admin_model_path
= self
.model
.__name__
.lower()
129 class ProtectRegionMixin(object):
131 def queryset(self
, request
):
132 qs
= super(ProtectRegionMixin
, self
).queryset(request
)
134 if in_drh_or_admin(request
.user
):
137 if user_gere_obj_de_sa_region(request
.user
):
138 region_user
= get_region_user(request
.user
)
139 q
= Q(**{self
.model
.prefix_implantation
: \
141 qs
= qs
.filter(q
).distinct()
145 def has_add_permission(self
, request
):
146 return user_can_add_obj(request
.user
)
148 def has_change_permission(self
, request
, obj
=None):
149 return user_can_change_obj(request
.user
, obj
) if obj
else True
151 def has_delete_permission(self
, request
, obj
=None):
152 return user_can_delete_obj(request
.user
, obj
) if obj
else True
155 class DerniereModificationAdmin(admin
.ModelAdmin
):
157 def queryset(self
, request
):
158 qs
= super(DerniereModificationAdmin
, self
).queryset(request
)
159 ct
= ContentType
.objects
.get_for_model(self
.model
)
160 db_table
= self
.model
._meta
.db_table
161 pk
= self
.model
._meta
.pk
.column
162 return qs
.extra(select
={
164 "SELECT action_time FROM django_admin_log "
165 "WHERE content_type_id = %d AND object_id = %s.%s "
166 "ORDER BY action_time DESC "
167 "LIMIT 1" % (ct
.id, db_table
, pk
),
171 "INNER JOIN django_admin_log l ON l.user_id = u.id "
172 "WHERE l.content_type_id = %d AND object_id = %s.%s "
173 "ORDER BY action_time DESC "
174 "LIMIT 1" % (ct
.id, db_table
, pk
),
177 def derniere_modification(self
, obj
):
179 if obj
.date_modification
:
180 text
+= obj
.date_modification
.strftime('%d-%m-%Y %H:%M')
181 if obj
.user_modification
:
182 text
+= ' par ' + obj
.user_modification
184 derniere_modification
.short_description
= u
'dernière modification'
185 derniere_modification
.admin_order_field
= 'date_modification'
190 class CommentaireInlineForm(forms
.ModelForm
):
192 def save(self
, commit
=True):
194 # Hack: reversion.VersionAdmin ne sauvegarde pas les champs qui ne
195 # sont pas explicitement dans le formulaire. Il plante cependant
196 # leur valeur dans `self.initial`. Ceci est un peu fragile. Si
197 # c'est possible, il serait plus approprié que Reversion se rende
198 # compte qu'il manque des champs.
199 instance
= super(CommentaireInlineForm
, self
).save(commit
=False)
200 if instance
.owner_id
is None and 'owner' in self
.initial
:
201 instance
.owner_id
= self
.initial
['owner']
202 if instance
.date_creation
is None and 'date_creation' in self
.initial
:
203 instance
.date_creation
= self
.initial
['date_creation']
210 class ReadOnlyInlineMixin(object):
212 def get_readonly_fields(self
, request
, obj
=None):
213 return [f
.name
for f
in self
.model
._meta
.fields
]
216 class AyantDroitInline(admin
.StackedInline
):
217 model
= rh
.AyantDroit
218 form
= AyantDroitForm
225 ('nom_affichage', 'genre'),
233 class AyantDroitCommentaireInline(admin
.TabularInline
):
234 readonly_fields
= ('owner',)
235 model
= rh
.AyantDroitCommentaire
237 form
= CommentaireInlineForm
240 class ContratInline(admin
.TabularInline
):
246 class DossierROInline(ReadOnlyInlineMixin
, LinkedInline
):
247 template
= "admin/rh/dossier/linked.html"
252 def has_add_permission(self
, request
=None):
255 def has_change_permission(self
, request
, obj
=None):
258 def has_delete_permission(self
, request
, obj
=None):
262 class DossierCommentaireInline(admin
.TabularInline
):
263 readonly_fields
= ('owner',)
264 model
= rh
.DossierCommentaire
266 form
= CommentaireInlineForm
269 class DossierPieceInline(admin
.TabularInline
):
270 model
= rh
.DossierPiece
274 class EmployeInline(admin
.TabularInline
):
278 class EmployeCommentaireInline(admin
.TabularInline
):
279 readonly_fields
= ('owner',)
280 model
= rh
.EmployeCommentaire
282 form
= CommentaireInlineForm
285 class EmployePieceInline(admin
.TabularInline
):
286 model
= rh
.EmployePiece
290 class PosteCommentaireInline(admin
.TabularInline
):
291 readonly_fields
= ('owner',)
292 model
= rh
.PosteCommentaire
294 form
= CommentaireInlineForm
297 class PosteFinancementInline(admin
.TabularInline
):
298 model
= rh
.PosteFinancement
301 class PostePieceInline(admin
.TabularInline
):
302 model
= rh
.PostePiece
305 class RemunerationInline(admin
.TabularInline
):
306 model
= rh
.Remuneration
310 class RemunerationROInline(ReadOnlyInlineMixin
, RemunerationInline
):
314 class TypePosteInline(admin
.TabularInline
):
318 class PosteComparaisonInline(admin
.TabularInline
):
319 model
= rh
.PosteComparaison
322 class ClassementAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
324 ignore_duplicate_revisions
= True
325 list_display
= ('_classement', 'derniere_modification')
327 (None, {'fields': ('type', 'echelon', 'degre', 'coefficient',)}),
330 def _classement(self
, obj
):
332 _classement
.short_description
= u
"Classement"
335 class DeviseAdmin(reversion
.VersionAdmin
, ArchivableAdmin
,
336 DerniereModificationAdmin
, BaseAdmin
):
337 ignore_duplicate_revisions
= True
339 'code', 'nom', '_archive', 'derniere_modification',
341 list_filter
= ('archive', )
343 (None, {'fields': ('code', 'nom', 'archive', )}),
347 class DossierAdmin(DateRangeMixin
, ProtectRegionMixin
, reversion
.VersionAdmin
,
348 AjaxSelect
, DerniereModificationAdmin
, BaseAdmin
):
349 change_list_template
= "admin/rh/dossier/change_list.html"
350 ignore_duplicate_revisions
= True
351 alphabet_filter
= 'employe__nom'
359 'poste__nom_feminin',
360 'poste__implantation__nom',
372 'derniere_modification',
375 list_display_links
= ('_nom',)
377 'poste__implantation__region',
378 'poste__implantation',
379 'poste__type_poste__categorie_emploi',
381 'rh_contrats__type_contrat',
384 inlines
= (DossierPieceInline
, ContratInline
,
386 DossierCommentaireInline
,
395 'organisme_bstg',)}),
400 'remplacement_de', )}),
404 ('regime_travail', 'regime_travail_nb_heure_semaine'),)}),
405 ('Occupation du Poste par cet Employe', {
406 'fields': (('date_debut', 'date_fin'), )}
409 form
= make_ajax_form(rh
.Dossier
, {
410 'employe': 'employes',
412 'remplacement_de': 'dossiers',
413 }, superclass
=DossierForm
)
415 def lookup_allowed(self
, key
, value
):
417 'employe__nom__istartswith',
418 'poste__implantation__region__id__exact',
419 'poste__implantation__id__exact',
420 'poste__type_poste__id__exact',
421 'poste__type_poste__categorie_emploi__id__exact',
422 'rh_contrats__type_contrat__id__exact',
430 _id
.short_description
= u
"#"
431 _id
.admin_order_field
= "id"
433 def _apercu(self
, d
):
434 apercu_link
= u
"""<a title="Aperçu du dossier"
435 onclick="return showAddAnotherPopup(this);"
437 <img src="%simg/dossier-apercu.png" />
439 (reverse('dossier_apercu', args
=(d
.id,)),
443 _apercu
.allow_tags
= True
444 _apercu
.short_description
= u
""
448 _nom
.allow_tags
= True
449 _nom
.short_description
= u
"Dossier"
451 def _employe(self
, obj
):
452 employe
= obj
.employe
453 view_link
= reverse('employe_apercu', args
=(employe
.id,))
454 edit_link
= reverse('admin:rh_employe_change', args
=(employe
.id,))
456 view
= u
"""<a href="%s"
457 title="Aperçu l'employé"
458 onclick="return showAddAnotherPopup(this);">
459 <img src="%simg/employe-apercu.png" />
460 </a>""" % (view_link
, settings
.STATIC_URL
,)
461 return u
"""%s<a href='%s' style="%s;">%s</a>""" % \
462 (view
, edit_link
, style
, employe
)
463 _employe
.allow_tags
= True
464 _employe
.short_description
= u
"Employé"
465 _employe
.admin_order_field
= "employe__nom"
467 def _poste(self
, dossier
):
468 link
= u
"""<a title="Aperçu du poste"
469 onclick="return showAddAnotherPopup(this);"
470 href='%s'><img src="%simg/poste-apercu.png" />
472 <a href="%s" title="Modifier le poste">%s [%d]</a>""" % \
473 (reverse('poste_apercu', args
=(dossier
.poste
.id,)),
475 reverse('admin:rh_poste_change', args
=(dossier
.poste
.id,)),
480 _poste
.allow_tags
= True
481 _poste
.short_description
= u
'Poste'
482 _poste
.admin_order_field
= 'poste__nom'
484 def _region(self
, obj
):
485 return obj
.poste
.implantation
.region
.code
486 _region
.short_description
= u
"Région"
487 _region
.admin_order_field
= 'poste__implantation__region__code'
489 def _implantation(self
, obj
):
490 return obj
.poste
.implantation
.nom
491 _implantation
.short_description
= u
"Implantation"
492 _implantation
.admin_order_field
= 'poste__implantation__nom'
494 def _date_debut(self
, obj
):
495 return date(obj
.date_debut
)
497 _date_debut
.short_description
= u
'Début'
498 _date_debut
.admin_order_field
= 'date_debut'
500 def _date_fin(self
, obj
):
501 return date(obj
.date_fin
)
502 _date_fin
.short_description
= u
'Fin'
503 _date_fin
.admin_order_field
= 'date_fin'
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'
513 dossiers_dae
= d
.dossiers_dae
.all()
514 if len(dossiers_dae
) > 0:
515 dossier_dae
= dossiers_dae
[0]
516 apercu_link
= u
"""<a title="Aperçu du dossier"
517 onclick="return showAddAnotherPopup(this);"
519 <img src="%simg/loupe.png" />
521 (reverse('embauche_consulter', args
=(dossier_dae
.id,)),
525 _dae
.allow_tags
= True
526 _dae
.short_description
= u
"DAE"
528 def save_formset(self
, request
, form
, formset
, change
):
529 instances
= formset
.save(commit
=False)
530 for instance
in instances
:
531 if instance
.__class__
== rh
.DossierCommentaire
:
532 instance
.owner
= request
.user
533 instance
.date_creation
= datetime
.datetime
.now()
537 class EmployeAdminBase(DateRangeMixin
, ProtectRegionMixin
,
538 DerniereModificationAdmin
, BaseAdmin
):
539 prefixe_recherche_temporelle
= "rh_dossiers__"
540 alphabet_filter
= 'nom'
541 DEFAULT_ALPHABET
= u
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
543 'id', 'nom', 'prenom', 'nom_affichage',
544 'rh_dossiers__poste__nom',
545 'rh_dossiers__poste__nom_feminin'
548 form
= EmployeAdminForm
550 '_id', '_apercu', '_nom', '_dossiers_postes',
554 'derniere_modification'
556 list_display_links
= ('_nom',)
558 'rh_dossiers__poste__implantation__region',
559 'rh_dossiers__poste__implantation', 'nb_postes'
562 AyantDroitInline
, DossierROInline
, EmployePieceInline
,
563 EmployeCommentaireInline
569 ('nom_affichage', 'genre'),
574 ('Informations personnelles', {
575 'fields': ('situation_famille', 'date_entree', )
577 ('Coordonnées personnelles', {
579 ('tel_domicile', 'tel_cellulaire'),
580 ('adresse', 'ville'),
581 ('code_postal', 'province'),
590 _id
.short_description
= u
"#"
591 _id
.admin_order_field
= "id"
593 def _apercu(self
, obj
):
594 return u
"""<a title="Aperçu de l'employé"
595 onclick="return showAddAnotherPopup(this);"
597 <img src="%simg/employe-apercu.png" />
599 (reverse('employe_apercu', args
=(obj
.id,)), settings
.STATIC_URL
)
600 _apercu
.allow_tags
= True
601 _apercu
.short_description
= u
""
604 edit_link
= reverse('admin:rh_employe_change', args
=(obj
.id,))
605 return u
"""<a href='%s'><strong>%s</strong></a>""" % \
606 (edit_link
, "%s %s" % (obj
.nom
.upper(), obj
.prenom
))
607 _nom
.allow_tags
= True
608 _nom
.short_description
= u
"Employé"
609 _nom
.admin_order_field
= "nom"
611 def _region(self
, obj
):
613 d
= rh
.Dossier
.objects
.filter(employe
=obj
.id, principal
=True)[0]
614 region
= d
.poste
.implantation
.region
.code
618 _region
.short_description
= u
"Région"
620 def _implantation(self
, obj
):
622 d
= rh
.Dossier
.objects
.filter(employe
=obj
.id, principal
=True)[0]
623 implantation
= d
.poste
.implantation
.nom
627 _implantation
.short_description
= u
"Implantation"
629 def _dossiers_postes(self
, obj
):
631 for d
in obj
.rh_dossiers
.all().order_by('-date_debut'):
634 if d
.date_fin
is not None and d
.date_fin
< datetime
.date
.today():
635 link_style
= u
' style="color:#666;"'
636 list_style
= u
' style="color:grey;"'
638 dossier
= u
"""<a title="Aperçu du dossier"
640 onclick="return showAddAnotherPopup(this);"
641 title="Aperçu du dossier">
642 <img src="%simg/dossier-apercu.png" />
644 <a href="%s"%s>Dossier</a>
646 (reverse('dossier_apercu', args
=(d
.id,)),
648 reverse('admin:rh_dossier_change', args
=(d
.id,)),
651 poste
= u
"""<a title="Aperçu du poste"
653 onclick="return showAddAnotherPopup(this);"
654 title="Aperçu du poste">
655 <img src="%simg/poste-apercu.png" />
657 <a href="%s"%s>%s [%d]</a>
659 (reverse('poste_apercu', args
=(d
.poste
.id,)),
661 reverse('admin:rh_poste_change', args
=(d
.poste
.id,)),
666 link
= u
"""<li%s>%s %s</li>""" % \
667 (list_style
, dossier
, poste
)
670 return "<ul>%s</ul>" % "\n".join(l
)
671 _dossiers_postes
.allow_tags
= True
672 _dossiers_postes
.short_description
= u
"Dossiers et postes"
674 def _date_modification(self
, obj
):
675 return date(obj
.date_modification
) \
676 if obj
.date_modification
is not None else "(aucune)"
677 _date_modification
.short_description
= u
'date modification'
678 _date_modification
.admin_order_field
= 'date_modification'
680 def queryset(self
, request
):
681 qs
= super(EmployeAdminBase
, self
).queryset(request
)
682 return qs
.select_related(depth
=1).order_by('nom')
684 def save_formset(self
, request
, form
, formset
, change
):
685 instances
= formset
.save(commit
=False)
686 for instance
in instances
:
687 if instance
.__class__
== rh
.EmployeCommentaire
:
688 instance
.owner
= request
.user
689 instance
.date_creation
= datetime
.datetime
.now()
693 class EmployeAdmin(reversion
.VersionAdmin
, EmployeAdminBase
):
694 change_list_template
= "admin/rh/employe/change_list.html"
695 ignore_duplicate_revisions
= True
698 class EmployeProxyAdmin(EmployeAdminBase
):
699 list_display
= ('_id', '_apercu', '_nom', '_organigramme')
703 def __init__(self
, *args
, **kwargs
):
704 super(EmployeProxyAdmin
, self
).__init__(*args
, **kwargs
)
705 self
.list_display_links
= (None, )
707 def queryset(self
, request
):
708 qs
= super(ProtectRegionMixin
, self
).queryset(request
)
710 if in_drh_or_admin(request
.user
) or \
711 user_gere_obj_de_sa_region(request
.user
):
716 def has_add_permission(self
, obj
):
719 def has_change_permission(self
, request
, obj
=None):
720 user_groups
= [g
.name
for g
in request
.user
.groups
.all()]
721 if groups
.CORRESPONDANT_RH
in user_groups
or \
722 groups
.ADMINISTRATEURS
in user_groups
or \
723 groups
.DIRECTEUR_DE_BUREAU
in user_groups
or \
724 in_drh_or_admin(request
.user
):
728 def _organigramme(self
, obj
):
730 for d
in rh
.Dossier
.objects
.filter(
731 Q(date_fin__gt
=datetime
.date
.today()) |
Q(date_fin
=None),
732 Q(date_debut__lt
=datetime
.date
.today()) |
Q(date_debut
=None),
736 u
'Organigramme, niveau: ' \
737 u
'<input type="text" id="level_%s" ' \
738 u
'style="width:30px;height:15px;" /> ' \
739 u
'<input type="button" value="Générer" ' \
740 u
"""onclick="window.location='%s' + """ \
741 u
"""document.getElementById('level_%s').value" />""" % (
743 reverse('rho_employe_sans_niveau', args
=(d
.poste
.id,)),
746 link
= u
"""<li>%s [%s]:<br />%s</li>""" % (
752 return "<ul>%s</ul>" % "\n".join(l
)
754 _organigramme
.allow_tags
= True
755 _organigramme
.short_description
= "Organigramme"
758 class CategorieEmploiAdmin(reversion
.VersionAdmin
,
759 DerniereModificationAdmin
, BaseAdmin
):
760 ignore_duplicate_revisions
= True
761 list_display
= ('nom', 'derniere_modification')
762 inlines
= (TypePosteInline
,)
764 (None, {'fields': ('nom', )}),
768 class OrganismeBstgAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
770 ignore_duplicate_revisions
= True
771 search_fields
= ('nom',)
772 list_display
= ('nom', 'type', 'pays', 'derniere_modification')
773 list_filter
= ('type', )
774 inlines
= (DossierROInline
,)
776 (None, {'fields': ('nom', 'type', 'pays',)}),
780 class PosteAdmin(DateRangeMixin
, ProtectRegionMixin
, reversion
.VersionAdmin
,
781 AjaxSelect
, DerniereModificationAdmin
, BaseAdmin
):
782 change_list_template
= "admin/rh/poste/change_list.html"
783 ignore_duplicate_revisions
= True
784 form
= make_ajax_form(rh
.Poste
, {
785 'implantation': 'implantations',
786 'type_poste': 'typepostes',
787 'responsable': 'postes',
788 'valeur_point_min': 'valeurpoints',
789 'valeur_point_max': 'valeurpoints',
791 alphabet_filter
= 'nom'
796 'implantation__region__code',
797 'implantation__region__nom',
798 'rh_dossiers__employe__id',
799 'rh_dossiers__employe__nom',
800 'rh_dossiers__employe__prenom',
803 '_id', '_apercu', '_nom', '_occupe_par', 'implantation', '_service',
804 '_responsable', 'date_debut', 'date_fin', 'derniere_modification',
808 'implantation__region',
812 'type_poste__categorie_emploi',
813 'type_poste__famille_professionnelle',
816 list_display_links
= ('_nom',)
819 ('nom', 'nom_feminin'),
829 'regime_travail_nb_heure_semaine'),
833 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
836 'fields': (('classement_min',
849 ('Comparatifs de rémunération', {
850 'fields': ('devise_comparaison',
851 ('comp_locale_min', 'comp_locale_max'),
852 ('comp_universite_min', 'comp_universite_max'),
853 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
854 ('comp_ong_min', 'comp_ong_max'),
855 ('comp_autre_min', 'comp_autre_max'))}
858 'fields': ('justification',)}
860 ('Autres Méta-données', {
861 'fields': ('date_debut', 'date_fin')}
865 inlines
= (PosteFinancementInline
,
868 PosteComparaisonInline
,
869 PosteCommentaireInline
, )
871 def lookup_allowed(self
, key
, value
):
873 'date_debut__gte', 'date_debut__isnull', 'date_fin__lte',
874 'date_fin__isnull', 'implantation__region__id__exact',
875 'implantation__id__exact', 'type_poste__id__exact',
876 'type_poste__categorie_emploi__id__exact', 'service__id__exact',
877 'service__isnull', 'vacant__exact', 'vacant__isnull',
878 ) or super(PosteAdmin
, self
).lookup_allowed(key
, value
)
882 _id
.short_description
= '#'
883 _id
.admin_order_field
= 'id'
885 def _apercu(self
, poste
):
886 view_link
= u
"""<a onclick="return showAddAnotherPopup(this);"
887 title="Aperçu du poste"
889 <img src="%simg/poste-apercu.png" />
891 (reverse('poste_apercu', args
=(poste
.id,)),
892 settings
.STATIC_URL
,)
894 _apercu
.allow_tags
= True
895 _apercu
.short_description
= ''
897 def _nom(self
, poste
):
898 return """<a href="%s">%s</a>""" % \
899 (reverse('admin:rh_poste_change', args
=(poste
.id,)),
901 _nom
.allow_tags
= True
902 _nom
.short_description
= u
'Poste'
903 _nom
.admin_order_field
= 'nom'
905 def _occupe_par(self
, obj
):
906 """Formatte la méthode Poste.occupe_par() pour l'admin"""
908 if obj
.date_fin
is not None and obj
.date_fin
< datetime
.date
.today():
910 employes
= obj
.occupe_par()
914 link
= u
"""<a href='%s'
915 title='Aperçu de l\'employé'
916 onclick='return showAddAnotherPopup(this)'>
917 <img src='%simg/employe-apercu.png' />
919 <a href='%s'>%s</a>""" % \
920 (reverse('employe_apercu', args
=(e
.id,)),
922 reverse('admin:rh_employe_change', args
=(e
.id,)),
925 output
= "\n<br />".join(l
)
927 _occupe_par
.allow_tags
= True
928 _occupe_par
.short_description
= "Occupé par"
930 def _region(self
, poste
):
931 return poste
.implantation
.region
.code
932 _region
.short_description
= 'Région'
933 _region
.admin_order_field
= 'implantation__region__code'
935 def _implantation(self
, poste
):
936 return poste
.implantation
.nom
937 _implantation
.short_description
= 'Implantation'
938 _implantation
.admin_order_field
= 'implantation'
940 def _service(self
, obj
):
942 _service
.short_description
= 'Service'
943 _service
.allow_tags
= True
945 def _responsable(self
, obj
):
947 responsable
= u
"""<a href="%s"
948 onclick="return showAddAnotherPopup(this)">
949 <img src="%simg/poste-apercu.png"
950 title="Aperçu du poste" />
952 <a href="%s">%s [%d]</a>
954 (reverse('poste_apercu', args
=(obj
.responsable
.id,)),
956 reverse('admin:rh_poste_change', args
=(obj
.responsable
.id,)),
963 dossier
= obj
.responsable
.rh_dossiers
.all() \
964 .order_by('-date_debut')[0]
965 employe_id
= dossier
.employe
.id
966 employe_html
= u
"""<br />
968 onclick="return showAddAnotherPopup(this)">
969 <img src="%simg/employe-apercu.png"
970 title="Aperçu de l'employé">
972 <a href="%s">%s</a>""" % \
973 (reverse('employe_apercu', args
=(employe_id
,)),
975 reverse('admin:rh_employe_change', args
=(employe_id
,)),
980 return "%s %s" % (responsable
, employe_html
)
981 _responsable
.short_description
= 'Responsable'
982 _responsable
.allow_tags
= True
984 def _date_debut(self
, obj
):
985 return date_format(obj
.date_debut
)
986 _date_debut
.short_description
= u
'Début'
987 _date_debut
.admin_order_field
= 'date_debut'
989 def _date_fin(self
, obj
):
990 return date_format(obj
.date_fin
)
991 _date_fin
.short_description
= u
'Fin'
992 _date_fin
.admin_order_field
= 'date_fin'
994 def _dae(self
, poste
):
996 postes_dae
= poste
.postes_dae
.all()
997 if len(postes_dae
) > 0:
998 poste_dae
= postes_dae
[0]
1000 u
'<a title="Aperçu du dossier" href="%s" ' \
1001 u
'onclick="return showAddAnotherPopup(this);">' \
1002 u
'<img src="%simg/loupe.png" /></a>' % (reverse(
1003 'poste_consulter', args
=("dae-%s" % poste_dae
.id,)
1004 ), settings
.STATIC_URL
)
1006 _dae
.allow_tags
= True
1007 _dae
.short_description
= u
"DAE"
1009 def save_formset(self
, request
, form
, formset
, change
):
1010 instances
= formset
.save(commit
=False)
1011 for instance
in instances
:
1012 if instance
.__class__
== rh
.PosteCommentaire
:
1013 instance
.owner
= request
.user
1014 instance
.date_creation
= datetime
.datetime
.now()
1019 class ResponsableInline(admin
.TabularInline
):
1020 model
= rh
.ResponsableImplantation
1022 fk_name
= "implantation"
1023 form
= ResponsableInlineForm
1026 class ResponsableImplantationAdmin(BaseAdmin
):
1029 inlines
= (ResponsableInline
, )
1030 list_filter
= ('region', 'statut', )
1031 list_display
= ('_region', '_nom', 'statut', '_responsable', )
1032 list_display_links
= ('_nom',)
1034 readonly_fields
= ('nom', )
1037 'responsable__employe__id',
1038 'responsable__employe__nom',
1039 'responsable__employe__prenom',
1042 inlines
= (ResponsableInline
, )
1044 def _region(self
, obj
):
1045 return obj
.region
.code
1046 _region
.short_description
= u
"Région"
1047 _region
.admin_order_field
= 'region__code'
1049 def _nom(self
, obj
):
1051 _nom
.short_description
= u
"Implantation"
1052 _nom
.admin_order_field
= 'nom'
1054 def _responsable(self
, obj
):
1056 employe
= obj
.responsable
.employe
1057 dossiers
= employe
.dossiers_encours()
1058 if len(dossiers
) == 0:
1059 return u
"<span style='color: red;'>%s %s </span>" % (
1060 employe
, u
"sans dossier actif")
1064 if obj
.statut
in (1, 2): # ouverte, ouverture imminente
1065 css
= "style='color: red;'"
1068 return u
"<span %s>Pas de responsable</span>" % css
1069 _responsable
.allow_tags
= True
1070 _responsable
.short_description
= u
"Responsable"
1071 _responsable
.admin_order_field
= 'responsable__employe__nom'
1073 def has_add_permission(self
, request
=None):
1076 def has_change_permission(self
, request
, obj
=None):
1077 return in_drh_or_admin(request
.user
)
1079 def has_delete_permission(self
, request
, obj
=None):
1083 class ServiceAdminBase(ArchivableAdmin
, DerniereModificationAdmin
, BaseAdmin
):
1084 list_display
= ('nom', '_archive', 'derniere_modification')
1085 list_filter
= ('archive', )
1087 (None, {'fields': ('nom', 'archive')}),
1091 class ServiceAdmin(reversion
.VersionAdmin
, ServiceAdminBase
):
1092 ignore_duplicate_revisions
= True
1095 class ServiceProxyAdmin(ServiceAdminBase
):
1096 list_display
= ('nom', '_organigramme', '_archive', )
1099 def __init__(self
, *args
, **kwargs
):
1100 super(ServiceProxyAdmin
, self
).__init__(*args
, **kwargs
)
1101 self
.list_display_links
= (None, )
1103 def queryset(self
, request
):
1104 return super(ServiceProxyAdmin
, self
).queryset(request
) \
1105 .annotate(num_postes
=Count('rh_postes')) \
1106 .filter(num_postes__gt
=0)
1108 def has_add_permission(self
, obj
):
1111 def has_change_permission(self
, request
, obj
=None):
1112 user_groups
= [g
.name
for g
in request
.user
.groups
.all()]
1113 if groups
.CORRESPONDANT_RH
in user_groups
or \
1114 groups
.ADMINISTRATEURS
in user_groups
or \
1115 groups
.DIRECTEUR_DE_BUREAU
in user_groups
or \
1116 in_drh_or_admin(request
.user
):
1120 def _organigramme(self
, obj
):
1121 return """<a href="%s"><strong>Organigramme</strong></a>""" % \
1122 (reverse('rho_service', args
=(obj
.id,)))
1123 _organigramme
.allow_tags
= True
1124 _organigramme
.short_description
= "Organigramme"
1127 class StatutAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
1129 ignore_duplicate_revisions
= True
1130 list_display
= ('code', 'nom', 'derniere_modification')
1133 'fields': ('code', 'nom', ),
1138 class TauxChangeAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
1140 ignore_duplicate_revisions
= True
1141 list_display
= ('taux', 'devise', 'annee', 'derniere_modification')
1142 list_filter
= ('devise',)
1145 'fields': ('taux', 'devise', 'annee', ),
1150 class TypeContratAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
1152 ignore_duplicate_revisions
= True
1153 list_display
= ('nom', 'nom_long', 'derniere_modification')
1156 'fields': ('nom', 'nom_long', ),
1161 class TypePosteAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
1163 ignore_duplicate_revisions
= True
1164 search_fields
= ('nom', 'nom_feminin', )
1165 list_display
= ('nom', 'categorie_emploi', 'derniere_modification')
1166 list_filter
= ('categorie_emploi', 'famille_professionnelle')
1170 'nom', 'nom_feminin', 'is_responsable', 'categorie_emploi',
1171 'famille_professionnelle',
1177 class TypeRemunerationAdmin(reversion
.VersionAdmin
, ArchivableAdmin
,
1178 DerniereModificationAdmin
, BaseAdmin
):
1179 ignore_duplicate_revisions
= True
1181 'nom', 'type_paiement', 'nature_remuneration', '_archive',
1182 'derniere_modification'
1184 list_filter
= ('archive', )
1188 'nom', 'type_paiement', 'nature_remuneration', 'archive'
1194 class TypeRevalorisationAdmin(reversion
.VersionAdmin
,
1195 DerniereModificationAdmin
, BaseAdmin
):
1196 ignore_duplicate_revisions
= True
1197 list_display
= ('nom', 'derniere_modification')
1199 (None, {'fields': ('nom',)}),
1203 class ValeurPointAdmin(reversion
.VersionAdmin
, DerniereModificationAdmin
,
1205 ignore_duplicate_revisions
= True
1207 '_devise_code', '_devise_nom', 'annee', 'implantation',
1208 'valeur', 'derniere_modification'
1210 list_filter
= ('annee', 'devise', 'implantation__region', )
1212 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee')}),
1215 def _devise_code(self
, obj
):
1216 return obj
.devise
.code
1217 _devise_code
.short_description
= "Code de la devise"
1219 def _devise_nom(self
, obj
):
1220 return obj
.devise
.nom
1221 _devise_nom
.short_description
= "Nom de la devise"
1224 class ImplantationProxyAdmin(BaseAdmin
):
1225 list_display
= ('nom', '_organigramme')
1228 def __init__(self
, *args
, **kwargs
):
1229 super(ImplantationProxyAdmin
, self
).__init__(*args
, **kwargs
)
1230 self
.list_display_links
= (None, )
1232 def has_add_permission(self
, obj
):
1235 def has_change_permission(self
, request
, obj
=None):
1236 user_groups
= [g
.name
for g
in request
.user
.groups
.all()]
1237 if groups
.CORRESPONDANT_RH
in user_groups
or \
1238 groups
.ADMINISTRATEURS
in user_groups
or \
1239 groups
.DIRECTEUR_DE_BUREAU
in user_groups
or \
1240 in_drh_or_admin(request
.user
):
1244 def _organigramme(self
, obj
):
1245 return '<a href="%s"><strong>Organigramme</strong></a>' % (
1246 reverse('rho_implantation', args
=(obj
.id,))
1248 _organigramme
.allow_tags
= True
1249 _organigramme
.short_description
= "Organigramme"
1252 class RegionProxyAdmin(BaseAdmin
):
1253 list_display
= ('nom', '_organigramme')
1256 def __init__(self
, *args
, **kwargs
):
1257 super(RegionProxyAdmin
, self
).__init__(*args
, **kwargs
)
1258 self
.list_display_links
= (None, )
1260 def has_add_permission(self
, obj
):
1263 def has_change_permission(self
, request
, obj
=None):
1264 user_groups
= [g
.name
for g
in request
.user
.groups
.all()]
1265 if groups
.CORRESPONDANT_RH
in user_groups
or \
1266 groups
.ADMINISTRATEURS
in user_groups
or \
1267 groups
.DIRECTEUR_DE_BUREAU
in user_groups
or \
1268 in_drh_or_admin(request
.user
):
1272 def _organigramme(self
, obj
):
1273 return """<a href="%s"><strong>Organigramme</strong></a>""" % (
1274 reverse('rho_region', args
=(obj
.id,))
1276 _organigramme
.allow_tags
= True
1277 _organigramme
.short_description
= "Organigramme"
1280 admin
.site
.register(rh
.Classement
, ClassementAdmin
)
1281 admin
.site
.register(rh
.Devise
, DeviseAdmin
)
1282 admin
.site
.register(rh
.Dossier
, DossierAdmin
)
1283 admin
.site
.register(EmployeProxy
, EmployeProxyAdmin
)
1284 admin
.site
.register(ServiceProxy
, ServiceProxyAdmin
)
1285 admin
.site
.register(rh
.Employe
, EmployeAdmin
)
1286 admin
.site
.register(rh
.CategorieEmploi
, CategorieEmploiAdmin
)
1287 admin
.site
.register(rh
.FamilleProfessionnelle
)
1288 admin
.site
.register(rh
.OrganismeBstg
, OrganismeBstgAdmin
)
1289 admin
.site
.register(rh
.Poste
, PosteAdmin
)
1290 admin
.site
.register(
1291 rh
.ResponsableImplantationProxy
, ResponsableImplantationAdmin
1293 admin
.site
.register(rh
.Service
, ServiceAdmin
)
1294 admin
.site
.register(rh
.Statut
, StatutAdmin
)
1295 admin
.site
.register(rh
.TauxChange
, TauxChangeAdmin
)
1296 admin
.site
.register(rh
.TypeContrat
, TypeContratAdmin
)
1297 admin
.site
.register(rh
.TypePoste
, TypePosteAdmin
)
1298 admin
.site
.register(rh
.TypeRemuneration
, TypeRemunerationAdmin
)
1299 admin
.site
.register(rh
.TypeRevalorisation
, TypeRevalorisationAdmin
)
1300 admin
.site
.register(rh
.ValeurPoint
, ValeurPointAdmin
)
1301 admin
.site
.register(ImplantationProxy
, ImplantationProxyAdmin
)
1302 admin
.site
.register(RegionProxy
, RegionProxyAdmin
)