fix vacant is null
[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():
4bdadf8b
OL
56 if 'date_debut' in k:
57 prefix_debut = "".join(k.split('date_debut')[0:-1]) + 'date_debut'
58 date_debut = v
3195667e 59 del self.params[k]
4bdadf8b
OL
60 elif 'date_fin' in k:
61 prefix_fin = "".join(k.split('date_fin')[0:-1]) + 'date_fin'
62 date_fin = v
a9f403cf 63 del self.params[k]
a9f403cf 64 qs = super(ChangeList, self).get_query_set()
4bdadf8b
OL
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:
b46d18bc
OL
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}))
860c9ec9 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}))
6b1d6053 78 q_non_supprime = Q(**{'%s__exact' % prefix_debut.replace('date_debut', 'supprime') : False})
860c9ec9 79 q = (q_left | q_right | q_both) & q_non_supprime
6b1d6053 80 qs = qs.filter(q).distinct()
3195667e 81
3195667e
OL
82 self.params = old
83 return qs
84
40b35603
OL
85################################################################################
86
53ae644d
OL
87# Override of the InlineModelAdmin to support the link in the tabular inline
88class 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
98class 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):
20b4867c 120 user_groups = request.user.groups.all()
a0d365ed
OL
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
a18bc295 126 if len(user_groups) == 0 and not request.user.is_superuser:
20b4867c
OL
127 return False
128
53ae644d
OL
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
137class 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
142class 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
154class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
155 readonly_fields = ('owner', )
156 model = rh.AyantDroitCommentaire
157 extra = 1
158
159
160class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
161 form = ContratForm
162 model = rh.Contrat
163 extra = 1
164
165
166class 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
183class DossierCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
184 readonly_fields = ('owner', )
185 model = rh.DossierCommentaire
186 extra = 1
187
188
189class DossierPieceInline(admin.TabularInline):
190 model = rh.DossierPiece
191 extra = 4
192
193
194class EmployeInline(admin.TabularInline):
195 model = rh.Employe
196
197class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
198 readonly_fields = ('owner', )
199 model = rh.EmployeCommentaire
200 extra = 1
201
202
203class EmployePieceInline(admin.TabularInline):
204 model = rh.EmployePiece
205 extra = 4
206
207
53ae644d
OL
208class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
209 readonly_fields = ('owner', )
210 model = rh.PosteCommentaire
211 extra = 1
212
213
214class PosteFinancementInline(admin.TabularInline):
215 model = rh.PosteFinancement
216
217
218class PostePieceInline(admin.TabularInline):
219 model = rh.PostePiece
220
221
222class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
223 model = rh.Remuneration
224 extra = 1
225
226
227class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
228 pass
229
230
231class TypePosteInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
232 model = rh.TypePoste
233
234
6f037929
OL
235class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
236 model = rh.PosteComparaison
237
53ae644d
OL
238
239class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 240 list_display = ('_classement', '_date_modification', 'user_modification', )
53ae644d
OL
241 fieldsets = AUFMetadataAdminMixin.fieldsets + (
242 (None, {
243 'fields': ('type', 'echelon', 'degre', 'coefficient', )
244 }),
245 )
246
c5964dc2
OL
247 def _classement(self, obj):
248 return unicode(obj)
249 _classement.short_description = u"Classement"
53ae644d 250
33232787
JPC
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
53ae644d
OL
256class CommentaireAdmin(admin.ModelAdmin):
257 pass
258
259
53ae644d 260class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
4bdadf8b 261 list_display = ('code', 'nom', '_date_modification', 'user_modification', '_archive',)
edb35076 262 list_filter = ('archive', )
53ae644d
OL
263 fieldsets = AUFMetadataAdminMixin.fieldsets + (
264 (None, {
edb35076 265 'fields': ('code', 'nom', 'archive', ),
53ae644d
OL
266 }),
267 )
268
4bdadf8b
OL
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
33232787
JPC
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'
53ae644d 288
40b35603 289class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
53ae644d
OL
290 alphabet_filter = 'employe__nom'
291 search_fields = ('employe__nom', 'employe__prenom', 'poste__nom', 'poste__nom_feminin')
292 list_display = (
293 '_id',
e49ac947
JPC
294 '_apercu',
295 '_nom',
53ae644d
OL
296 '_poste',
297 '_employe',
298 '_date_debut',
299 '_date_fin',
33232787 300 '_date_modification',
c5964dc2 301 'user_modification',
53ae644d 302 )
e49ac947 303 list_display_links = ('_nom',)
53ae644d
OL
304 list_filter = (
305 'poste__implantation__region',
306 'poste__implantation',
53ae644d 307 'poste__type_poste__famille_emploi',
7baa5523 308 'poste__type_poste',
53ae644d 309 'rh_contrats__type_contrat',
f614ca5c
OL
310 'date_debut',
311 'date_fin',
53ae644d
OL
312 )
313 inlines = (DossierPieceInline, ContratInline,
314 RemunerationInline,
53ae644d
OL
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',
53ae644d
OL
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',
f614ca5c
OL
345 'date_debut__gte',
346 'date_debut__isnull',
347 'date_fin__lte',
348 'date_fin__isnull',
53ae644d
OL
349 ):
350 return True
351
e49ac947
JPC
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):
5429c435 365 apercu_link = u"""<a title="Aperçu du dossier" onclick="return showAddAnotherPopup(this);" href='%s'><img src="%simg/loupe.png" /></a>""" % \
b10920ea 366 (reverse('dossier_apercu', args=(d.id,)),
822a2c33 367 settings.STATIC_URL,
b10920ea 368 )
e49ac947
JPC
369 return apercu_link
370 _apercu.allow_tags = True
371 _apercu.short_description = u""
53ae644d
OL
372
373
53ae644d 374 def _date_debut(self, obj):
5f36f262
OL
375 return date(obj.date_debut)
376
53ae644d
OL
377 _date_debut.short_description = u'Occupation début'
378 _date_debut.admin_order_field = 'date_debut'
379
380 def _date_fin(self, obj):
5f36f262 381 return date(obj.date_fin)
53ae644d
OL
382 _date_fin.short_description = u'Occupation fin'
383 _date_fin.admin_order_field = 'date_fin'
384
33232787
JPC
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
53ae644d 391 def _poste(self, dossier):
211a0e56 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>""" % \
53ae644d 393 (reverse('poste_apercu', args=(dossier.poste.id,)),
822a2c33 394 settings.STATIC_URL,
211a0e56
JPC
395 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
396 dossier.poste,
53ae644d
OL
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
f614ca5c
OL
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,)
e6c107de
JPC
410 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
411 (view, edit_link, style, employe)
53ae644d 412 _employe.allow_tags = True
e49ac947 413 _employe.short_description = u"Employé"
53ae644d
OL
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
02e69aa2 421 instance.date_creation = datetime.datetime.now()
53ae644d
OL
422 instance.save()
423
424
425class DossierPieceAdmin(admin.ModelAdmin):
426 pass
427
428
429class DossierCommentaireAdmin(admin.ModelAdmin):
430 pass
431
432
40b35603 433class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin,):
53ae644d
OL
434 alphabet_filter = 'nom'
435 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
436 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
437 ordering = ('nom', )
438 form = EmployeAdminForm
a7f013f5 439 list_display = ('_id', '_apercu', '_nom', '_dossiers_postes', '_date_modification', 'user_modification', )
e49ac947 440 list_display_links = ('_nom',)
b46d18bc 441 list_filter = ('rh_dossiers__poste__implantation__region', 'rh_dossiers__poste__implantation', 'nb_postes', 'rh_dossiers__date_debut', 'rh_dossiers__date_fin')
7f4d1233
OL
442 date_borne_gauche = 'rh_dossiers__date_debut'
443 date_borne_droite = 'rh_dossiers__date_fin'
53ae644d
OL
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
b10920ea
JPC
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>""" % \
822a2c33 462 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
b10920ea
JPC
463 _apercu.allow_tags = True
464 _apercu.short_description = u""
b10920ea 465
53ae644d 466 def _nom(self, obj):
53ae644d 467 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
e6c107de 468 return u"""<a href='%s'><strong>%s</strong></a>""" % \
e49ac947 469 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
53ae644d 470 _nom.allow_tags = True
e49ac947 471 _nom.short_description = u"Employé"
53ae644d
OL
472 _nom.admin_order_field = "nom"
473
e49ac947
JPC
474 def _id(self, obj):
475 return obj.id
476 _id.short_description = u"#"
477 _id.admin_order_field = "id"
478
33232787
JPC
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
a7f013f5 484 def _dossiers_postes(self, obj):
53ae644d
OL
485 l = []
486 for d in obj.rh_dossiers.all().order_by('-date_debut'):
a7f013f5
JPC
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,
53ae644d 500 d.date_debut.year,
a7f013f5
JPC
501 d.poste.id,
502 d.poste.nom,
53ae644d 503 )
b5cc0357
OL
504
505 # Dossier terminé en gris non cliquable
506 if d.date_fin is not None:
a7f013f5 507 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
b5cc0357 508 (d.date_debut.year,
a7f013f5
JPC
509 d.poste.id,
510 d.poste.nom,
b5cc0357
OL
511 )
512
53ae644d
OL
513 l.append(link)
514 return "<ul>%s</ul>" % "\n".join(l)
a7f013f5
JPC
515 _dossiers_postes.allow_tags = True
516 _dossiers_postes.short_description = u"Dossiers et postes"
53ae644d
OL
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
02e69aa2 527 instance.date_creation = datetime.datetime.now()
53ae644d
OL
528 instance.save()
529
530
531
532class EmployeCommentaireAdmin(admin.ModelAdmin):
533 pass
534
535
536class EmployePieceAdmin(admin.ModelAdmin):
537 pass
538
539
540class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 541 list_display = ('nom', '_date_modification', 'user_modification', )
53ae644d
OL
542 inlines = (TypePosteInline,)
543 fieldsets = AUFMetadataAdminMixin.fieldsets + (
544 (None, {
545 'fields': ('nom', )
546 }),
547 )
548
33232787
JPC
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'
53ae644d 553
95b630cf 554class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
c5964dc2 555 search_fields = ('nom',)
33232787 556 list_display = ('nom', 'type', 'pays', '_date_modification', 'user_modification', )
c5964dc2 557 list_filter = ('type', )
53ae644d
OL
558 inlines = (DossierROInline,)
559 fieldsets = AUFMetadataAdminMixin.fieldsets + (
560 (None, {
561 'fields': ('nom', 'type', 'pays', )
562 }),
563 )
564
33232787
JPC
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
53ae644d 570
40b35603 571class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
53ae644d
OL
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',
1ce71322
JPC
585 'rh_dossiers__employe__nom',
586 'rh_dossiers__employe__prenom',
53ae644d
OL
587 )
588 list_display = (
e49ac947 589 '_id',
8f3ca727 590 '_apercu',
53ae644d
OL
591 '_nom',
592 '_occupe_par',
593 'implantation',
c5964dc2 594 '_service',
53ae644d
OL
595 'date_debut',
596 'date_fin',
33232787 597 '_date_modification',
53ae644d 598 'user_modification',
53ae644d 599 )
f614ca5c 600 list_filter = (
53ae644d
OL
601 'implantation__region',
602 'implantation',
e8dd3d54 603 'service',
53ae644d
OL
604 'type_poste',
605 'type_poste__famille_emploi',
f614ca5c
OL
606 'date_debut',
607 'date_fin',
4c53dda4 608 'vacant',
53ae644d 609 )
e49ac947 610 list_display_links = ('_nom',)
53ae644d
OL
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 }),
48a6df80 638 ('Autres Méta-données', {
53ae644d
OL
639 'fields': ('date_debut', 'date_fin')
640 }),
641 )
642
643 inlines = (PosteFinancementInline,
644 PostePieceInline,
645 DossierROInline,
6f037929 646 PosteComparaisonInline,
53ae644d
OL
647 PosteCommentaireInline, )
648
b46d18bc 649
f614ca5c
OL
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',
7f4d1233
OL
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',
d48f0922 661 'service__isnull',
7f4d1233 662 'vacant__exact',
2b48822f 663 'vacant__isnull',
f614ca5c
OL
664 ):
665 return True
666
c5964dc2 667
8f3ca727 668 def _apercu(self, poste):
23de8cea 669 view_link = u"""<a onclick="return showAddAnotherPopup(this);" title="Aperçu du poste" href='%s'><img src="%simg/loupe.png" /></a>""" % \
8f3ca727 670 (reverse('poste_apercu', args=(poste.id,)),
822a2c33 671 settings.STATIC_URL,
23de8cea 672 )
e49ac947 673 return view_link
8f3ca727 674 _apercu.allow_tags = True
e49ac947
JPC
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'
8f3ca727 681
c5964dc2
OL
682 def _service(self, obj):
683 return obj.service
6c2b1160 684 _service.short_description = 'Service'
53ae644d
OL
685
686 def _nom(self, poste):
e49ac947
JPC
687 return """<a href="%s">%s</a>""" % \
688 (reverse('admin:rh_poste_change', args=(poste.id,)),
689 poste.nom
690 )
53ae644d
OL
691 _nom.allow_tags = True
692 _nom.short_description = u'Nom'
693 _nom.admin_order_field = 'nom'
694
33232787
JPC
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
53ae644d
OL
700 def _occupe_par(self, obj):
701 """Formatte la méthode Poste.occupe_par() pour l'admin"""
15c5f55a 702 output = u"Vacant"
3195667e 703 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
954ead19 704 return u"s/o"
53ae644d
OL
705 employes = obj.occupe_par()
706 if employes:
707 l = []
708 for e in employes:
b10920ea
JPC
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,)),
822a2c33 711 settings.STATIC_URL,
b10920ea
JPC
712 reverse('admin:rh_employe_change', args=(e.id,)),
713 e
714 )
53ae644d
OL
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
02e69aa2 726 instance.date_creation = datetime.datetime.now()
53ae644d
OL
727 instance.save()
728 formset.save_m2m()
729
730
731class PosteCommentaireAdmin(admin.ModelAdmin):
732 pass
733
734
735class PosteFinancementAdmin(admin.ModelAdmin):
736 pass
737
738
739class PostePieceAdmin(admin.ModelAdmin):
740 fk_name = 'poste'
741
742
743class RemunerationAdmin(admin.ModelAdmin):
744 pass
745
746
747class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
748 fieldsets = AUFMetadataAdminMixin.fieldsets + (
749 (None, {
750 'fields': ('employe', 'implantation', ),
751 }),
752 )
753
754
755class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 756 list_display = ('nom', '_date_modification', 'user_modification', )
53ae644d
OL
757 fieldsets = AUFMetadataAdminMixin.fieldsets + (
758 (None, {
759 'fields': ('nom', ),
760 }),
761 )
762
33232787
JPC
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
53ae644d 769class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 770 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
53ae644d
OL
771 fieldsets = AUFMetadataAdminMixin.fieldsets + (
772 (None, {
773 'fields': ('code', 'nom', ),
774 }),
775 )
776
33232787
JPC
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
53ae644d 782class TauxChangeAdmin(admin.ModelAdmin):
33232787 783 list_display = ('taux', 'devise', 'annee', '_date_modification', 'user_modification', )
53ae644d
OL
784 list_filter = ('devise', )
785 fieldsets = AUFMetadataAdminMixin.fieldsets + (
786 (None, {
787 'fields': ('taux', 'devise', 'annee', ),
788 }),
789 )
790
33232787
JPC
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
53ae644d 796class TypeContratAdmin(admin.ModelAdmin):
33232787 797 list_display = ('nom', 'nom_long', '_date_modification', 'user_modification', )
53ae644d
OL
798 fieldsets = AUFMetadataAdminMixin.fieldsets + (
799 (None, {
800 'fields': ('nom', 'nom_long', ),
801 }),
802 )
803
33232787
JPC
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
53ae644d
OL
809
810class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
811 search_fields = ('nom', 'nom_feminin', )
33232787 812 list_display = ('nom', 'famille_emploi', '_date_modification', 'user_modification', )
53ae644d
OL
813 list_filter = ('famille_emploi', )
814 fieldsets = AUFMetadataAdminMixin.fieldsets + (
815 (None, {
816 'fields': ('nom', 'nom_feminin', 'is_responsable', 'famille_emploi', )
817 }),
818 )
819
33232787
JPC
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
53ae644d
OL
825
826class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 827 list_display = ('nom', 'type_paiement', 'nature_remuneration', '_date_modification', 'user_modification', )
53ae644d
OL
828 fieldsets = AUFMetadataAdminMixin.fieldsets + (
829 (None, {
830 'fields': ('nom', 'type_paiement', 'nature_remuneration', )
831 }),
832 )
833
33232787
JPC
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
53ae644d
OL
839
840class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 841 list_display = ('nom', '_date_modification', 'user_modification', )
53ae644d
OL
842 fieldsets = AUFMetadataAdminMixin.fieldsets + (
843 (None, {
844 'fields': ('nom', )
845 }),
846 )
847
33232787
JPC
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
53ae644d
OL
853
854class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 855 list_display = ('_devise_code', '_devise_nom', 'annee', 'valeur', '_date_modification', 'user_modification', )
c5964dc2 856 list_filter = ('annee', 'devise', )
53ae644d
OL
857 fieldsets = AUFMetadataAdminMixin.fieldsets + (
858 (None, {
859 'fields': ('valeur', 'devise', 'implantation', 'annee', )
860 }),
861 )
862
33232787
JPC
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
53ae644d
OL
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
877admin.site.register(rh.Classement, ClassementAdmin)
878admin.site.register(rh.Devise, DeviseAdmin)
879admin.site.register(rh.Dossier, DossierAdmin)
880admin.site.register(rh.Employe, EmployeAdmin)
881admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
882admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
883admin.site.register(rh.Poste, PosteAdmin)
884admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
885admin.site.register(rh.Service, ServiceAdmin)
c5964dc2 886admin.site.register(rh.Statut, StatutAdmin)
53ae644d 887admin.site.register(rh.TauxChange, TauxChangeAdmin)
c5964dc2 888admin.site.register(rh.TypeContrat, TypeContratAdmin)
53ae644d
OL
889admin.site.register(rh.TypePoste, TypePosteAdmin)
890admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
891admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
892admin.site.register(rh.ValeurPoint, ValeurPointAdmin)