[#2658] Intégration de reversion à l'app rh
[auf_rh_dae.git] / project / rh / graph.py
1 # -*- encoding: utf-8 -*-
2
3 from datetime import date
4
5 from django.db.models import Q
6 from django.core.urlresolvers import reverse
7 import pygraphviz as pgv
8
9 from project.rh import models as rh
10
11
12 def bind_poste_to_graph(graph, postes_by_id):
13 for n in graph.nodes():
14 dossiers = rh.Dossier.objects.select_related('employe').filter(
15 (Q(date_fin__gt=date.today()) | Q(date_fin=None)) &
16 (Q(date_debut__lt=date.today()) | Q(date_debut=None)) &
17 Q(poste__id=n)
18 ).all()
19
20 if dossiers:
21 employes = "\\n".join(
22 ["[%s] %s %s" %
23 (d.employe_id, d.employe.nom.upper(),
24 d.employe.prenom
25 ) for d in dossiers]
26 )
27 label = u"%s\\n%s\\n%s" % (
28 d.poste.nom, employes, d.poste.implantation
29 )
30 else:
31 poste = postes_by_id[int(n)]
32 label = u"%s\\n---\\n%s" % (poste.nom, poste.implantation)
33 n.attr['fillcolor'] = 'azure4'
34 n.attr['style'] = 'filled'
35
36 n.attr['label'] = label.encode('ascii', 'xmlcharrefreplace')
37 n.attr['href'] = reverse("admin:rh_poste_change", args=(n,))
38
39 return graph
40
41
42 def organigramme_postes_cluster(cluster_filter, titre=u"Organigramme",
43 cluster_titre=u"Cluster 1"):
44 """
45 Crée un organigramme des postes avec un cluster défini par le keyword
46 qui sera rajouté au queryset en tant que filter.
47
48 cluster_filter doit être un map de format (field: value) qui sera
49 appliqué au queryset.
50
51 Par exemple: cluster_filter={"service__exact": 19}
52 """
53 if type(titre) != type(unicode()):
54 raise "Le titre du graphique doit être un unicode"
55 if type(cluster_titre) != type(unicode()):
56 raise "Le titre du cluster doit être un unicode"
57
58 postes_by_id = dict((p.id, p) for p in rh.Poste.objects.all())
59
60 postes = rh.Poste.objects.select_related('implantation').filter(
61 Q(date_fin__gt=date.today()) | Q(date_fin=None),
62 Q(date_debut__lt=date.today()) | Q(date_debut=None),
63 **cluster_filter
64 ).exclude(responsable=None)
65
66 nom = titre.encode('ascii', 'xmlcharrefreplace')
67 graph = pgv.AGraph(directed=True, name=nom)
68 #pour mettre l'organigramme de gauche à droite (au lieu du haut à bas)
69 #graph.rankdir='LR'
70 graph_service = graph.subgraph(nbunch=[1, 2], name="cluster1")
71 graph_service.graph_attr['style'] = 'filled'
72 graph_service.graph_attr['color'] = 'lightgrey'
73 graph_service.graph_attr['label'] = \
74 cluster_titre.encode('ascii', 'xmlcharrefreplace')
75 graph_service.graph_attr['labeljust'] = 'l'
76
77 for p in postes:
78 graph_service.add_node(p.id)
79 if p.responsable_id:
80 graph.add_edge(p.responsable_id, p.id)
81
82 for p_id in graph_service.nodes():
83 if postes_by_id[int(p_id)].responsable_id:
84 poste_remontant = postes_by_id[int(p_id)]
85 while poste_remontant.responsable_id \
86 and poste_remontant.responsable_id \
87 and poste_remontant.responsable_id != poste_remontant.id:
88 poste_remontant = postes_by_id[poste_remontant.responsable_id]
89 if poste_remontant.responsable_id:
90 graph.add_edge(
91 poste_remontant.responsable_id, poste_remontant.id
92 )
93
94 bind_poste_to_graph(graph, postes_by_id)
95
96 graph.layout(prog='dot')
97
98 svg = graph.draw(format='svg')
99
100 return svg