index improvement
[auf_rh_dae.git] / project / rh / admin.py
CommitLineData
53ae644d
OL
1# -*- encoding: utf-8 -*-
2
53ae644d
OL
3import datetime
4
53ae644d 5from django.core.urlresolvers import reverse
50fa9bc1 6from django.contrib import admin
53ae644d
OL
7from django.conf import settings
8from django.db.models import Q
5f36f262 9from django.template.defaultfilters import date
53ae644d 10from ajax_select import make_ajax_form
22343fe7
OL
11from auf.django.metadata.admin import AUFMetadataAdminMixin, \
12 AUFMetadataInlineAdminMixin, \
13 AUF_METADATA_READONLY_FIELDS
6bee05ff
OL
14from forms import ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect, \
15DossierForm
a47ed016 16from dae import models as dae
53ae644d 17from dae.utils import get_employe_from_user
a17e2236 18from change_list import ChangeList
a12ddd52
OL
19from groups import grp_correspondants_rh
20from decorators import in_drh_or_admin
53ae644d 21import models as rh
82af5c19
JPC
22import auf.django.references.models as ref
23
7ba822a6
OL
24class ArchiveMixin(object):
25 """
26 Archive Mixin pour gérer le queryset et le display
27 NON COMPRIS : list_filter, et list_display, field à setter dans la classe.
28 """
29
30 def queryset(self, request):
31 return self.model._base_manager
32
33 def _archive(self, obj):
34 if obj.archive:
35 return "oui"
36 else:
37 return "non"
38 _archive.short_description = u'Archivé'
39 _archive.admin_order_field = 'archive'
40
9da4c195
JPC
41class RegionProxy(ref.Region):
42 """ Proxy utilisé pour les organigrammes par région """
43 class Meta:
44 proxy = True
45 verbose_name = u"Organigramme par région"
46 verbose_name_plural = u"Organigramme par région"
47
48
82af5c19
JPC
49class ImplantationProxy(ref.Implantation):
50 """ Proxy utilisé pour les organigrammes par implantation """
51 class Meta:
52 proxy = True
53 verbose_name = u"Organigramme par implantations"
54 verbose_name_plural = u"Organigramme par implantations"
55
22343fe7 56
5c0f1778
JPC
57class ServiceProxy(rh.Service):
58 """ Proxy utilisé pour les organigrammes opar service """
59 class Meta:
60 proxy = True
61 verbose_name = u"Organigramme par services"
62 verbose_name_plural = u"Organigramme par services"
63
22343fe7 64
5c0f1778
JPC
65class EmployeProxy(rh.Employe):
66 """ Proxy utilisé pour les organigrammes des employés """
22343fe7
OL
67 class Meta:
68 proxy = True
69 verbose_name = u"Organigramme des employés"
70 verbose_name_plural = u"Organigramme des employés"
71
f614ca5c 72
40b35603 73class DateRangeMixin(object):
a17e2236 74 prefixe_recherche_temporelle = ""
22343fe7 75
40b35603 76 def get_changelist(self, request, **kwargs):
22343fe7 77 if 'HTTP_REFERER' in request.META.keys():
910e39e5
OL
78 referer = request.META['HTTP_REFERER']
79 referer = "/".join(referer.split('/')[3:])
80 referer = "/%s" % referer.split('?')[0]
22343fe7
OL
81 change_list_view = 'admin:%s_%s_changelist' % (
82 self.model._meta.app_label,
83 self.model.__name__.lower(),)
910e39e5
OL
84 if referer != reverse(change_list_view):
85 params = request.GET.copy()
22343fe7 86 params.update({'statut': 'Actif'})
910e39e5 87 request.GET = params
40b35603 88 return ChangeList
3195667e 89
22343fe7 90
53ae644d
OL
91# Override of the InlineModelAdmin to support the link in the tabular inline
92class LinkedInline(admin.options.InlineModelAdmin):
93 template = "admin/linked.html"
94 admin_model_path = None
95
96 def __init__(self, *args):
97 super(LinkedInline, self).__init__(*args)
98 if self.admin_model_path is None:
99 self.admin_model_path = self.model.__name__.lower()
100
101
102class ProtectRegionMixin(object):
103
104 def queryset(self, request):
53ae644d
OL
105 qs = super(ProtectRegionMixin, self).queryset(request)
106
53ae644d 107 user_groups = request.user.groups.all()
a12ddd52 108 if in_drh_or_admin(request.user):
53ae644d
OL
109 return qs
110
111 if grp_correspondants_rh in user_groups:
112 employe = get_employe_from_user(request.user)
22343fe7
OL
113 q = Q(**{self.model.prefix_implantation: \
114 employe.implantation.region})
53ae644d
OL
115 qs = qs.filter(q).distinct()
116 return qs
117 return qs.none()
118
c0be8705
OL
119 def has_add_permission(self, request):
120 if not in_drh_or_admin(request.user):
121 return False
122 else:
123 return True
124
53ae644d 125 def has_change_permission(self, request, obj=None):
20b4867c 126 user_groups = request.user.groups.all()
a0d365ed
OL
127
128 # Lock pour autoriser uniquement les DRH à utiliser RH
a12ddd52 129 if not in_drh_or_admin(request.user):
a0d365ed
OL
130 return False
131
a18bc295 132 if len(user_groups) == 0 and not request.user.is_superuser:
20b4867c
OL
133 return False
134
53ae644d
OL
135 if obj is None:
136 return True
137 ids = [o.id for o in self.queryset(request)]
138 return obj.id in ids
139
140
141# Inlines
142
143class ReadOnlyInlineMixin(object):
22343fe7 144
53ae644d 145 def get_readonly_fields(self, request, obj=None):
22343fe7
OL
146 return [f.name for f in self.model._meta.fields \
147 if f.name not in AUF_METADATA_READONLY_FIELDS]
53ae644d
OL
148
149
150class AyantDroitInline(AUFMetadataInlineAdminMixin, admin.StackedInline):
151 model = rh.AyantDroit
152 form = AyantDroitForm
153 extra = 0
154
155 fieldsets = (
156 (None, {
22343fe7
OL
157 'fields': (
158 ('nom', 'prenom'),
159 ('nom_affichage', 'genre'),
160 'nationalite',
161 'date_naissance',
162 'lien_parente',
163 )}),
53ae644d
OL
164 )
165
166
22343fe7
OL
167class AyantDroitCommentaireInline(AUFMetadataInlineAdminMixin, \
168 admin.TabularInline):
53ae644d
OL
169 readonly_fields = ('owner', )
170 model = rh.AyantDroitCommentaire
171 extra = 1
172
173
174class ContratInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
175 form = ContratForm
176 model = rh.Contrat
177 extra = 1
178
179
180class DossierROInline(ReadOnlyInlineMixin, LinkedInline):
181 template = "admin/rh/dossier/linked.html"
182 exclude = AUF_METADATA_READONLY_FIELDS
183 model = rh.Dossier
184 extra = 0
185 can_delete = False
186
187 def has_add_permission(self, request=None):
188 return False
189
190 def has_change_permission(self, request, obj=None):
191 return False
192
193 def has_delete_permission(self, request, obj=None):
194 return False
195
196
22343fe7
OL
197class DossierCommentaireInline(AUFMetadataInlineAdminMixin, \
198 admin.TabularInline):
53ae644d
OL
199 readonly_fields = ('owner', )
200 model = rh.DossierCommentaire
201 extra = 1
202
203
204class DossierPieceInline(admin.TabularInline):
205 model = rh.DossierPiece
206 extra = 4
207
208
209class EmployeInline(admin.TabularInline):
210 model = rh.Employe
211
22343fe7
OL
212
213class EmployeCommentaireInline(AUFMetadataInlineAdminMixin, \
214 admin.TabularInline):
53ae644d
OL
215 readonly_fields = ('owner', )
216 model = rh.EmployeCommentaire
217 extra = 1
218
219
220class EmployePieceInline(admin.TabularInline):
221 model = rh.EmployePiece
222 extra = 4
223
224
53ae644d
OL
225class PosteCommentaireInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
226 readonly_fields = ('owner', )
227 model = rh.PosteCommentaire
228 extra = 1
229
230
231class PosteFinancementInline(admin.TabularInline):
232 model = rh.PosteFinancement
233
234
235class PostePieceInline(admin.TabularInline):
236 model = rh.PostePiece
237
238
239class RemunerationInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
240 model = rh.Remuneration
241 extra = 1
242
243
244class RemunerationROInline(ReadOnlyInlineMixin, RemunerationInline):
245 pass
246
247
248class TypePosteInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
249 model = rh.TypePoste
250
251
6f037929
OL
252class PosteComparaisonInline(AUFMetadataInlineAdminMixin, admin.TabularInline):
253 model = rh.PosteComparaison
254
53ae644d
OL
255
256class ClassementAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 257 list_display = ('_classement', '_date_modification', 'user_modification', )
53ae644d
OL
258 fieldsets = AUFMetadataAdminMixin.fieldsets + (
259 (None, {
22343fe7 260 'fields': ('type', 'echelon', 'degre', 'coefficient',)}),
53ae644d
OL
261 )
262
c5964dc2
OL
263 def _classement(self, obj):
264 return unicode(obj)
265 _classement.short_description = u"Classement"
53ae644d 266
33232787 267 def _date_modification(self, obj):
22343fe7
OL
268 return date(obj.date_modification) \
269 if obj.date_modification is not None else "(aucune)"
33232787
JPC
270 _date_modification.short_description = u'date modification'
271 _date_modification.admin_order_field = 'date_modification'
272
22343fe7 273
53ae644d
OL
274class CommentaireAdmin(admin.ModelAdmin):
275 pass
276
277
7ba822a6 278class DeviseAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
22343fe7
OL
279 list_display = (
280 'code',
281 'nom',
282 '_archive',
283 '_date_modification',
284 'user_modification',
285 )
edb35076 286 list_filter = ('archive', )
53ae644d
OL
287 fieldsets = AUFMetadataAdminMixin.fieldsets + (
288 (None, {
edb35076 289 'fields': ('code', 'nom', 'archive', ),
53ae644d
OL
290 }),
291 )
292
33232787 293 def _date_modification(self, obj):
22343fe7
OL
294 return date(obj.date_modification) \
295 if obj.date_modification is not None else "(aucune)"
33232787
JPC
296 _date_modification.short_description = u'date modification'
297 _date_modification.admin_order_field = 'date_modification'
53ae644d 298
22343fe7
OL
299
300class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
301 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
53ae644d 302 alphabet_filter = 'employe__nom'
22343fe7
OL
303 search_fields = (
304 'employe__nom',
305 'employe__prenom',
306 'poste__nom',
307 'poste__nom_feminin')
53ae644d
OL
308 list_display = (
309 '_id',
e49ac947
JPC
310 '_apercu',
311 '_nom',
53ae644d
OL
312 '_poste',
313 '_employe',
314 '_date_debut',
315 '_date_fin',
33232787 316 '_date_modification',
c5964dc2 317 'user_modification',
a47ed016 318 '_dae',
53ae644d 319 )
e49ac947 320 list_display_links = ('_nom',)
53ae644d
OL
321 list_filter = (
322 'poste__implantation__region',
323 'poste__implantation',
53ae644d 324 'poste__type_poste__famille_emploi',
7baa5523 325 'poste__type_poste',
53ae644d 326 'rh_contrats__type_contrat',
6bee05ff 327 'principal',
53ae644d
OL
328 )
329 inlines = (DossierPieceInline, ContratInline,
330 RemunerationInline,
53ae644d
OL
331 DossierCommentaireInline,
332 )
333 fieldsets = AUFMetadataAdminMixin.fieldsets + (
334 (None, {
22343fe7
OL
335 'fields': (
336 'employe',
337 'poste',
6bee05ff 338 'principal',
22343fe7
OL
339 'statut',
340 'organisme_bstg',)}),
53ae644d 341 ('Recrutement', {
22343fe7
OL
342 'fields': (
343 'statut_residence',
344 'remplacement',
345 'remplacement_de', )}),
53ae644d 346 ('Rémunération', {
22343fe7
OL
347 'fields': (
348 'classement',
349 ('regime_travail', 'regime_travail_nb_heure_semaine'),)}),
53ae644d 350 ('Occupation du Poste par cet Employe', {
22343fe7
OL
351 'fields': (('date_debut', 'date_fin'), )}
352 ),
53ae644d 353 )
22343fe7
OL
354 form = make_ajax_form(rh.Dossier, {
355 'employe': 'employes',
356 'poste': 'postes',
357 'remplacement_de': 'dossiers',
6bee05ff 358 }, superclass=DossierForm)
53ae644d
OL
359
360 def lookup_allowed(self, key, value):
361 if key in (
362 'employe__nom__istartswith',
53ae644d
OL
363 'poste__implantation__region__id__exact',
364 'poste__implantation__id__exact',
365 'poste__type_poste__id__exact',
366 'poste__type_poste__famille_emploi__id__exact',
367 'rh_contrats__type_contrat__id__exact',
6bee05ff
OL
368 'principal__exact',
369 'principal__isnull',
53ae644d
OL
370 ):
371 return True
372
e49ac947
JPC
373 def _id(self, obj):
374 return obj.id
375 _id.short_description = u"#"
376 _id.admin_order_field = "id"
377
378 def _nom(self, obj):
22343fe7
OL
379 return "%d : %s %s" % (
380 obj.date_debut.year,
381 obj.employe.nom.upper(),
382 obj.employe.prenom)
e49ac947
JPC
383 _nom.allow_tags = True
384 _nom.short_description = u"Dossier"
385
e49ac947 386 def _apercu(self, d):
22343fe7
OL
387 apercu_link = u"""<a title="Aperçu du dossier"
388 onclick="return showAddAnotherPopup(this);"
389 href='%s'>
390 <img src="%simg/loupe.png" />
391 </a>""" % \
b10920ea 392 (reverse('dossier_apercu', args=(d.id,)),
822a2c33 393 settings.STATIC_URL,
b10920ea 394 )
e49ac947
JPC
395 return apercu_link
396 _apercu.allow_tags = True
397 _apercu.short_description = u""
53ae644d 398
a47ed016
OL
399 def _dae(self, d):
400 apercu_link = ""
401 if dae.ImportDossier.objects.filter(rh=d).exists():
402 dae_id = dae.ImportDossier.objects.get(rh=d).dae_id
403 apercu_link = u"""<a title="Aperçu du dossier"
404 onclick="return showAddAnotherPopup(this);"
405 href='%s'>
406 <img src="%simg/loupe.png" />
407 </a>""" % \
408 (reverse('embauche_consulter', args=(dae_id,)),
409 settings.STATIC_URL,
410 )
411 return apercu_link
412 _dae.allow_tags = True
413 _dae.short_description = u"DAE"
414
53ae644d 415 def _date_debut(self, obj):
5f36f262
OL
416 return date(obj.date_debut)
417
53ae644d
OL
418 _date_debut.short_description = u'Occupation début'
419 _date_debut.admin_order_field = 'date_debut'
420
421 def _date_fin(self, obj):
5f36f262 422 return date(obj.date_fin)
53ae644d
OL
423 _date_fin.short_description = u'Occupation fin'
424 _date_fin.admin_order_field = 'date_fin'
425
33232787 426 def _date_modification(self, obj):
22343fe7
OL
427 return date(obj.date_modification) \
428 if obj.date_modification is not None else "(aucune)"
33232787
JPC
429 _date_modification.short_description = u'date modification'
430 _date_modification.admin_order_field = 'date_modification'
431
53ae644d 432 def _poste(self, dossier):
22343fe7
OL
433 link = u"""<a title="Aperçu du poste"
434 onclick="return showAddAnotherPopup(this);"
435 href='%s'><img src="%simg/loupe.png" />
436 </a>
437 <a href="%s" title="Modifier le poste">%s</a>""" % \
53ae644d 438 (reverse('poste_apercu', args=(dossier.poste.id,)),
822a2c33 439 settings.STATIC_URL,
211a0e56
JPC
440 reverse('admin:rh_poste_change', args=(dossier.poste.id,)),
441 dossier.poste,
53ae644d
OL
442 )
443 return link
444 _poste.allow_tags = True
445 _poste.short_description = u'Poste'
446 _poste.admin_order_field = 'poste__nom'
447
448 def _employe(self, obj):
449 employe = obj.employe
450 view_link = reverse('employe_apercu', args=(employe.id,))
451 edit_link = reverse('admin:rh_employe_change', args=(employe.id,))
452
f614ca5c 453 style = ""
22343fe7
OL
454 view = u"""<a href="%s"
455 title="Aperçu l'employé"
456 onclick="return showAddAnotherPopup(this);">
457 <img src="%simg/loupe.png" />
458 </a>""" % (view_link, settings.STATIC_URL,)
e6c107de
JPC
459 return u"""%s<a href='%s' style="%s;">%s</a>""" % \
460 (view, edit_link, style, employe)
53ae644d 461 _employe.allow_tags = True
e49ac947 462 _employe.short_description = u"Employé"
53ae644d 463 _employe.admin_order_field = "employe__nom"
22343fe7 464
53ae644d
OL
465 def save_formset(self, request, form, formset, change):
466 instances = formset.save(commit=False)
467 for instance in instances:
468 if instance.__class__ == rh.DossierCommentaire:
469 instance.owner = request.user
02e69aa2 470 instance.date_creation = datetime.datetime.now()
53ae644d
OL
471 instance.save()
472
473
474class DossierPieceAdmin(admin.ModelAdmin):
475 pass
476
477
478class DossierCommentaireAdmin(admin.ModelAdmin):
479 pass
480
481
22343fe7
OL
482class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
483 ProtectRegionMixin, admin.ModelAdmin,):
7eb6b687 484 prefixe_recherche_temporelle = "rh_dossiers__"
53ae644d
OL
485 alphabet_filter = 'nom'
486 DEFAULT_ALPHABET = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
487 search_fields = ('id', 'nom', 'prenom', 'nom_affichage', )
488 ordering = ('nom', )
489 form = EmployeAdminForm
22343fe7
OL
490 list_display = (
491 '_id',
492 '_apercu',
493 '_nom',
494 '_dossiers_postes',
495 '_date_modification',
496 'user_modification',
497 )
e49ac947 498 list_display_links = ('_nom',)
22343fe7
OL
499 list_filter = (
500 'rh_dossiers__poste__implantation__region',
501 'rh_dossiers__poste__implantation',
502 'nb_postes',
503 )
53ae644d
OL
504 inlines = (AyantDroitInline,
505 DossierROInline,
506 EmployePieceInline,
507 EmployeCommentaireInline)
508 fieldsets = AUFMetadataAdminMixin.fieldsets + (
509 ('Identification', {
22343fe7
OL
510 'fields': (
511 ('nom', 'prenom'),
512 ('nom_affichage', 'genre'),
513 'nationalite',
514 'date_naissance',
515 )}
516 ),
53ae644d 517 ('Informations personnelles', {
22343fe7
OL
518 'fields': ('situation_famille', 'date_entree', )}
519 ),
53ae644d 520 ('Coordonnées', {
22343fe7
OL
521 'fields': (
522 ('tel_domicile', 'tel_cellulaire'),
523 ('adresse', 'ville'),
524 ('code_postal', 'province'),
525 'pays',
526 )}
527 ),
53ae644d
OL
528 )
529
b10920ea 530 def _apercu(self, obj):
22343fe7
OL
531 return u"""<a title="Aperçu de l'employé"
532 onclick="return showAddAnotherPopup(this);"
533 href='%s'>
534 <img src="%simg/loupe.png" />
535 </a>""" % \
536 (reverse('employe_apercu', args=(obj.id,)), settings.STATIC_URL)
b10920ea
JPC
537 _apercu.allow_tags = True
538 _apercu.short_description = u""
b10920ea 539
53ae644d 540 def _nom(self, obj):
53ae644d 541 edit_link = reverse('admin:rh_employe_change', args=(obj.id,))
e6c107de 542 return u"""<a href='%s'><strong>%s</strong></a>""" % \
e49ac947 543 (edit_link, "%s %s" % (obj.nom.upper(), obj.prenom))
53ae644d 544 _nom.allow_tags = True
e49ac947 545 _nom.short_description = u"Employé"
53ae644d
OL
546 _nom.admin_order_field = "nom"
547
e49ac947
JPC
548 def _id(self, obj):
549 return obj.id
550 _id.short_description = u"#"
551 _id.admin_order_field = "id"
552
33232787 553 def _date_modification(self, obj):
22343fe7
OL
554 return date(obj.date_modification) \
555 if obj.date_modification is not None else "(aucune)"
33232787
JPC
556 _date_modification.short_description = u'date modification'
557 _date_modification.admin_order_field = 'date_modification'
558
a7f013f5 559 def _dossiers_postes(self, obj):
53ae644d
OL
560 l = []
561 for d in obj.rh_dossiers.all().order_by('-date_debut'):
22343fe7
OL
562 dossier = u"""<a title="Aperçu du dossier"
563 href="%s"
564 onclick="return showAddAnotherPopup(this);"
565 title="Aperçu du dossier">
566 <img src="%simg/loupe.png" />
567 </a>
568 <a href="%s">Dossier</a>
569 &nbsp;""" % \
570 (reverse('dossier_apercu', args=(d.id,)),
571 settings.STATIC_URL,
572 reverse('admin:rh_dossier_change', args=(d.id,)))
573
574 poste = u"""<a title="Aperçu du poste"
575 href="%s"
576 onclick="return showAddAnotherPopup(this);"
577 title="Aperçu du poste">
578 <img src="%simg/loupe.png" />
579 </a>
580 <a href="%s">Poste</a>
581 &nbsp;""" % \
582 (reverse('poste_apercu', args=(d.poste.id,)),
583 settings.STATIC_URL,
584 reverse('admin:rh_poste_change', args=(d.poste.id,)))
a7f013f5
JPC
585 link = u"""<li>%s %s - %s : [%s] %s</li>""" % \
586 (dossier, poste,
53ae644d 587 d.date_debut.year,
a7f013f5
JPC
588 d.poste.id,
589 d.poste.nom,
53ae644d 590 )
b5cc0357
OL
591
592 # Dossier terminé en gris non cliquable
a4329fae 593 if d.date_fin is not None and d.date_fin < datetime.date.today():
a7f013f5 594 link = u"""<li style="color: grey">%s : [%s] %s</li>""" % \
b5cc0357 595 (d.date_debut.year,
a7f013f5
JPC
596 d.poste.id,
597 d.poste.nom,
b5cc0357
OL
598 )
599
53ae644d
OL
600 l.append(link)
601 return "<ul>%s</ul>" % "\n".join(l)
a7f013f5
JPC
602 _dossiers_postes.allow_tags = True
603 _dossiers_postes.short_description = u"Dossiers et postes"
53ae644d
OL
604
605 def queryset(self, request):
22343fe7 606 qs = super(EmployeAdmin, self).queryset(request)
53ae644d
OL
607 return qs.select_related(depth=1).order_by('nom')
608
609 def save_formset(self, request, form, formset, change):
610 instances = formset.save(commit=False)
611 for instance in instances:
612 if instance.__class__ == rh.EmployeCommentaire:
613 instance.owner = request.user
02e69aa2 614 instance.date_creation = datetime.datetime.now()
53ae644d
OL
615 instance.save()
616
22343fe7 617
08faf06e 618class EmployeProxyAdmin(EmployeAdmin):
22343fe7 619 list_display = ('_id', '_apercu', '_nom', '_organigramme')
bd917a45
JPC
620 actions = None
621
622 def __init__(self, *args, **kwargs):
623 super(EmployeProxyAdmin, self).__init__(*args, **kwargs)
624 self.list_display_links = (None, )
08faf06e 625
22343fe7
OL
626 def has_add_permission(self, obj):
627 return False
628
08faf06e
JPC
629 def _organigramme(self, obj):
630 l = []
bab5679b 631 for d in rh.Dossier.objects.filter((Q(date_fin__gt=datetime.date.today()) | Q(date_fin=None)) & (Q(date_debut__lt=datetime.date.today()) | Q(date_debut=None)) ).filter(employe=obj.id).all():
56264a85
JPC
632 organigramme = u"""Organigramme, niveau: <input type="text" id="level_%s" style="width:30px;height:15px;" /> <input type="button" value="Générer" onclick="window.location='%s'+document.getElementById('level_%s').value" />""" % \
633 (d.poste.id, reverse('rho_employe_sans_niveau', args=(d.poste.id,)), d.poste.id)
634 link = u"""<li>%s - [%s] %s : %s</li>""" % \
635 (d.date_debut.year,
08faf06e
JPC
636 d.poste.id,
637 d.poste.nom,
56264a85 638 organigramme
08faf06e
JPC
639 )
640 l.append(link)
641 return "<ul>%s</ul>" % "\n".join(l)
642
643 _organigramme.allow_tags = True
644 _organigramme.short_description = "Organigramme"
645
53ae644d 646
53ae644d
OL
647class EmployeCommentaireAdmin(admin.ModelAdmin):
648 pass
649
650
651class EmployePieceAdmin(admin.ModelAdmin):
652 pass
653
654
655class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 656 list_display = ('nom', '_date_modification', 'user_modification', )
53ae644d 657 inlines = (TypePosteInline,)
22343fe7
OL
658 fieldsets = AUFMetadataAdminMixin.fieldsets + (
659 (None, {'fields': ('nom', )}),)
53ae644d 660
33232787 661 def _date_modification(self, obj):
22343fe7
OL
662 return date(obj.date_modification) \
663 if obj.date_modification is not None else "(aucune)"
33232787
JPC
664 _date_modification.short_description = u'date modification'
665 _date_modification.admin_order_field = 'date_modification'
53ae644d 666
22343fe7 667
95b630cf 668class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
c5964dc2 669 search_fields = ('nom',)
22343fe7
OL
670 list_display = (
671 'nom',
672 'type',
673 'pays',
674 '_date_modification',
675 'user_modification',
676 )
c5964dc2 677 list_filter = ('type', )
53ae644d 678 inlines = (DossierROInline,)
22343fe7
OL
679 fieldsets = AUFMetadataAdminMixin.fieldsets + (
680 (None, {'fields': ('nom', 'type', 'pays',)}),
53ae644d
OL
681 )
682
33232787 683 def _date_modification(self, obj):
22343fe7
OL
684 return date(obj.date_modification) \
685 if obj.date_modification is not None else "(aucune)"
33232787
JPC
686 _date_modification.short_description = u'date modification'
687 _date_modification.admin_order_field = 'date_modification'
688
53ae644d 689
22343fe7
OL
690class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
691 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
692 form = make_ajax_form(rh.Poste, {
693 'implantation': 'implantations',
694 'type_poste': 'typepostes',
695 'responsable': 'postes',
696 'valeur_point_min': 'valeurpoints',
697 'valeur_point_max': 'valeurpoints',
53ae644d
OL
698 })
699 alphabet_filter = 'nom'
22343fe7 700 search_fields = (
397bf8dd 701 'id',
22343fe7 702 'nom',
22343fe7
OL
703 'implantation__nom',
704 'implantation__region__code',
705 'implantation__region__nom',
706 'rh_dossiers__employe__nom',
707 'rh_dossiers__employe__prenom',
708 )
53ae644d 709 list_display = (
e49ac947 710 '_id',
8f3ca727 711 '_apercu',
22343fe7 712 '_nom',
53ae644d 713 '_occupe_par',
22343fe7
OL
714 'implantation',
715 '_service',
1ce2ddb9 716 '_responsable',
352fa696 717 'date_debut',
53ae644d 718 'date_fin',
33232787 719 '_date_modification',
53ae644d 720 'user_modification',
a47ed016 721 '_dae',
53ae644d 722 )
f614ca5c 723 list_filter = (
22343fe7 724 'implantation__region',
53ae644d 725 'implantation',
22343fe7 726 'service',
53ae644d
OL
727 'type_poste',
728 'type_poste__famille_emploi',
4c53dda4 729 'vacant',
53ae644d 730 )
e49ac947 731 list_display_links = ('_nom',)
53ae644d 732 fieldsets = AUFMetadataAdminMixin.fieldsets + (
22343fe7
OL
733 (None, {'fields': (
734 ('nom', 'nom_feminin'),
735 'implantation',
736 'type_poste',
737 'service',
738 'responsable',
739 )}
740 ),
53ae644d 741 ('Contrat', {
22343fe7
OL
742 'fields': ((
743 'regime_travail',
744 'regime_travail_nb_heure_semaine'),
745 )}
746 ),
53ae644d 747 ('Recrutement', {
22343fe7
OL
748 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
749 ),
53ae644d 750 ('Rémunération', {
22343fe7
OL
751 'fields': (('classement_min',
752 'valeur_point_min',
753 'devise_min',
754 'salaire_min',
755 'indemn_min',
756 'autre_min',),
757 ('classement_max',
758 'valeur_point_max',
759 'devise_max',
760 'salaire_max',
761 'indemn_max',
762 'autre_max',),
763 )}),
53ae644d
OL
764 ('Comparatifs de rémunération', {
765 'fields': ('devise_comparaison',
766 ('comp_locale_min', 'comp_locale_max'),
767 ('comp_universite_min', 'comp_universite_max'),
768 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
769 ('comp_ong_min', 'comp_ong_max'),
22343fe7
OL
770 ('comp_autre_min', 'comp_autre_max'))}
771 ),
53ae644d 772 ('Justification', {
22343fe7
OL
773 'fields': ('justification',)}
774 ),
48a6df80 775 ('Autres Méta-données', {
22343fe7
OL
776 'fields': ('date_debut', 'date_fin')}
777 ),
53ae644d
OL
778 )
779
780 inlines = (PosteFinancementInline,
781 PostePieceInline,
782 DossierROInline,
6f037929 783 PosteComparaisonInline,
53ae644d
OL
784 PosteCommentaireInline, )
785
f614ca5c
OL
786 def lookup_allowed(self, key, value):
787 if key in (
788 'date_debut__gte',
789 'date_debut__isnull',
790 'date_fin__lte',
791 'date_fin__isnull',
7f4d1233
OL
792 'implantation__region__id__exact',
793 'implantation__id__exact',
794 'type_poste__id__exact',
795 'type_poste__famille_emploi__id__exact',
796 'service__id__exact',
d48f0922 797 'service__isnull',
7f4d1233 798 'vacant__exact',
c4a762e1 799 'vacant__isnull',
f614ca5c
OL
800 ):
801 return True
802
8f3ca727 803 def _apercu(self, poste):
22343fe7
OL
804 view_link = u"""<a onclick="return showAddAnotherPopup(this);"
805 title="Aperçu du poste"
806 href='%s'>
807 <img src="%simg/loupe.png" />
808 </a>""" % \
8f3ca727 809 (reverse('poste_apercu', args=(poste.id,)),
22343fe7
OL
810 settings.STATIC_URL,)
811 return view_link
8f3ca727 812 _apercu.allow_tags = True
e49ac947
JPC
813 _apercu.short_description = ''
814
a47ed016
OL
815 def _dae(self, poste):
816 apercu_link = ""
817 if dae.ImportPoste.objects.filter(rh=poste).exists():
818 dae_id = dae.ImportPoste.objects.get(rh=poste).dae_id
819 apercu_link = u"""<a title="Aperçu du dossier"
820 onclick="return showAddAnotherPopup(this);"
821 href='%s'>
822 <img src="%simg/loupe.png" />
823 </a>""" % \
824 (reverse('poste_consulter', args=("dae-%s" % dae_id,)),
825 settings.STATIC_URL,
826 )
827 return apercu_link
828 _dae.allow_tags = True
829 _dae.short_description = u"DAE"
830
e49ac947
JPC
831 def _id(self, obj):
832 return "%s" % obj.id
833 _id.short_description = '#'
834 _id.admin_order_field = 'id'
8f3ca727 835
c5964dc2 836 def _service(self, obj):
1b130b25
JPC
837 if obj.service.supprime:
838 return """<span style="color:red">%s</span>""" % obj.service
839 else:
840 return obj.service
6c2b1160 841 _service.short_description = 'Service'
1b130b25 842 _service.allow_tags = True
53ae644d 843
1ce2ddb9
JPC
844 def _responsable(self, obj):
845 try:
22343fe7
OL
846 responsable = u"""<a href="%s"
847 onclick="return showAddAnotherPopup(this)">
848 <img src="%simg/loupe.png"
849 title="Aperçu du poste" />
850 </a>
851 <a href="%s">%s</a>
852 <br />""" % \
853 (reverse('poste_apercu', args=(obj.responsable.id,)),
854 settings.STATIC_URL,
855 reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
856 obj.responsable.nom)
1ce2ddb9
JPC
857 except:
858 responsable = ''
859
860 try:
1ce2ddb9 861 employe_id = obj.responsable.rh_dossiers.all()[0].id
22343fe7
OL
862 employe = u"""<br />
863 <a href="%s"
864 onclick="return showAddAnotherPopup(this)">
865 <img src="%simg/loupe.png"
866 title="Aperçu de l'employé">
867 </a>
868 <a href="%s">%s</a>""" % \
869 (reverse('employe_apercu', args=(employe_id,)),
870 settings.STATIC_URL,
871 reverse('admin:rh_employe_change', args=(employe_id,)),
872 employe)
1ce2ddb9
JPC
873 except:
874 employe = ""
875
876 return "%s %s" % (responsable, employe)
877 _responsable.short_description = 'Responsable'
878 _responsable.allow_tags = True
879
53ae644d 880 def _nom(self, poste):
e49ac947
JPC
881 return """<a href="%s">%s</a>""" % \
882 (reverse('admin:rh_poste_change', args=(poste.id,)),
22343fe7 883 poste.nom)
53ae644d
OL
884 _nom.allow_tags = True
885 _nom.short_description = u'Nom'
886 _nom.admin_order_field = 'nom'
887
33232787
JPC
888 def _date_modification(self, obj):
889 return date(obj.date_modification)
890 _date_modification.short_description = u'date modification'
891 _date_modification.admin_order_field = 'date_modification'
892
53ae644d
OL
893 def _occupe_par(self, obj):
894 """Formatte la méthode Poste.occupe_par() pour l'admin"""
15c5f55a 895 output = u"Vacant"
ae5d7df3 896 if obj.date_fin is not None and obj.date_fin < datetime.date.today():
954ead19 897 return u"s/o"
53ae644d
OL
898 employes = obj.occupe_par()
899 if employes:
900 l = []
901 for e in employes:
22343fe7
OL
902 link = u"""<a href='%s'
903 title='Aperçu de l\'employer'
904 onclick='return showAddAnotherPopup(this)'>
905 <img src='%simg/loupe.png' />
906 </a>
907 <a href='%s'>%s</a>""" % \
b10920ea 908 (reverse('employe_apercu', args=(e.id,)),
822a2c33 909 settings.STATIC_URL,
b10920ea 910 reverse('admin:rh_employe_change', args=(e.id,)),
22343fe7 911 e)
53ae644d
OL
912 l.append(link)
913 output = "\n<br />".join(l)
914 return output
915 _occupe_par.allow_tags = True
22343fe7 916 _occupe_par.short_description = "Occupé par"
53ae644d
OL
917
918 def save_formset(self, request, form, formset, change):
919 instances = formset.save(commit=False)
920 for instance in instances:
921 if instance.__class__ == rh.PosteCommentaire:
922 instance.owner = request.user
02e69aa2 923 instance.date_creation = datetime.datetime.now()
53ae644d
OL
924 instance.save()
925 formset.save_m2m()
926
927
928class PosteCommentaireAdmin(admin.ModelAdmin):
929 pass
930
931
932class PosteFinancementAdmin(admin.ModelAdmin):
933 pass
934
935
936class PostePieceAdmin(admin.ModelAdmin):
937 fk_name = 'poste'
938
939
940class RemunerationAdmin(admin.ModelAdmin):
941 pass
942
943
944class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
22343fe7 945 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
946 (None, {
947 'fields': ('employe', 'implantation', ),
948 }),
949 )
22343fe7 950
53ae644d 951
7ba822a6 952class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
22343fe7
OL
953 list_display = (
954 'nom',
955 '_archive',
956 '_date_modification',
957 'user_modification',
958 )
cbb0373e 959 list_filter = ('archive', )
22343fe7 960 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d 961 (None, {
cbb0373e 962 'fields': ('nom', 'archive', ),
53ae644d
OL
963 }),
964 )
965
33232787 966 def _date_modification(self, obj):
22343fe7
OL
967 return date(obj.date_modification) \
968 if obj.date_modification is not None else "(aucune)"
33232787
JPC
969 _date_modification.short_description = u'date modification'
970 _date_modification.admin_order_field = 'date_modification'
971
5c0f1778
JPC
972class ServiceProxyAdmin(ServiceAdmin):
973 list_display = ('nom', '_organigramme')
8135fc65
JPC
974 actions = None
975
976 def __init__(self, *args, **kwargs):
977 super(ServiceProxyAdmin, self).__init__(*args, **kwargs)
978 self.list_display_links = (None, )
5c0f1778
JPC
979
980 def has_add_permission(self, obj):
981 return False
982
aa2c508e
JPC
983 def has_change_permission(self, request, obj=None):
984 return in_drh_or_admin(request.user)
985
a4ec07f1
JPC
986 def changelist_view(self, request, extra_context=None):
987 if not request.GET.has_key('status__exact'):
988 q = request.GET.copy()
989 q['archive__exact'] = '0'
990 request.GET = q
991 request.META['QUERY_STRING'] = request.GET.urlencode()
992 return super(ServiceProxyAdmin,self).changelist_view(request,
993 extra_context=extra_context)
994
5c0f1778 995 def _organigramme(self, obj):
8135fc65
JPC
996 return """<a href="%s"><strong>Organigramme</strong></a>""" % \
997 (reverse('rho_service', args=(obj.id,)))
5c0f1778
JPC
998 _organigramme.allow_tags = True
999 _organigramme.short_description = "Organigramme"
1000
8135fc65 1001
53ae644d 1002class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 1003 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
22343fe7 1004 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
1005 (None, {
1006 'fields': ('code', 'nom', ),
1007 }),
1008 )
1009
33232787 1010 def _date_modification(self, obj):
22343fe7
OL
1011 return date(obj.date_modification) \
1012 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1013 _date_modification.short_description = u'date modification'
1014 _date_modification.admin_order_field = 'date_modification'
1015
22343fe7 1016
53ae644d 1017class TauxChangeAdmin(admin.ModelAdmin):
22343fe7
OL
1018 list_display = (
1019 'taux',
1020 'devise',
1021 'annee',
1022 '_date_modification',
1023 'user_modification',
1024 )
53ae644d 1025 list_filter = ('devise', )
22343fe7 1026 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
1027 (None, {
1028 'fields': ('taux', 'devise', 'annee', ),
1029 }),
1030 )
1031
33232787 1032 def _date_modification(self, obj):
22343fe7
OL
1033 return date(obj.date_modification) \
1034 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1035 _date_modification.short_description = u'date modification'
1036 _date_modification.admin_order_field = 'date_modification'
1037
22343fe7 1038
53ae644d 1039class TypeContratAdmin(admin.ModelAdmin):
22343fe7
OL
1040 list_display = (
1041 'nom',
1042 'nom_long',
1043 '_date_modification',
1044 'user_modification',
1045 )
1046 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
1047 (None, {
1048 'fields': ('nom', 'nom_long', ),
1049 }),
1050 )
1051
33232787 1052 def _date_modification(self, obj):
22343fe7
OL
1053 return date(obj.date_modification) \
1054 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1055 _date_modification.short_description = u'date modification'
1056 _date_modification.admin_order_field = 'date_modification'
1057
53ae644d
OL
1058
1059class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1060 search_fields = ('nom', 'nom_feminin', )
22343fe7
OL
1061 list_display = (
1062 'nom',
1063 'famille_emploi',
1064 '_date_modification',
1065 'user_modification',
1066 )
53ae644d 1067 list_filter = ('famille_emploi', )
22343fe7 1068 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d 1069 (None, {
22343fe7
OL
1070 'fields': (
1071 'nom',
1072 'nom_feminin',
1073 'is_responsable',
1074 'famille_emploi',
1075 )}
1076 ),
53ae644d
OL
1077 )
1078
33232787 1079 def _date_modification(self, obj):
22343fe7
OL
1080 return date(obj.date_modification) \
1081 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1082 _date_modification.short_description = u'date modification'
1083 _date_modification.admin_order_field = 'date_modification'
1084
53ae644d 1085
7ba822a6 1086class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
22343fe7
OL
1087 list_display = (
1088 'nom',
1089 'type_paiement',
1090 'nature_remuneration',
7ba822a6 1091 '_archive',
22343fe7
OL
1092 '_date_modification',
1093 'user_modification',)
7ba822a6 1094 list_filter = ('archive', )
22343fe7 1095 fieldsets = AUFMetadataAdminMixin.fieldsets + (
7ba822a6
OL
1096 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1097 'archive')}),
53ae644d
OL
1098 )
1099
33232787 1100 def _date_modification(self, obj):
22343fe7
OL
1101 return date(obj.date_modification) \
1102 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1103 _date_modification.short_description = u'date modification'
1104 _date_modification.admin_order_field = 'date_modification'
1105
53ae644d
OL
1106
1107class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 1108 list_display = ('nom', '_date_modification', 'user_modification', )
22343fe7
OL
1109 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1110 (None, {'fields': ('nom', )}),
53ae644d
OL
1111 )
1112
33232787 1113 def _date_modification(self, obj):
22343fe7
OL
1114 return date(obj.date_modification) \
1115 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1116 _date_modification.short_description = u'date modification'
1117 _date_modification.admin_order_field = 'date_modification'
1118
53ae644d
OL
1119
1120class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
22343fe7
OL
1121 list_display = (
1122 '_devise_code',
1123 '_devise_nom',
1124 'annee',
88202dc3 1125 'implantation',
22343fe7
OL
1126 'valeur',
1127 '_date_modification',
1128 'user_modification',
1129 )
88202dc3 1130 list_filter = ('annee', 'devise', 'implantation__region', )
22343fe7
OL
1131 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1132 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
53ae644d
OL
1133 )
1134
33232787 1135 def _date_modification(self, obj):
22343fe7
OL
1136 return date(obj.date_modification) \
1137 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1138 _date_modification.short_description = u'date modification'
1139 _date_modification.admin_order_field = 'date_modification'
1140
53ae644d
OL
1141 def _devise_code(self, obj):
1142 return obj.devise.code
1143 _devise_code.short_description = "Code de la devise"
1144
1145 def _devise_nom(self, obj):
1146 return obj.devise.nom
1147 _devise_nom.short_description = "Nom de la devise"
1148
82af5c19
JPC
1149class ImplantationProxyAdmin(admin.ModelAdmin):
1150 list_display = ('nom', '_organigramme')
8135fc65
JPC
1151 actions = None
1152
1153 def __init__(self, *args, **kwargs):
1154 super(ImplantationProxyAdmin, self).__init__(*args, **kwargs)
1155 self.list_display_links = (None, )
82af5c19
JPC
1156
1157 def has_add_permission(self, obj):
1158 return False
1159
aa2c508e
JPC
1160 def has_change_permission(self, request, obj=None):
1161 return in_drh_or_admin(request.user)
1162
82af5c19 1163 def _organigramme(self, obj):
8135fc65 1164 return """<a href="%s"><strong>Organigramme</strong></a>""" % (reverse('rho_implantation', args=(obj.id,)))
82af5c19
JPC
1165 _organigramme.allow_tags = True
1166 _organigramme.short_description = "Organigramme"
1167
9da4c195
JPC
1168class RegionProxyAdmin(admin.ModelAdmin):
1169 list_display = ('nom', '_organigramme')
8135fc65
JPC
1170 actions = None
1171
1172 def __init__(self, *args, **kwargs):
1173 super(RegionProxyAdmin, self).__init__(*args, **kwargs)
1174 self.list_display_links = (None, )
9da4c195
JPC
1175
1176 def has_add_permission(self, obj):
1177 return False
1178
aa2c508e
JPC
1179 def has_change_permission(self, request, obj=None):
1180 return in_drh_or_admin(request.user)
1181
9da4c195 1182 def _organigramme(self, obj):
8135fc65 1183 return """<a href="%s"><strong>Organigramme</strong></a>""" % (reverse('rho_region', args=(obj.id,)))
9da4c195
JPC
1184 _organigramme.allow_tags = True
1185 _organigramme.short_description = "Organigramme"
1186
1187
82af5c19 1188
53ae644d
OL
1189
1190admin.site.register(rh.Classement, ClassementAdmin)
1191admin.site.register(rh.Devise, DeviseAdmin)
1192admin.site.register(rh.Dossier, DossierAdmin)
22343fe7 1193admin.site.register(EmployeProxy, EmployeProxyAdmin)
5c0f1778 1194admin.site.register(ServiceProxy, ServiceProxyAdmin)
53ae644d
OL
1195admin.site.register(rh.Employe, EmployeAdmin)
1196admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
1197admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1198admin.site.register(rh.Poste, PosteAdmin)
1199admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
1200admin.site.register(rh.Service, ServiceAdmin)
c5964dc2 1201admin.site.register(rh.Statut, StatutAdmin)
53ae644d 1202admin.site.register(rh.TauxChange, TauxChangeAdmin)
c5964dc2 1203admin.site.register(rh.TypeContrat, TypeContratAdmin)
53ae644d
OL
1204admin.site.register(rh.TypePoste, TypePosteAdmin)
1205admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1206admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1207admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
82af5c19 1208admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
9da4c195 1209admin.site.register(RegionProxy, RegionProxyAdmin)