From 08faf06eee2165d748fefcd8d9c71e2a960424cb Mon Sep 17 00:00:00 2001 From: Jean-Philippe Caissy Date: Wed, 29 Feb 2012 16:27:29 -0600 Subject: [PATCH] Organigramme de poste --- project/menu.py | 4 +++ project/rh/admin.py | 26 ++++++++++++++ project/rh/models.py | 25 ++++++++------ .../admin/rh/employeproxy/change_list.html | 7 ++++ project/rh/templates/rh/organigrammes/employe.html | 1 + project/rh/urls.py | 1 + project/rh/views.py | 36 ++++++++++++++++++++ 7 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 project/rh/templates/admin/rh/employeproxy/change_list.html create mode 100644 project/rh/templates/rh/organigrammes/employe.html diff --git a/project/menu.py b/project/menu.py index 96572e8..1a1ab8e 100644 --- a/project/menu.py +++ b/project/menu.py @@ -52,6 +52,10 @@ class CustomMenu(Menu): #items.MenuItem('Rapport hiérarchique des postes', reverse('rhr_postes_hierarchie')), ] ), + items.MenuItem('Organigrammes', + children=[ + ] + ), ] super(CustomMenu, self).init_with_context(context) diff --git a/project/rh/admin.py b/project/rh/admin.py index 33d79be..8735c2d 100644 --- a/project/rh/admin.py +++ b/project/rh/admin.py @@ -465,6 +465,31 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ProtectRegionMixin, ad instance.date_creation = datetime.datetime.now() instance.save() +class EmployeProxyAdmin(EmployeAdmin): + list_display = ('_id', '_apercu', '_nom', '_organigramme') + list_display_links = ('_nom',) + + def _organigramme(self, obj): + l = [] + for d in obj.rh_dossiers.all().order_by('-date_debut'): + poste = u"""Poste """ % \ + ( reverse('poste_apercu', args=(d.poste.id,)), + settings.STATIC_URL, + reverse('admin:rh_poste_change', args=(d.poste.id,)) + ) + organigramme = u"""Organigramme""" % (reverse('rho_employe', args=(d.poste.id,))) + link = u"""
  • %s %s - %s : [%s] %s
  • """ % \ + (poste, organigramme, + d.date_debut.year, + d.poste.id, + d.poste.nom, + ) + l.append(link) + return "" % "\n".join(l) + + _organigramme.allow_tags = True + _organigramme.short_description = "Organigramme" + class EmployeCommentaireAdmin(admin.ModelAdmin): @@ -855,6 +880,7 @@ class ValeurPointAdmin(AUFMetadataAdminMixin, admin.ModelAdmin): admin.site.register(rh.Classement, ClassementAdmin) admin.site.register(rh.Devise, DeviseAdmin) admin.site.register(rh.Dossier, DossierAdmin) +admin.site.register(rh.EmployeProxy, EmployeProxyAdmin) admin.site.register(rh.Employe, EmployeAdmin) admin.site.register(rh.FamilleEmploi, FamilleEmploiAdmin) admin.site.register(rh.OrganismeBstg, OrganismeBstgAdmin) diff --git a/project/rh/models.py b/project/rh/models.py index 0ada264..12f13aa 100644 --- a/project/rh/models.py +++ b/project/rh/models.py @@ -8,6 +8,7 @@ from django.db.models import signals from django.core.files.storage import FileSystemStorage from django.db import models from django.conf import settings +from django.db.models import Q from auf.django.emploi.models import GENRE_CHOICES, SITUATION_CHOICES # devrait plutot être dans references from auf.django.metadata.models import AUFMetadata @@ -197,9 +198,9 @@ class Poste_(AUFMetadata): def __unicode__(self): representation = u'%s - %s [%s]' % (self.implantation, self.nom, self.id) + return "%s" % self.id return representation - prefix_implantation = "implantation__region" def get_regions(self): return [self.implantation.region] @@ -473,6 +474,12 @@ class EmployeCommentaire(Commentaire): verbose_name = u"Employé commentaire" verbose_name_plural = u"Employé commentaires" +class EmployeProxy(Employe): + + class Meta: + proxy = True + verbose_name = u"Organigramme des employés" + verbose_name_plural = u"Organigramme des employés" LIEN_PARENTE_CHOICES = ( ('Conjoint', 'Conjoint'), @@ -640,7 +647,6 @@ class Dossier_(AUFMetadata): except: return None - class Dossier(Dossier_): __doc__ = Dossier_.__doc__ poste = models.ForeignKey('%s.Poste' % app_context(), @@ -658,7 +664,7 @@ class DossierPiece_(models.Model): """Documents relatifs au Dossier (à l'occupation de ce poste par employé). Ex.: Lettre de motivation. """ - dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='%(app_label)s_dossierpieces') + dossier = models.ForeignKey('%s.Dossier' % app_context(), db_column='dossier', related_name='+') nom = models.CharField(verbose_name = u"Nom", max_length=255) fichier = models.FileField(verbose_name = u"Fichier", upload_to=dossier_piece_dispatch, @@ -699,7 +705,7 @@ class DossierComparaison_(models.Model): abstract = True def taux_devise(self): - annee = self.dossier.contrat_date_debut.year + annee = self.dossier.poste.date_debut.year taux = [tc.taux for tc in TauxChange.objects.filter(devise=self.devise, annee=annee)] taux = set(taux) if len(taux) != 1: @@ -759,17 +765,15 @@ class Remuneration_(RemunerationMixin): return 1 annee = datetime.datetime.now().year - if self.dossier.poste.date_debut is not None: - annee = self.dossier.poste.date_debut.year - if self.dossier.date_debut is not None: - annee = self.dossier.date_debut.year if self.date_debut is not None: annee = self.date_debut.year + if self.dossier.poste.date_debut is not None: + annee = self.dossier.poste.date_debut.year taux = [tc.taux for tc in TauxChange.objects.filter(devise=self.devise_id, annee=annee)] taux = set(taux) if len(taux) != 1: - raise Exception(u"Le taux de la devise %s n'a pas n'existe pas pour %s ou il existe plusieurs taux pour la même année %s (%s)" % (self.devise.code, annee, taux, self.dossier)) + raise Exception(u"Le taux de la devise %s n'a pas n'existe pas pour %s ou il existe plusieurs taux pour la même année" % (self.devise.id, annee)) else: return list(taux)[0] @@ -1099,7 +1103,8 @@ class Classement_(AUFMetadata): verbose_name_plural = u"Classements" def __unicode__(self): - return u'%s.%s.%s' % (self.type, self.echelon, self.degre, ) + return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre, + self.coefficient) class Classement(Classement_): __doc__ = Classement_.__doc__ diff --git a/project/rh/templates/admin/rh/employeproxy/change_list.html b/project/rh/templates/admin/rh/employeproxy/change_list.html new file mode 100644 index 0000000..b0b747f --- /dev/null +++ b/project/rh/templates/admin/rh/employeproxy/change_list.html @@ -0,0 +1,7 @@ +{% extends "alphafilter/change_list.html" %} +{% load change_list %} + +{% block search %} + {{ block.super }} + {% recherche_par_annees cl %} +{% endblock %} diff --git a/project/rh/templates/rh/organigrammes/employe.html b/project/rh/templates/rh/organigrammes/employe.html new file mode 100644 index 0000000..840b13f --- /dev/null +++ b/project/rh/templates/rh/organigrammes/employe.html @@ -0,0 +1 @@ + diff --git a/project/rh/urls.py b/project/rh/urls.py index 4479d29..48aedd2 100644 --- a/project/rh/urls.py +++ b/project/rh/urls.py @@ -15,4 +15,5 @@ urlpatterns = patterns( url(r'^admin/rh/dossier/(\d+)/apercu/$', 'dossier_apercu', name='dossier_apercu'), url(r'^admin/rh/employe/(\d+)/apercu/$', 'employe_apercu', name='employe_apercu'), url(r'^admin/rh/poste/(\d+)/apercu/$', 'poste_apercu', name='poste_apercu'), + url(r'^admin/rh/organigrammes/employe/(\d+)$', 'organigrammes_employe', name='rho_employe'), ) diff --git a/project/rh/views.py b/project/rh/views.py index 27dc661..bb660ae 100644 --- a/project/rh/views.py +++ b/project/rh/views.py @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- from datetime import date from itertools import izip +from base64 import b64encode import networkx as nx from django.db.models import Q @@ -89,6 +90,11 @@ def rapports_postes_hierarchie(request): @login_required @drh_or_admin_required +def hierarchie_poste(request): + pass + +@login_required +@drh_or_admin_required def rapports_poste(request): lookup_params = dict(request.GET.items()) @@ -468,4 +474,34 @@ def employe_apercu(request, employe_id): } return render_to_response('admin/rh/employe/apercu.html', c, RequestContext(request)) +def organigrammes_employe(request, id): + + poste = get_object_or_404(rh.Poste, pk=id) + + graph = nx.DiGraph() + dossiers = rh.Dossier.objects.select_related('employe', 'poste', 'poste__implantation').filter((Q(poste__date_fin__gt=date.today()) | Q(poste__date_fin=None)) & (Q(poste__date_debut__lt=date.today()) | Q(poste__date_debut=None)) ).exclude(poste__supprime=True).exclude(poste__responsable=None).all() + dossiers_by_poste = dict((d.poste_id, d) for d in rh.Dossier.objects.select_related('employe', 'poste').all()) + for p in rh.Poste.objects.all(): + graph.add_node(p.id) + + for d in dossiers: + if d.poste.responsable_id != d.poste.id: + graph.add_edge(dossiers_by_poste[d.poste.responsable_id].poste_id, d.poste.id) + graph = nx.bfs_tree(graph, id) + a = nx.to_agraph(graph) + for n in a.nodes(): + d = dossiers_by_poste[int(n)] + n.attr['label'] = u"%s\\n%s\\n%s" % (d.poste.nom, "%s %s" % (d.employe.nom.upper(), d.employe.prenom), d.poste.implantation) + + a.graph_attr['normalize'] = True + a.graph_attr['level'] = 2 + a.layout(prog='dot') + + png = a.draw(format='png') + + + c = { + 'png': b64encode(png) + } + return render_to_response('rh/organigrammes/employe.html', c, RequestContext(request)) -- 1.7.10.4