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