From 61b306edc04aa8fcb205d7dd53d8746ef00df00d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 21 Oct 2013 14:57:23 +0200 Subject: [PATCH] [ADD] format floating-point values (including monetary values) according to user lang bzr revid: xmo@openerp.com-20131021125723-66rc4w5ist6rx22o --- openerp/addons/base/ir/ir_qweb.py | 68 +++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index a250620cc09..be15e9fd58b 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -9,6 +9,7 @@ import urllib import xml # FIXME use lxml and etree import Image +import math import werkzeug.utils from openerp.osv import osv, orm, fields @@ -557,6 +558,24 @@ class FieldConverter(osv.AbstractModel): return self.qweb_object().render_element( source_element, t_att, g_att, qweb_context, content or '') + def user_lang(self, cr, uid, context): + """ + Fetches the res.lang object corresponding to the language code stored + in the user's context. Fallbacks to en_US if no lang is present in the + context *or the language code is not valid*. + + :returns: res.lang browse_record + """ + if context is None: context = {} + + lang_code = context.get('lang') or 'en_US' + Lang = self.pool['res.lang'] + + lang_ids = Lang.search(cr, uid, [('code', '=', lang_code)], context=context) \ + or Lang.search(cr, uid, [('code', '=', 'en_US')], context=context) + + return Lang.browse(cr, uid, lang_ids[0], context=context) + class FloatConverter(osv.AbstractModel): _name = 'ir.qweb.field.float' _inherit = 'ir.qweb.field' @@ -567,10 +586,12 @@ class FloatConverter(osv.AbstractModel): def value_to_html(self, cr, uid, value, column, options=None, context=None): precision = self.precision(cr, uid, column, options=options, context=context) - fmt = '{value}' if precision is None else '{value:.{precision}f}' + fmt = '%s' if precision is None else '%.{precision}f' + + lang = self.user_lang(cr, uid, context) return werkzeug.utils.escape( - fmt.format(value=value, precision=precision, )) + lang.format(fmt.format(precision=precision), value, grouping=True)) class TextConverter(osv.AbstractModel): _name = 'ir.qweb.field.text' @@ -658,22 +679,35 @@ class MonetaryConverter(osv.AbstractModel): Currency = self.pool['res.currency'] display = self.display_currency(cr, uid, options) - symbol_pre = symbol_post = space_pre = space_post = u'' - if display.position == 'before': - space_pre = u' ' - symbol_pre = display.symbol - else: - space_post = u' ' - symbol_post = display.symbol + # lang.format mandates a sprintf-style format. These formats are non- + # minimal (they have a default fixed precision instead), and + # lang.format will not set one by default. currency.round will not + # provide one either. So we need to generate a precision value + # (integer > 0) from the currency's rounding (a float generally < 1.0). + # + # The log10 of the rounding should be the number of digits involved if + # negative, if positive clamp to 0 digits and call it a day. + # nb: int() ~ floor(), we want nearest rounding instead + precision = int(round(math.log10(display.rounding))) + fmt = "%.{0}f".format(-precision if precision < 0 else 0) - return u'{symbol_pre}{space_pre}' \ - u'{0}' \ - u'{space_post}{symbol_post}'.format( - Currency.round(cr, uid, display, record[field_name]), - space_pre=space_pre, - symbol_pre=symbol_pre, - space_post=space_post, - symbol_post=symbol_post,) + lang = self.user_lang(cr, uid, context=context) + formatted_amount = lang.format( + fmt, Currency.round(cr, uid, display, record[field_name]), + grouping=True, monetary=True) + + pre = post = u'' + if display.position == 'before': + pre = u'{symbol} ' + else: + post = u' {symbol}' + + return u'{pre}{0}{post}'.format( + formatted_amount, + pre=pre, post=post, + ).format( + symbol=display.symbol, + ) def display_currency(self, cr, uid, options): return self.qweb_object().eval_object(