distinct
[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):
5c9d5e55 591 link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /> %s</a>""" % \
8f3ca727 592 (reverse('poste_apercu', args=(poste.id,)),
822a2c33 593 settings.STATIC_URL,
5c9d5e55 594 poste.id,
8f3ca727
JPC
595 )
596 return link
597 _apercu.allow_tags = True
5c9d5e55
OL
598 _apercu.short_description = 'Poste __#'
599 _apercu.admin_order_field = 'id'
8f3ca727 600
c5964dc2
OL
601 def _service(self, obj):
602 return obj.service
53ae644d
OL
603
604 def _nom(self, poste):
b10920ea 605 link = u"""<a href="%s" title="Modifier le poste"><strong>%s</strong></a>""" % \
8f3ca727 606 (reverse('admin:rh_poste_change', args=(poste.id,)),
53ae644d 607 poste.nom,
53ae644d
OL
608 )
609 return link
610 _nom.allow_tags = True
611 _nom.short_description = u'Nom'
612 _nom.admin_order_field = 'nom'
613
614 def _occupe_par(self, obj):
615 """Formatte la méthode Poste.occupe_par() pour l'admin"""
15c5f55a 616 output = u"Vacant"
3195667e 617 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
954ead19 618 return u"s/o"
53ae644d
OL
619 employes = obj.occupe_par()
620 if employes:
621 l = []
622 for e in employes:
b10920ea
JPC
623 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>" % \
624 (reverse('employe_apercu', args=(e.id,)),
822a2c33 625 settings.STATIC_URL,
b10920ea
JPC
626 reverse('admin:rh_employe_change', args=(e.id,)),
627 e
628 )
53ae644d
OL
629 l.append(link)
630 output = "\n<br />".join(l)
631 return output
632 _occupe_par.allow_tags = True
633 _occupe_par.short_description = "Occupé par"
634
635 def save_formset(self, request, form, formset, change):
636 instances = formset.save(commit=False)
637 for instance in instances:
638 if instance.__class__ == rh.PosteCommentaire:
639 instance.owner = request.user
02e69aa2 640 instance.date_creation = datetime.datetime.now()
53ae644d
OL
641 instance.save()
642 formset.save_m2m()
643
644
645class PosteCommentaireAdmin(admin.ModelAdmin):
646 pass
647
648
649class PosteFinancementAdmin(admin.ModelAdmin):
650 pass
651
652
653class PostePieceAdmin(admin.ModelAdmin):
654 fk_name = 'poste'
655
656
657class RemunerationAdmin(admin.ModelAdmin):
658 pass
659
660
661class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
662 fieldsets = AUFMetadataAdminMixin.fieldsets + (
663 (None, {
664 'fields': ('employe', 'implantation', ),
665 }),
666 )
667
668
669class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
f614ca5c 670 list_display = ('nom', 'date_modification', 'user_modification', )
53ae644d
OL
671 fieldsets = AUFMetadataAdminMixin.fieldsets + (
672 (None, {
673 'fields': ('nom', ),
674 }),
675 )
676
677class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
f614ca5c 678 list_display = ('code', 'nom', 'date_modification', 'user_modification', )
53ae644d
OL
679 fieldsets = AUFMetadataAdminMixin.fieldsets + (
680 (None, {
681 'fields': ('code', 'nom', ),
682 }),
683 )
684
685class TauxChangeAdmin(admin.ModelAdmin):
c5964dc2 686 list_display = ('taux', 'devise', 'annee', 'date_modification', 'user_modification', )
53ae644d
OL
687 list_filter = ('devise', )
688 fieldsets = AUFMetadataAdminMixin.fieldsets + (
689 (None, {
690 'fields': ('taux', 'devise', 'annee', ),
691 }),
692 )
693
694class TypeContratAdmin(admin.ModelAdmin):
f614ca5c 695 list_display = ('nom', 'nom_long', 'date_modification', 'user_modification', )
53ae644d
OL
696 fieldsets = AUFMetadataAdminMixin.fieldsets + (
697 (None, {
698 'fields': ('nom', 'nom_long', ),
699 }),
700 )
701
702
703class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
704 search_fields = ('nom', 'nom_feminin', )
f614ca5c 705 list_display = ('nom', 'famille_emploi', 'date_modification', 'user_modification', )
53ae644d
OL
706 list_filter = ('famille_emploi', )
707 fieldsets = AUFMetadataAdminMixin.fieldsets + (
708 (None, {
709 'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi', )
710 }),
711 )
712
713
714class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
f614ca5c 715 list_display = ('nom', 'type_paiement', 'nature_remuneration', 'date_modification', 'user_modification', )
53ae644d
OL
716 fieldsets = AUFMetadataAdminMixin.fieldsets + (
717 (None, {
718 'fields': ('nom', 'type_paiement', 'nature_remuneration', )
719 }),
720 )
721
722
723class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
f614ca5c 724 list_display = ('nom', 'date_modification', 'user_modification', )
53ae644d
OL
725 fieldsets = AUFMetadataAdminMixin.fieldsets + (
726 (None, {
727 'fields': ('nom', )
728 }),
729 )
730
731
732class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
c5964dc2
OL
733 list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur', 'date_modification', 'user_modification', )
734 list_filter = ('annee', 'devise', )
53ae644d
OL
735 fieldsets = AUFMetadataAdminMixin.fieldsets + (
736 (None, {
737 'fields': ('valeur', 'devise', 'implantation', 'annee', )
738 }),
739 )
740
741 def _devise_code(self, obj):
742 return obj.devise.code
743 _devise_code.short_description = "Code de la devise"
744
745 def _devise_nom(self, obj):
746 return obj.devise.nom
747 _devise_nom.short_description = "Nom de la devise"
748
749
750admin.site.register(rh.Classement, ClassementAdmin)
751admin.site.register(rh.Devise, DeviseAdmin)
752admin.site.register(rh.Dossier, DossierAdmin)
753admin.site.register(rh.Employe, EmployeAdmin)
754admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
755admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
756admin.site.register(rh.Poste, PosteAdmin)
757admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
758admin.site.register(rh.Service, ServiceAdmin)
c5964dc2 759admin.site.register(rh.Statut, StatutAdmin)
53ae644d 760admin.site.register(rh.TauxChange, TauxChangeAdmin)
c5964dc2 761admin.site.register(rh.TypeContrat, TypeContratAdmin)
53ae644d
OL
762admin.site.register(rh.TypePoste, TypePosteAdmin)
763admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
764admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
765admin.site.register(rh.ValeurPoint, ValeurPointAdmin)