Account_Report:Tree-structured report content for Indicators.
[odoo/odoo.git] / addons / account_report / report / print_indicator.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 # -*- encoding: utf-8 -*-
24 ##############################################################################
25 #
26 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
27 #
28 # $Id$
29 #
30 # WARNING: This program as such is intended to be used by professional
31 # programmers who take the whole responsability of assessing all potential
32 # consequences resulting from its eventual inadequacies and bugs
33 # End users who are looking for a ready-to-use solution with commercial
34 # garantees and support are strongly adviced to contract a Free Software
35 # Service Company
36 #
37 # This program is Free Software; you can redistribute it and/or
38 # modify it under the terms of the GNU General Public License
39 # as published by the Free Software Foundation; either version 2
40 # of the License, or (at your option) any later version.
41 #
42 # This program is distributed in the hope that it will be useful,
43 # but WITHOUT ANY WARRANTY; without even the implied warranty of
44 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45 # GNU General Public License for more details.
46 #
47 # You should have received a copy of the GNU General Public License
48 # along with this program; if not, write to the Free Software
49 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
50 #
51 ##############################################################################
52
53 import pooler
54 import time
55 from report import report_sxw
56
57 #from report.interface import report_int
58 #from reportlab.graphics.shapes import Drawing
59 #from reportlab.graphics.charts.barcharts import VerticalBarChart
60 #import reportlab.lib.colors as colors
61 #from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection
62 #from reportlab.graphics.charts.textlabels import BarChartLabel
63 #from reportlab.graphics import renderPM
64 #from report.render import render
65 #from report.interface import report_int
66 from pychart import *
67 import StringIO
68 theme.use_color = 1
69 theme.default_font_family = "Helvetica-Bold"
70 theme.default_font_size = 18
71 theme.default_line_width = 1.0
72 import tools
73 import os
74
75
76 parents = {
77     'tr':1,
78     'li':1,
79     'story': 0,
80     'section': 0
81 }
82
83 class accounting_report_indicator(report_sxw.rml_parse):
84
85     def __init__(self, cr, uid, name, context):
86         super(accounting_report_indicator, self).__init__(cr, uid, name, context)
87         self.ret_list = []
88         self.localcontext.update({
89             'time': time,
90             'getgraph': self.getgraph,
91             'lines':self.lines,
92             'getarray':self.getarray,
93             'gettree':self.gettree,
94         })
95         self.count=0
96         self.treecount=0
97         self.list=[]
98         self.header_name=self.header_val=[]
99         self.main_dict={}
100
101     def repeatIn(self, lst, name, nodes_parent=False,td=False,width=[],value=[],type=[]):
102         self._node.data = ''
103         node = self._find_parent(self._node, nodes_parent or parents)
104         ns = node.nextSibling
105 #start
106         if not name=='array':
107             return super(accounting_report_indicator,self).repeatIn(lst, name, nodes_parent=False)
108
109         value=['Data']
110         value.extend(self.header_name)
111         type=['string'].extend(['float']*len(self.header_name))
112         width=[40]*(len(self.header_name)+1)
113
114         if not lst:
115             lst.append(1)
116         for ns in node.childNodes :
117             if ns and ns.nodeName!='#text' and ns.tagName=='blockTable' and td :
118                 width_str = ns._attrs['colWidths'].nodeValue
119                 ns.removeAttribute('colWidths')
120                 total_td = td * len(value)
121
122                 if not width:
123                     for v in value:
124                         width.append(30)
125                 for v in range(len(value)):
126                     width_str +=',%d'%width[v]
127
128                 ns.setAttribute('colWidths',width_str)
129
130                 child_list =  ns.childNodes
131                 check=0
132                 for child in child_list:
133                     if child.nodeName=='tr':
134                         lc = child.childNodes[1]
135 #                        for t in range(td):
136                         i=0
137                         for v in value:
138                             newnode = lc.cloneNode(1)
139                             if check==1:
140                                 t1="[[ %s['%s'] ]]"%(name,v)
141                             else:
142                                 t1="%s"%(v)
143                             newnode.childNodes[1].lastChild.data = t1
144                             child.appendChild(newnode)
145                             newnode=False
146                             i+=1
147                         check=1
148
149         return super(accounting_report_indicator,self).repeatIn(lst, name, nodes_parent=False)
150
151     def lines(self,data):
152         res={}
153         result=[]
154         ind_ids=self.pool.get('account.report.report').search(self.cr,self.uid,[])
155         obj_inds=self.pool.get('account.report.report').browse(self.cr,self.uid,ind_ids)
156
157 #        def find_child(obj):
158 #            self.list.append(obj)
159 #            if obj.child_ids:
160 #                for child in obj.child_ids:
161 #                    find_child(child)
162 #            return True
163 #
164 #        find_child(obj_inds)
165
166         for obj_ind in obj_inds:
167             res = {
168                 'id':obj_ind.id,
169                 'name':obj_ind.name,
170                 'code':obj_ind.code,
171                 'expression':obj_ind.expression,
172                 'disp_graph':obj_ind.disp_graph,
173                 'disp_tree':obj_ind.disp_tree,
174                 'note':obj_ind.note,
175                 'type':obj_ind.type,
176                 }
177             result.append(res)
178         return result
179
180     def getarray(self,data,object):
181         res={}
182         result=[]
183         self.getgraph(data,object,intercall=True)
184         self.header_val=[str(x) for x in self.header_val]
185         temp_dict=zip(self.header_name,self.header_val)
186         res=dict(temp_dict)
187         res['Data']='Value'
188         result.append(res)
189         return result
190
191     def gettree(self,data,object):
192         pool_history=self.pool.get('account.report.report')
193         obj_history=pool_history.browse(self.cr,self.uid,object['id'])
194         result=[]
195         self.treecount +=1
196         path=tools.config['addons_path']+"/account_report/tmp_images/tree_image"
197
198         dirname =tools.config['addons_path']+'/account_report/tmp_images/'
199         if not os.path.isdir(dirname):
200             os.mkdir(dirname)
201
202         can = canvas.init('tree_image'+str(self.treecount)+".png")
203
204         theme.default_font_size = 12
205
206         self.child_dist=0
207
208         level=0
209         self.level=0
210         self.child_dist=0
211
212         def draw_tree(obj_history,base_x,base_y,level=0,i=0):
213             self.line_y=base_y
214             if obj_history.child_ids:
215                 if self.child_dist:
216                     diff=i*self.child_dist
217                     self.child_dist=0
218                 else:
219                     diff=i
220                 if self.level>0 and (base_y-(50*diff)) >= self.level:
221                         base_y=self.level-(50*i)
222                 else:
223                     base_y=base_y-(50*diff)
224                 tb = text_box.T(loc=(base_x,base_y),line_style=line_style.darkblue,text="/hC"+str(obj_history.code)+":\n"+str(obj_history.amount))
225
226                 tb.add_arrow((base_x+100,base_y))
227                 tb.draw()
228
229                 if level!=0:
230                     a = arrow.T(head_style = 1)
231                     a.draw([(base_x-30,base_y), (base_x,base_y)])
232                 level+=1
233
234                 if i>0:
235                     can.line(line_style.black,base_x-30,base_y,base_x-30,self.line_y)
236
237                 i=0
238                 for child in obj_history.child_ids:
239                     draw_tree(child,base_x+(100),base_y,level,i)
240                     i+=1
241
242                 child_dist=len(obj_history.child_ids)
243                 self.child_dist=max(self.child_dist,child_dist)
244
245             else:
246
247                 if self.level>0 and  (base_y-(50*i)) >= self.level:
248                     base_y=self.level-(50)
249                 else:
250                     base_y=base_y-(50*(i))
251
252                 tb12 = text_box.T(loc=(base_x,base_y), text="/hC"+str(obj_history.code)+":\n"+str(obj_history.amount))
253                 tb12.draw()
254
255                 if i>0:
256                     can.line(line_style.black,base_x-30,base_y,base_x-30,self.line_y)
257                     a = arrow.T(head_style = 1)
258                     a.draw([(base_x-30,base_y), (base_x,base_y)])
259                 self.level=base_y
260         self.line_y=900
261         draw_tree(obj_history,0,900,0)
262         can.close()
263
264         os.system('cp '+'tree_image'+str(self.treecount)+'.png ' +path+str(self.treecount)+'.png')
265         os.system('rm '+'tree_image'+str(self.treecount)+'.png')
266
267         return path+str(self.treecount)+'.png'
268
269     def getgraph(self,data,object,intercall=False):
270         obj_history=self.pool.get('account.report.history')
271
272         if data['select_base']=='year':
273             tuple_search=('fiscalyear_id','in',data['base_selection'][0][2])
274             base='year'
275         else:
276             tuple_search=('period_id','in',data['base_selection'][0][2])
277             base='period'
278
279         history_ids=obj_history.search(self.cr,self.uid,[('name','=',object['id']),tuple_search])
280         history_ids.sort()
281         obj_his=obj_history.browse(self.cr,self.uid,history_ids)
282
283         data_val=[]
284         data_period=[]
285         if base=='period':
286             for item in obj_his:
287                 data_val.append(item.val)
288                 data_period.append(item.period_id.name)
289         else:
290             for i in data['base_selection'][0][2]:
291                 val_temp=[]
292                 data_period.append(self.pool.get('account.fiscalyear').browse(self.cr,self.uid,i).name)
293                 for item in obj_his:
294                     if item.fiscalyear_id.id==i:
295                         val_temp.append(item.val)
296                 data_val.append(sum(val_temp))
297
298         self.header_name=data_period
299         self.header_val=data_val
300
301         if intercall:
302             return True
303         self.count +=1
304 #        drawing = Drawing(400, 300)
305 #        data = [
306 #                 tuple(data_val),
307 #                 ]
308 #        value_min=0.0
309 #        vmin=min(data_val)
310 #        vmax=max(data_val)
311 #
312 #        val_min=((vmin < 0.00 and vmin-2.00)  or 0.00)
313 #        # calculating maximum
314 #        val_max=(vmax/(pow(10,len(str(int(vmax)))-2))+1)*pow(10,len(str(int(vmax)))-2)
315 #        bc = VerticalBarChart()
316 #        bc.x = 50
317 #        bc.y = 50
318 #        bc.height = 245
319 #        bc.width = 300
320 #        bc.data = data
321 #        value_step=(abs(val_max)-abs(val_min))/5
322 #
323 #        bc.strokeColor = colors.black
324 #        bc.valueAxis.valueMin = val_min
325 #        bc.valueAxis.valueMax = val_max
326 #        bc.valueAxis.valueStep = value_step
327 #
328 #        bc.categoryAxis.labels.boxAnchor = 'ne'
329 #        bc.categoryAxis.labels.dx = 8
330 #
331 #        bc.categoryAxis.labels.dy = -2
332 #        bc.categoryAxis.labels.angle = 30
333 #        bc.categoryAxis.categoryNames = data_period
334 #        drawing.add(bc)
335 #        drawing.save(formats=['png'],fnRoot=path+str(self.count),title="helo")
336 #        renderPM.drawToFile(drawing1, 'example1.jpg','jpg')
337         import os
338         path=tools.config['addons_path']+"/account_report/tmp_images/image"
339
340         dirname =tools.config['addons_path']+'/account_report/tmp_images/'
341         if not os.path.isdir(dirname):
342             os.mkdir(dirname)
343
344         can = canvas.init('image'+str(self.count)+".png")
345 #        can.clip(0,0,600,400)
346
347         data=zip(self.header_name,self.header_val)
348
349         ar = area.T(size = (650,450),x_coord = category_coord.T(data, 0), y_range = (None, None),
350             x_axis = axis.X(label="Period // Year",format="/a-30{}%s"),
351             y_axis = axis.Y(label="Value"))
352
353         ar.add_plot(bar_plot.T(data = data,width=15, data_label_format="/o/15{}%s",label = "Value",fill_style=fill_style.red))
354         ar.draw()
355
356         can.close()
357         os.system('cp '+'image'+str(self.count)+'.png ' +path+str(self.count)+'.png')
358         os.system('rm '+'image'+str(self.count)+'.png')
359 #        can.endclip()
360         return path+str(self.count)+'.png'
361
362 report_sxw.report_sxw('report.print.indicators', 'account.report.history',
363         'addons/account_report/report/print_indicator.rml',
364         parser=accounting_report_indicator, header=False)
365
366
367 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
368