Launchpad automatic translations update.
[odoo/odoo.git] / addons / l10n_ch / report / report_webkit_html.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    Author: Nicolas Bessi. Copyright Camptocamp SA
5 #    Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import time
23 from report import report_sxw
24 from report_webkit import webkit_report
25 from report_webkit import report_helper 
26 from osv import osv
27 from tools import mod10r
28 import sys
29 import os
30 import re
31 import wizard
32 import addons
33 import pooler
34 from tools.config import config
35 from mako.template import Template
36 from mako import exceptions
37 from tools.translate import _
38 from osv.osv import except_osv
39
40
41 class l10n_ch_report_webkit_html(report_sxw.rml_parse):
42     def __init__(self, cr, uid, name, context):
43         super(l10n_ch_report_webkit_html, self).__init__(cr, uid, name, context=context)
44         self.localcontext.update({
45             'time': time,
46             'cr': cr,
47             'uid': uid,
48             'user':self.pool.get("res.users").browse(cr, uid, uid),
49             'mod10r': mod10r,
50             '_space': self._space,
51             '_get_ref': self._get_ref,
52             'comma_me': self.comma_me,
53             'police_absolute_path': self.police_absolute_path,
54             'bvr_absolute_path': self.bvr_absolute_path,
55             'headheight': self.headheight
56         })
57
58     _compile_get_ref = re.compile('[^0-9]')
59     _compile_comma_me = re.compile("^(-?\d+)(\d{3})")
60     _compile_check_bvr = re.compile('[0-9][0-9]-[0-9]{3,6}-[0-9]')
61     _compile_check_bvr_add_num = re.compile('[0-9]*$')
62     
63     def set_context(self, objects, data, ids, report_type=None):
64         user = self.pool.get('res.users').browse(self.cr, self.uid, self.uid)
65         company = user.company_id
66         if not company.invoice_only:
67             self._check(ids)
68         return super(l10n_ch_report_webkit_html, self).set_context(objects, data, ids, report_type=report_type)
69     
70     def police_absolute_path(self, inner_path) :
71         """Will get the ocrb police absolute path"""
72         path = addons.get_module_resource(os.path.join('l10n_ch', 'report', inner_path))
73         return  path
74         
75     def bvr_absolute_path(self) :
76         """Will get the ocrb police absolute path"""
77         path = addons.get_module_resource(os.path.join('l10n_ch', 'report', 'bvr1.jpg'))
78         return  path
79         
80     def headheight(self):
81         report_id = self.pool.get('ir.actions.report.xml').search(self.cr, self.uid, [('name','=', 'BVR invoice')])[0]
82         report = self.pool.get('ir.actions.report.xml').browse(self.cr, self.uid, report_id)
83         return report.webkit_header.margin_top
84
85     def comma_me(self, amount):
86         """Fast swiss number formatting"""
87         if  isinstance(amount, float):
88             amount = str('%.2f'%amount)
89         else :
90             amount = str(amount)
91         orig = amount
92         new = self._compile_comma_me.sub("\g<1>'\g<2>", amount)
93         if orig == new:
94             return new
95         else:
96             return self.comma_me(new)
97
98     def _space(self, nbr, nbrspc=5):
99         """Spaces * 5.
100
101         Example:
102             >>> self._space('123456789012345')
103             '12 34567 89012 345'
104         """
105         return ''.join([' '[(i - 2) % nbrspc:] + c for i, c in enumerate(nbr)])
106       
107         
108     def _get_ref(self, inv):
109         """Retrieve ESR/BVR reference form invoice in order to print it"""
110         res = ''
111         if inv.partner_bank_id.bvr_adherent_num:
112             res = inv.partner_bank_id.bvr_adherent_num
113         invoice_number = ''
114         if inv.number:
115             invoice_number = self._compile_get_ref.sub('', inv.number)
116         return mod10r(res + invoice_number.rjust(26-len(res), '0'))
117         
118     def _check(self, invoice_ids):
119         """Check if the invoice is ready to be printed"""
120         if not invoice_ids:
121             invoice_ids = []
122         cursor = self.cr
123         pool = self.pool
124         invoice_obj = pool.get('account.invoice')
125         ids = invoice_ids
126         for invoice in invoice_obj.browse(cursor, self.uid, ids):
127             if not invoice.partner_bank_id:
128                 raise except_osv(_('UserError'),
129                         _('No bank specified on invoice:\n' + \
130                                 invoice_obj.name_get(cursor, self.uid, [invoice.id],
131                                     context={})[0][1]))
132             if not self._compile_check_bvr.match(
133                     invoice.partner_bank_id.post_number or ''):
134                 raise except_osv(_('UserError'),
135                         _('Your bank BVR number should be of the form 0X-XXX-X! ' +
136                           'Please check your company ' +
137                           'information for the invoice:\n' + 
138                            invoice_obj.name_get(cursor, self.uid, [invoice.id],
139                            context={})[0][1]))
140             if invoice.partner_bank_id.bvr_adherent_num \
141                     and not self._compile_check_bvr_add_num.match(
142                             invoice.partner_bank_id.bvr_adherent_num):
143                 raise except_osv(_('UserError'),
144                         _('Your bank BVR adherent number must contain exactly seven' +
145                           'digits!\nPlease check your company ' +
146                           'information for the invoice:\n' +
147                           invoice_obj.name_get(cursor, self.uid, [invoice.id],
148                           context={})[0][1]))
149         return ''
150
151 class BVRWebKitParser(webkit_report.WebKitParser):
152     
153     def setLang(self, lang):
154         if not lang:
155             lang = 'en_US'
156         self.localcontext['lang'] = lang
157         
158     def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False):
159         """format using the know cursor, language from localcontext"""
160         if digits is None:
161             digits = self.parser_instance.get_digits(value)
162         if isinstance(value, (str, unicode)) and not value:
163             return ''
164         pool_lang = self.pool.get('res.lang')
165         lang = self.localcontext['lang']
166
167         lang_ids = pool_lang.search(self.parser_instance.cr, self.parser_instance.uid, [('code','=',lang)])[0]
168         lang_obj = pool_lang.browse(self.parser_instance.cr, self.parser_instance.uid, lang_ids)
169
170         if date or date_time:
171             if not str(value):
172                 return ''
173
174             date_format = lang_obj.date_format
175             parse_format = '%Y-%m-%d'
176             if date_time:
177                 value=value.split('.')[0]
178                 date_format = date_format + " " + lang_obj.time_format
179                 parse_format = '%Y-%m-%d %H:%M:%S'
180             if not isinstance(value, time.struct_time):
181                 return time.strftime(date_format, time.strptime(value, parse_format))
182
183             else:
184                 date = datetime(*value.timetuple()[:6])
185             return date.strftime(date_format)
186
187         return lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
188     
189     def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
190         """generate the PDF"""
191         self.parser_instance = self.parser(
192                                             cursor, 
193                                             uid, 
194                                             self.name2, 
195                                             context=context
196                                         )
197         self.pool = pooler.get_pool(cursor.dbname)
198         objs = self.getObjects(cursor, uid, ids, context)
199         self.parser_instance.set_context(objs, data, ids, report_xml.report_type)
200         template =  False
201         if report_xml.report_file :
202             path = addons.get_module_resource(report_xml.report_file)
203             if os.path.exists(path) :
204                 template = file(path).read()
205         if not template and report_xml.report_webkit_data :
206             template =  report_xml.report_webkit_data
207         if not template :
208             raise except_osv(_('Webkit Report template not found !'), _(''))
209         header = report_xml.webkit_header.html
210         footer = report_xml.webkit_header.footer_html
211         if not header and report_xml.header:
212           raise except_osv(
213                 _('No header defined for this Webkit report!'),
214                 _('Please set a header in company settings')
215             )
216         if not report_xml.header :
217             #I know it could be cleaner ...
218             header = u"""
219 <html>
220     <head>
221         <style type="text/css"> 
222             ${css}
223         </style>
224         <script>
225         function subst() {
226            var vars={};
227            var x=document.location.search.substring(1).split('&');
228            for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
229            var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
230            for(var i in x) {
231              var y = document.getElementsByClassName(x[i]);
232              for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
233            }
234          }
235         </script>
236     </head>
237 <body style="border:0; margin: 0;" onload="subst()">
238 </body>
239 </html>"""
240         self.parser_instance.localcontext.update({'setLang':self.setLang})
241         self.parser_instance.localcontext.update({'formatLang':self.formatLang})
242         css = report_xml.webkit_header.css
243         if not css :
244             css = ''
245         user = self.pool.get('res.users').browse(cursor, uid, uid)
246         company = user.company_id
247         parse_template = template
248         #default_filters=['unicode', 'entity'] can be used to set global filter
249         body_mako_tpl = Template(parse_template ,input_encoding='utf-8', output_encoding='utf-8')
250         #BVR specific
251         bvr_path = addons.get_module_resource(os.path.join('l10n_ch','report','bvr.mako'))
252         body_bvr_tpl = Template(file(bvr_path).read(), input_encoding='utf-8', output_encoding='utf-8')
253
254         helper = report_helper.WebKitHelper(cursor, uid, report_xml.id, context)
255         ##BVR Specific
256         htmls = []
257         for obj in objs :
258             self.parser_instance.localcontext['objects'] = [obj]
259             if not company.bvr_only:
260                 try:
261                     html = body_mako_tpl.render(
262                                                 helper=helper, 
263                                                 css=css,
264                                                 _=self.translate_call,
265                                                 **self.parser_instance.localcontext
266                                                 )
267                 except Exception, e:
268                    raise Exception(exceptions.text_error_template().render())
269                 htmls.append(html)
270             if not company.invoice_only:
271                 try:
272                     bvr = body_bvr_tpl.render(
273                                         helper=helper, 
274                                         css=css,
275                                         _=self.translate_call,
276                                         **self.parser_instance.localcontext
277                                         )
278                 except Exception, e:
279                    raise Exception(exceptions.text_error_template().render())
280                 htmls.append(bvr)                            
281         head_mako_tpl = Template(header, input_encoding='utf-8', output_encoding='utf-8')
282         try:
283             head = head_mako_tpl.render(
284                                         helper=helper, 
285                                         css=css,
286                                         _debug=False,
287                                         _=self.translate_call,
288                                         **self.parser_instance.localcontext
289                                     )
290         except Exception, e:
291            raise Exception(exceptions.text_error_template().render())
292         foot = False
293         if footer and company.invoice_only :
294             foot_mako_tpl = Template(footer, input_encoding='utf-8', output_encoding='utf-8')
295             try:
296                 foot = foot_mako_tpl.render(
297                                             helper=helper, 
298                                             css=css, 
299                                             _=self.translate_call,
300                                             **self.parser_instance.localcontext
301                                             )
302             except Exception, e:
303                raise Exception(exceptions.text_error_template().render())
304         if report_xml.webkit_debug :
305             try:
306                 deb = head_mako_tpl.render(
307                                             helper=helper, 
308                                             css=css, 
309                                             _debug=html,
310                                             _=self.translate_call,
311                                             **self.parser_instance.localcontext
312                                             )
313             except Exception, e:
314                raise Exception(exceptions.text_error_template().render())
315             return (deb, 'html')
316         bin = self.get_lib(cursor, uid, company.id)
317         pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)
318         return (pdf, 'pdf')
319     
320
321 BVRWebKitParser('report.invoice_web_bvr',
322                'account.invoice', 
323                'addons/l10n_ch/report/report_webkit_html.mako',
324                parser=l10n_ch_report_webkit_html)
325
326 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: