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