1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Author: Nicolas Bessi. Copyright Camptocamp SA
5 # Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
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.
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.
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/>.
20 ##############################################################################
23 from report import report_sxw
24 from report_webkit import webkit_report
25 from report_webkit import report_helper
27 from tools import mod10r
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
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({
48 'user':self.pool.get("res.users").browse(cr, uid, uid),
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
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]*$')
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:
68 return super(l10n_ch_report_webkit_html, self).set_context(objects, data, ids, report_type=report_type)
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))
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'))
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
85 def comma_me(self, amount):
86 """Fast swiss number formatting"""
87 if isinstance(amount, float):
88 amount = str('%.2f'%amount)
92 new = self._compile_comma_me.sub("\g<1>'\g<2>", amount)
96 return self.comma_me(new)
98 def _space(self, nbr, nbrspc=5):
102 >>> self._space('123456789012345')
105 return ''.join([' '[(i - 2) % nbrspc:] + c for i, c in enumerate(nbr)])
108 def _get_ref(self, inv):
109 """Retrieve ESR/BVR reference form invoice in order to print it"""
111 if inv.partner_bank_id.bvr_adherent_num:
112 res = inv.partner_bank_id.bvr_adherent_num
115 invoice_number = self._compile_get_ref.sub('', inv.number)
116 return mod10r(res + invoice_number.rjust(26-len(res), '0'))
118 def _check(self, invoice_ids):
119 """Check if the invoice is ready to be printed"""
124 invoice_obj = pool.get('account.invoice')
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],
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],
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],
151 class BVRWebKitParser(webkit_report.WebKitParser):
153 def setLang(self, lang):
156 self.localcontext['lang'] = lang
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"""
161 digits = self.parser_instance.get_digits(value)
162 if isinstance(value, (str, unicode)) and not value:
164 pool_lang = self.pool.get('res.lang')
165 lang = self.localcontext['lang']
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)
170 if date or date_time:
174 date_format = lang_obj.date_format
175 parse_format = '%Y-%m-%d'
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))
184 date = datetime(*value.timetuple()[:6])
185 return date.strftime(date_format)
187 return lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
189 def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
190 """generate the PDF"""
191 self.parser_instance = self.parser(
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)
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
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:
213 _('No header defined for this Webkit report!'),
214 _('Please set a header in company settings')
216 if not report_xml.header :
217 #I know it could be cleaner ...
221 <style type="text/css">
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'];
231 var y = document.getElementsByClassName(x[i]);
232 for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
237 <body style="border:0; margin: 0;" onload="subst()">
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
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')
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')
254 helper = report_helper.WebKitHelper(cursor, uid, report_xml.id, context)
258 self.parser_instance.localcontext['objects'] = [obj]
259 if not company.bvr_only:
261 html = body_mako_tpl.render(
264 _=self.translate_call,
265 **self.parser_instance.localcontext
268 raise Exception(exceptions.text_error_template().render())
270 if not company.invoice_only:
272 bvr = body_bvr_tpl.render(
275 _=self.translate_call,
276 **self.parser_instance.localcontext
279 raise Exception(exceptions.text_error_template().render())
281 head_mako_tpl = Template(header, input_encoding='utf-8', output_encoding='utf-8')
283 head = head_mako_tpl.render(
287 _=self.translate_call,
288 **self.parser_instance.localcontext
291 raise Exception(exceptions.text_error_template().render())
293 if footer and company.invoice_only :
294 foot_mako_tpl = Template(footer, input_encoding='utf-8', output_encoding='utf-8')
296 foot = foot_mako_tpl.render(
299 _=self.translate_call,
300 **self.parser_instance.localcontext
303 raise Exception(exceptions.text_error_template().render())
304 if report_xml.webkit_debug :
306 deb = head_mako_tpl.render(
310 _=self.translate_call,
311 **self.parser_instance.localcontext
314 raise Exception(exceptions.text_error_template().render())
316 bin = self.get_lib(cursor, uid, company.id)
317 pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)
321 BVRWebKitParser('report.invoice_web_bvr',
323 'addons/l10n_ch/report/report_webkit_html.mako',
324 parser=l10n_ch_report_webkit_html)
326 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: