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