Refactoring des graphs et organigrammes par service
[auf_rh_dae.git] / project / rh / views.py
index d378fff..bbefc74 100644 (file)
@@ -1,16 +1,15 @@
 # -*- encoding: utf-8 -*-
 
-import unicodedata
 from datetime import date
 from itertools import izip
 import networkx as nx
+import pygraphviz as pgv
 
 from django.db.models import Q
 from django.contrib.auth.decorators import login_required
 from django.utils.encoding import smart_str
 from django.shortcuts import render_to_response, get_object_or_404
 from django.template import RequestContext
-from django.core.urlresolvers import reverse
 from django.http import HttpResponse
 
 from datamaster_modeles import models as ref
@@ -20,6 +19,7 @@ from rh.lib import calc_remun
 from rh.decorators import drh_or_admin_required
 from rh.templatetags.rapports import SortHeaders
 from rh.change_list import RechercheTemporelle
+from rh import graph as rh_graph
 
 # pas de reference a DAE devrait etre refactorisé
 from dae.utils import get_employe_from_user
@@ -481,11 +481,15 @@ def employe_apercu(request, employe_id):
 def organigrammes_employe(request, id):
 
     poste = get_object_or_404(rh.Poste, pk=id)
+    dossiers_by_poste = dict((d.poste_id, d) for d in rh.Dossier.objects.select_related('employe', 'poste').all())
+    postes_by_id = dict((p.id, p) for p in rh.Poste.objects.all())
+
+    e = dossiers_by_poste[poste.id].employe
+    name = u"Organigramme de [%s] %s %s" % (e.id, e.nom.upper(), e.prenom)
+    graph = nx.DiGraph(name=name)
+
     if rh.Poste.objects.filter(responsable=poste).count() > 0:
-        graph = nx.DiGraph()
         postes = rh.Poste.objects.select_related('implantation').filter((Q(date_fin__gt=date.today()) | Q(date_fin=None)) & (Q(date_debut__lt=date.today()) | Q(date_debut=None)) ).exclude(supprime=True).exclude(responsable=None).all()
-        dossiers_by_poste = dict((d.poste_id, d) for d in rh.Dossier.objects.select_related('employe', 'poste').all())
-        postes_by_id = dict((p.id, p) for p in rh.Poste.objects.all())
 
         for p in rh.Poste.objects.filter((Q(date_fin__gt=date.today()) | Q(date_fin=None)) & (Q(date_debut__lt=date.today()) | Q(date_debut=None)) ).exclude(supprime=True).exclude(responsable=None).all():
             graph.add_node(p.id)
@@ -495,42 +499,26 @@ def organigrammes_employe(request, id):
                 graph.add_edge(dossiers_by_poste[p.responsable_id].poste_id, p.id)
 
         graph = nx.bfs_tree(graph, poste.id)
-        a = nx.to_agraph(graph)
-
-        poste_remontant = poste
-        while poste_remontant.responsable_id:
-            a.add_edge(poste_remontant.responsable_id, poste_remontant.id)
-            poste_remontant = poste_remontant.responsable
-
-        for n in a.nodes():
-            p = postes_by_id[int(n)]
-            try:
-                d = rh.Dossier.objects.select_related('employe').filter((Q(date_fin__gt=date.today()) | Q(date_fin=None)) & (Q(date_debut__lt=date.today()) | Q(date_debut=None)) & Q(poste=p)).exclude(supprime=True).all()[0]
-
-
-                label = u"%s\\n[%s] %s\\n%s" % (d.poste.nom, d.employe_id, "%s %s" %
-                        (d.employe.nom.upper(), d.employe.prenom),
-                        d.poste.implantation)
-            except IndexError:
-                label = u"%s\\n---\\n%s" % (d.poste.nom, d.poste.implantation)
-                n.attr['fillcolor'] = 'azure4'
-                n.attr['style'] = 'filled'
-
-            label = unicodedata.normalize('NFKD', label).encode('ascii','ignore')
-            n.attr['label'] = label
-            n.attr['href'] = reverse("admin:rh_employe_change", args=(d.employe_id,))
-        
-        #a.graph_attr['normalize'] = True
-        #a.graph_attr['level'] = 2
-        a.layout(prog='dot')
-
-        svg = a.draw(format='svg')
-
-        c = {
-            'svg': svg
-        }
     else:
-        c = {}
+        graph.add_node(poste.id)
+
+    a = nx.to_agraph(graph)
+
+    poste_remontant = poste
+    while poste_remontant.responsable_id:
+        a.add_edge(poste_remontant.responsable_id, poste_remontant.id)
+        poste_remontant = poste_remontant.responsable
+
+    rh_graph.bind_poste_to_graph(a, postes_by_id)
+    #a.graph_attr['normalize'] = True
+    #a.graph_attr['level'] = 2
+    a.layout(prog='dot')
+
+    svg = a.draw(format='svg')
+
+    c = {
+        'svg': svg
+    }
 
     if 'forcer' in request.GET:
         response = HttpResponse(svg, mimetype='image/svg+xml')
@@ -538,3 +526,54 @@ def organigrammes_employe(request, id):
         return response
 
     return render_to_response('rh/organigrammes/employe.html', c, RequestContext(request), mimetype="image/svg+xml")
+
+
+@login_required
+@drh_or_admin_required
+def organigrammes_service(request, id):
+
+    service = get_object_or_404(rh.Service, pk=id)
+
+    postes_by_id = dict((p.id, p) for p in rh.Poste.objects.all())
+
+    postes = rh.Poste.objects.select_related('implantation').filter((Q(date_fin__gt=date.today()) | Q(date_fin=None)) & (Q(date_debut__lt=date.today()) | Q(date_debut=None)) ).filter(service=service).exclude(supprime=True, responsable=None).all()
+
+    graph = pgv.AGraph(directed=True, name=u"Organigramme de « %s »" % service.nom)
+    graph_service = graph.subgraph(nbunch=[1,2], \
+            name="cluster1", \
+            style='filled', \
+            color='lightgrey', \
+            label=service.nom,
+            labeljust="l")
+
+    for p in postes:
+        graph_service.add_node(p.id)
+        if p.responsable_id:
+            graph.add_edge(p.responsable_id, p.id)
+
+    for p_id in graph_service.nodes():
+        if postes_by_id[int(p_id)].responsable_id:
+            poste_remontant = postes_by_id[int(p_id)]
+            while poste_remontant.responsable_id and poste_remontant.responsable_id and poste_remontant.responsable_id != poste_remontant.id:
+                poste_remontant = postes_by_id[poste_remontant.responsable_id]
+                if poste_remontant.responsable_id:
+                    graph.add_edge(poste_remontant.responsable_id, poste_remontant.id)
+
+    rh_graph.bind_poste_to_graph(graph, postes_by_id)
+
+    graph.layout(prog='dot')
+
+    svg = graph.draw(format='svg')
+
+    c = {
+        'svg': svg
+    }
+
+    if 'forcer' in request.GET:
+        response = HttpResponse(svg, mimetype='image/svg+xml')
+        response['Content-Disposition'] = 'attachment; filename=organigramme.svg'
+        return response
+
+    return render_to_response('rh/organigrammes/service.html', c, RequestContext(request), mimetype="image/svg+xml")
+
+