Normalisation de la liste pour employes, dossiers et postes
[auf_rh_dae.git] / project / rh / admin.py
1 # -*- encoding: utf-8 -*-
2
3 from collections import defaultdict
4 import datetime
5
6 from django.db import models
7 from django import forms
8 from django.core.urlresolvers import reverse
9 from django.contrib import admin
10 from django.contrib.admin.views.main import ChangeList as DjangoChangeList
11 from django.conf import settings
12 from django.db.models import Q
13 from django.template.defaultfilters import date
14 from ajax_select import make_ajax_form
15 from auf.django.metadata.admin import AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, AUF_METADATA_READONLY_FIELDS
16 from forms import ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect
17 from dae.utils import get_employe_from_user
18 from groups import grp_drh
19 import models as rh
20 import filters
21
22 ################################################################################
23 # FILTRAGE PAR DATE
24 ################################################################################
25 class DateRangeMixin(object):
26 """
27 Mixin pour que le model admin utilise le changelist trafiqué permettant de filter par range
28 non strict.
29 Par défaut, le filtrage est configuré sur aujourd'hui, soit les actifs
30 """
31 date_borne_gauche = 'date_debut'
32 date_borne_droite = 'date_fin'
33 def get_changelist(self, request, **kwargs):
34 if request.META.has_key('HTTP_REFERER'):
35 referer = request.META['HTTP_REFERER']
36 referer = "/".join(referer.split('/')[3:])
37 referer = "/%s" % referer.split('?')[0]
38 change_list_view = 'admin:%s_%s_changelist' % (self.model._meta.app_label, self.model.__name__.lower())
39 if referer != reverse(change_list_view):
40 params = request.GET.copy()
41 today = datetime.date.today()
42 params.update({'%s__gte' % self.date_borne_gauche : str(today), '%s__lte' % self.date_borne_droite : str(today) })
43 request.GET = params
44 return ChangeList
45
46 class ChangeList(DjangoChangeList):
47
48 def __init__(self, *args, **kwargs):
49 super(ChangeList, self).__init__(*args, **kwargs)
50
51 def get_query_set(self):
52 old = self.params.copy()
53 date_debut = None
54 date_fin = None
55 for k, v in self.params.items():
56 if 'date_debut' in k:
57 prefix_debut = "".join(k.split('date_debut')[0:-1]) + 'date_debut'
58 date_debut = v
59 del self.params[k]
60 elif 'date_fin' in k:
61 prefix_fin = "".join(k.split('date_fin')[0:-1]) + 'date_fin'
62 date_fin = v
63 del self.params[k]
64 qs = super(ChangeList, self).get_query_set()
65
66 if date_fin is None and date_debut is not None:
67 date_fin = date_debut
68 prefix_fin = prefix_debut.replace('debut', 'fin')
69 if date_debut is None and date_fin is not None:
70 date_debut = date_fin
71 prefix_debut = prefix_fin.replace('fin', 'debut')
72
73 if date_debut is not None and date_fin is not None:
74 q_left = (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__lte' % prefix_debut : date_debut})) & (Q(**{'%s__gte' % prefix_fin : date_debut}) & Q(**{'%s__lte' % prefix_fin : date_fin}))
75 q_right = (Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__gte' % prefix_fin : date_fin})) & (Q(**{'%s__gte' % prefix_debut : date_debut}) & Q(**{'%s__lte' % prefix_debut : date_fin}))
76 q_both = Q(**{'%s__isnull' % prefix_fin : True}) | Q(**{'%s__lte' % prefix_fin : date_fin}) & (Q(**{'%s__isnull' % prefix_debut : True}) | Q(**{'%s__gte' % prefix_debut : date_debut}))
77 q_non_supprime = Q(**{'%s__exact' % prefix_debut.replace('date_debut', 'supprime') : False})
78 q = (q_left | q_right | q_both) & q_non_supprime
79 qs = qs.filter(q).distinct()
80
81 self.params = old
82 return qs
83
84 ################################################################################
85
86 # Override of the InlineModelAdmin to support the link in the tabular inline
87 class LinkedInline(admin.options.InlineModelAdmin):
88 template = "admin/linked.html"
89 admin_model_path = None
90
91 def __init__(self, *args):
92 super(LinkedInline, self).__init__(*args)
93 if self.admin_model_path is None:
94 self.admin_model_path = self.model.__name__.lower()
95
96
97 class ProtectRegionMixin(object):
98
99 def queryset(self, request):
100 from dae.workflow import grp_drh, grp_correspondants_rh
101 qs = super(ProtectRegionMixin, self).queryset(request)
102
103 if request.user.is_superuser:
104 return qs
105
106 user_groups = request.user.groups.all()
107
108 if grp_drh in user_groups:
109 return qs
110
111 if grp_correspondants_rh in user_groups:
112 employe = get_employe_from_user(request.user)
113 q = Q(**{self.model.prefix_implantation: employe.implantation.region})
114 qs = qs.filter(q).distinct()
115 return qs
116 return qs.none()
117
118 def has_change_permission(self, request, obj=None):
119 user_groups = request.user.groups.all()
120
121 # Lock pour autoriser uniquement les DRH à utiliser RH
122 if not request.user.is_superuser and not grp_drh in user_groups:
123 return False
124
125 if len(user_groups) == 0 and not request.user.is_superuser:
126 return False
127
128 if obj is None:
129 return True
130 ids = [o.id for o in self.queryset(request)]
131 return obj.id in ids
132
133
134 # Inlines
135
136 class ReadOnlyInlineMixin(object):
137 def get_readonly_fields(self, request, obj=None):
138 return [f.name for f in self.model._meta.fields if f.name not in AUF_METADATA_READONLY_FIELDS]
139
140
141 class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
142 model = rh.AyantDroit
143 form = AyantDroitForm
144 extra = 0
145
146 fieldsets = (
147 (None, {
148 'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', 'lien_parente', )
149 }),
150 )
151
152
153 class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
154 readonly_fields = ('owner', )
155 model = rh.AyantDroitCommentaire
156 extra = 1
157
158
159 class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
160 form = ContratForm
161 model = rh.Contrat
162 extra = 1
163
164
165 class DossierROInline(ReadOnlyInlineMixin, LinkedInline):
166 template = "admin/rh/dossier/linked.html"
167 exclude = AUF_METADATA_READONLY_FIELDS
168 model = rh.Dossier
169 extra = 0
170 can_delete = False
171
172 def has_add_permission(self, request=None):
173 return False
174
175 def has_change_permission(self, request, obj=None):
176 return False
177
178 def has_delete_permission(self, request, obj=None):
179 return False
180
181
182 class DossierCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
183 readonly_fields = ('owner', )
184 model = rh.DossierCommentaire
185 extra = 1
186
187
188 class DossierPieceInline(admin.TabularInline):
189 model = rh.DossierPiece
190 extra = 4
191
192
193 class EmployeInline(admin.TabularInline):
194 model = rh.Employe
195
196 class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
197 readonly_fields = ('owner', )
198 model = rh.EmployeCommentaire
199 extra = 1
200
201
202 class EmployePieceInline(admin.TabularInline):
203 model = rh.EmployePiece
204 extra = 4
205
206
207 class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
208 readonly_fields = ('owner', )
209 model = rh.PosteCommentaire
210 extra = 1
211
212
213 class PosteFinancementInline(admin.TabularInline):
214 model = rh.PosteFinancement
215
216
217 class PostePieceInline(admin.TabularInline):
218 model = rh.PostePiece
219
220
221 class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
222 model = rh.Remuneration
223 extra = 1
224
225
226 class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
227 pass
228
229
230 class TypePosteInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
231 model = rh.TypePoste
232
233
234 class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
235 model = rh.PosteComparaison
236
237
238 class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
239 list_display = ('_classement', '_date_modification', 'user_modification', )
240 fieldsets = AUFMetadataAdminMixin.fieldsets + (
241 (None, {
242 'fields': ('type', 'echelon', 'degre', 'coefficient', )
243 }),
244 )
245
246 def _classement(self, obj):
247 return unicode(obj)
248 _classement.short_description = u"Classement"
249
250 def _date_modification(self, obj):
251 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
252 _date_modification.short_description = u'date modification'
253 _date_modification.admin_order_field = 'date_modification'
254
255 class CommentaireAdmin(admin.ModelAdmin):
256 pass
257
258
259 class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
260 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
261 fieldsets = AUFMetadataAdminMixin.fieldsets + (
262 (None, {
263 'fields': ('code', 'nom', ),
264 }),
265 )
266
267 def _date_modification(self, obj):
268 return date(obj.date_modification) 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 class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
273 alphabet_filter = 'employe__nom'
274 search_fields = ('employe__nom', 'employe__prenom', 'poste__nom', 'poste__nom_feminin')
275 list_display = (
276 '_id',
277 '_apercu',
278 '_nom',
279 '_poste',
280 '_employe',
281 '_date_debut',
282 '_date_fin',
283 '_date_modification',
284 'user_modification',
285 )
286 list_display_links = ('_nom',)
287 list_filter = (
288 'poste__implantation__region',
289 'poste__implantation',
290 'poste__type_poste__famille_emploi',
291 'poste__type_poste',
292 'rh_contrats__type_contrat',
293 'date_debut',
294 'date_fin',
295 )
296 inlines = (DossierPieceInline, ContratInline,
297 RemunerationInline,
298 DossierCommentaireInline,
299 )
300 fieldsets = AUFMetadataAdminMixin.fieldsets + (
301 (None, {
302 'fields': ('employe', 'poste', 'statut', 'organisme_bstg',)
303 }),
304 ('Recrutement', {
305 'fields': ('statut_residence', 'remplacement', 'remplacement_de', )
306 }),
307 ('Rémunération', {
308 'fields': ('classement', ('regime_travail', 'regime_travail_nb_heure_semaine'),)
309 }),
310 ('Occupation du Poste par cet Employe', {
311 'fields': (('date_debut', 'date_fin'), )
312 }),
313 )
314 form = make_ajax_form(rh.Dossier, {
315 'employe' : 'employes',
316 'poste' : 'postes',
317 'remplacement_de' : 'dossiers',
318 })
319
320 def lookup_allowed(self, key, value):
321 if key in (
322 'employe__nom__istartswith',
323 'poste__implantation__region__id__exact',
324 'poste__implantation__id__exact',
325 'poste__type_poste__id__exact',
326 'poste__type_poste__famille_emploi__id__exact',
327 'rh_contrats__type_contrat__id__exact',
328 'date_debut__gte',
329 'date_debut__isnull',
330 'date_fin__lte',
331 'date_fin__isnull',
332 ):
333 return True
334
335 def _id(self, obj):
336 return obj.id
337 _id.short_description = u"#"
338 _id.admin_order_field = "id"
339
340 def _nom(self, obj):
341 return "%d : %s %s" % \
342 (obj.date_debut.year, obj.employe.nom.upper(), obj.employe.prenom)
343 _nom.allow_tags = True
344 _nom.short_description = u"Dossier"
345
346
347 def _apercu(self, d):
348 apercu_link = u"""<a title="Aperçu du dossier" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
349 (reverse('dossier_apercu', args=(d.id,)),
350 settings.STATIC_URL,
351 )
352 return apercu_link
353 _apercu.allow_tags = True
354 _apercu.short_description = u""
355
356
357 def _date_debut(self, obj):
358 return date(obj.date_debut)
359
360 _date_debut.short_description = u'Occupation début'
361 _date_debut.admin_order_field = 'date_debut'
362
363 def _date_fin(self, obj):
364 return date(obj.date_fin)
365 _date_fin.short_description = u'Occupation fin'
366 _date_fin.admin_order_field = 'date_fin'
367
368
369 def _date_modification(self, obj):
370 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
371 _date_modification.short_description = u'date modification'
372 _date_modification.admin_order_field = 'date_modification'
373
374 def _poste(self, dossier):
375 link = u"""<a title="Aperçu du poste" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a> <a href="%s" title="Modifier le poste">%s</a>""" % \
376 (reverse('poste_apercu', args=(dossier.poste.id,)),
377 settings.STATIC_URL,
378 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
379 dossier.poste,
380 )
381 return link
382 _poste.allow_tags = True
383 _poste.short_description = u'Poste'
384 _poste.admin_order_field = 'poste__nom'
385
386 def _employe(self, obj):
387 employe = obj.employe
388 view_link = reverse('employe_apercu', args=(employe.id,))
389 edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
390
391 style = ""
392 view = u"""<a href="%s" title="Aperçu l'employé" onclick="return showAddAnotherPopup(this);"><img src="%simg/loupe.png" /></a>""" % (view_link, settings.STATIC_URL,)
393 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
394 (view, edit_link, style, employe)
395 _employe.allow_tags = True
396 _employe.short_description = u"Employé"
397 _employe.admin_order_field = "employe__nom"
398
399 def save_formset(self, request, form, formset, change):
400 instances = formset.save(commit=False)
401 for instance in instances:
402 if instance.__class__ == rh.DossierCommentaire:
403 instance.owner = request.user
404 instance.date_creation = datetime.datetime.now()
405 instance.save()
406
407
408 class DossierPieceAdmin(admin.ModelAdmin):
409 pass
410
411
412 class DossierCommentaireAdmin(admin.ModelAdmin):
413 pass
414
415
416 class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin,):
417 alphabet_filter = 'nom'
418 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
419 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
420 ordering = ('nom', )
421 form = EmployeAdminForm
422 list_display = ('_id', '_apercu', '_nom', '_dossiers', '_date_modification', 'user_modification', )
423 list_display_links = ('_nom',)
424 list_filter = ('rh_dossiers__poste__implantation__region', 'rh_dossiers__poste__implantation', 'nb_postes', 'rh_dossiers__date_debut', 'rh_dossiers__date_fin')
425 date_borne_gauche = 'rh_dossiers__date_debut'
426 date_borne_droite = 'rh_dossiers__date_fin'
427 inlines = (AyantDroitInline,
428 DossierROInline,
429 EmployePieceInline,
430 EmployeCommentaireInline)
431 fieldsets = AUFMetadataAdminMixin.fieldsets + (
432 ('Identification', {
433 'fields': (('nom', 'prenom'), ('nom_affichage', 'genre'), 'nationalite', 'date_naissance', )
434 }),
435 ('Informations personnelles', {
436 'fields': ('situation_famille', 'date_entree', )
437 }),
438 ('Coordonnées', {
439 'fields': (('tel_domicile', 'tel_cellulaire'), ('adresse', 'ville'), ('code_postal', 'province'), 'pays', )
440 }),
441 )
442
443 def _apercu(self, obj):
444 return u"""<a title="Aperçu de l'employé" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
445 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
446 _apercu.allow_tags = True
447 _apercu.short_description = u""
448
449 def _nom(self, obj):
450 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
451 return u"""<a href='%s'><strong>%s</strong></a>""" % \
452 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
453 _nom.allow_tags = True
454 _nom.short_description = u"Employé"
455 _nom.admin_order_field = "nom"
456
457 def _id(self, obj):
458 return obj.id
459 _id.short_description = u"#"
460 _id.admin_order_field = "id"
461
462 def _date_modification(self, obj):
463 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
464 _date_modification.short_description = u'date modification'
465 _date_modification.admin_order_field = 'date_modification'
466
467 def _dossiers(self, obj):
468 l = []
469 for d in obj.rh_dossiers.all().order_by('-date_debut'):
470 apercu = u"""<a title="Aperçu du dossier" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du dossier"><img src="%simg/loupe.png" /></a>""" % \
471 (reverse('dossier_apercu', args=(d.id,)), settings.STATIC_URL,)
472 link = u"""<li>%s<a href='%s'>%s : %s</a></li>""" % \
473 (apercu,
474 reverse('admin:rh_dossier_change', args=(d.id,)),
475 d.date_debut.year,
476 d.poste,
477 )
478
479 # Dossier terminé en gris non cliquable
480 if d.date_fin is not None:
481 link = u"""<li style="color: grey">%s : %s</li>""" % \
482 (d.date_debut.year,
483 d.poste,
484 )
485
486 l.append(link)
487 return "<ul>%s</ul>" % "\n".join(l)
488 _dossiers.allow_tags = True
489 _dossiers.short_description = u"Dossiers"
490
491 def queryset(self, request):
492 qs = super(EmployeAdmin, self).queryset(request)
493 return qs.select_related(depth=1).order_by('nom')
494
495 def save_formset(self, request, form, formset, change):
496 instances = formset.save(commit=False)
497 for instance in instances:
498 if instance.__class__ == rh.EmployeCommentaire:
499 instance.owner = request.user
500 instance.date_creation = datetime.datetime.now()
501 instance.save()
502
503
504
505 class EmployeCommentaireAdmin(admin.ModelAdmin):
506 pass
507
508
509 class EmployePieceAdmin(admin.ModelAdmin):
510 pass
511
512
513 class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
514 list_display = ('nom', '_date_modification', 'user_modification', )
515 inlines = (TypePosteInline,)
516 fieldsets = AUFMetadataAdminMixin.fieldsets + (
517 (None, {
518 'fields': ('nom', )
519 }),
520 )
521
522 def _date_modification(self, obj):
523 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
524 _date_modification.short_description = u'date modification'
525 _date_modification.admin_order_field = 'date_modification'
526
527 class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
528 search_fields = ('nom',)
529 list_display = ('nom', 'type', 'pays', '_date_modification', 'user_modification', )
530 list_filter = ('type', )
531 inlines = (DossierROInline,)
532 fieldsets = AUFMetadataAdminMixin.fieldsets + (
533 (None, {
534 'fields': ('nom', 'type', 'pays', )
535 }),
536 )
537
538 def _date_modification(self, obj):
539 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
540 _date_modification.short_description = u'date modification'
541 _date_modification.admin_order_field = 'date_modification'
542
543
544 class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
545 form = make_ajax_form(rh.Poste, {
546 'implantation' : 'implantations',
547 'type_poste' : 'typepostes',
548 'responsable' : 'postes',
549 'valeur_point_min' : 'valeurpoints',
550 'valeur_point_max' : 'valeurpoints',
551 })
552 alphabet_filter = 'nom'
553 search_fields = ('nom',
554 'implantation__code',
555 'implantation__nom',
556 'implantation__region__code',
557 'implantation__region__nom',
558 'rh_dossiers__employe__nom',
559 'rh_dossiers__employe__prenom',
560 )
561 list_display = (
562 '_id',
563 '_apercu',
564 '_nom',
565 '_occupe_par',
566 'implantation',
567 '_service',
568 'date_debut',
569 'date_fin',
570 '_date_modification',
571 'user_modification',
572 )
573 list_filter = (
574 'implantation__region',
575 'implantation',
576 'service',
577 'type_poste',
578 'type_poste__famille_emploi',
579 'date_debut',
580 'date_fin',
581 'vacant',
582 )
583 list_display_links = ('_nom',)
584 fieldsets = AUFMetadataAdminMixin.fieldsets + (
585 (None, {
586 'fields': (('nom', 'nom_feminin'), 'implantation', 'type_poste',
587 'service', 'responsable')
588 }),
589 ('Contrat', {
590 'fields': (('regime_travail', 'regime_travail_nb_heure_semaine'), )
591 }),
592 ('Recrutement', {
593 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)
594 }),
595 ('Rémunération', {
596 'fields': (('classement_min', 'valeur_point_min', 'devise_min', 'salaire_min', 'indemn_min', 'autre_min', ),
597 ('classement_max', 'valeur_point_max' ,'devise_max', 'salaire_max', 'indemn_max', 'autre_max', ),
598 )
599 }),
600 ('Comparatifs de rémunération', {
601 'fields': ('devise_comparaison',
602 ('comp_locale_min', 'comp_locale_max'),
603 ('comp_universite_min', 'comp_universite_max'),
604 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
605 ('comp_ong_min', 'comp_ong_max'),
606 ('comp_autre_min', 'comp_autre_max'))
607 }),
608 ('Justification', {
609 'fields': ('justification',)
610 }),
611 ('Autres Méta-données', {
612 'fields': ('date_debut', 'date_fin')
613 }),
614 )
615
616 inlines = (PosteFinancementInline,
617 PostePieceInline,
618 DossierROInline,
619 PosteComparaisonInline,
620 PosteCommentaireInline, )
621
622
623 def lookup_allowed(self, key, value):
624 if key in (
625 'date_debut__gte',
626 'date_debut__isnull',
627 'date_fin__lte',
628 'date_fin__isnull',
629 'implantation__region__id__exact',
630 'implantation__id__exact',
631 'type_poste__id__exact',
632 'type_poste__famille_emploi__id__exact',
633 'service__id__exact',
634 'vacant__exact',
635 ):
636 return True
637
638
639 def _apercu(self, poste):
640 view_link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /></a>""" % \
641 (reverse('poste_apercu', args=(poste.id,)),
642 settings.STATIC_URL,
643 )
644 return view_link
645 _apercu.allow_tags = True
646 _apercu.short_description = ''
647
648 def _id(self, obj):
649 return "%s" % obj.id
650 _id.short_description = '#'
651 _id.admin_order_field = 'id'
652
653 def _service(self, obj):
654 return obj.service
655
656 def _nom(self, poste):
657 return """<a href="%s">%s</a>""" % \
658 (reverse('admin:rh_poste_change', args=(poste.id,)),
659 poste.nom
660 )
661 _nom.allow_tags = True
662 _nom.short_description = u'Nom'
663 _nom.admin_order_field = 'nom'
664
665 def _date_modification(self, obj):
666 return date(obj.date_modification)
667 _date_modification.short_description = u'date modification'
668 _date_modification.admin_order_field = 'date_modification'
669
670 def _occupe_par(self, obj):
671 """Formatte la méthode Poste.occupe_par() pour l'admin"""
672 output = u"Vacant"
673 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
674 return u"s/o"
675 employes = obj.occupe_par()
676 if employes:
677 l = []
678 for e in employes:
679 link = "<a href='%s' title='Aperçu de l\'employer' onclick='return showAddAnotherPopup(this)'><img src='%simg/loupe.png' /></a> <a href='%s'>%s</a>" % \
680 (reverse('employe_apercu', args=(e.id,)),
681 settings.STATIC_URL,
682 reverse('admin:rh_employe_change', args=(e.id,)),
683 e
684 )
685 l.append(link)
686 output = "\n<br />".join(l)
687 return output
688 _occupe_par.allow_tags = True
689 _occupe_par.short_description = "Occupé par"
690
691 def save_formset(self, request, form, formset, change):
692 instances = formset.save(commit=False)
693 for instance in instances:
694 if instance.__class__ == rh.PosteCommentaire:
695 instance.owner = request.user
696 instance.date_creation = datetime.datetime.now()
697 instance.save()
698 formset.save_m2m()
699
700
701 class PosteCommentaireAdmin(admin.ModelAdmin):
702 pass
703
704
705 class PosteFinancementAdmin(admin.ModelAdmin):
706 pass
707
708
709 class PostePieceAdmin(admin.ModelAdmin):
710 fk_name = 'poste'
711
712
713 class RemunerationAdmin(admin.ModelAdmin):
714 pass
715
716
717 class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
718 fieldsets = AUFMetadataAdminMixin.fieldsets + (
719 (None, {
720 'fields': ('employe', 'implantation', ),
721 }),
722 )
723
724
725 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
726 list_display = ('nom', '_date_modification', 'user_modification', )
727 fieldsets = AUFMetadataAdminMixin.fieldsets + (
728 (None, {
729 'fields': ('nom', ),
730 }),
731 )
732
733 def _date_modification(self, obj):
734 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
735 _date_modification.short_description = u'date modification'
736 _date_modification.admin_order_field = 'date_modification'
737
738
739 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
740 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
741 fieldsets = AUFMetadataAdminMixin.fieldsets + (
742 (None, {
743 'fields': ('code', 'nom', ),
744 }),
745 )
746
747 def _date_modification(self, obj):
748 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
749 _date_modification.short_description = u'date modification'
750 _date_modification.admin_order_field = 'date_modification'
751
752 class TauxChangeAdmin(admin.ModelAdmin):
753 list_display = ('taux', 'devise', 'annee', '_date_modification', 'user_modification', )
754 list_filter = ('devise', )
755 fieldsets = AUFMetadataAdminMixin.fieldsets + (
756 (None, {
757 'fields': ('taux', 'devise', 'annee', ),
758 }),
759 )
760
761 def _date_modification(self, obj):
762 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
763 _date_modification.short_description = u'date modification'
764 _date_modification.admin_order_field = 'date_modification'
765
766 class TypeContratAdmin(admin.ModelAdmin):
767 list_display = ('nom', 'nom_long', '_date_modification', 'user_modification', )
768 fieldsets = AUFMetadataAdminMixin.fieldsets + (
769 (None, {
770 'fields': ('nom', 'nom_long', ),
771 }),
772 )
773
774 def _date_modification(self, obj):
775 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
776 _date_modification.short_description = u'date modification'
777 _date_modification.admin_order_field = 'date_modification'
778
779
780 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
781 search_fields = ('nom', 'nom_feminin', )
782 list_display = ('nom', 'famille_emploi', '_date_modification', 'user_modification', )
783 list_filter = ('famille_emploi', )
784 fieldsets = AUFMetadataAdminMixin.fieldsets + (
785 (None, {
786 'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi', )
787 }),
788 )
789
790 def _date_modification(self, obj):
791 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
792 _date_modification.short_description = u'date modification'
793 _date_modification.admin_order_field = 'date_modification'
794
795
796 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
797 list_display = ('nom', 'type_paiement', 'nature_remuneration', '_date_modification', 'user_modification', )
798 fieldsets = AUFMetadataAdminMixin.fieldsets + (
799 (None, {
800 'fields': ('nom', 'type_paiement', 'nature_remuneration', )
801 }),
802 )
803
804 def _date_modification(self, obj):
805 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
806 _date_modification.short_description = u'date modification'
807 _date_modification.admin_order_field = 'date_modification'
808
809
810 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
811 list_display = ('nom', '_date_modification', 'user_modification', )
812 fieldsets = AUFMetadataAdminMixin.fieldsets + (
813 (None, {
814 'fields': ('nom', )
815 }),
816 )
817
818 def _date_modification(self, obj):
819 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
820 _date_modification.short_description = u'date modification'
821 _date_modification.admin_order_field = 'date_modification'
822
823
824 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
825 list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur', '_date_modification', 'user_modification', )
826 list_filter = ('annee', 'devise', )
827 fieldsets = AUFMetadataAdminMixin.fieldsets + (
828 (None, {
829 'fields': ('valeur', 'devise', 'implantation', 'annee', )
830 }),
831 )
832
833 def _date_modification(self, obj):
834 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
835 _date_modification.short_description = u'date modification'
836 _date_modification.admin_order_field = 'date_modification'
837
838 def _devise_code(self, obj):
839 return obj.devise.code
840 _devise_code.short_description = "Code de la devise"
841
842 def _devise_nom(self, obj):
843 return obj.devise.nom
844 _devise_nom.short_description = "Nom de la devise"
845
846
847 admin.site.register(rh.Classement, ClassementAdmin)
848 admin.site.register(rh.Devise, DeviseAdmin)
849 admin.site.register(rh.Dossier, DossierAdmin)
850 admin.site.register(rh.Employe, EmployeAdmin)
851 admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
852 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
853 admin.site.register(rh.Poste, PosteAdmin)
854 admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
855 admin.site.register(rh.Service, ServiceAdmin)
856 admin.site.register(rh.Statut, StatutAdmin)
857 admin.site.register(rh.TauxChange, TauxChangeAdmin)
858 admin.site.register(rh.TypeContrat, TypeContratAdmin)
859 admin.site.register(rh.TypePoste, TypePosteAdmin)
860 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
861 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
862 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)