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