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