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