Merge lp:~mechiscogo/aeroo/mx into lp:aeroo/trunk

Proposed by Prabhu
Status: Needs review
Proposed branch: lp:~mechiscogo/aeroo/mx
Merge into: lp:aeroo/trunk
Diff against target: 3132 lines (+3039/-0)
17 files modified
ExtraFunctions.py (+367/-0)
__init__.py (+31/-0)
__openerp__.py (+37/-0)
barcode/EANBarCode.py (+148/-0)
barcode/__init__.py (+30/-0)
barcode/barcode.py (+59/-0)
barcode/code128.py (+184/-0)
barcode/code39.py (+153/-0)
currency_to_text.py (+490/-0)
data/report_aeroo_data.xml (+25/-0)
domain_parser.py (+45/-0)
report_aeroo.py (+636/-0)
report_view.xml (+224/-0)
report_xml.py (+365/-0)
wizard/__init__.py (+30/-0)
wizard/report_actions.py (+118/-0)
wizard/report_actions_remove.py (+97/-0)
To merge this branch: bzr merge lp:~mechiscogo/aeroo/mx
Reviewer Review Type Date Requested Status
Alistek developers - http://www.alistek.com Pending
Review via email: mp+113566@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

2. By mechiscogo <mechiscogo@openerp>

Adds MXN (Mexican peso) and Spanish translations to currency_to_text. All the translations for Spanish have the Mexican format: <amount in words> <cents>/100 <currency>

1. By mechiscogo <mechiscogo@openerp>

Agrega moneda MXN y traducciones al español en currency_to_text. Todas las traducciones llevan formato para México <importe con letra> <centavos>/100 <moneda>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'ExtraFunctions.py'
--- ExtraFunctions.py 1970-01-01 00:00:00 +0000
+++ ExtraFunctions.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,367 @@
1##############################################################################
2#
3# Copyright (c) 2008-2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29from barcode import barcode
30from tools import translate
31from domain_parser import domain2statement
32from currency_to_text import currency_to_text
33import base64
34import StringIO
35from PIL import Image
36import pooler
37import time
38import osv
39from report import report_sxw
40from tools.translate import _
41import netsvc
42
43class ExtraFunctions(object):
44 """ This class contains some extra functions which
45 can be called from the report's template.
46 """
47 def __init__(self, cr, uid, report_id, context):
48 self.cr = cr
49 self.uid = uid
50 self.pool = pooler.get_pool(self.cr.dbname)
51 self.report_id = report_id
52 self.context = context
53 self.functions = {
54 'asarray':self._asarray,
55 'asimage':self._asimage,
56 'html_embed_image':self._embed_image,
57 'get_attachments':self._get_attachments,
58 'get_name':self._get_name,
59 'get_label':self._get_label,
60 'getLang':self._get_lang,
61 'get_selection_item':self._get_selection_items('item'),
62 'safe':self._get_safe,
63 'countif':self._countif,
64 'count':self._count,
65 'sumif':self._sumif,
66 'sum':self._sum,
67 'max':self._max,
68 'min':self._min,
69 'average':self._average,
70 'large':self._large,
71 'small':self._small,
72 'count_blank':self._count_blank,
73 '_':self._translate_text,
74 'gettext':self._translate_text,
75 'currency_to_text':self._currency2text(context['company'].currency_id.name), #self._currency2text(context['company'].currency_id.code),
76 'barcode':barcode.make_barcode,
77 'debugit':self.debugit,
78 'dec_to_time':self._dec2time,
79 'chunks':self._chunks,
80 'browse':self._browse,
81 'field_size':self._field_size,
82 'bool_as_icon':self._bool_as_icon,
83 'time':time,
84 'report_xml': self._get_report_xml(),
85 'get_log': self._perm_read(self.cr, self.uid),
86 'get_selection_items': self._get_selection_items(),
87 }
88
89 def _perm_read(self, cr, uid):
90 def get_log(obj, field=None):
91 if field:
92 return obj.perm_read(self.uid, [obj.id])[0][field]
93 else:
94 return obj.perm_read(self.uid, [obj.id])[0]
95 return get_log
96
97 def _get_report_xml(self):
98 return self.pool.get('ir.actions.report.xml').browse(self.cr, self.uid, self.report_id)
99
100 def _get_lang(self, source='current'):
101 if source=='current':
102 return self.context['lang'] or self.context['user_lang']
103 elif source=='company':
104 return self.context['user'].company_id.partner_id.lang
105 elif source=='user':
106 return self.context['user_lang']
107
108 def _bool_as_icon(self, val, kind=0):
109 if isinstance(kind, (list, tuple)):
110 if val==True:
111 return kind [0]
112 elif val==False:
113 return kind[1]
114 else:
115 return kind[2]
116 bool_kind = {0:{True:self._translate_text('True'), False:self._translate_text('False'), None:""},
117 1:{True:self._translate_text('T'), False:self._translate_text('F'), None:""},
118 2:{True:self._translate_text('Yes'), False:self._translate_text('No'), None:""},
119 3:{True:self._translate_text('Y'), False:self._translate_text('N'), None:""},
120 4:{True:'+', False:'-', None:""},
121 5:{True:'[ + ]', False:'[ - ]', None:"[ ]"},
122 6:{True:'[ x ]', False:'[ ]', None:"[ ]"},
123 }
124 return bool_kind.get(kind, {}).get(val, val)
125
126 def _dec2time(self, dec, h_format, min_format):
127 if dec==0.0:
128 return None
129 elif int(dec)==0:
130 return min_format.replace('%M', str(int(round((dec-int(dec))*60))))
131 elif dec-int(dec)==0.0:
132 return h_format.replace('%H', str(int(dec)))
133 else:
134 return h_format.replace('%H', str(int(dec)))+min_format.replace('%M', str(int(round((dec-int(dec))*60))))
135
136 def _currency2text(self, currency):
137 def c_to_text(sum, currency=currency, language=None):
138 return unicode(currency_to_text(sum, currency, language or self._get_lang()), "UTF-8")
139 return c_to_text
140
141 def _translate_text(self, source):
142 trans_obj = self.pool.get('ir.translation')
143 trans = trans_obj.search(self.cr,self.uid,[('res_id','=',self.report_id),('type','=','report'),('src','=',source),('lang','=',self.context['lang'] or self.context['user_lang'])])
144 if not trans:
145 trans_obj.create(self.cr, self.uid, {'src':source,'type':'report','lang':self._get_lang(),'res_id':self.report_id,'name':('ir.actions.report.xml,%s' % source)[:128]})
146 return translate(self.cr, False, 'report', self._get_lang(), source) or source
147
148 def _countif(self, attr, domain):
149 statement = domain2statement(domain)
150 expr = "for o in objects:\n\tif%s:\n\t\tcount+=1" % statement
151 localspace = {'objects':attr, 'count':0}
152 exec expr in localspace
153 return localspace['count']
154
155 def _count_blank(self, attr, field):
156 expr = "for o in objects:\n\tif not o.%s:\n\t\tcount+=1" % field
157 localspace = {'objects':attr, 'count':0}
158 exec expr in localspace
159 return localspace['count']
160
161 def _count(self, attr):
162 return len(attr)
163
164 def _sumif(self, attr, sum_field, domain):
165 statement = domain2statement(domain)
166 expr = "for o in objects:\n\tif%s:\n\t\tsumm+=float(o.%s)" % (statement, sum_field)
167 localspace = {'objects':attr, 'summ':0}
168 exec expr in localspace
169 return localspace['summ']
170
171 def _sum(self, attr, sum_field):
172 expr = "for o in objects:\n\tsumm+=float(o.%s)" % sum_field
173 localspace = {'objects':attr, 'summ':0}
174 exec expr in localspace
175 return localspace['summ']
176
177 def _max(self, attr, field):
178 expr = "for o in objects:\n\tvalue_list.append(o.%s)" % field
179 localspace = {'objects':attr, 'value_list':[]}
180 exec expr in localspace
181 return max(localspace['value_list'])
182
183 def _min(self, attr, field):
184 expr = "for o in objects:\n\tvalue_list.append(o.%s)" % field
185 localspace = {'objects':attr, 'value_list':[]}
186 exec expr in localspace
187 return min(localspace['value_list'])
188
189 def _average(self, attr, field):
190 expr = "for o in objects:\n\tvalue_list.append(o.%s)" % field
191 localspace = {'objects':attr, 'value_list':[]}
192 exec expr in localspace
193 return float(sum(localspace['value_list']))/float(len(localspace['value_list']))
194
195 def _asarray(self, attr, field):
196 expr = "for o in objects:\n\tvalue_list.append(o.%s)" % field
197 localspace = {'objects':attr, 'value_list':[]}
198 exec expr in localspace
199 return localspace['value_list']
200
201 def _get_name(self, obj):
202 if obj.__class__==osv.orm.browse_record:
203 return self.pool.get(obj._table_name).name_get(self.cr, self.uid, [obj.id], {'lang':self._get_lang()})[0][1]
204 return ''
205
206 #def _get_label(self, obj, field):
207 # try:
208 # if isinstance(obj, report_sxw.browse_record_list):
209 # obj = obj[0]
210 # if isinstance(obj, (str,unicode)):
211 # model = obj
212 # else:
213 # model = obj._table_name
214 # if isinstance(obj, (str,unicode)) or hasattr(obj, field):
215 # label = self.pool.get(model)._columns[field].string
216 # return translate(self.cr, False, 'field', self._get_lang(), label) or label
217 # except Exception, e:
218 # return ''
219
220 def _get_label(self, obj, field):
221 try:
222 if isinstance(obj, report_sxw.browse_record_list):
223 obj = obj[0]
224 if isinstance(obj, (str,unicode)):
225 model = obj
226 else:
227 model = obj._table_name
228 if isinstance(obj, (str,unicode)) or hasattr(obj, field):
229 labels = self.pool.get(model).fields_get(self.cr, self.uid, fields=[field], context=self.context)
230 return labels[field]['string']
231 except Exception, e:
232 return ''
233
234 def _field_size(self, obj, field):
235 try:
236 if getattr(obj, field):
237 size = self.pool.get(obj._table_name)._columns[field].size
238 return size
239 except Exception:
240 return ''
241
242 def _get_selection_items(self, kind='items'):
243 def get_selection_item(obj, field, value=None):
244 try:
245 if isinstance(obj, report_sxw.browse_record_list):
246 obj = obj[0]
247 if isinstance(obj, (str,unicode)):
248 model = obj
249 field_val = value
250 else:
251 model = obj._table_name
252 field_val = getattr(obj, field)
253 if kind=='item':
254 if field_val:
255 return dict(self.pool.get(model).fields_get(self.cr, self.uid, fields=[field], context=self.context)[field]['selection'])[field_val]
256 elif kind=='items':
257 return self.pool.get(model).fields_get(self.cr, self.uid, fields=[field], context=self.context)[field]['selection']
258 #selection = self.pool.get(model)._columns[field].selection
259 #if selection.__class__==list:
260 # val_dict = dict(selection)
261 #else:
262 # val_dict = dict(selection(self.pool.get(model), self.cr, self.uid, {'lang':self._get_lang()}))
263 #return val_dict[field_val]
264 return ''
265 except Exception:
266 return ''
267 return get_selection_item
268
269 def _get_attachments(self, o, index=None):
270 attach_obj = self.pool.get('ir.attachment')
271 srch_param = [('res_model','=',o._name),('res_id','=',o.id)]
272 if type(index)==str:
273 srch_param.append(('name','=',index))
274 attachments = attach_obj.search(self.cr,self.uid,srch_param)
275 res = [x['datas'] for x in attach_obj.read(self.cr,self.uid,attachments,['datas']) if x['datas']]
276 if type(index)==int:
277 return res[index]
278 return len(res)==1 and res[0] or res
279
280 def _asimage(self, field_value, rotate=None):
281 if not field_value:
282 return StringIO.StringIO(), 'image/png'
283 field_value = base64.decodestring(field_value)
284 tf = StringIO.StringIO(field_value)
285 tf.seek(0)
286 im=Image.open(tf)
287 try:
288 if rotate!=None:
289 im=im.rotate(int(rotate))
290 tf.seek(0)
291 im.save(tf, im.format.lower())
292 except Exception, e:
293 pass
294 size_x = str(im.size[0]/96.0)+'in'
295 size_y = str(im.size[1]/96.0)+'in'
296 return tf, 'image/%s' % im.format.lower(), size_x, size_y
297
298 def _embed_image(self, extention, img, width=0, height=0) :
299 "Transform a DB image into an embeded HTML image"
300 try:
301 if width :
302 width = 'width="%spx"'%(width)
303 else :
304 width = ' '
305 if height :
306 height = 'width="%spx"'%(height)
307 else :
308 height = ' '
309 toreturn = '<img %s %s src="data:image/%s;base64,%s">' % (width, height, extention, str(img))
310 return toreturn
311 except Exception, exp:
312 print exp
313 return 'No image'
314
315 def _large(self, attr, field, n):
316 array=self._asarray(attr, field)
317 try:
318 n-=1
319 while(n):
320 array.remove(max(array))
321 n-=1
322 return max(array)
323 except ValueError, e:
324 return None
325
326 def _small(self, attr, field, n):
327 array=self._asarray(attr, field)
328 try:
329 n-=1
330 while(n):
331 array.remove(min(array))
332 n-=1
333 return min(array)
334 except ValueError, e:
335 return None
336
337 def _chunks(self, l, n):
338 """ Yield successive n-sized chunks from l.
339 """
340 for i in xrange(0, len(l), n):
341 yield l[i:i+n]
342
343 def _browse(self, *args):
344 if not args or (args and not args[0]):
345 return None
346 if len(args)==1:
347 model, id = args[0].split(',')
348 id = int(id)
349 elif len(args)==2:
350 model, id = args
351 else:
352 raise None
353 return self.pool.get(model).browse(self.cr, self.uid, id)
354
355 def _get_safe(self, expression, obj):
356 try:
357 return eval(expression, {'o':obj})
358 except Exception, e:
359 return None
360
361 def debugit(self, object):
362 """ Run the server from command line and
363 call 'debugit' from the template to inspect variables.
364 """
365 import pdb;pdb.set_trace()
366 return
367
0368
=== added file '__init__.py'
--- __init__.py 1970-01-01 00:00:00 +0000
+++ __init__.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,31 @@
1##############################################################################
2#
3# Copyright (c) 2008-2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29import report_xml
30import report_aeroo
31import wizard
032
=== added file '__openerp__.py'
--- __openerp__.py 1970-01-01 00:00:00 +0000
+++ __openerp__.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,37 @@
1# -*- encoding: utf-8 -*-
2
3#########################################################################
4# #
5# Copyright (C) 2009 Domsense s.r.l. #
6# @authors: Simone Orsi #
7# Copyright (C) 2009-2010 KN dati, Ltd #
8# #
9#This program is free software: you can redistribute it and/or modify #
10#it under the terms of the GNU General Public License as published by #
11#the Free Software Foundation, either version 3 of the License, or #
12#(at your option) any later version. #
13# #
14#This program is distributed in the hope that it will be useful, #
15#but WITHOUT ANY WARRANTY; without even the implied warranty of #
16#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
17#GNU General Public License for more details. #
18# #
19#You should have received a copy of the GNU General Public License #
20#along with this program. If not, see <http://www.gnu.org/licenses/>. #
21#########################################################################
22
23{
24 'name': 'Aeroo Reports',
25 'version': '1.0',
26 'category': 'Generic Modules/Aeroo Reporting',
27 'description': """ Make possible to easily create complicated reports with OOo.
28 Requires "relatorio", "openoffice.org", "openoffice-python" to be installed.
29 """,
30 'author': 'KN dati Ltd, Simone Orsi - Domsense',
31 'website': 'http://www.alistek.com',
32 'depends': ['base'],
33 "init_xml" : [],
34 'update_xml': ["report_view.xml", "data/report_aeroo_data.xml", "security/ir.model.access.csv"],
35 'installable': True,
36 'active': False,
37}
038
=== added directory 'barcode'
=== added file 'barcode/EANBarCode.py'
--- barcode/EANBarCode.py 1970-01-01 00:00:00 +0000
+++ barcode/EANBarCode.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,148 @@
1# Copyright (c) 2009-2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
2# General contacts <info@kndati.lv>
3
4from tools import config
5
6"""
7This class generate EAN bar code, it required PIL (python imaging library)
8installed.
9
10If the code has not checksum (12 digits), it added automatically.
11
12Create bar code sample :
13 from EANBarCode import EanBarCode
14 bar = EanBarCode()
15 bar.getImage("9782212110708",50,"gif")
16
17"""
18
19class EanBarCode:
20 """ Compute the EAN bar code """
21 def __init__(self):
22 A = {0 : "0001101", 1 : "0011001", 2 : "0010011", 3 : "0111101", 4 : "0100011",
23 5 : "0110001", 6 : "0101111", 7 : "0111011", 8 : "0110111", 9 : "0001011"}
24 B = {0 : "0100111", 1 : "0110011", 2 : "0011011", 3 : "0100001", 4 : "0011101",
25 5 : "0111001", 6 : "0000101", 7 : "0010001", 8 : "0001001", 9 : "0010111"}
26 C = {0 : "1110010", 1 : "1100110", 2 : "1101100", 3 : "1000010", 4 : "1011100",
27 5 : "1001110", 6 : "1010000", 7 : "1000100", 8 : "1001000", 9 : "1110100"}
28 self.groupC = C
29
30 self.family = {0 : (A,A,A,A,A,A), 1 : (A,A,B,A,B,B), 2 : (A,A,B,B,A,B), 3 : (A,A,B,B,B,A), 4 : (A,B,A,A,B,B),
31 5 : (A,B,B,A,A,B), 6 : (A,B,B,B,A,A), 7 : (A,B,A,B,A,B), 8 : (A,B,A,B,B,A), 9 : (A,B,B,A,B,A)}
32
33
34 def makeCode(self, code):
35 """ Create the binary code
36 return a string which contains "0" for white bar, "1" for black bar, "L" for long bar """
37
38 # Convert code string in integer list
39 self.EAN13 = []
40 for digit in code:
41 self.EAN13.append(int(digit))
42
43 # If the code has already a checksum
44 if len(self.EAN13) == 13:
45 # Verify checksum
46 self.verifyChecksum(self.EAN13)
47 # If the code has not yet checksum
48 elif len(self.EAN13) == 12:
49 # Add checksum value
50 self.EAN13.append(self.computeChecksum(self.EAN13))
51
52 # Get the left codage class
53 left = self.family[self.EAN13[0]]
54
55 # Add start separator
56 strCode = 'L0L'
57
58 # Compute the left part of bar code
59 for i in range(0,6):
60 strCode += left[i][self.EAN13[i+1]]
61
62 # Add middle separator
63 strCode += '0L0L0'
64
65 # Compute the right codage class
66 for i in range (7,13):
67 strCode += self.groupC[self.EAN13[i]]
68
69 # Add stop separator
70 strCode += 'L0L'
71
72 return strCode
73
74
75 def computeChecksum(self, arg):
76 """ Compute the checksum of bar code """
77 # UPCA/EAN13
78 weight=[1,3]*6
79 magic=10
80 sum = 0
81
82 for i in range(12): # checksum based on first 12 digits.
83 sum = sum + int(arg[i]) * weight[i]
84 z = ( magic - (sum % magic) ) % magic
85 if z < 0 or z >= magic:
86 return None
87 return z
88
89
90 def verifyChecksum(self, bits):
91 """ Verify the checksum """
92 computedChecksum = self.computeChecksum(bits[:12])
93 codeBarChecksum = bits[12]
94
95 if codeBarChecksum != computedChecksum:
96 raise Exception ("Bad checksum is %s and should be %s"%(codeBarChecksum, computedChecksum))
97
98
99 def getImage(self, value, height = 50, xw=1, rotate=None, extension = "PNG"):
100 """ Get an image with PIL library
101 value code barre value
102 height height in pixel of the bar code
103 extension image file extension"""
104 import Image, ImageFont, ImageDraw, os
105 from string import lower, upper
106
107 # Get the bar code list
108 bits = self.makeCode(value)
109
110 # Get thee bar code with the checksum added
111 code = ""
112 for digit in self.EAN13:
113 code += "%d"%digit
114
115 # Create a new image
116 position = 8
117 im = Image.new("1",(len(bits)+position,height))
118
119 # Load font
120 font = ImageFont.load(config['addons_path']+"/report_aeroo/barcode/courB08.pil")
121
122 # Create drawer
123 draw = ImageDraw.Draw(im)
124
125 # Erase image
126 draw.rectangle(((0,0),(im.size[0],im.size[1])),fill=256)
127
128 # Draw first part of number
129 draw.text((0, height-9), code[0], font=font, fill=0)
130
131 # Draw first part of number
132 draw.text((position+7, height-9), code[1:7], font=font, fill=0)
133
134 # Draw second part of number
135 draw.text((len(bits)/2+6+position, height-9), code[7:], font=font, fill=0)
136
137 # Draw the bar codes
138 for bit in range(len(bits)):
139 # Draw normal bar
140 if bits[bit] == '1':
141 draw.rectangle(((bit+position,0),(bit+position,height-10)),fill=0)
142 # Draw long bar
143 elif bits[bit] == 'L':
144 draw.rectangle(((bit+position,0),(bit+position,height-3)),fill=0)
145
146 # Save the result image
147 return im
148
0149
=== added file 'barcode/FreeMonoBold.ttf'
1Binary files barcode/FreeMonoBold.ttf 1970-01-01 00:00:00 +0000 and barcode/FreeMonoBold.ttf 2012-07-05 12:25:24 +0000 differ150Binary files barcode/FreeMonoBold.ttf 1970-01-01 00:00:00 +0000 and barcode/FreeMonoBold.ttf 2012-07-05 12:25:24 +0000 differ
=== added file 'barcode/__init__.py'
--- barcode/__init__.py 1970-01-01 00:00:00 +0000
+++ barcode/__init__.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,30 @@
1##############################################################################
2#
3# Copyright (c) 2008-2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29import barcode
30
031
=== added file 'barcode/barcode.py'
--- barcode/barcode.py 1970-01-01 00:00:00 +0000
+++ barcode/barcode.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,59 @@
1##############################################################################
2#
3# Copyright (c) 2008-2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29from code128 import get_code
30from code39 import create_c39
31from EANBarCode import EanBarCode
32try:
33 from cStringIO import StringIO
34except ImportError:
35 from StringIO import StringIO
36
37def make_barcode(code, code_type='ean13', rotate=None, height=50, xw=1):
38 if code:
39 if code_type.lower()=='ean13':
40 bar=EanBarCode()
41 im = bar.getImage(code,height)
42 elif code_type.lower()=='code128':
43 im = get_code(code, xw, height)
44 elif code_type.lower()=='code39':
45 im = create_c39(height, xw, code)
46 else:
47 return StringIO(), 'image/png'
48
49 tf = StringIO()
50 try:
51 if rotate!=None:
52 im=im.rotate(int(rotate))
53 except Exception, e:
54 pass
55 im.save(tf, 'png')
56 size_x = str(im.size[0]/96.0)+'in'
57 size_y = str(im.size[1]/96.0)+'in'
58 return tf, 'image/png', size_x, size_y
59
060
=== added file 'barcode/code128.py'
--- barcode/code128.py 1970-01-01 00:00:00 +0000
+++ barcode/code128.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,184 @@
1# Copyright (c) 2009-2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
2# General contacts <info@kndati.lv>
3# This list was cut'n'pasted verbatim from the "Code 128 Specification Page"
4# at http://www.adams1.com/pub/russadam/128code.html
5
6codelist="""0 SP SP 00 2 1 2 2 2 2
71 ! ! 01 2 2 2 1 2 2
82 " " 02 2 2 2 2 2 1
93 # # 03 1 2 1 2 2 3
104 $ $ 04 1 2 1 3 2 2
115 % % 05 1 3 1 2 2 2
126 & & 06 1 2 2 2 1 3
137 ' ' 07 1 2 2 3 1 2
148 ( ( 08 1 3 2 2 1 2
159 ) ) 09 2 2 1 2 1 3
1610 * * 10 2 2 1 3 1 2
1711 + + 11 2 3 1 2 1 2
1812 , , 12 1 1 2 2 3 2
1913 - - 13 1 2 2 1 3 2
2014 . . 14 1 2 2 2 3 1
2115 / / 15 1 1 3 2 2 2
2216 0 0 16 1 2 3 1 2 2
2317 1 1 17 1 2 3 2 2 1
2418 2 2 18 2 2 3 2 1 1
2519 3 3 19 2 2 1 1 3 2
2620 4 4 20 2 2 1 2 3 1
2721 5 5 21 2 1 3 2 1 2
2822 6 6 22 2 2 3 1 1 2
2923 7 7 23 3 1 2 1 3 1
3024 8 8 24 3 1 1 2 2 2
3125 9 9 25 3 2 1 1 2 2
3226 : : 26 3 2 1 2 2 1
3327 ; ; 27 3 1 2 2 1 2
3428 < < 28 3 2 2 1 1 2
3529 = = 29 3 2 2 2 1 1
3630 > > 30 2 1 2 1 2 3
3731 ? ? 31 2 1 2 3 2 1
3832 @ @ 32 2 3 2 1 2 1
3933 A A 33 1 1 1 3 2 3
4034 B B 34 1 3 1 1 2 3
4135 C C 35 1 3 1 3 2 1
4236 D D 36 1 1 2 3 1 3
4337 E E 37 1 3 2 1 1 3
4438 F F 38 1 3 2 3 1 1
4539 G G 39 2 1 1 3 1 3
4640 H H 40 2 3 1 1 1 3
4741 I I 41 2 3 1 3 1 1
4842 J J 42 1 1 2 1 3 3
4943 K K 43 1 1 2 3 3 1
5044 L L 44 1 3 2 1 3 1
5145 M M 45 1 1 3 1 2 3
5246 N N 46 1 1 3 3 2 1
5347 O O 47 1 3 3 1 2 1
5448 P P 48 3 1 3 1 2 1
5549 Q Q 49 2 1 1 3 3 1
5650 R R 50 2 3 1 1 3 1
5751 S S 51 2 1 3 1 1 3
5852 T T 52 2 1 3 3 1 1
5953 U U 53 2 1 3 1 3 1
6054 V V 54 3 1 1 1 2 3
6155 W W 55 3 1 1 3 2 1
6256 X X 56 3 3 1 1 2 1
6357 Y Y 57 3 1 2 1 1 3
6458 Z Z 58 3 1 2 3 1 1
6559 [ [ 59 3 3 2 1 1 1
6660 \\ \\ 60 3 1 4 1 1 1
6761 ] ] 61 2 2 1 4 1 1
6862 ^ ^ 62 4 3 1 1 1 1
6963 _ _ 63 1 1 1 2 2 4
7064 NUL ' 64 1 1 1 4 2 2
7165 SOH a 65 1 2 1 1 2 4
7266 STX b 66 1 2 1 4 2 1
7367 ETX c 67 1 4 1 1 2 2
7468 EOT d 68 1 4 1 2 2 1
7569 ENQ e 69 1 1 2 2 1 4
7670 ACK f 70 1 1 2 4 1 2
7771 BEL g 61 1 2 2 1 1 4
7872 BS h 72 1 2 2 4 1 1
7973 HT i 73 1 4 2 1 1 2
8074 LF j 74 1 4 2 2 1 1
8175 VT k 75 2 4 1 2 1 1
8276 FF l 76 2 2 1 1 1 4
8377 CR m 77 4 1 3 1 1 1
8478 SO n 78 2 4 1 1 1 2
8579 SI o 79 1 3 4 1 1 1
8680 DLE p 80 1 1 1 2 4 2
8781 DC1 q 81 1 2 1 1 4 2
8882 DC2 r 82 1 2 1 2 4 1
8983 DC3 s 83 1 1 4 2 1 2
9084 DC4 t 84 1 2 4 1 1 2
9185 NAK u 85 1 2 4 2 1 1
9286 SYN v 86 4 1 1 2 1 2
9387 ETB w 87 4 2 1 1 1 2
9488 CAN x 88 4 2 1 2 1 1
9589 EM y 89 2 1 2 1 4 1
9690 SUB z 90 2 1 4 1 2 1
9791 ESC { 91 4 1 2 1 2 1
9892 FS | 92 1 1 1 1 4 3
9993 GS } 93 1 1 1 3 4 1
10094 RS ~ 94 1 3 1 1 4 1
10195 (Hex 7F) US DEL 95 1 1 4 1 1 3
10296 (Hex 80) FNC 3 FNC 3 96 1 1 4 3 1 1
10397 (Hex 81) FNC 2 FNC 2 97 4 1 1 1 1 3
10498 (Hex 82) SHIFT SHIFT 98 4 1 1 3 1 1
10599 (Hex 83) CODE C CODE C 99 1 1 3 1 4 1
106100 (Hex 84) CODE B FNC 4 CODE B 1 1 4 1 3 1
107101 (Hex 85) FNC 4 CODE A CODE A 3 1 1 1 4 1
108102 (Hex 86) FNC 1 FNC 1 FNC 1 4 1 1 1 3 1"""
109
110
111
112
113other="""103 (Hex 87) START (Code A) 2 1 1 4 1 2
114104 (Hex 88) START (Code B) 2 1 1 2 1 4
115105 (Hex 89) START (Code C) 2 1 1 2 3 2
116106 STOP 2 3 3 1 1 1 2"""
117
118
119codes={}
120values={}
121for l in codelist.split('\n'):
122 l.strip()
123 num,a1,b1,c1,code=l.split('\t')
124 num=int(num.split(' ')[0])
125 values[num]=[int(x) for x in code.split()]
126 codes[b1.strip()]=num
127
128codes[' ']=codes['SP']
129
130for l in other.split('\n'):
131 l.strip()
132 num,name,code=l.split('\t')
133 num=int(num.split(' ')[0])
134 values[num]=[int(x) for x in code.split()]
135 codes[name.strip()]=num
136
137def encode_message(msg):
138 startnum=codes['START (Code B)']
139 message=values[startnum][:]
140 chksum=startnum
141 mult=1
142 for c in msg:
143 if not codes.has_key(c):
144 raise "No code for "+c
145 chksum=chksum+mult*codes[c]
146 mult=mult+1
147 message=message+values[codes[c]]
148
149 chksum=chksum%103
150
151 message=message+values[chksum]
152 message=message+values[codes['STOP']]
153
154 return message
155
156
157import Image, os
158def get_code(message,xw=1,h=100,rotate=None):
159 """ message is message to code.
160 xw is horizontal multiplier (in pixels width of narrowest bar)
161 h is height in pixels.
162
163 Returns a Python Imaging Library object."""
164
165 widths=[xw*20]+encode_message(message)+[xw*20]
166
167 bits=[]
168 i=1
169 for w in widths:
170 bits=bits+[i]*w*xw
171 i=1-i
172
173 #print len(bits)
174 #print bits
175
176 i=Image.new('1',(len(bits),h),1)
177
178 for b in range(len(bits)):
179 for y in range(h):
180 i.putpixel((b,y),255*bits[b])
181
182 return i
183
184
0185
=== added file 'barcode/code39.py'
--- barcode/code39.py 1970-01-01 00:00:00 +0000
+++ barcode/code39.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,153 @@
1# Copyright (c) 2008 marscel.wordpress.com
2#
3# Copyright (c) 2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5
6# Code39.py v1
7# Requires Python and Python Imaging Library (PIL),
8# has been tested with Python v2.6 and PIL v1.1.6
9
10# Usage example:
11# code39.py 100 2 "Hello World" barcode.png
12#
13# This creates a PNG image "barcode.png" containing a barcode of the height of 100px
14# a min line width of 2px with "Hello World" encoded as "*HELLO WORLD*" in Code 39
15
16import Image, ImageDraw, ImageFont, sys
17from tools import config
18
19marginx = 10
20marginy = 10
21fontsize = 15
22
23charmap = {
24'*':[0,3,0,1,2,1,2,1,0],
25'-':[0,3,0,1,0,1,2,1,2],
26'$':[0,3,0,3,0,3,0,1,0],
27'%':[0,1,0,3,0,3,0,3,0],
28' ':[0,3,2,1,0,1,2,1,0],
29'.':[2,3,0,1,0,1,2,1,0],
30'/':[0,3,0,3,0,1,0,3,0],
31'+':[0,3,0,1,0,3,0,3,0],
32'0':[0,1,0,3,2,1,2,1,0],
33'1':[2,1,0,3,0,1,0,1,2],
34'2':[0,1,2,3,0,1,0,1,2],
35'3':[2,1,2,3,0,1,0,1,0],
36'4':[0,1,0,3,2,1,0,1,2],
37'5':[2,1,0,3,2,1,0,1,0],
38'6':[0,1,2,3,2,1,0,1,0],
39'7':[0,1,0,3,0,1,2,1,2],
40'8':[2,1,0,3,0,1,2,1,0],
41'9':[0,1,2,3,0,1,2,1,0],
42'A':[2,1,0,1,0,3,0,1,2],
43'B':[0,1,2,1,0,3,0,1,2],
44'C':[2,1,2,1,0,3,0,1,0],
45'D':[0,1,0,1,2,3,0,1,2],
46'E':[2,1,0,1,2,3,0,1,0],
47'F':[0,1,2,1,2,3,0,1,0],
48'G':[0,1,0,1,0,3,2,1,2],
49'H':[2,1,0,1,0,3,2,1,0],
50'I':[0,1,2,1,0,3,2,1,0],
51'J':[0,1,0,1,2,3,2,1,0],
52'K':[2,1,0,1,0,1,0,3,2],
53'L':[0,1,2,1,0,1,0,3,2],
54'M':[2,1,2,1,0,1,0,3,0],
55'N':[0,1,0,1,2,1,0,3,2],
56'O':[2,1,0,1,2,1,0,3,0],
57'P':[0,1,2,1,2,1,0,3,0],
58'Q':[0,1,0,1,0,1,2,3,2],
59'R':[2,1,0,1,0,1,2,3,0],
60'S':[0,1,2,1,0,1,2,3,0],
61'T':[0,1,0,1,2,1,2,3,0],
62'U':[2,3,0,1,0,1,0,1,2],
63'V':[0,3,2,1,0,1,0,1,2],
64'W':[2,3,2,1,0,1,0,1,0],
65'X':[0,3,0,1,2,1,0,1,2],
66'Y':[2,3,0,1,2,1,0,1,0],
67'Z':[0,3,2,1,2,1,0,1,0]
68}
69
70def create_c39(height, smallest, text):
71 pixel_length = 0
72 i = 0
73 newtext = ""
74 machinetext = "*" + text + "*"
75 seglist = []
76 while i < len(machinetext):
77 char = machinetext[i].capitalize()
78 i = i + 1
79 try:
80 map = charmap[char]
81 if len(map) != 9:
82 continue
83
84 j = 0
85 while j < 9:
86 seg = int(map[j])
87
88 if seg == 0 or seg == 1:
89 pixel_length = pixel_length + smallest
90 seglist.append(seg)
91 elif seg == 2 or seg == 3:
92 pixel_length = pixel_length + smallest * 3
93 seglist.append(seg)
94
95 j = j + 1
96
97 newtext += char
98 except:
99 continue
100
101 pixel_length = pixel_length + 2*marginx + len(newtext) * smallest
102 pixel_height = height + 2*marginy + fontsize
103
104 barcode_img = Image.new('RGB', [pixel_length, pixel_height], "white")
105
106 if len(seglist) == 0:
107 return barcode_img
108
109 i = 0
110 draw = ImageDraw.Draw(barcode_img)
111 current_x = marginx
112
113 while i < len(seglist):
114 seg = seglist[i]
115 color = (255, 255, 255)
116 wdth = smallest
117
118 if seg == 0 or seg == 2:
119 color = 0
120 if seg == 0:
121 wdth = smallest
122 else:
123 wdth = smallest * 3
124 elif seg == 1 or seg == 3:
125 color = (255, 255, 255)
126 if seg == 1:
127 wdth = smallest
128 else:
129 wdth = smallest * 3
130
131 j = 1
132
133 while j <= wdth:
134 draw.line((current_x, marginy, current_x, marginy+height), fill=color)
135 current_x = current_x + 1
136 j = j + 1
137
138 if ((i+1) % 9) == 0:
139 j = 1
140 while j <= smallest:
141 draw.line((current_x, marginy, current_x, marginy+height), fill=(255,255,255))
142 current_x = current_x + 1
143 j = j + 1
144 i = i + 1
145
146 font = ImageFont.truetype(config['addons_path']+"/report_aeroo/barcode/FreeMonoBold.ttf", fontsize)
147
148 draw.text((pixel_length/2 - len(newtext)*(fontsize/2)/2-len(newtext), height+fontsize), newtext, font=font, fill=0)
149
150 del draw
151
152 return barcode_img
153
0154
=== added file 'barcode/courB08.pbm'
1Binary files barcode/courB08.pbm 1970-01-01 00:00:00 +0000 and barcode/courB08.pbm 2012-07-05 12:25:24 +0000 differ155Binary files barcode/courB08.pbm 1970-01-01 00:00:00 +0000 and barcode/courB08.pbm 2012-07-05 12:25:24 +0000 differ
=== added file 'barcode/courB08.pil'
2Binary files barcode/courB08.pil 1970-01-01 00:00:00 +0000 and barcode/courB08.pil 2012-07-05 12:25:24 +0000 differ156Binary files barcode/courB08.pil 1970-01-01 00:00:00 +0000 and barcode/courB08.pil 2012-07-05 12:25:24 +0000 differ
=== added file 'currency_to_text.py'
--- currency_to_text.py 1970-01-01 00:00:00 +0000
+++ currency_to_text.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,490 @@
1#!/usr/bin/python
2# -*- coding: utf8 -*-
3
4###########################################################
5# Developed by Kaspars Vilkens - KN dati Ltd. (c) 2009
6# pep-8, unicode and doctests by Paul Stevens, paul@nfg.nl, 2010
7#
8# Supported currencies: LVL, EUR, USD, UAH
9# Supported sum: 0 ... 999999999999.99
10# Supported languages: lv_LV, en_US, ru_RU, uk_UA
11###########################################################
12import string
13
14supported_currency = ['LVL','EUR','USD', 'UAH']
15supported_language = ['lv_LV','en_US','ru_RU', 'uk_UA']
16
17def currency_to_text(sum, currency, language):
18 """
19
20 first some simple tests
21
22 >>> currency_to_text(123, 'EUR', 'en_US')
23 'one hundred twenty three euros zero cents'
24
25 >>> currency_to_text(1.11, 'EUR', 'en_US')
26 'one euro eleven cents'
27
28 >>> currency_to_text(1.10, 'USD', 'en_US')
29 'one US dollar ten cents'
30
31 >>> currency_to_text(1.01, 'USD', 'en_US')
32 'one US dollar one cent'
33
34 >>> currency_to_text(1.01, 'LVL', 'lv_LV') == 'viens lats viens santīms'
35 True
36
37 >>> currency_to_text(123.12, 'LVL', 'ru_RU') == 'стo двaдцать три лата двенадцать сантимов'
38 True
39
40 >>> currency_to_text(123.12, 'USD', 'ru_RU') == 'стo двaдцать три доллара США двенадцать центов'
41 True
42
43
44 """
45 if sum < 0 or sum > 999999999999.99 :
46 raise Exception('Sum out of bounds: must be from 0 to 999999999999.99')
47 if currency not in supported_currency:
48 raise Exception("""Unsupported or no currency: must be one of (%s)""" % \
49 string.join(supported_currency,','))
50 if language not in supported_language:
51 raise Exception("""Unsupported or no language: must be one of (%s)""" % \
52 string.join(supported_language,','))
53#--------------for currencies with 100 fractions
54 sum = float(sum)
55 sum = round(sum, 2)
56 # find out digits before floating point - currency
57 sum_cur = int(sum)
58 # find out digits after floating point - fractions
59 sum_frc = int(round((sum - sum_cur) * 100,0))
60 cur_in_words = dtowords(sum_cur, language)
61 #print cur_in_words
62 frc_in_words = dtowords(sum_frc, language)
63 #print frc_in_words
64 #------------------------------------
65 if language == 'lv_LV' :
66 if sum_cur == 1 or (str(sum_cur)[-1] == '1' and str(sum_cur)[-2] != '1'): # is the currency sum one
67 if currency == 'LVL':
68 cur_in_words += u' lats'
69 elif currency == 'EUR':
70 cur_in_words += u' eiro'
71 elif currency == 'USD':
72 cur_in_words += u' dolārs'
73 elif currency == 'UAH':
74 cur_in_words += u' grivna'
75 else:
76 if currency == 'LVL':
77 cur_in_words += u' lati'
78 elif currency == 'EUR':
79 cur_in_words += u' eiro'
80 elif currency == 'USD':
81 cur_in_words += u' dolāri'
82 elif currency == 'UAH':
83 cur_in_words += u' grivnas'
84
85 if sum_frc == 1 or (str(sum_frc)[-1] == '1' and str(sum_frc)[-2] != '1'): # is the fraction sum one
86 if currency == 'LVL':
87 frc_in_words += u' santīms'
88 elif currency == 'EUR' or currency == 'USD' :
89 frc_in_words += u' cents'
90 elif currency == 'UAH':
91 frc_in_words += u' kapeika'
92 else:
93 if currency == 'LVL':
94 frc_in_words += u' santīmi'
95 elif currency == 'EUR' or currency == 'USD':
96 frc_in_words += u' centi'
97 elif currency == 'UAH':
98 frc_in_words += u' kapeikas'
99 #------------------------------------
100 if language == 'en_US' :
101 if sum_cur == 1 or (str(sum_cur)[-1] == '1' and str(sum_cur)[-2] != '1'): # is the currency sum one
102 if currency == 'LVL':
103 cur_in_words += u' Latvian lats'
104 elif currency == 'EUR':
105 cur_in_words += u' euro'
106 elif currency == 'USD':
107 cur_in_words += u' US dollar'
108 else:
109 if currency == 'LVL':
110 cur_in_words += u' Latvian lats'
111 elif currency == 'EUR':
112 cur_in_words += u' euros'
113 elif currency == 'USD':
114 cur_in_words += u' dollars'
115 if sum_frc == 1 or (str(sum_frc)[-1] == '1' and str(sum_frc)[-2] != '1'): # is the fraction sum one
116 if currency == 'LVL':
117 frc_in_words += u' santim'
118 elif currency == 'EUR' or currency == 'USD':
119 frc_in_words += u' cent'
120 else:
121 if currency == 'LVL':
122 frc_in_words += u' santims'
123 elif currency == 'EUR' or currency == 'USD' :
124 frc_in_words += u' cents'
125 #------------------------------------
126 if language == 'ru_RU' :
127 if sum_cur == 1 or (str(sum_cur)[-1] == '1' and str(sum_cur)[-2] != '1'): # is the currency sum one
128 if currency == 'LVL':
129 cur_in_words += u' лат'
130 elif currency == 'EUR':
131 cur_in_words += u' евро'
132 elif currency == 'USD':
133 cur_in_words += u' доллар США'
134 elif (sum_cur in [2, 3, 4]) or (str(sum_cur)[-1] in ['2', '3', '4'] and str(sum_cur)[-2] != '1'):
135 if currency == 'LVL':
136 cur_in_words += u' лата'
137 elif currency == 'EUR' :
138 cur_in_words += u' евро'
139 elif currency == 'USD' :
140 cur_in_words += u' доллара США'
141 elif (sum_cur >= 5 and sum_cur <= 20) or str(sum_cur)[-1] not in [2, 3, 4]:
142 if currency == 'LVL' :
143 cur_in_words += u' латов'
144 elif currency == 'EUR' :
145 cur_in_words += u' евро'
146 elif currency == 'USD' :
147 cur_in_words += u' долларов США'
148
149 if sum_frc == 1 or (str(sum_frc)[-1] == '1' and str(sum_frc)[-2] != '1') : # is the fraction one
150 if currency == 'LVL' :
151 frc_in_words += u' сантим'
152 elif currency == 'EUR' or currency == 'USD' :
153 frc_in_words += u' цент'
154 elif (sum_frc in [2, 3, 4]) or (str(sum_frc)[-1] in ['2', '3', '4'] and str(sum_frc)[-2] != '1') :
155 if currency == 'LVL' :
156 frc_in_words += u' сантима'
157 elif currency == 'EUR' or currency == 'USD' :
158 frc_in_words += u' цента'
159 elif (sum_frc >= 5 and sum_frc <= 20) or str(sum_frc)[-1] not in [2, 3, 4] :
160 if currency == 'LVL' :
161 frc_in_words += u' сантимов'
162 elif currency == 'EUR' or currency == 'USD' :
163 frc_in_words += u' центов'
164 #------------------------------------
165 if language == 'uk_UA' :
166 if sum_cur == 1 or (str(sum_cur)[-1] == '1' and str(sum_cur)[-2] != '1') : # is the currency sum one
167 if currency == 'LVL' :
168 cur_in_words += u' лат'
169 elif currency == 'EUR' :
170 cur_in_words += u' евро'
171 elif currency == 'USD' :
172 cur_in_words += u' доллар США'
173 elif currency == 'UAH' :
174 cur_in_words += u' гривня'
175 elif (sum_cur in [2, 3, 4]) or (str(sum_cur)[-1] in ['2', '3', '4'] and str(sum_cur)[-2] != '1') :
176 if currency == 'LVL' :
177 cur_in_words += u' лата'
178 elif currency == 'EUR' :
179 cur_in_words += u' евро'
180 elif currency == 'USD' :
181 cur_in_words += u' доллара США'
182 elif currency == 'UAH' :
183 cur_in_words += u' гривні'
184 elif (sum_cur >= 5 and sum_cur <= 20) or str(sum_cur)[-1] not in [2, 3, 4] :
185 if currency == 'LVL' :
186 cur_in_words += u' латов'
187 elif currency == 'EUR' :
188 cur_in_words += u' евро'
189 elif currency == 'USD' :
190 cur_in_words += u' долларов США'
191 elif currency == 'UAH' :
192 cur_in_words += u' гривень'
193
194 if sum_frc == 1 or (str(sum_frc)[-1] == '1' and str(sum_frc)[-2] != '1') : # is the fraction one
195 if currency == 'LVL' :
196 frc_in_words += u' сантим'
197 elif currency == 'EUR' or currency == 'USD' :
198 frc_in_words += u' цент'
199 elif currency == 'UAH' :
200 frc_in_words += u' копійка'
201 elif (sum_frc in [2, 3, 4]) or (str(sum_frc)[-1] in ['2', '3', '4'] and str(sum_frc)[-2] != '1') :
202 if currency == 'LVL' :
203 frc_in_words += u' сантима'
204 elif currency == 'EUR' or currency == 'USD' :
205 frc_in_words += u' цента'
206 elif currency == 'UAH' :
207 frc_in_words += u' копійки'
208 elif (sum_frc >= 5 and sum_frc <= 20) or str(sum_frc)[-1] not in [2, 3, 4] :
209 if currency == 'LVL' :
210 frc_in_words += u' сантимов'
211 elif currency == 'EUR' or currency == 'USD' :
212 frc_in_words += u' центов'
213 elif currency == 'UAH' :
214 frc_in_words += u' копійок'
215 frc_in_words = str(sum_frc) + u' коп.'
216
217 return (cur_in_words + ' ' + frc_in_words).strip().encode('utf-8')
218
219
220def dtowords(sum_integers, language):
221 """
222 >>> dtowords(0, 'en_US')
223 u'zero'
224
225 >>> dtowords(1, 'en_US')
226 u'one'
227
228 >>> dtowords(11, 'en_US')
229 u'eleven'
230
231 >>> dtowords(169, 'en_US')
232 u'one hundred sixty nine'
233
234 >>> dtowords(12345, 'en_US')
235 u'twelve thousand three hundred fourty five'
236
237 >>> dtowords(123456, 'en_US')
238 u'one hundred twenty three thousand four hundred fifty six'
239
240 >>> dtowords(0, 'lv_LV')
241 u'nulle'
242
243 >>> dtowords(1, 'lv_LV')
244 u'viens'
245
246 >>> dtowords(11, 'lv_LV')
247 u'vienpadsmit'
248
249 >>> dtowords(169, 'lv_LV').encode('utf-8') == 'simts sešdesmit deviņi'
250 True
251
252 >>> dtowords(12345, 'lv_LV').encode('utf-8') == 'divpadsmit tūkstoši trīs simti četrdesmit pieci'
253 True
254
255 >>> dtowords(123456, 'lv_LV').encode('utf-8') == 'simts divdesmit trīs tūkstoši četri simti piecdesmit seši'
256 True
257
258 >>> dtowords(0, 'ru_RU').encode('utf-8') == 'ноль'
259 True
260
261 >>> dtowords(1, 'ru_RU').encode('utf-8') == 'один'
262 True
263
264 >>> dtowords(11, 'ru_RU').encode('utf-8') == 'одиннадцать'
265 True
266
267 >>> dtowords(169, 'ru_RU').encode('utf-8') == 'стo шестьдесят девять'
268 True
269
270 >>> dtowords(12345, 'ru_RU').encode('utf-8') == 'двенадцать тысяч триста сорок пять'
271 True
272
273 >>> dtowords(123456, 'ru_RU').encode('utf-8') == 'стo двaдцать три тысячи четыреста пятьдесят шесть'
274 True
275
276
277 """
278 diginwords = u''
279 if sum_integers == 0:
280 return wordify('0', 0, language)
281 elif sum_integers > 0:
282 lengthx = len(str(sum_integers))
283 nrchunks = (lengthx / 3)
284 if nrchunks < (float(lengthx) / 3) :
285 nrchunks+=1
286 inc = 1
287 while inc <= nrchunks:
288 startpos = (lengthx - inc * 3)
289 chunklength = 3
290 if startpos < 0:
291 chunklength += startpos
292 startpos = 0
293 chunk = str(sum_integers)[startpos : startpos + chunklength]
294 #print str(startpos)+' '+str(chunklength)+' '+ chunk
295 wordified = wordify(chunk, inc-1, language)
296 inc += 1
297 spacer = ''
298 if len(diginwords) > 0 :
299 spacer = ' '
300 diginwords = wordified + spacer + diginwords
301 return diginwords
302
303def wordify(chunk, chunknr, language):
304 #print 'chunk '+str(chunk)
305 #print 'cunknr '+str(chunknr)
306 words = u''
307
308 if language == 'lv_LV':
309 skaitli = [u'nulle', u'viens', u'divi', u'trīs', u'četri', u'pieci',
310 u'seši', u'septiņi', u'astoņi', u'deviņi']
311 skaitlix = [u'nulle', u'vien', u'div', u'trīs', u'četr', u'piec', u'seš',
312 u'septiņ', u'astoņ', u'deviņ']
313 skaitli_teens = [u'desmit', u'vienpadsmit', u'divpadsmit', u'trīspadsmit',
314 u'četrpadsmit', u'piecpadsmit', u'sešpadsmit',
315 u'septiņpadsmit', u'astoņpadsmit', u'deviņpadsmit']
316 daudzums = [u'simts', u' tūkstotis', u' miljons', u' miljards']
317 daudzumsx = [u' simti', u' tūkstoši', u' miljoni', u' miljardi']
318
319 elif language == 'en_US':
320 skaitli = [u'zero', u'one', u'two', u'three', u'four', u'five', u'six',
321 u'seven', u'eight', u'nine']
322 skaitlix = [u'zero', u'one', u'twen', u'thir', u'four', u'fif', u'six',
323 u'seven', u'eigh', u'nine']
324 skaitli_teens = [u'ten', u'eleven', u'twelve', u'thirteen', u'fourteen',
325 u'fifteen', u'sixteen', u'seventeen', u'eighteen', u'nineteen']
326 daudzums = [u' hundred', u' thousand', u' million', u' billion']
327 daudzumsx = daudzums
328
329 elif language == 'ru_RU':
330 skaitli = [u'ноль', u'один', u'два', u'три', u'четыре', u'пять', u'шесть',
331 u'семь', u'восемь', u'девять']
332 skaitlix = [u'', u'один', u'двa', u'три', u'четыре', u'пять', u'шесть',
333 u'семь', u'восемь', u'девять']
334 skaitli_teens = [u'десять', u'одиннадцать', u'двенадцать', u'тринадцать',
335 u'четырнадцать', u'пятнадцать', u'шестнадцать', u'семнадцать',
336 u'восемнадцать', u'девятнадцать']
337 daudzums = [u'стo', u' тысяча', u' миллион', u' миллиард']
338 daudzumsx = [u'сoт', u' тысяч', u' миллионов', u' миллиардов']
339
340 elif language == 'uk_UA' :
341 skaitli = [u'ноль', u'один', u'два', u'три', u'чотири', u'п\'ять', u'шість',
342 u'сім', u'вісім', u'дев\'ять']
343 skaitlix = [u'', u'один', u'двa', u'три', u'чотири', u'п\'ять', u'шість',
344 u'сім', u'вісім', u'дев\'ять']
345 skaitli_teens = [u'десять', u'одинадцять', u'дванадцять', u'тринадцять',
346 u'чотирнадцять', u'п\'ятнадцять', u'шістнадцять', u'сімнадцять',
347 u'вісімнадцять', u'дев\'ятнадцять']
348 daudzums = [u'стo', u' тисяча', u' мiллiон', u' мiллiард']
349 daudzumsx = [u'сoт', u' тисяч', u' мiллiонiв', u' мiллiардов']
350 digit1 = u''
351 digit2 = u''
352 digit3 = u''
353 chunklength = len(chunk)
354 # placing digits in right places
355 if chunklength == 1:
356 digit3 = chunk[0 : 1]
357 if chunklength == 2:
358 digit2 = chunk[0 : 1]
359 digit3 = chunk[1 : 2]
360 if chunklength == 3:
361 digit1 = chunk[0 : 1]
362 digit2 = chunk[1 : 2]
363 digit3 = chunk[-1]
364 # processing zero
365 if chunklength == 1 and digit3 == '0' :
366 return skaitli[0]
367 # processing hundreds
368 if chunklength == 3 :
369 if digit1 == '1' :
370 if language == 'lv_LV' or language == 'ru_RU' or language == 'uk_UA':
371 words += daudzums[0]
372 elif language == 'en_US' :
373 words += skaitli[int(digit1)] + daudzumsx[0]
374 else :
375 if language == 'lv_LV' :
376 if int(digit1) > 1 : words += skaitli[int(digit1)] + daudzumsx[0]
377 elif language == 'en_US' :
378 if int(digit1) > 1 : words += skaitli[int(digit1)] + daudzumsx[0]
379 elif language == 'ru_RU' :
380 if int(digit1) == 2 :
381 words += u'двести'
382 elif int(digit1) == 3 :
383 words += u'триста'
384 elif int(digit1) == 4 :
385 words += u'четыреста'
386 elif int(digit1) >= 5 :
387 words += skaitli[int(digit1)] + daudzumsx[0]
388 elif language == 'uk_UA' :
389 if int(digit1) == 2 :
390 words += u'двісті'
391 elif int(digit1) == 3 :
392 words += u'триста'
393 elif int(digit1) == 4 :
394 words += u'чотириста'
395 elif int(digit1) >= 5 :
396 words += skaitli[int(digit1)] + daudzumsx[0]
397 # processing tens
398 if chunklength > 1:
399 spacer = ''
400 if len(words) > 0 : spacer = ' '
401 if digit2 == '1':
402 if language == 'lv_LV' or language == 'en_US' or language == 'ru_RU' or language == 'uk_UA':
403 words += spacer + skaitli_teens[int(digit3)]
404 else:
405 if language == 'lv_LV':
406 if int(digit2) > 1 and int(digit2) > 0:
407 words += spacer + skaitlix[int(digit2)] + u'desmit'
408 elif language == 'en_US':
409 if int(digit2) > 1 and int(digit2) > 0:
410 words += spacer + skaitlix[int(digit2)] + u'ty'
411 elif language == 'ru_RU':
412 if int(digit2) > 1 and int(digit2) < 4:
413 words += spacer + skaitlix[int(digit2)] + u'дцать'
414 elif digit2 == '4':
415 words += spacer + u'сорок'
416 elif int(digit2) >= 5 and int(digit2) != 9:
417 words += spacer + skaitlix[int(digit2)] + u'десят'
418 elif digit2 == '9':
419 words += spacer + u'девяносто'
420 elif language == 'uk_UA' :
421 if int(digit2) > 1 and int(digit2) < 4:
422 words += spacer + skaitlix[int(digit2)] + u'дцять'
423 elif digit2 == '4':
424 words += spacer + u'сорок'
425 elif int(digit2) >= 5 and int(digit2) != 9:
426 words += spacer + skaitlix[int(digit2)] + u'десят'
427 elif digit2 == '9':
428 words += spacer + u'дев\'яносто'
429 # processing ones
430 if chunklength > 0 and digit2 != '1' :
431 spacer = ''
432 if len(words) > 0: spacer = u' '
433 if language == 'lv_LV' or language == 'en_US':
434 if int(digit3) > 0:
435 words += spacer + skaitli[int(digit3)]
436 elif language == 'ru_RU':
437 if chunknr == 1:
438 if int(digit3) == 1:
439 words += spacer + u'одна'
440 elif int(digit3) == 2:
441 words += spacer + u'две'
442 elif int(digit3) >= 3 and int(digit3) != 0:
443 words += spacer + skaitli[int(digit3)]
444 else:
445 if int(digit3) > 0: words += spacer + skaitli[int(digit3)]
446 elif language == 'uk_UA' :
447 if chunknr == 1 :
448 if int(digit3) == 1 : words += spacer + u'одна'
449 elif int(digit3) == 2 : words += spacer + u'дві'
450 elif int(digit3) >= 3 and int(digit3) != 0: words += spacer + skaitli[int(digit3)]
451 else:
452 if int(digit3) > 0 : words += spacer + skaitli[int(digit3)]
453 # end processing
454 if len(words) > 0 :
455
456 if digit3 == '1' and chunknr > 0:
457 return words + daudzums[chunknr]
458 elif digit3 != '1' and chunknr > 0:
459 if language == 'lv_LV' or language == 'en_US' :
460 return words + daudzumsx[chunknr]
461 elif language == 'ru_RU' :
462 if (int(digit3) == 2 or int(digit3) == 3 or int(digit3) == 4) and digit2 != '1' :
463 if chunknr == 1 :
464 return words + u' тысячи'
465 elif chunknr == 2 :
466 return words + u' миллионa'
467 elif chunknr == 3 :
468 return words + u' миллиардa'
469 else:
470 return words + daudzumsx[chunknr]
471 elif language == 'uk_UA' :
472 if (int(digit3) == 2 or int(digit3) == 3 or int(digit3) == 4) and digit2 != '1' :
473 if chunknr == 1 :
474 return words + u' тисячі'
475 elif chunknr == 2 :
476 return words + u' мілліонa'
477 elif chunknr == 3 :
478 return words + u' мілліардa'
479 else:
480 return words + daudzumsx[chunknr]
481 else:
482 return words
483 else:
484 return ''
485
486
487if __name__ == '__main__':
488 import doctest
489 doctest.testmod()
490
0491
=== added directory 'data'
=== added file 'data/report_aeroo_data.xml'
--- data/report_aeroo_data.xml 1970-01-01 00:00:00 +0000
+++ data/report_aeroo_data.xml 2012-07-05 12:25:24 +0000
@@ -0,0 +1,25 @@
1<?xml version="1.0"?>
2<openerp>
3 <data noupdate="1">
4
5 <record model="report.mimetypes" id="report_mimetypes_odt_odt" >
6 <field name="name">ODF Text Document (.odt)</field>
7 <field name="code">oo-odt</field>
8 <field name="compatible_types">oo-odt</field>
9 </record>
10
11 <record model="report.mimetypes" id="report_mimetypes_ods_ods" >
12 <field name="name">ODF Spreadsheet (.ods)</field>
13 <field name="code">oo-ods</field>
14 <field name="compatible_types">oo-ods</field>
15 </record>
16
17 <record model="report.mimetypes" id="report_mimetypes_raw" >
18 <field name="name">Generic</field>
19 <field name="code">genshi-raw</field>
20 <field name="compatible_types">genshi-raw</field>
21 </record>
22
23 </data>
24</openerp>
25
026
=== added file 'domain_parser.py'
--- domain_parser.py 1970-01-01 00:00:00 +0000
+++ domain_parser.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,45 @@
1##############################################################################
2#
3# Copyright (c) 2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29def domain2statement(domain):
30 statement=''
31 operator=False
32 for d in domain:
33 if not operator:
34 if type(d)==str:
35 if d=='|':
36 operator=' or'
37 continue
38 else:
39 operator=False
40 statement+=' o.'+str(d[0])+' '+(d[1]=='=' and '==' or d[1])+' '+(isinstance(d[2], str) and '\''+d[2]+'\'' or str(d[2]))
41 if d!=domain[-1]:
42 statement+=operator or ' and'
43 operator=False
44 return statement
45
046
=== added file 'report_aeroo.py'
--- report_aeroo.py 1970-01-01 00:00:00 +0000
+++ report_aeroo.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,636 @@
1# -*- encoding: utf-8 -*-
2
3##############################################################################
4#
5# Copyright (c) 2009-2010 KN dati, SIA. (http://kndati.lv) All Rights Reserved.
6# General contacts <info@kndati.lv>
7# Copyright (C) 2009 Domsense s.r.l.
8#
9# WARNING: This program as such is intended to be used by professional
10# programmers who take the whole responsability of assessing all potential
11# consequences resulting from its eventual inadequacies and bugs
12# End users who are looking for a ready-to-use solution with commercial
13# garantees and support are strongly adviced to contract a Free Software
14# Service Company
15#
16# This program is Free Software; you can redistribute it and/or
17# modify it under the terms of the GNU General Public License
18# as published by the Free Software Foundation; either version 2
19# of the License, or (at your option) any later version.
20#
21# This program is distributed in the hope that it will be useful,
22# but WITHOUT ANY WARRANTY; without even the implied warranty of
23# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24# GNU General Public License for more details.
25#
26# You should have received a copy of the GNU General Public License
27# along with this program; if not, write to the Free Software
28# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29#
30##############################################################################
31
32import os, sys, traceback
33import tempfile
34import report
35from report.report_sxw import *
36#import zipfile
37try:
38 from cStringIO import StringIO
39except ImportError:
40 from StringIO import StringIO
41from xml.dom import minidom
42import base64
43from osv import osv
44from tools.translate import _
45import time
46import re
47import copy
48
49from addons import load_information_from_description_file
50import release
51
52import aeroolib
53from aeroolib.plugins.opendocument import Template, OOSerializer
54from genshi.template import NewTextTemplate
55import pooler
56import netsvc
57logger = netsvc.Logger()
58
59from ExtraFunctions import ExtraFunctions
60
61class Counter(object):
62 def __init__(self, name, start=0, interval=1):
63 self.name = name
64 self._number = start
65 self._interval = interval
66
67 def next(self):
68 curr_number = self._number
69 self._number += self._interval
70 return curr_number
71
72 def get_inc(self):
73 return self._number
74
75 def prev(self):
76 return self._number-self._interval
77
78class Aeroo_report(report_sxw):
79
80 def logger(self, message, level=netsvc.LOG_DEBUG):
81 netsvc.Logger().notifyChannel('report_aeroo', level, message)
82
83 def __init__(self, cr, name, table, rml=False, parser=False, header=True, store=False):
84 super(Aeroo_report, self).__init__(name, table, rml, parser, header, store)
85 self.logger("registering %s (%s)" % (name, table), netsvc.LOG_INFO)
86 self.oo_subreports = []
87 self.epl_images = []
88 self.counters = {}
89
90 pool = pooler.get_pool(cr.dbname)
91 ir_obj = pool.get('ir.actions.report.xml')
92 report_xml_ids = ir_obj.search(cr, 1, [('report_name', '=', name[7:])])
93 if report_xml_ids:
94 report_xml = ir_obj.browse(cr, 1, report_xml_ids[0])
95
96 if report_xml.preload_mode == 'preload':
97 file_data = report_xml.report_sxw_content
98 if not file_data:
99 self.logger("template is not defined in %s (%s) !" % (name, table), netsvc.LOG_WARNING)
100 template_io = None
101 else:
102 template_io = StringIO()
103 template_io.write(base64.decodestring(file_data))
104 style_io=self.get_styles_file(cr, 1, report_xml)
105 if template_io:
106 self.serializer = OOSerializer(template_io, oo_styles=style_io)
107
108 ##### Counter functions #####
109 def _def_inc(self, name, start=0, interval=1):
110 self.counters[name] = Counter(name, start, interval)
111
112 def _get_inc(self, name):
113 return self.counters[name].get_inc()
114
115 def _prev(self, name):
116 return self.counters[name].prev()
117
118 def _next(self, name):
119 return self.counters[name].next()
120 #############################
121
122 def _epl_asimage(self, data):
123 from PIL import Image
124 from math import ceil
125 if not data:
126 return ''
127 img = Image.open(StringIO(base64.decodestring(data)))
128 if img.format!='BMP':
129 return ''
130 data = base64.decodestring(data)[62:]
131 line_len = int(ceil(img.size[0]/32.0)*4)
132 temp_data = ''
133 for n in range(img.size[1]):
134 curr_pos = n*line_len
135 temp_data = data[curr_pos:curr_pos+line_len][:int(img.size[0]/8)] + temp_data
136
137 new_data = ''
138 for d in temp_data:
139 new_data += chr(ord(d)^255)
140 self.epl_images.append(new_data)
141 return img.size
142
143 def _epl2_gw(self, start_x, start_y, data):
144 if not data:
145 return None
146 size_x, size_y = self._epl_asimage(data)
147 return 'GW'+str(start_x)+','+str(start_y)+','+str(int(size_x/8))+','+str(size_y)+',<binary_data>'
148
149 def _include_document(self, aeroo_ooo=False):
150 def include_document(data, silent=False):
151 if not aeroo_ooo:
152 return _("Error! Include document not available!")
153 import binascii, urllib2
154 dummy_fd, temp_file_name = tempfile.mkstemp(suffix='.odt', prefix='aeroo-report-')
155 temp_file = open(temp_file_name, 'wb')
156 if os.path.isfile(data):
157 fd = file(data, 'rb')
158 data = fd.read()
159 else:
160 error = False
161 try:
162 url_file = urllib2.urlopen(data)
163 data = url_file.read()
164 except urllib2.HTTPError:
165 os.unlink(temp_file_name)
166 error = _('HTTP Error 404! Not file found:')+' %s' % data
167 except urllib2.URLError, e:
168 os.unlink(temp_file_name)
169 error = _('Error!')+' %s' % e
170 except IOError, e:
171 os.unlink(temp_file_name)
172 error = _('Error!')+' %s' % e
173 except Exception, e:
174 try:
175 data = base64.decodestring(data)
176 except binascii.Error:
177 os.unlink(temp_file_name)
178 error = _('Error! Not file found:')+' %s' % data
179 if error:
180 if not silent:
181 return error
182 else:
183 return None
184 try:
185 temp_file.write(data)
186 finally:
187 temp_file.close()
188 self.oo_subreports.append(temp_file_name)
189 return "<insert_doc('%s')>" % temp_file_name
190 return include_document
191
192 def _subreport(self, cr, uid, output='odt', aeroo_ooo=False, context={}):
193 pool = pooler.get_pool(cr.dbname)
194 ir_obj = pool.get('ir.actions.report.xml')
195 #### for odt documents ####
196 def odt_subreport(name=None, obj=None):
197 if not aeroo_ooo:
198 return _("Error! Subreports not available!")
199 report_xml_ids = ir_obj.search(cr, uid, [('report_name', '=', name)], context=context)
200 if report_xml_ids:
201 report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
202 data = {'model': obj._table_name, 'id': obj.id, 'report_type': 'aeroo', 'in_format': 'oo-odt'}
203 report, output = netsvc.Service._services['report.%s' % name].create_aeroo_report(cr, uid, \
204 [obj.id], data, report_xml, context=context, output='odt') # change for OpenERP 6.0 - Service class usage
205
206 dummy_fd, temp_file_name = tempfile.mkstemp(suffix='.odt', prefix='aeroo-report-')
207 temp_file = open(temp_file_name, 'wb')
208 try:
209 temp_file.write(report)
210 finally:
211 temp_file.close()
212
213 self.oo_subreports.append(temp_file_name)
214
215 return "<insert_doc('%s')>" % temp_file_name
216 return None
217 #### for text documents ####
218 def raw_subreport(name=None, obj=None):
219 report_xml_ids = ir_obj.search(cr, uid, [('report_name', '=', name)], context=context)
220 if report_xml_ids:
221 report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
222 data = {'model': obj._table_name, 'id': obj.id, 'report_type': 'aeroo', 'in_format': 'genshi-raw'}
223 report, output = netsvc.Service._services['report.%s' % name].create_genshi_raw_report(cr, uid, \
224 [obj.id], data, report_xml, context=context, output=output) # change for OpenERP 6.0 - Service class usage
225 return report
226 return None
227
228 if output=='odt':
229 return odt_subreport
230 elif output=='raw':
231 return raw_subreport
232
233 def set_xml_data_fields(self, objects, parser):
234 xml_data_fields = parser.localcontext.get('xml_data_fields', False)
235 if xml_data_fields:
236 for field in xml_data_fields:
237 for o in objects:
238 if getattr(o, field):
239 xml_data = base64.decodestring(getattr(o, field))
240 xmldoc = minidom.parseString(xml_data)
241 setattr(o, field, xmldoc.firstChild)
242 return objects
243
244 def get_other_template(self, cr, uid, data, parser):
245 if hasattr(parser, 'get_template'):
246 pool = pooler.get_pool(cr.dbname)
247 record = pool.get(data['model']).browse(cr, uid, data['id'], {})
248 template = parser.get_template(cr, uid, record)
249 return template
250 else:
251 return False
252
253 def get_styles_file(self, cr, uid, report_xml, context=None):
254 pool = pooler.get_pool(cr.dbname)
255 style_io=None
256 if report_xml.styles_mode!='default':
257 if report_xml.styles_mode=='global':
258 company_id = pool.get('res.users')._get_company(cr, uid, context=context)
259 style_content = pool.get('res.company').browse(cr, uid, company_id, context=context).stylesheet_id
260 style_content = style_content and style_content.report_styles or False
261 elif report_xml.styles_mode=='specified':
262 style_content = report_xml.stylesheet_id
263 style_content = style_content and style_content.report_styles or False
264 if style_content:
265 style_io = StringIO()
266 style_io.write(base64.decodestring(style_content))
267 return style_io
268
269 def create_genshi_raw_report(self, cr, uid, ids, data, report_xml, context=None, output='raw'):
270 def preprocess(data):
271 self.epl_images.reverse()
272 while self.epl_images:
273 img = self.epl_images.pop()
274 data = data.replace('<binary_data>', img, 1)
275 return data.replace('\n', '\r\n')
276
277 if not context:
278 context={}
279 context = context.copy()
280 objects = self.getObjects(cr, uid, ids, context)
281 oo_parser = self.parser(cr, uid, self.name2, context=context)
282 oo_parser.objects = objects
283 self.set_xml_data_fields(objects, oo_parser) # Get/Set XML
284 file_data = self.get_other_template(cr, uid, data, oo_parser) or report_xml.report_sxw_content # Get other Tamplate
285 ################################################
286 if not file_data:
287 return False, output
288
289 oo_parser.localcontext['objects'] = objects
290 oo_parser.localcontext['data'] = data
291 oo_parser.localcontext['user_lang'] = context['lang']
292 if len(objects)>0:
293 oo_parser.localcontext['o'] = objects[0]
294 xfunc = ExtraFunctions(cr, uid, report_xml.id, oo_parser.localcontext)
295 oo_parser.localcontext.update(xfunc.functions)
296 oo_parser.localcontext['include_subreport'] = self._subreport(cr, uid, output='raw', aeroo_ooo=False, context=context)
297 oo_parser.localcontext['epl2_gw'] = self._epl2_gw
298
299 self.epl_images = []
300 basic = NewTextTemplate(source=file_data)
301 #try:
302 data = preprocess(basic.generate(**oo_parser.localcontext).render().decode('utf8').encode(report_xml.charset))
303 #except Exception, e:
304 # self.logger(str(e), netsvc.LOG_ERROR)
305 # return False, output
306
307 if report_xml.content_fname:
308 output = report_xml.content_fname
309 return data, output
310
311 def create_aeroo_report(self, cr, uid, ids, data, report_xml, context=None, output='odt'):
312 """ Returns an aeroo report generated with aeroolib
313 """
314 pool = pooler.get_pool(cr.dbname)
315 if not context:
316 context={}
317 context = context.copy()
318 if self.name=='report.printscreen.list':
319 context['model'] = data['model']
320 context['ids'] = ids
321
322 objects = not context.get('no_objects', False) and self.getObjects(cr, uid, ids, context) or []
323 oo_parser = self.parser(cr, uid, self.name2, context=context)
324
325 oo_parser.objects = objects
326 self.set_xml_data_fields(objects, oo_parser) # Get/Set XML
327
328 style_io=self.get_styles_file(cr, uid, report_xml, context)
329 if report_xml.tml_source in ('file', 'database'):
330 file_data = base64.decodestring(report_xml.report_sxw_content)
331 else:
332 file_data = self.get_other_template(cr, uid, data, oo_parser)
333 if not file_data and not report_xml.report_sxw_content:
334 return False, output
335 #elif file_data:
336 # template_io = StringIO()
337 # template_io.write(file_data or report_xml.report_sxw_content)
338 # basic = Template(source=template_io, styles=style_io)
339 else:
340 if report_xml.preload_mode == 'preload' and hasattr(self, 'serializer'):
341 serializer = copy.copy(self.serializer)
342 serializer.apply_style(style_io)
343 template_io = serializer.template
344 else:
345 template_io = StringIO()
346 template_io.write(file_data or base64.decodestring(report_xml.report_sxw_content) )
347 serializer = OOSerializer(template_io, oo_styles=style_io)
348 basic = Template(source=template_io, serializer=serializer)
349
350 #if not file_data:
351 # return False, output
352
353 #basic = Template(source=template_io, serializer=serializer)
354
355 oo_parser.localcontext['objects'] = objects
356 oo_parser.localcontext['data'] = data
357 oo_parser.localcontext['user_lang'] = context['lang']
358 if len(objects)==1:
359 oo_parser.localcontext['o'] = objects[0]
360 xfunc = ExtraFunctions(cr, uid, report_xml.id, oo_parser.localcontext)
361 oo_parser.localcontext.update(xfunc.functions)
362
363 ###### Detect report_aeroo_ooo module ######
364 aeroo_ooo = False
365 cr.execute("SELECT id, state FROM ir_module_module WHERE name='report_aeroo_ooo'")
366 helper_module = cr.dictfetchone()
367 if helper_module['state'] in ('installed', 'to upgrade'):
368 aeroo_ooo = True
369 ############################################
370
371 oo_parser.localcontext['include_subreport'] = self._subreport(cr, uid, output='odt', aeroo_ooo=aeroo_ooo, context=context)
372 oo_parser.localcontext['include_document'] = self._include_document(aeroo_ooo)
373
374 ####### Add counter functons to localcontext #######
375 oo_parser.localcontext.update({'def_inc':self._def_inc,
376 'get_inc':self._get_inc,
377 'prev':self._prev,
378 'next':self._next})
379
380 user_name = pool.get('res.users').browse(cr, uid, uid, {}).name
381 model_id = pool.get('ir.model').search(cr, uid, [('model','=',data['model'])])[0]
382 model_name = pool.get('ir.model').browse(cr, uid, model_id).name
383
384 #basic = Template(source=None, filepath=odt_path)
385
386 basic.Serializer.add_title(model_name)
387 basic.Serializer.add_creation_user(user_name)
388 version = load_information_from_description_file('report_aeroo')['version']
389 basic.Serializer.add_generator_info('Aeroo Lib/%s Aeroo Reports/%s' % (aeroolib.__version__, version))
390 basic.Serializer.add_custom_property('Aeroo Reports %s' % version, 'Generator')
391 basic.Serializer.add_custom_property('OpenERP %s' % release.version, 'Software')
392 basic.Serializer.add_custom_property('http://www.alistek.com/', 'URL')
393 basic.Serializer.add_creation_date(time.strftime('%Y-%m-%dT%H:%M:%S'))
394
395 try:
396 data = basic.generate(**oo_parser.localcontext).render().getvalue()
397 except Exception, e:
398 tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
399 self.logger(tb_s, netsvc.LOG_ERROR)
400 for sub_report in self.oo_subreports:
401 os.unlink(sub_report)
402 raise Exception(_("Aeroo Reports: Error while generating the report."), e, str(e), _("For more reference inspect error logs."))
403 #return False, output
404
405 ######### OpenOffice extras #########
406 DC = netsvc.Service._services.get('openoffice')
407 if (output!=report_xml.in_format[3:] or self.oo_subreports):
408 if aeroo_ooo and DC:
409 try:
410 DC.putDocument(data)
411 if self.oo_subreports:
412 DC.insertSubreports(self.oo_subreports)
413 self.oo_subreports = []
414 data = DC.saveByStream(report_xml.out_format.filter_name)
415 DC.closeDocument()
416 #del DC
417 except Exception, e:
418 self.logger(str(e), netsvc.LOG_ERROR)
419 output=report_xml.in_format[3:]
420 self.oo_subreports = []
421 else:
422 output=report_xml.in_format[3:]
423 elif output in ('pdf', 'doc', 'xls'):
424 output=report_xml.in_format[3:]
425 #####################################
426
427 if report_xml.content_fname:
428 output = report_xml.content_fname
429 return data, output
430
431 # override needed to keep the attachments' storing procedure
432 def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
433 if not context:
434 context={}
435 if report_xml.report_type == 'aeroo':
436 if report_xml.out_format.code.startswith('oo-'):
437 output = report_xml.out_format.code[3:]
438 return self.create_aeroo_report(cr, uid, ids, data, report_xml, context=context, output=output)
439 elif report_xml.out_format.code =='genshi-raw':
440 return self.create_genshi_raw_report(cr, uid, ids, data, report_xml, context=context, output='raw')
441 logo = None
442 context = context.copy()
443 title = report_xml.name
444 rml = report_xml.report_rml_content
445 oo_parser = self.parser(cr, uid, self.name2, context=context)
446 objs = self.getObjects(cr, uid, ids, context)
447 oo_parser.set_context(objs, data, ids, report_xml.report_type)
448 processed_rml = self.preprocess_rml(etree.XML(rml),report_xml.report_type)
449 if report_xml.header:
450 oo_parser._add_header(processed_rml)
451 if oo_parser.logo:
452 logo = base64.decodestring(oo_parser.logo)
453 create_doc = self.generators[report_xml.report_type]
454 pdf = create_doc(etree.tostring(processed_rml),oo_parser.localcontext,logo,title.encode('utf8'))
455 return (pdf, report_xml.report_type)
456
457 def create_source_odt(self, cr, uid, ids, data, report_xml, context=None):
458 if not context:
459 context={}
460 pool = pooler.get_pool(cr.dbname)
461 results = []
462 attach = report_xml.attachment
463 if attach:
464 objs = self.getObjects(cr, uid, ids, context)
465 for obj in objs:
466 aname = eval(attach, {'object':obj, 'time':time})
467 result = False
468 if report_xml.attachment_use and aname and context.get('attachment_use', True):
469 aids = pool.get('ir.attachment').search(cr, uid, [('datas_fname','=',aname+'.odt'),('res_model','=',self.table),('res_id','=',obj.id)])
470 if aids:
471 brow_rec = pool.get('ir.attachment').browse(cr, uid, aids[0])
472 if not brow_rec.datas:
473 continue
474 d = base64.decodestring(brow_rec.datas)
475 results.append((d,'odt'))
476 continue
477 result = self.create_single_pdf(cr, uid, [obj.id], data, report_xml, context)
478 try:
479 if aname:
480 name = aname+'.'+result[1]
481 pool.get('ir.attachment').create(cr, uid, {
482 'name': aname,
483 'datas': base64.encodestring(result[0]),
484 'datas_fname': name,
485 'res_model': self.table,
486 'res_id': obj.id,
487 }, context=context
488 )
489 cr.commit()
490 except Exception,e:
491 self.logger(str(e), netsvc.LOG_ERROR)
492 results.append(result)
493
494 return results and len(results)==1 and results[0] or self.create_single_pdf(cr, uid, ids, data, report_xml, context)
495
496 # override needed to intercept the call to the proper 'create' method
497 def create(self, cr, uid, ids, data, context=None):
498 pool = pooler.get_pool(cr.dbname)
499 ir_obj = pool.get('ir.actions.report.xml')
500 report_xml_ids = ir_obj.search(cr, uid,
501 [('report_name', '=', self.name[7:])], context=context)
502 if report_xml_ids:
503 report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
504 report_xml.report_rml = None
505 report_xml.report_rml_content = None
506 report_xml.report_sxw_content_data = None
507 report_rml.report_sxw_content = None
508 report_rml.report_sxw = None
509 else:
510 title = ''
511 rml = tools.file_open(self.tmpl, subdir=None).read()
512 report_type= data.get('report_type', 'pdf')
513 class a(object):
514 def __init__(self, *args, **argv):
515 for key,arg in argv.items():
516 setattr(self, key, arg)
517 report_xml = a(title=title, report_type=report_type, report_rml_content=rml, name=title, attachment=False, header=self.header)
518
519 report_type = report_xml.report_type
520 if report_type in ['sxw','odt']:
521 fnct = self.create_source_odt
522 elif report_type in ['pdf','raw','txt','html']:
523 fnct = self.create_source_pdf
524 elif report_type=='html2html':
525 fnct = self.create_source_html2html
526 elif report_type=='mako2html':
527 fnct = self.create_source_mako2html
528 elif report_type=='aeroo':
529 if report_xml.out_format.code in ['oo-pdf']:
530 fnct = self.create_source_pdf
531 elif report_xml.out_format.code in ['oo-odt','oo-ods','oo-doc','oo-xls','genshi-raw']:
532 fnct = self.create_source_odt
533 else:
534 return super(Aeroo_report, self).create(cr, uid, ids, data, context)
535 else:
536 raise 'Unknown Report Type'
537 return fnct(cr, uid, ids, data, report_xml, context)
538
539class ReportTypeException(Exception):
540 def __init__(self, value):
541 self.parameter = value
542 def __str__(self):
543 return repr(self.parameter)
544
545#########################################################################
546
547#import imp, sys
548#from tools.config import config
549
550#def load_from_file(path, dbname, key):
551# class_inst = None
552# expected_class = 'Parser'
553
554# try:
555# if path.find(config['addons_path'])==-1:
556# filepath=config['addons_path']+os.path.sep+path
557# filepath = os.path.normpath(filepath)
558# if not os.path.lexists(filepath):
559# filepath = os.path.normpath(config['root_path']+os.path.sep+path)
560# sys.path.append(os.path.dirname(filepath))
561# mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])
562# mod_name = '%s_%s_%s' % (dbname,mod_name,key)
563
564# if file_ext.lower() == '.py':
565# py_mod = imp.load_source(mod_name, filepath)
566
567# elif file_ext.lower() == '.pyc':
568# py_mod = imp.load_compiled(mod_name, filepath)
569
570# if expected_class in dir(py_mod):
571# class_inst = py_mod.Parser
572# return class_inst
573# except Exception, e:
574# return None
575
576#def load_from_source(source):
577# expected_class = 'Parser'
578# context = {'Parser':None}
579# try:
580# exec source in context
581# return context['Parser']
582# except Exception, e:
583# return None
584
585#def delete_report_service(name):
586# name = 'report.%s' % name
587# if netsvc.Service.exists( name ): # change for OpenERP 6.0 - Service class usage
588# netsvc.Service.remove( name ) # change for OpenERP 6.0 - Service class usage
589
590#def register_report(cr, name, model, tmpl_path, parser):
591# name = 'report.%s' % name
592# if netsvc.Service.exists( name ): # change for OpenERP 6.0 - Service class usage
593# netsvc.Service.remove( name ) # change for OpenERP 6.0 - Service class usage
594# Aeroo_report(cr, name, model, tmpl_path, parser=parser)
595
596#old_register_all = report.interface.register_all
597#def new_register_all(db):
598# value = old_register_all(db)
599
600# cr = db.cursor()
601
602 ########### Run OpenOffice service ###########
603# try:
604# from report_aeroo_ooo.report import OpenOffice_service
605# except Exception, e:
606# OpenOffice_service = False
607
608# if OpenOffice_service:
609# cr.execute("SELECT id, state FROM ir_module_module WHERE name='report_aeroo_ooo'")
610# helper_module = cr.dictfetchone()
611# helper_installed = helper_module['state']=='installed'
612
613# if OpenOffice_service and helper_installed:
614# cr.execute("SELECT host, port FROM oo_config")
615# host, port = cr.fetchone()
616# try:
617# OpenOffice_service(cr, host, port)
618# netsvc.Logger().notifyChannel('report_aeroo', netsvc.LOG_INFO, "OpenOffice connection successfully established")
619# except DocumentConversionException, e:
620# netsvc.Logger().notifyChannel('report_aeroo', netsvc.LOG_WARNING, e)
621 ##############################################
622
623# cr.execute("SELECT * FROM ir_act_report_xml WHERE report_type = 'aeroo' ORDER BY id") # change for OpenERP 6.0
624# records = cr.dictfetchall()
625# for record in records:
626# parser=rml_parse
627# if record['parser_state']=='loc' and record['parser_loc']:
628# parser=load_from_file(record['parser_loc'], db.dbname, record['id']) or parser
629# elif record['parser_state']=='def' and record['parser_def']:
630# parser=load_from_source("from report import report_sxw\n"+record['parser_def']) or parser
631# register_report(cr, record['report_name'], record['model'], record['report_rml'], parser)
632# cr.close()
633# return value
634
635#report.interface.register_all = new_register_all
636
0637
=== added file 'report_view.xml'
--- report_view.xml 1970-01-01 00:00:00 +0000
+++ report_view.xml 2012-07-05 12:25:24 +0000
@@ -0,0 +1,224 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4
5 <record model="ir.ui.view" id="act_report_xml_view1">
6 <field name="name">ir.actions.report.xml.aeroo.form</field>
7 <field name="model">ir.actions.report.xml</field>
8 <field name="priority">14</field>
9 <field name="type">form</field>
10 <field name="arch" type="xml">
11 <form string="Aeroo Report">
12 <group col="6" colspan="4">
13 <field name="name" select="1"/>
14 <field name="model" select="1"/>
15 <field name="type" select="1" invisible="1"/>
16
17 <field name="report_name" select="1"/>
18 <field name="usage"/>
19 <field name="report_type" invisible="1"/>
20 </group>
21 <group col="6" colspan="4">
22 <field name="in_format" required="1" on_change="change_input_format(in_format)"/>
23 <field name="out_format" required="1" domain="[('compatible_types','=',in_format)]"/>
24 <field name="content_fname"/>
25 </group>
26
27 <notebook colspan="4">
28 <page string="Other Configuration">
29 <separator string="Template" colspan="4"/>
30 <group colspan="4" col="8">
31 <field name="tml_source" colspan="2" required="1"/>
32 <group colspan="6">
33 <field name="report_sxw_content_data" string="Template Content" attrs="{'invisible': [('tml_source','&lt;&gt;','database')],'required': [('tml_source','=','database')]}"/>
34 <field name="report_rml" string="Template path" attrs="{'invisible': [('tml_source','&lt;&gt;','file')],'required': [('tml_source','=','file')]}"/>
35 </group>
36 </group>
37 <group attrs="{'invisible': [('in_format','=','genshi-raw')]}" colspan="4">
38 <separator string="Stylesheet" colspan="4"/>
39 <group colspan="4" col="8">
40 <field name="styles_mode" colspan="2"/>
41 <group colspan="6">
42 <field name="stylesheet_id" attrs="{'invisible': [('styles_mode','&lt;&gt;','specified')]}"/>
43 </group>
44 </group>
45 </group>
46 <group attrs="{'invisible': [('in_format','&lt;&gt;','genshi-raw')]}" colspan="4" col="8">
47 <field name="charset" colspan="2"/>
48 <separator colspan="2"/>
49 </group>
50 <group col="2" colspan="2">
51 <separator string="Attachments" colspan="2"/>
52 <group colspan="2">
53 <group colspan="2">
54 <field name="attachment"/>
55 </group>
56 </group>
57 <field name="attachment_use" colspan="2"/>
58 </group>
59 <group col="2" colspan="2">
60 <separator string="Miscellaneous" colspan="2"/>
61 <field name="preload_mode" attrs="{'invisible': [('in_format','=','genshi-raw'),('tml_source','=','parser')]}"/>
62 <field name="multi" colspan="2"/>
63 </group>
64 </page>
65 <page string="Parser">
66 <group colspan="2">
67 <field name="parser_state"/>
68 </group>
69 <group attrs="{'invisible': [('parser_state','&lt;&gt;','def')]}" colspan="4" expand="1">
70 <separator string="Parser Definition" colspan="4"/>
71 <field name="parser_def" nolabel="1"/>
72 </group>
73 <field name="parser_loc" attrs="{'invisible': [('parser_state','&lt;&gt;','loc')],'required': [('parser_state','=','loc')]}"/>
74 </page>
75 <page string="Security">
76 <separator string="Groups" colspan="4"/>
77 <field colspan="4" name="groups_id" nolabel="1"/>
78 </page>
79 </notebook>
80
81 </form>
82 </field>
83 </record>
84
85 <record id="act_aeroo_report_xml_view_tree" model="ir.ui.view">
86 <field name="name">ir.actions.report.xml.tree</field>
87 <field name="model">ir.actions.report.xml</field>
88 <field name="type">tree</field>
89 <field name="arch" type="xml">
90 <tree string="Report xml">
91 <field name="name"/>
92 <field name="model"/>
93 <field name="report_name"/>
94 <field name="in_format"/>
95 <field name="out_format"/>
96 <field name="tml_source"/>
97 </tree>
98 </field>
99 </record>
100
101 <record id="act_aeroo_report_xml_search_view" model="ir.ui.view">
102 <field name="name">ir.actions.report.xml.search</field>
103 <field name="model">ir.actions.report.xml</field>
104 <field name="type">search</field>
105 <field name="arch" type="xml">
106 <search string="Report xml">
107 <group col="10" colspan="4">
108 <field name="name"/>
109 <field name="model"/>
110 <field name="type"/>
111 <field name="in_format"/>
112 <field name="out_format"/>
113 </group>
114 <newline/>
115 <group expand="0" string="Group By" colspan="4">
116 <filter string="Template Mime-type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'in_format'}"/>
117 <filter string="Output Mime-type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'out_format'}"/>
118 <separator orientation="vertical"/>
119 <filter string="Template Source" icon="gtk-copy" domain="[]" context="{'group_by':'tml_source'}"/>
120 </group>
121 </search>
122 </field>
123 </record>
124
125 <record id="view_company_form1" model="ir.ui.view">
126 <field name="name">res.company.form</field>
127 <field name="model">res.company</field>
128 <field name="type">form</field>
129 <field name="inherit_id" ref="base.view_company_form"/>
130 <field name="arch" type="xml">
131 <field name="rml_footer2" position="after">
132 <field name="stylesheet_id"/>
133 </field>
134 </field>
135 </record>
136
137 <record id="view_report_stylesheets_form" model="ir.ui.view">
138 <field name="name">report.stylesheets.form</field>
139 <field name="model">report.stylesheets</field>
140 <field name="type">form</field>
141 <field name="arch" type="xml">
142 <form string="Report Stylesheet">
143 <field name="name" select="1" colspan="4"/>
144 <field name="report_styles"/>
145 </form>
146 </field>
147 </record>
148
149 <record id="view_report_stylesheets_tree" model="ir.ui.view">
150 <field name="name">report.stylesheets.tree</field>
151 <field name="model">report.stylesheets</field>
152 <field name="type">tree</field>
153 <field name="arch" type="xml">
154 <tree string="Report Stylesheets">
155 <field name="name"/>
156 </tree>
157 </field>
158 </record>
159
160 <record model="ir.actions.act_window" id="action_report_stylesheets">
161 <field name="name">Report Stylesheets</field>
162 <field name="res_model">report.stylesheets</field>
163 <field name="view_type">form</field>
164 <field name="view_mode">tree,form</field>
165 </record>
166
167 <act_window name="Translations"
168 domain="[('type', '=', 'report'),('res_id', '=', active_id)]"
169 view_type="form"
170 res_model="ir.translation"
171 src_model="ir.actions.report.xml"
172 id="act_translations"/>
173
174 <!-- For the original views -->
175 <record model="ir.actions.act_window.view" id="act_report_xml_tree_view">
176 <field name="sequence" eval="1"/>
177 <field name="view_mode">tree</field>
178 <field name="view_id" ref="base.act_report_xml_view_tree"/>
179 <field name="act_window_id" ref="base.ir_action_report_xml"/>
180 </record>
181
182 <record model="ir.actions.act_window.view" id="act_report_xml_form_view">
183 <field name="sequence" eval="1"/>
184 <field name="view_mode">form</field>
185 <field name="view_id" ref="base.act_report_xml_view"/>
186 <field name="act_window_id" ref="base.ir_action_report_xml"/>
187 </record>
188 <!--========================-->
189
190 <wizard string="Add Print Button" model="ir.actions.report.xml" name="aeroo.report_actions" menu="True" id="wizard_oo_report_actions" />
191 <wizard string="Remove Print Button" model="ir.actions.report.xml" name="aeroo.report_actions_remove" menu="True" id="wizard_oo_report_actions_remove" />
192
193 <menuitem name="Aeroo Reports" id="menu_ir_action_aeroo_reports_xml" parent="base.menu_custom"/>
194
195 <record id="action_aeroo_report_xml_tree" model="ir.actions.act_window">
196 <field name="name">Reports</field>
197 <field name="type">ir.actions.act_window</field>
198 <field name="res_model">ir.actions.report.xml</field>
199 <field name="view_type">form</field>
200 <field name="view_mode">tree,form</field>
201 <field name="domain">[('report_type','=','aeroo')]</field>
202 <field name="view_id" ref="act_aeroo_report_xml_view_tree"/>
203 <field name="search_view_id" ref="act_aeroo_report_xml_search_view"/>
204 </record>
205
206 <record model="ir.actions.act_window.view" id="act_aeroo_report_xml_tree_view">
207 <field name="sequence" eval="1"/>
208 <field name="view_mode">tree</field>
209 <field name="view_id" ref="act_aeroo_report_xml_view_tree"/>
210 <field name="act_window_id" ref="action_aeroo_report_xml_tree"/>
211 </record>
212
213 <record model="ir.actions.act_window.view" id="act_aeroo_report_xml_form_view">
214 <field name="sequence" eval="1"/>
215 <field name="view_mode">form</field>
216 <field name="view_id" ref="act_report_xml_view1"/>
217 <field name="act_window_id" ref="action_aeroo_report_xml_tree"/>
218 </record>
219
220 <menuitem action="action_aeroo_report_xml_tree" id="menu_ir_action_aeroo_report_xml" parent="menu_ir_action_aeroo_reports_xml"/>
221 <menuitem action="action_report_stylesheets" parent="menu_ir_action_aeroo_reports_xml" id="menu_report_stylesheets"/>
222
223 </data>
224</openerp>
0225
=== added file 'report_xml.py'
--- report_xml.py 1970-01-01 00:00:00 +0000
+++ report_xml.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,365 @@
1##############################################################################
2#
3# Copyright (c) 2009-2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29from osv import osv,fields
30import netsvc
31from report_aeroo import Aeroo_report
32from report.report_sxw import rml_parse
33import base64, binascii
34import tools
35import encodings
36from tools.translate import _
37
38import imp, sys, os
39from tools.config import config
40
41class report_stylesheets(osv.osv):
42 '''
43 Open ERP Model
44 '''
45 _name = 'report.stylesheets'
46 _description = 'Report Stylesheets'
47
48 _columns = {
49 'name':fields.char('Name', size=64, required=True),
50 'report_styles' : fields.binary('Template Stylesheet', help='OpenOffice.org stylesheet (.odt)'),
51
52 }
53
54report_stylesheets()
55
56class res_company(osv.osv):
57 _name = 'res.company'
58 _inherit = 'res.company'
59
60 _columns = {
61 #'report_styles' : fields.binary('Report Styles', help='OpenOffice stylesheet (.odt)'),
62 'stylesheet_id':fields.many2one('report.stylesheets', 'Aeroo Global Stylesheet'),
63 }
64
65res_company()
66
67class report_mimetypes(osv.osv):
68 '''
69 Aeroo Report Mime-Type
70 '''
71 _name = 'report.mimetypes'
72 _description = 'Report Mime-Types'
73
74 _columns = {
75 'name':fields.char('Name', size=64, required=True, readonly=True),
76 'code':fields.char('Code', size=16, required=True, readonly=True),
77 'compatible_types':fields.char('Compatible Mime-Types', size=128, readonly=True),
78 'filter_name':fields.char('Filter Name', size=128, readonly=True),
79
80 }
81
82report_mimetypes()
83
84class report_xml(osv.osv):
85 _name = 'ir.actions.report.xml'
86 _inherit = 'ir.actions.report.xml'
87
88 def load_from_file(self, path, dbname, key):
89 class_inst = None
90 expected_class = 'Parser'
91
92 try:
93 if path.find(config['addons_path'])==-1:
94 filepath=config['addons_path']+os.path.sep+path
95 filepath = os.path.normpath(filepath)
96 if not os.path.lexists(filepath):
97 filepath = os.path.normpath(config['root_path']+os.path.sep+path)
98 sys.path.append(os.path.dirname(filepath))
99 mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])
100 mod_name = '%s_%s_%s' % (dbname,mod_name,key)
101
102 if file_ext.lower() == '.py':
103 py_mod = imp.load_source(mod_name, filepath)
104
105 elif file_ext.lower() == '.pyc':
106 py_mod = imp.load_compiled(mod_name, filepath)
107
108 if expected_class in dir(py_mod):
109 class_inst = py_mod.Parser
110 return class_inst
111 except Exception, e:
112 return None
113
114 def load_from_source(self, source):
115 expected_class = 'Parser'
116 context = {'Parser':None}
117 try:
118 exec source in context
119 return context['Parser']
120 except Exception, e:
121 return None
122
123 def delete_report_service(self, name):
124 name = 'report.%s' % name
125 if netsvc.Service.exists( name ): # change for OpenERP 6.0 - Service class usage
126 netsvc.Service.remove( name ) # change for OpenERP 6.0 - Service class usage
127
128 def register_report(self, cr, name, model, tmpl_path, parser):
129 name = 'report.%s' % name
130 if netsvc.Service.exists( name ): # change for OpenERP 6.0 - Service class usage
131 netsvc.Service.remove( name ) # change for OpenERP 6.0 - Service class usage
132 Aeroo_report(cr, name, model, tmpl_path, parser=parser)
133
134 def register_all(self, cr):
135 ########### Run OpenOffice service ###########
136 try:
137 from report_aeroo_ooo.report import OpenOffice_service
138 except Exception, e:
139 OpenOffice_service = False
140
141 if OpenOffice_service:
142 cr.execute("SELECT id, state FROM ir_module_module WHERE name='report_aeroo_ooo'")
143 helper_module = cr.dictfetchone()
144 helper_installed = helper_module['state']=='installed'
145
146 if OpenOffice_service and helper_installed:
147 cr.execute("SELECT host, port FROM oo_config")
148 host, port = cr.fetchone()
149 try:
150 OpenOffice_service(cr, host, port)
151 netsvc.Logger().notifyChannel('report_aeroo', netsvc.LOG_INFO, "OpenOffice.org connection successfully established")
152 except Exception, e:
153 netsvc.Logger().notifyChannel('report_aeroo', netsvc.LOG_WARNING, e)
154 ##############################################
155
156 cr.execute("SELECT * FROM ir_act_report_xml WHERE report_type = 'aeroo' ORDER BY id") # change for OpenERP 6.0
157 records = cr.dictfetchall()
158 for record in records:
159 parser=rml_parse
160 if record['parser_state']=='loc' and record['parser_loc']:
161 parser=self.load_from_file(record['parser_loc'], cr.dbname, record['id']) or parser
162 elif record['parser_state']=='def' and record['parser_def']:
163 parser=self.load_from_source("from report import report_sxw\n"+record['parser_def']) or parser
164 self.register_report(cr, record['report_name'], record['model'], record['report_rml'], parser)
165
166
167 def _report_content(self, cursor, user, ids, name, arg, context=None):
168 res = {}
169 for report in self.browse(cursor, user, ids, context=context):
170 data = report[name + '_data']# and base64.decodestring(report[name + '_data'])
171 if not data and report[name[:-8]]:
172 try:
173 fp = tools.file_open(report[name[:-8]], mode='rb')
174 data = base64.encodestring(fp.read())
175 except:
176 data = ''
177 res[report.id] = data
178 return res
179
180 def _get_encodings(self, cursor, user, context={}):
181 l = list(set(encodings._aliases.values()))
182 l.sort()
183 return zip(l, l)
184
185 def _report_content_inv(self, cursor, user, id, name, value, arg, context=None):
186 if value:
187 self.write(cursor, user, id, {name+'_data': value}, context=context)
188
189 def change_input_format(self, cr, uid, ids, in_format):
190 out_format = self.pool.get('report.mimetypes').search(cr, uid, [('code','=',in_format)])
191 return {
192 'value':{'out_format': out_format and out_format[0] or False}
193 }
194
195 def _get_in_mimetypes(self, cr, uid, context={}):
196 obj = self.pool.get('report.mimetypes')
197 ids = obj.search(cr, uid, [('filter_name','=',False)], context=context)
198 res = obj.read(cr, uid, ids, ['code', 'name'], context)
199 return [(r['code'], r['name']) for r in res] + [('','')]
200
201 _columns = {
202 'charset':fields.selection(_get_encodings, string='Charset', required=True),
203 'content_fname': fields.char('Override Extension',size=64, help='Here you can override output file extension'),
204 'styles_mode': fields.selection([
205 ('default','Not used'),
206 ('global', 'Global'),
207 ('specified', 'Specified'),
208 ], string='Stylesheet'),
209 #'report_styles' : fields.binary('Template Styles', help='OpenOffice stylesheet (.odt)'),
210 'stylesheet_id':fields.many2one('report.stylesheets', 'Template Stylesheet'),
211 'preload_mode':fields.selection([
212 ('static',_('Static')),
213 ('preload',_('Preload')),
214 ],'Preload Mode'),
215 'tml_source':fields.selection([
216 ('database','Database'),
217 ('file','File'),
218 ('parser','Parser'),
219 ],'Template source', select=True),
220 'parser_def': fields.text('Parser Definition'),
221 'parser_loc':fields.char('Parser location', size=128),
222 'parser_state':fields.selection([
223 ('default',_('Default')),
224 ('def',_('Definition')),
225 ('loc',_('Location')),
226 ],'State of Parser', select=True),
227 'in_format': fields.selection(_get_in_mimetypes, 'Template Mime-type'),
228 'out_format':fields.many2one('report.mimetypes', 'Output Mime-type'),
229 'report_sxw_content': fields.function(_report_content,
230 fnct_inv=_report_content_inv, method=True,
231 type='binary', string='SXW content',),
232 }
233
234 def unlink(self, cr, uid, ids, context=None):
235 #TODO: process before delete resource
236 trans_obj = self.pool.get('ir.translation')
237 trans_ids = trans_obj.search(cr, uid, [('type','=','report'),('res_id','in',ids)])
238 trans_obj.unlink(cr, uid, trans_ids)
239 ####################################
240 reports = self.read(cr, uid, ids, ['report_name','model'])
241 for r in reports:
242 ir_value_ids = self.pool.get('ir.values').search(cr, uid, [('name','=',r['report_name']),
243 ('value','=','ir.actions.report.xml,%s' % r['id']),
244 ('model','=',r['model'])
245 ])
246 if ir_value_ids:
247 self.pool.get('ir.values').unlink(cr, uid, ir_value_ids)
248 self.pool.get('ir.model.data')._unlink(cr, uid, 'ir.actions.report.xml', ids)
249 ####################################
250 res = super(report_xml, self).unlink(cr, uid, ids, context)
251 return res
252
253 def create(self, cr, user, vals, context={}):
254 #if context and not self.pool.get('ir.model').search(cr, user, [('model','=',vals['model'])]):
255 # raise osv.except_osv(_('Object model is not correct !'),_('Please check "Object" field !') )
256 if 'report_type' in vals and vals['report_type'] == 'aeroo':
257 parser=rml_parse
258 if vals['parser_state']=='loc' and vals['parser_loc']:
259 parser=self.load_from_file(vals['parser_loc'], cr.dbname, vals['name'].lower().replace(' ','_')) or parser
260 elif vals['parser_state']=='def' and vals['parser_def']:
261 parser=self.load_from_source("from report import report_sxw\n"+vals['parser_def']) or parser
262
263 res_id = super(report_xml, self).create(cr, user, vals, context)
264 try:
265 self.register_report(cr, vals['report_name'], vals['model'], vals.get('report_rml', False), parser)
266 except Exception, e:
267 raise osv.except_osv(_('Report registration error !'), _('Report was not registered in system !'))
268 return res_id
269
270 res_id = super(report_xml, self).create(cr, user, vals, context)
271 return res_id
272
273 def write(self, cr, user, ids, vals, context=None):
274 if 'report_sxw_content_data' in vals:
275 if vals['report_sxw_content_data']:
276 try:
277 base64.decodestring(vals['report_sxw_content_data'])
278 except binascii.Error:
279 vals['report_sxw_content_data'] = False
280 if type(ids)==list:
281 ids = ids[0]
282 record = self.read(cr, user, ids)
283 #if context and 'model' in vals and not self.pool.get('ir.model').search(cr, user, [('model','=',vals['model'])]):
284 # raise osv.except_osv(_('Object model is not correct !'),_('Please check "Object" field !') )
285 if vals.get('report_type', record['report_type']) == 'aeroo':
286 parser=rml_parse
287 if vals.get('parser_state', False)=='loc':
288 parser = self.load_from_file(vals.get('parser_loc', False) or record['parser_loc'], cr.dbname, record['id']) or parser
289 elif vals.get('parser_state', False)=='def':
290 parser = self.load_from_source("from report import report_sxw\n"+(vals.get('parser_loc', False) or record['parser_def'] or '')) or parser
291 elif vals.get('parser_state', False)=='default':
292 parser = rml_parse
293 elif record['parser_state']=='loc':
294 parser = self.load_from_file(record['parser_loc'], cr.dbname, record['id']) or parser
295 elif record['parser_state']=='def':
296 parser = self.load_from_source("from report import report_sxw\n"+record['parser_def']) or parser
297 elif record['parser_state']=='default':
298 parser = rml_parse
299
300 if vals.get('parser_loc', False):
301 parser=self.load_from_file(vals['parser_loc'], cr.dbname, record['id']) or parser
302 elif vals.get('parser_def', False):
303 parser=self.load_from_source("from report import report_sxw\n"+vals['parser_def']) or parser
304 if vals.get('report_name', False) and vals['report_name']!=record['report_name']:
305 self.delete_report_service(record['report_name'])
306 report_name = vals['report_name']
307 else:
308 self.delete_report_service(record['report_name'])
309 report_name = record['report_name']
310
311 res = super(report_xml, self).write(cr, user, ids, vals, context)
312 try:
313 self.register_report(cr, report_name, vals.get('model', record['model']), vals.get('report_rml', record['report_rml']), parser)
314 except Exception, e:
315 raise osv.except_osv(_('Report registration error !'), _('Report was not registered in system !'))
316 return res
317
318 res = super(report_xml, self).write(cr, user, ids, vals, context)
319 return res
320
321 def _get_default_outformat(self, cr, uid, context):
322 obj = self.pool.get('report.mimetypes')
323 res = obj.search(cr, uid, [('code','=','oo-odt')])
324 return res and res[0] or False
325
326 _defaults = {
327 #'report_type' : lambda*a: 'oo-odt',
328 'tml_source': lambda*a: 'database',
329 'in_format' : lambda*a: 'oo-odt',
330 'out_format' : _get_default_outformat,
331 'charset': lambda*a: 'ascii',
332 'styles_mode' : lambda*a: 'default',
333 'preload_mode': lambda*a: 'static',
334 'parser_state': lambda*a: 'default',
335 'parser_def':lambda*a: """class Parser(report_sxw.rml_parse):
336 def __init__(self, cr, uid, name, context):
337 super(Parser, self).__init__(cr, uid, name, context)
338 self.localcontext.update({})"""
339 }
340
341 #def _object_check(self, cr, uid, ids):
342 # for r in self.browse(cr, uid, ids, {}):
343 # if not self.pool.get('ir.model').search(cr, uid, [('model','=',r.model)]):
344 # return False
345 # return True
346
347 #_constraints = [
348 # (_object_check, _('Object model is not correct')+' !\n'+_('Please check "Object" field')+' !', ['model'])
349 # ]
350
351report_xml()
352
353class ir_translation(osv.osv):
354 _name = 'ir.translation'
355 _inherit = 'ir.translation'
356
357 def __init__(self, pool, cr):
358 super(ir_translation, self).__init__(pool, cr)
359 if ('report', 'Report') not in self._columns['type'].selection:
360 self._columns['type'].selection.append(
361 ('report', 'Report'),
362 )
363
364ir_translation()
365
0366
=== added directory 'wizard'
=== added file 'wizard/__init__.py'
--- wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ wizard/__init__.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,30 @@
1##############################################################################
2#
3# Copyright (c) 2008-2009 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29import report_actions
30import report_actions_remove
031
=== added file 'wizard/report_actions.py'
--- wizard/report_actions.py 1970-01-01 00:00:00 +0000
+++ wizard/report_actions.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,118 @@
1##############################################################################
2#
3# Copyright (c) 2008-2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29import wizard
30import pooler
31import ir
32from tools.translate import _
33
34class report_actions_wizard(wizard.interface):
35 '''
36 Add Print Button
37 '''
38 form = '''<?xml version="1.0"?>
39 <form string="Add Print Button">
40 <!--<field name="print_button"/>-->
41 <field name="open_action"/>
42 </form>'''
43
44 ex_form = '''<?xml version="1.0"?>
45 <form string="Add Print Button">
46 <label string="Report Action already exist for this report."/>
47 </form>'''
48
49 done_form = '''<?xml version="1.0"?>
50 <form string="Remove print button">
51 <label string="The print button is successfully added"/>
52 </form>'''
53
54 fields = {
55 #'print_button': {'string': 'Add print button', 'type': 'boolean', 'default': True, 'help':'Add action to menu context in print button.'},
56 'open_action': {'string': 'Open added action', 'type': 'boolean', 'default': False},
57 }
58
59 def _do_action(self, cr, uid, data, context):
60 pool = pooler.get_pool(cr.dbname)
61 report = pool.get(data['model']).browse(cr, uid, data['id'], context=context)
62 #if data['form']['print_button']:
63 res = ir.ir_set(cr, uid, 'action', 'client_print_multi', report.report_name, [report.model], 'ir.actions.report.xml,%d' % data['id'], isobject=True)
64 #else:
65 # res = ir.ir_set(cr, uid, 'action', 'client_print_multi', report.report_name, [report.model,0], 'ir.actions.report.xml,%d' % data['id'], isobject=True)
66 return {'value_id':res[0]}
67
68 def _check(self, cr, uid, data, context):
69 pool = pooler.get_pool(cr.dbname)
70 report = pool.get(data['model']).browse(cr, uid, data['id'], context=context)
71 ids = pool.get('ir.values').search(cr, uid, [('value','=',report.type+','+str(data['id']))])
72 if not ids:
73 return 'add'
74 else:
75 return 'exist'
76
77 def _action_open_window(self, cr, uid, data, context):
78 form=data['form']
79 if not form['open_action']:
80 return {}
81 return {
82 'domain':"[('id','=',%d)]" % (form['value_id']),
83 'name': _('Client Actions Connections'),
84 'view_type': 'form',
85 'view_mode': 'tree,form',
86 'res_model': 'ir.values',
87 'view_id': False,
88 'type': 'ir.actions.act_window',
89 }
90
91 states = {
92 'init': {
93 'actions': [],
94 'result': {'type':'choice','next_state':_check}
95 },
96 'add': {
97 'actions': [],
98 'result': {'type': 'form', 'arch': form, 'fields': fields, 'state': (('end', _('_Cancel')), ('process', _('_Ok')))},
99 },
100 'exist': {
101 'actions': [],
102 'result': {'type': 'form', 'arch': ex_form, 'fields': {}, 'state': (('end', _('_Close')),)},
103 },
104 'process': {
105 'actions': [_do_action],
106 'result': {'type': 'state', 'state': 'done'},
107 },
108 'done': {
109 'actions': [],
110 'result': {'type': 'form', 'arch': done_form, 'fields': {}, 'state': (('exit', _('_Close')),)},
111 },
112 'exit': {
113 'actions': [],
114 'result': {'type': 'action', 'action': _action_open_window, 'state': 'end'},
115 },
116 }
117report_actions_wizard('aeroo.report_actions')
118
0119
=== added file 'wizard/report_actions_remove.py'
--- wizard/report_actions_remove.py 1970-01-01 00:00:00 +0000
+++ wizard/report_actions_remove.py 2012-07-05 12:25:24 +0000
@@ -0,0 +1,97 @@
1##############################################################################
2#
3# Copyright (c) 2008-2010 SIA "KN dati". (http://kndati.lv) All Rights Reserved.
4# General contacts <info@kndati.lv>
5#
6# WARNING: This program as such is intended to be used by professional
7# programmers who take the whole responsability of assessing all potential
8# consequences resulting from its eventual inadequacies and bugs
9# End users who are looking for a ready-to-use solution with commercial
10# garantees and support are strongly adviced to contract a Free Software
11# Service Company
12#
13# This program is Free Software; you can redistribute it and/or
14# modify it under the terms of the GNU General Public License
15# as published by the Free Software Foundation; either version 2
16# of the License, or (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26#
27##############################################################################
28
29import wizard
30import pooler
31import ir
32from tools.translate import _
33
34class report_actions_remove_wizard(wizard.interface):
35 '''
36 Remove print button
37 '''
38 form = '''<?xml version="1.0"?>
39 <form string="Remove print button">
40 <label string="Or you want to remove print button for this report?"/>
41 </form>'''
42
43 ex_form = '''<?xml version="1.0"?>
44 <form string="Remove print button">
45 <label string="No Report Action to delete for this report"/>
46 </form>'''
47
48 done_form = '''<?xml version="1.0"?>
49 <form string="Remove print button">
50 <label string="The print button is successfully removed"/>
51 </form>'''
52
53 def _do_action(self, cr, uid, data, context):
54 pool = pooler.get_pool(cr.dbname)
55 report = pool.get(data['model']).browse(cr, uid, data['id'], context=context)
56 res = ir.ir_get(cr, uid, 'action', 'client_print_multi', [report.model])
57 id = res[0][0]
58 res = ir.ir_del(cr, uid, id)
59 return {}
60
61 def _check(self, cr, uid, data, context):
62 pool = pooler.get_pool(cr.dbname)
63 report = pool.get(data['model']).browse(cr, uid, data['id'], context=context)
64 ids = pool.get('ir.values').search(cr, uid, [('value','=',report.type+','+str(data['id']))])
65 if not ids:
66 return 'no_exist'
67 else:
68 return 'remove'
69
70 states = {
71 'init': {
72 'actions': [],
73 'result': {'type':'choice','next_state':_check}
74 },
75 'remove': {
76 'actions': [],
77 'result': {'type': 'form', 'arch': form, 'fields': {}, 'state': (('end', _('_No')), ('process', _('_Yes')))},
78 },
79 'no_exist': {
80 'actions': [],
81 'result': {'type': 'form', 'arch': ex_form, 'fields': {}, 'state': (('end', _('_Close')),)},
82 },
83 'process': {
84 'actions': [_do_action],
85 'result': {'type': 'state', 'state': 'done'},
86 },
87 'done': {
88 'actions': [],
89 'result': {'type': 'form', 'arch': done_form, 'fields': {}, 'state': (('exit', _('_Close')),)},
90 },
91 'exit': {
92 'actions': [],
93 'result': {'type': 'state', 'state': 'end'},
94 },
95 }
96report_actions_remove_wizard('aeroo.report_actions_remove')
97

Subscribers

People subscribed via source and target branches