poste import + liens dans RH
[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')
08faf06e
JPC
620 list_display_links = ('_nom',)
621
22343fe7
OL
622 def has_add_permission(self, obj):
623 return False
624
08faf06e
JPC
625 def _organigramme(self, obj):
626 l = []
bab5679b 627 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
628 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" />""" % \
629 (d.poste.id, reverse('rho_employe_sans_niveau', args=(d.poste.id,)), d.poste.id)
630 link = u"""<li>%s - [%s] %s : %s</li>""" % \
631 (d.date_debut.year,
08faf06e
JPC
632 d.poste.id,
633 d.poste.nom,
56264a85 634 organigramme
08faf06e
JPC
635 )
636 l.append(link)
637 return "<ul>%s</ul>" % "\n".join(l)
638
639 _organigramme.allow_tags = True
640 _organigramme.short_description = "Organigramme"
641
53ae644d 642
53ae644d
OL
643class EmployeCommentaireAdmin(admin.ModelAdmin):
644 pass
645
646
647class EmployePieceAdmin(admin.ModelAdmin):
648 pass
649
650
651class FamilleEmploiAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 652 list_display = ('nom', '_date_modification', 'user_modification', )
53ae644d 653 inlines = (TypePosteInline,)
22343fe7
OL
654 fieldsets = AUFMetadataAdminMixin.fieldsets + (
655 (None, {'fields': ('nom', )}),)
53ae644d 656
33232787 657 def _date_modification(self, obj):
22343fe7
OL
658 return date(obj.date_modification) \
659 if obj.date_modification is not None else "(aucune)"
33232787
JPC
660 _date_modification.short_description = u'date modification'
661 _date_modification.admin_order_field = 'date_modification'
53ae644d 662
22343fe7 663
95b630cf 664class OrganismeBstgAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
c5964dc2 665 search_fields = ('nom',)
22343fe7
OL
666 list_display = (
667 'nom',
668 'type',
669 'pays',
670 '_date_modification',
671 'user_modification',
672 )
c5964dc2 673 list_filter = ('type', )
53ae644d 674 inlines = (DossierROInline,)
22343fe7
OL
675 fieldsets = AUFMetadataAdminMixin.fieldsets + (
676 (None, {'fields': ('nom', 'type', 'pays',)}),
53ae644d
OL
677 )
678
33232787 679 def _date_modification(self, obj):
22343fe7
OL
680 return date(obj.date_modification) \
681 if obj.date_modification is not None else "(aucune)"
33232787
JPC
682 _date_modification.short_description = u'date modification'
683 _date_modification.admin_order_field = 'date_modification'
684
53ae644d 685
22343fe7
OL
686class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, \
687 ProtectRegionMixin, admin.ModelAdmin, AjaxSelect,):
688 form = make_ajax_form(rh.Poste, {
689 'implantation': 'implantations',
690 'type_poste': 'typepostes',
691 'responsable': 'postes',
692 'valeur_point_min': 'valeurpoints',
693 'valeur_point_max': 'valeurpoints',
53ae644d
OL
694 })
695 alphabet_filter = 'nom'
22343fe7 696 search_fields = (
397bf8dd 697 'id',
22343fe7 698 'nom',
22343fe7
OL
699 'implantation__nom',
700 'implantation__region__code',
701 'implantation__region__nom',
702 'rh_dossiers__employe__nom',
703 'rh_dossiers__employe__prenom',
704 )
53ae644d 705 list_display = (
e49ac947 706 '_id',
8f3ca727 707 '_apercu',
22343fe7 708 '_nom',
53ae644d 709 '_occupe_par',
22343fe7
OL
710 'implantation',
711 '_service',
1ce2ddb9 712 '_responsable',
352fa696 713 'date_debut',
53ae644d 714 'date_fin',
33232787 715 '_date_modification',
53ae644d 716 'user_modification',
a47ed016 717 '_dae',
53ae644d 718 )
f614ca5c 719 list_filter = (
22343fe7 720 'implantation__region',
53ae644d 721 'implantation',
22343fe7 722 'service',
53ae644d
OL
723 'type_poste',
724 'type_poste__famille_emploi',
4c53dda4 725 'vacant',
53ae644d 726 )
e49ac947 727 list_display_links = ('_nom',)
53ae644d 728 fieldsets = AUFMetadataAdminMixin.fieldsets + (
22343fe7
OL
729 (None, {'fields': (
730 ('nom', 'nom_feminin'),
731 'implantation',
732 'type_poste',
733 'service',
734 'responsable',
735 )}
736 ),
53ae644d 737 ('Contrat', {
22343fe7
OL
738 'fields': ((
739 'regime_travail',
740 'regime_travail_nb_heure_semaine'),
741 )}
742 ),
53ae644d 743 ('Recrutement', {
22343fe7
OL
744 'fields': (('local', 'expatrie', 'mise_a_disposition', 'appel'),)}
745 ),
53ae644d 746 ('Rémunération', {
22343fe7
OL
747 'fields': (('classement_min',
748 'valeur_point_min',
749 'devise_min',
750 'salaire_min',
751 'indemn_min',
752 'autre_min',),
753 ('classement_max',
754 'valeur_point_max',
755 'devise_max',
756 'salaire_max',
757 'indemn_max',
758 'autre_max',),
759 )}),
53ae644d
OL
760 ('Comparatifs de rémunération', {
761 'fields': ('devise_comparaison',
762 ('comp_locale_min', 'comp_locale_max'),
763 ('comp_universite_min', 'comp_universite_max'),
764 ('comp_fonctionpub_min', 'comp_fonctionpub_max'),
765 ('comp_ong_min', 'comp_ong_max'),
22343fe7
OL
766 ('comp_autre_min', 'comp_autre_max'))}
767 ),
53ae644d 768 ('Justification', {
22343fe7
OL
769 'fields': ('justification',)}
770 ),
48a6df80 771 ('Autres Méta-données', {
22343fe7
OL
772 'fields': ('date_debut', 'date_fin')}
773 ),
53ae644d
OL
774 )
775
776 inlines = (PosteFinancementInline,
777 PostePieceInline,
778 DossierROInline,
6f037929 779 PosteComparaisonInline,
53ae644d
OL
780 PosteCommentaireInline, )
781
f614ca5c
OL
782 def lookup_allowed(self, key, value):
783 if key in (
784 'date_debut__gte',
785 'date_debut__isnull',
786 'date_fin__lte',
787 'date_fin__isnull',
7f4d1233
OL
788 'implantation__region__id__exact',
789 'implantation__id__exact',
790 'type_poste__id__exact',
791 'type_poste__famille_emploi__id__exact',
792 'service__id__exact',
d48f0922 793 'service__isnull',
7f4d1233 794 'vacant__exact',
c4a762e1 795 'vacant__isnull',
f614ca5c
OL
796 ):
797 return True
798
8f3ca727 799 def _apercu(self, poste):
22343fe7
OL
800 view_link = u"""<a onclick="return showAddAnotherPopup(this);"
801 title="Aperçu du poste"
802 href='%s'>
803 <img src="%simg/loupe.png" />
804 </a>""" % \
8f3ca727 805 (reverse('poste_apercu', args=(poste.id,)),
22343fe7
OL
806 settings.STATIC_URL,)
807 return view_link
8f3ca727 808 _apercu.allow_tags = True
e49ac947
JPC
809 _apercu.short_description = ''
810
a47ed016
OL
811 def _dae(self, poste):
812 apercu_link = ""
813 if dae.ImportPoste.objects.filter(rh=poste).exists():
814 dae_id = dae.ImportPoste.objects.get(rh=poste).dae_id
815 apercu_link = u"""<a title="Aperçu du dossier"
816 onclick="return showAddAnotherPopup(this);"
817 href='%s'>
818 <img src="%simg/loupe.png" />
819 </a>""" % \
820 (reverse('poste_consulter', args=("dae-%s" % dae_id,)),
821 settings.STATIC_URL,
822 )
823 return apercu_link
824 _dae.allow_tags = True
825 _dae.short_description = u"DAE"
826
e49ac947
JPC
827 def _id(self, obj):
828 return "%s" % obj.id
829 _id.short_description = '#'
830 _id.admin_order_field = 'id'
8f3ca727 831
c5964dc2 832 def _service(self, obj):
1b130b25
JPC
833 if obj.service.supprime:
834 return """<span style="color:red">%s</span>""" % obj.service
835 else:
836 return obj.service
6c2b1160 837 _service.short_description = 'Service'
1b130b25 838 _service.allow_tags = True
53ae644d 839
1ce2ddb9
JPC
840 def _responsable(self, obj):
841 try:
22343fe7
OL
842 responsable = u"""<a href="%s"
843 onclick="return showAddAnotherPopup(this)">
844 <img src="%simg/loupe.png"
845 title="Aperçu du poste" />
846 </a>
847 <a href="%s">%s</a>
848 <br />""" % \
849 (reverse('poste_apercu', args=(obj.responsable.id,)),
850 settings.STATIC_URL,
851 reverse('admin:rh_poste_change', args=(obj.responsable.id,)),
852 obj.responsable.nom)
1ce2ddb9
JPC
853 except:
854 responsable = ''
855
856 try:
1ce2ddb9 857 employe_id = obj.responsable.rh_dossiers.all()[0].id
22343fe7
OL
858 employe = u"""<br />
859 <a href="%s"
860 onclick="return showAddAnotherPopup(this)">
861 <img src="%simg/loupe.png"
862 title="Aperçu de l'employé">
863 </a>
864 <a href="%s">%s</a>""" % \
865 (reverse('employe_apercu', args=(employe_id,)),
866 settings.STATIC_URL,
867 reverse('admin:rh_employe_change', args=(employe_id,)),
868 employe)
1ce2ddb9
JPC
869 except:
870 employe = ""
871
872 return "%s %s" % (responsable, employe)
873 _responsable.short_description = 'Responsable'
874 _responsable.allow_tags = True
875
53ae644d 876 def _nom(self, poste):
e49ac947
JPC
877 return """<a href="%s">%s</a>""" % \
878 (reverse('admin:rh_poste_change', args=(poste.id,)),
22343fe7 879 poste.nom)
53ae644d
OL
880 _nom.allow_tags = True
881 _nom.short_description = u'Nom'
882 _nom.admin_order_field = 'nom'
883
33232787
JPC
884 def _date_modification(self, obj):
885 return date(obj.date_modification)
886 _date_modification.short_description = u'date modification'
887 _date_modification.admin_order_field = 'date_modification'
888
53ae644d
OL
889 def _occupe_par(self, obj):
890 """Formatte la méthode Poste.occupe_par() pour l'admin"""
15c5f55a 891 output = u"Vacant"
3195667e 892 if obj.date_fin is not None and obj.date_fin < datetime.date.now():
954ead19 893 return u"s/o"
53ae644d
OL
894 employes = obj.occupe_par()
895 if employes:
896 l = []
897 for e in employes:
22343fe7
OL
898 link = u"""<a href='%s'
899 title='Aperçu de l\'employer'
900 onclick='return showAddAnotherPopup(this)'>
901 <img src='%simg/loupe.png' />
902 </a>
903 <a href='%s'>%s</a>""" % \
b10920ea 904 (reverse('employe_apercu', args=(e.id,)),
822a2c33 905 settings.STATIC_URL,
b10920ea 906 reverse('admin:rh_employe_change', args=(e.id,)),
22343fe7 907 e)
53ae644d
OL
908 l.append(link)
909 output = "\n<br />".join(l)
910 return output
911 _occupe_par.allow_tags = True
22343fe7 912 _occupe_par.short_description = "Occupé par"
53ae644d
OL
913
914 def save_formset(self, request, form, formset, change):
915 instances = formset.save(commit=False)
916 for instance in instances:
917 if instance.__class__ == rh.PosteCommentaire:
918 instance.owner = request.user
02e69aa2 919 instance.date_creation = datetime.datetime.now()
53ae644d
OL
920 instance.save()
921 formset.save_m2m()
922
923
924class PosteCommentaireAdmin(admin.ModelAdmin):
925 pass
926
927
928class PosteFinancementAdmin(admin.ModelAdmin):
929 pass
930
931
932class PostePieceAdmin(admin.ModelAdmin):
933 fk_name = 'poste'
934
935
936class RemunerationAdmin(admin.ModelAdmin):
937 pass
938
939
940class ResponsableImplantationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
22343fe7 941 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
942 (None, {
943 'fields': ('employe', 'implantation', ),
944 }),
945 )
22343fe7 946
53ae644d 947
7ba822a6 948class ServiceAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
22343fe7
OL
949 list_display = (
950 'nom',
951 '_archive',
952 '_date_modification',
953 'user_modification',
954 )
cbb0373e 955 list_filter = ('archive', )
22343fe7 956 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d 957 (None, {
cbb0373e 958 'fields': ('nom', 'archive', ),
53ae644d
OL
959 }),
960 )
961
33232787 962 def _date_modification(self, obj):
22343fe7
OL
963 return date(obj.date_modification) \
964 if obj.date_modification is not None else "(aucune)"
33232787
JPC
965 _date_modification.short_description = u'date modification'
966 _date_modification.admin_order_field = 'date_modification'
967
968
5c0f1778
JPC
969class ServiceProxyAdmin(ServiceAdmin):
970 list_display = ('nom', '_organigramme')
971 list_display_links = ('nom',)
972
973 def has_add_permission(self, obj):
974 return False
975
976 def _organigramme(self, obj):
1035822c 977 return """<a href="%s">Organigramme</a>""" % (reverse('rho_service', args=(obj.id,)))
5c0f1778
JPC
978 _organigramme.allow_tags = True
979 _organigramme.short_description = "Organigramme"
980
53ae644d 981class StatutAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 982 list_display = ('code', 'nom', '_date_modification', 'user_modification', )
22343fe7 983 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
984 (None, {
985 'fields': ('code', 'nom', ),
986 }),
987 )
988
33232787 989 def _date_modification(self, obj):
22343fe7
OL
990 return date(obj.date_modification) \
991 if obj.date_modification is not None else "(aucune)"
33232787
JPC
992 _date_modification.short_description = u'date modification'
993 _date_modification.admin_order_field = 'date_modification'
994
22343fe7 995
53ae644d 996class TauxChangeAdmin(admin.ModelAdmin):
22343fe7
OL
997 list_display = (
998 'taux',
999 'devise',
1000 'annee',
1001 '_date_modification',
1002 'user_modification',
1003 )
53ae644d 1004 list_filter = ('devise', )
22343fe7 1005 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
1006 (None, {
1007 'fields': ('taux', 'devise', 'annee', ),
1008 }),
1009 )
1010
33232787 1011 def _date_modification(self, obj):
22343fe7
OL
1012 return date(obj.date_modification) \
1013 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1014 _date_modification.short_description = u'date modification'
1015 _date_modification.admin_order_field = 'date_modification'
1016
22343fe7 1017
53ae644d 1018class TypeContratAdmin(admin.ModelAdmin):
22343fe7
OL
1019 list_display = (
1020 'nom',
1021 'nom_long',
1022 '_date_modification',
1023 'user_modification',
1024 )
1025 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d
OL
1026 (None, {
1027 'fields': ('nom', 'nom_long', ),
1028 }),
1029 )
1030
33232787 1031 def _date_modification(self, obj):
22343fe7
OL
1032 return date(obj.date_modification) \
1033 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1034 _date_modification.short_description = u'date modification'
1035 _date_modification.admin_order_field = 'date_modification'
1036
53ae644d
OL
1037
1038class TypePosteAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
1039 search_fields = ('nom', 'nom_feminin', )
22343fe7
OL
1040 list_display = (
1041 'nom',
1042 'famille_emploi',
1043 '_date_modification',
1044 'user_modification',
1045 )
53ae644d 1046 list_filter = ('famille_emploi', )
22343fe7 1047 fieldsets = AUFMetadataAdminMixin.fieldsets + (
53ae644d 1048 (None, {
22343fe7
OL
1049 'fields': (
1050 'nom',
1051 'nom_feminin',
1052 'is_responsable',
1053 'famille_emploi',
1054 )}
1055 ),
53ae644d
OL
1056 )
1057
33232787 1058 def _date_modification(self, obj):
22343fe7
OL
1059 return date(obj.date_modification) \
1060 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1061 _date_modification.short_description = u'date modification'
1062 _date_modification.admin_order_field = 'date_modification'
1063
53ae644d 1064
7ba822a6 1065class TypeRemunerationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin, ArchiveMixin):
22343fe7
OL
1066 list_display = (
1067 'nom',
1068 'type_paiement',
1069 'nature_remuneration',
7ba822a6 1070 '_archive',
22343fe7
OL
1071 '_date_modification',
1072 'user_modification',)
7ba822a6 1073 list_filter = ('archive', )
22343fe7 1074 fieldsets = AUFMetadataAdminMixin.fieldsets + (
7ba822a6
OL
1075 (None, {'fields': ('nom', 'type_paiement', 'nature_remuneration',
1076 'archive')}),
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
OL
1085
1086class TypeRevalorisationAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
33232787 1087 list_display = ('nom', '_date_modification', 'user_modification', )
22343fe7
OL
1088 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1089 (None, {'fields': ('nom', )}),
53ae644d
OL
1090 )
1091
33232787 1092 def _date_modification(self, obj):
22343fe7
OL
1093 return date(obj.date_modification) \
1094 if obj.date_modification is not None else "(aucune)"
33232787
JPC
1095 _date_modification.short_description = u'date modification'
1096 _date_modification.admin_order_field = 'date_modification'
1097
53ae644d
OL
1098
1099class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
22343fe7
OL
1100 list_display = (
1101 '_devise_code',
1102 '_devise_nom',
1103 'annee',
1104 'valeur',
1105 '_date_modification',
1106 'user_modification',
1107 )
c5964dc2 1108 list_filter = ('annee', 'devise', )
22343fe7
OL
1109 fieldsets = AUFMetadataAdminMixin.fieldsets + (
1110 (None, {'fields': ('valeur', 'devise', 'implantation', 'annee', )}),
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 def _devise_code(self, obj):
1120 return obj.devise.code
1121 _devise_code.short_description = "Code de la devise"
1122
1123 def _devise_nom(self, obj):
1124 return obj.devise.nom
1125 _devise_nom.short_description = "Nom de la devise"
1126
82af5c19
JPC
1127class ImplantationProxyAdmin(admin.ModelAdmin):
1128 list_display = ('nom', '_organigramme')
1129 list_display_links = ('nom',)
1130
1131 def has_add_permission(self, obj):
1132 return False
1133
1134 def _organigramme(self, obj):
1135 return """<a href="%s">Organigramme</a>""" % (reverse('rho_implantation', args=(obj.id,)))
1136 _organigramme.allow_tags = True
1137 _organigramme.short_description = "Organigramme"
1138
9da4c195
JPC
1139class RegionProxyAdmin(admin.ModelAdmin):
1140 list_display = ('nom', '_organigramme')
1141 list_display_links = ('nom',)
1142
1143 def has_add_permission(self, obj):
1144 return False
1145
1146 def _organigramme(self, obj):
1147 return """<a href="%s">Organigramme</a>""" % (reverse('rho_region', args=(obj.id,)))
1148 _organigramme.allow_tags = True
1149 _organigramme.short_description = "Organigramme"
1150
1151
82af5c19 1152
53ae644d
OL
1153
1154admin.site.register(rh.Classement, ClassementAdmin)
1155admin.site.register(rh.Devise, DeviseAdmin)
1156admin.site.register(rh.Dossier, DossierAdmin)
22343fe7 1157admin.site.register(EmployeProxy, EmployeProxyAdmin)
5c0f1778 1158admin.site.register(ServiceProxy, ServiceProxyAdmin)
53ae644d
OL
1159admin.site.register(rh.Employe, EmployeAdmin)
1160admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin)
1161admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin)
1162admin.site.register(rh.Poste, PosteAdmin)
1163admin.site.register(rh.ResponsableImplantation, ResponsableImplantationAdmin)
1164admin.site.register(rh.Service, ServiceAdmin)
c5964dc2 1165admin.site.register(rh.Statut, StatutAdmin)
53ae644d 1166admin.site.register(rh.TauxChange, TauxChangeAdmin)
c5964dc2 1167admin.site.register(rh.TypeContrat, TypeContratAdmin)
53ae644d
OL
1168admin.site.register(rh.TypePoste, TypePosteAdmin)
1169admin.site.register(rh.TypeRemuneration, TypeRemunerationAdmin)
1170admin.site.register(rh.TypeRevalorisation, TypeRevalorisationAdmin)
1171admin.site.register(rh.ValeurPoint, ValeurPointAdmin)
82af5c19 1172admin.site.register(ImplantationProxy, ImplantationProxyAdmin)
9da4c195 1173admin.site.register(RegionProxy, RegionProxyAdmin)