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