fix vacant is null
[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_postes', '_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_postes(self, obj):
485 l = []
486 for d in obj.rh_dossiers.all().order_by('-date_debut'):
487 dossier = u"""<a title="Aperçu du dossier" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du dossier"><img src="%simg/loupe.png" /></a><a href="%s">Dossier</a>&nbsp;""" % \
488 ( reverse('dossier_apercu', args=(d.id,)),
489 settings.STATIC_URL,
490 reverse('admin:rh_dossier_change', args=(d.id,))
491 )
492
493 poste = u"""<a title="Aperçu du poste" href="%s" onclick="return showAddAnotherPopup(this);" title="Aperçu du poste"><img src="%simg/loupe.png" /></a><a href="%s">Poste</a>&nbsp;""" % \
494 ( reverse('poste_apercu', args=(d.poste.id,)),
495 settings.STATIC_URL,
496 reverse('admin:rh_poste_change', args=(d.poste.id,))
497 )
498 link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
499 (dossier, poste,
500 d.date_debut.year,
501 d.poste.id,
502 d.poste.nom,
503 )
504
505 # Dossier terminé en gris non cliquable
506 if d.date_fin is not None:
507 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
508 (d.date_debut.year,
509 d.poste.id,
510 d.poste.nom,
511 )
512
513 l.append(link)
514 return "<ul>%s</ul>" % "\n".join(l)
515 _dossiers_postes.allow_tags = True
516 _dossiers_postes.short_description = u"Dossiers et postes"
517
518 def queryset(self, request):
519 qs = super(EmployeAdmin, self).queryset(request)
520 return qs.select_related(depth=1).order_by('nom')
521
522 def save_formset(self, request, form, formset, change):
523 instances = formset.save(commit=False)
524 for instance in instances:
525 if instance.__class__ == rh.EmployeCommentaire:
526 instance.owner = request.user
527 instance.date_creation = datetime.datetime.now()
528 instance.save()
529
530
531
532 class EmployeCommentaireAdmin(admin.ModelAdmin):
533 pass
534
535
536 class EmployePieceAdmin(admin.ModelAdmin):
537 pass
538
539
540 class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
541 list_display = ('nom', '_date_modification', 'user_modification', )
542 inlines = (TypePosteInline,)
543 fieldsets = AUFMetadataAdminMixin.fieldsets + (
544 (None, {
545 'fields': ('nom', )
546 }),
547 )
548
549 def _date_modification(self, obj):
550 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
551 _date_modification.short_description = u'date modification'
552 _date_modification.admin_order_field = 'date_modification'
553
554 class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
555 search_fields = ('nom',)
556 list_display = ('nom', 'type', 'pays', '_date_modification', 'user_modification', )
557 list_filter = ('type', )
558 inlines = (DossierROInline,)
559 fieldsets = AUFMetadataAdminMixin.fieldsets + (
560 (None, {
561 'fields': ('nom', 'type', 'pays', )
562 }),
563 )
564
565 def _date_modification(self, obj):
566 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
567 _date_modification.short_description = u'date modification'
568 _date_modification.admin_order_field = 'date_modification'
569
570
571 class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
572 form = make_ajax_form(rh.Poste, {
573 'implantation' : 'implantations',
574 'type_poste' : 'typepostes',
575 'responsable' : 'postes',
576 'valeur_point_min' : 'valeurpoints',
577 'valeur_point_max' : 'valeurpoints',
578 })
579 alphabet_filter = 'nom'
580 search_fields = ('nom',
581 'implantation__code',
582 'implantation__nom',
583 'implantation__region__code',
584 'implantation__region__nom',
585 'rh_dossiers__employe__nom',
586 'rh_dossiers__employe__prenom',
587 )
588 list_display = (
589 '_id',
590 '_apercu',
591 '_nom',
592 '_occupe_par',
593 'implantation',
594 '_service',
595 'date_debut',
596 'date_fin',
597 '_date_modification',
598 'user_modification',
599 )
600 list_filter = (
601 'implantation__region',
602 'implantation',
603 'service',
604 'type_poste',
605 'type_poste__famille_emploi',
606 'date_debut',
607 'date_fin',
608 'vacant',
609 )
610 list_display_links = ('_nom',)
611 fieldsets = AUFMetadataAdminMixin.fieldsets + (
612 (None, {
613 'fields': (('nom', 'nom_feminin'), 'implantation', 'type_poste',
614 'service', 'responsable')
615 }),
616 ('Contrat', {
617 'fields': (('regime_travail', 'regime_travail_nb_heure_semaine'), )
618 }),
619 ('Recrutement', {
620 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)
621 }),
622 ('Rémunération', {
623 'fields': (('classement_min', 'valeur_point_min', 'devise_min', 'salaire_min', 'indemn_min', 'autre_min', ),
624 ('classement_max', 'valeur_point_max' ,'devise_max', 'salaire_max', 'indemn_max', 'autre_max', ),
625 )
626 }),
627 ('Comparatifs de rémunération', {
628 'fields': ('devise_comparaison',
629 ('comp_locale_min', 'comp_locale_max'),
630 ('comp_universite_min', 'comp_universite_max'),
631 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
632 ('comp_ong_min', 'comp_ong_max'),
633 ('comp_autre_min', 'comp_autre_max'))
634 }),
635 ('Justification', {
636 'fields': ('justification',)
637 }),
638 ('Autres Méta-données', {
639 'fields': ('date_debut', 'date_fin')
640 }),
641 )
642
643 inlines = (PosteFinancementInline,
644 PostePieceInline,
645 DossierROInline,
646 PosteComparaisonInline,
647 PosteCommentaireInline, )
648
649
650 def lookup_allowed(self, key, value):
651 if key in (
652 'date_debut__gte',
653 'date_debut__isnull',
654 'date_fin__lte',
655 'date_fin__isnull',
656 'implantation__region__id__exact',
657 'implantation__id__exact',
658 'type_poste__id__exact',
659 'type_poste__famille_emploi__id__exact',
660 'service__id__exact',
661 'service__isnull',
662 'vacant__exact',
663 'vacant__isnull',
664 ):
665 return True
666
667
668 def _apercu(self, poste):
669 view_link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /></a>""" % \
670 (reverse('poste_apercu', args=(poste.id,)),
671 settings.STATIC_URL,
672 )
673 return view_link
674 _apercu.allow_tags = True
675 _apercu.short_description = ''
676
677 def _id(self, obj):
678 return "%s" % obj.id
679 _id.short_description = '#'
680 _id.admin_order_field = 'id'
681
682 def _service(self, obj):
683 return obj.service
684 _service.short_description = 'Service'
685
686 def _nom(self, poste):
687 return """<a href="%s">%s</a>""" % \
688 (reverse('admin:rh_poste_change', args=(poste.id,)),
689 poste.nom
690 )
691 _nom.allow_tags = True
692 _nom.short_description = u'Nom'
693 _nom.admin_order_field = 'nom'
694
695 def _date_modification(self, obj):
696 return date(obj.date_modification)
697 _date_modification.short_description = u'date modification'
698 _date_modification.admin_order_field = 'date_modification'
699
700 def _occupe_par(self, obj):
701 """Formatte la méthode Poste.occupe_par() pour l'admin"""
702 output = u"Vacant"
703 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
704 return u"s/o"
705 employes = obj.occupe_par()
706 if employes:
707 l = []
708 for e in employes:
709 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>" % \
710 (reverse('employe_apercu', args=(e.id,)),
711 settings.STATIC_URL,
712 reverse('admin:rh_employe_change', args=(e.id,)),
713 e
714 )
715 l.append(link)
716 output = "\n<br />".join(l)
717 return output
718 _occupe_par.allow_tags = True
719 _occupe_par.short_description = "Occupé par"
720
721 def save_formset(self, request, form, formset, change):
722 instances = formset.save(commit=False)
723 for instance in instances:
724 if instance.__class__ == rh.PosteCommentaire:
725 instance.owner = request.user
726 instance.date_creation = datetime.datetime.now()
727 instance.save()
728 formset.save_m2m()
729
730
731 class PosteCommentaireAdmin(admin.ModelAdmin):
732 pass
733
734
735 class PosteFinancementAdmin(admin.ModelAdmin):
736 pass
737
738
739 class PostePieceAdmin(admin.ModelAdmin):
740 fk_name = 'poste'
741
742
743 class RemunerationAdmin(admin.ModelAdmin):
744 pass
745
746
747 class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
748 fieldsets = AUFMetadataAdminMixin.fieldsets + (
749 (None, {
750 'fields': ('employe', 'implantation', ),
751 }),
752 )
753
754
755 class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
756 list_display = ('nom', '_date_modification', 'user_modification', )
757 fieldsets = AUFMetadataAdminMixin.fieldsets + (
758 (None, {
759 'fields': ('nom', ),
760 }),
761 )
762
763 def _date_modification(self, obj):
764 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
765 _date_modification.short_description = u'date modification'
766 _date_modification.admin_order_field = 'date_modification'
767
768
769 class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
770 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
771 fieldsets = AUFMetadataAdminMixin.fieldsets + (
772 (None, {
773 'fields': ('code', 'nom', ),
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 class TauxChangeAdmin(admin.ModelAdmin):
783 list_display = ('taux', 'devise', 'annee', '_date_modification', 'user_modification', )
784 list_filter = ('devise', )
785 fieldsets = AUFMetadataAdminMixin.fieldsets + (
786 (None, {
787 'fields': ('taux', 'devise', 'annee', ),
788 }),
789 )
790
791 def _date_modification(self, obj):
792 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
793 _date_modification.short_description = u'date modification'
794 _date_modification.admin_order_field = 'date_modification'
795
796 class TypeContratAdmin(admin.ModelAdmin):
797 list_display = ('nom', 'nom_long', '_date_modification', 'user_modification', )
798 fieldsets = AUFMetadataAdminMixin.fieldsets + (
799 (None, {
800 'fields': ('nom', 'nom_long', ),
801 }),
802 )
803
804 def _date_modification(self, obj):
805 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
806 _date_modification.short_description = u'date modification'
807 _date_modification.admin_order_field = 'date_modification'
808
809
810 class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
811 search_fields = ('nom', 'nom_feminin', )
812 list_display = ('nom', 'famille_emploi', '_date_modification', 'user_modification', )
813 list_filter = ('famille_emploi', )
814 fieldsets = AUFMetadataAdminMixin.fieldsets + (
815 (None, {
816 'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi', )
817 }),
818 )
819
820 def _date_modification(self, obj):
821 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
822 _date_modification.short_description = u'date modification'
823 _date_modification.admin_order_field = 'date_modification'
824
825
826 class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
827 list_display = ('nom', 'type_paiement', 'nature_remuneration', '_date_modification', 'user_modification', )
828 fieldsets = AUFMetadataAdminMixin.fieldsets + (
829 (None, {
830 'fields': ('nom', 'type_paiement', 'nature_remuneration', )
831 }),
832 )
833
834 def _date_modification(self, obj):
835 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
836 _date_modification.short_description = u'date modification'
837 _date_modification.admin_order_field = 'date_modification'
838
839
840 class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
841 list_display = ('nom', '_date_modification', 'user_modification', )
842 fieldsets = AUFMetadataAdminMixin.fieldsets + (
843 (None, {
844 'fields': ('nom', )
845 }),
846 )
847
848 def _date_modification(self, obj):
849 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
850 _date_modification.short_description = u'date modification'
851 _date_modification.admin_order_field = 'date_modification'
852
853
854 class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
855 list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur', '_date_modification', 'user_modification', )
856 list_filter = ('annee', 'devise', )
857 fieldsets = AUFMetadataAdminMixin.fieldsets + (
858 (None, {
859 'fields': ('valeur', 'devise', 'implantation', 'annee', )
860 }),
861 )
862
863 def _date_modification(self, obj):
864 return date(obj.date_modification) if obj.date_modification is not None else "(aucune)"
865 _date_modification.short_description = u'date modification'
866 _date_modification.admin_order_field = 'date_modification'
867
868 def _devise_code(self, obj):
869 return obj.devise.code
870 _devise_code.short_description = "Code de la devise"
871
872 def _devise_nom(self, obj):
873 return obj.devise.nom
874 _devise_nom.short_description = "Nom de la devise"
875
876
877 admin.site.register(rh.Classement, ClassementAdmin)
878 admin.site.register(rh.Devise, DeviseAdmin)
879 admin.site.register(rh.Dossier, DossierAdmin)
880 admin.site.register(rh.Employe, EmployeAdmin)
881 admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
882 admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
883 admin.site.register(rh.Poste, PosteAdmin)
884 admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
885 admin.site.register(rh.Service, ServiceAdmin)
886 admin.site.register(rh.Statut, StatutAdmin)
887 admin.site.register(rh.TauxChange, TauxChangeAdmin)
888 admin.site.register(rh.TypeContrat, TypeContratAdmin)
889 admin.site.register(rh.TypePoste, TypePosteAdmin)
890 admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
891 admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
892 admin.site.register(rh.ValeurPoint, ValeurPointAdmin)