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