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