diff --git a/smile_decimal_precision/__manifest__.py b/smile_decimal_precision/__manifest__.py index 4e6a82c0..e077b148 100644 --- a/smile_decimal_precision/__manifest__.py +++ b/smile_decimal_precision/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Display Decimal Precision", "version": "0.3", - "depends": ["base"], + "depends": ["web","account"], "author": "Smile", "license": 'AGPL-3', "description": """ diff --git a/smile_decimal_precision/models/__init__.py b/smile_decimal_precision/models/__init__.py index f9fede94..9e9dc556 100644 --- a/smile_decimal_precision/models/__init__.py +++ b/smile_decimal_precision/models/__init__.py @@ -5,3 +5,4 @@ from . import fields from . import ir_http from . import res_currency +from . import account_tax \ No newline at end of file diff --git a/smile_decimal_precision/models/account_tax.py b/smile_decimal_precision/models/account_tax.py new file mode 100644 index 00000000..fca5c435 --- /dev/null +++ b/smile_decimal_precision/models/account_tax.py @@ -0,0 +1,27 @@ +# (C) 2023 Smile () +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, tools +from odoo.tools.misc import formatLang + +class AccountTax(models.Model): + _inherit = 'account.tax' + + @api.model + def _prepare_tax_totals(self, base_lines, currency, tax_lines=None): + res = super()._prepare_tax_totals(base_lines, currency, tax_lines) + + groups = res.get('groups_by_subtotal',{}) + subtotals = res.get('subtotals',{}) + for group in groups: + items = groups.get(group) + for item in items: + item.update({'formatted_tax_group_amount':formatLang(self.env, item['tax_group_amount'], digits=currency.display_decimal_places, currency_obj=currency)}) + for subtotal in subtotals: + subtotal.update({'formatted_amount':formatLang(self.env, subtotal['amount'], digits=currency.display_decimal_places, currency_obj=currency)}) + + res.update({'formatted_amount_total':formatLang(self.env, res['amount_total'], digits=currency.display_decimal_places, currency_obj=currency), + 'formatted_amount_untaxed':formatLang(self.env, res['amount_untaxed'], digits=currency.display_decimal_places, currency_obj=currency) + + }) + return res diff --git a/smile_decimal_precision/report/ir_qweb.py b/smile_decimal_precision/report/ir_qweb.py index c7d1f822..26084318 100644 --- a/smile_decimal_precision/report/ir_qweb.py +++ b/smile_decimal_precision/report/ir_qweb.py @@ -1,8 +1,9 @@ # (C) 2023 Smile () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo.addons.base.models.ir_qweb_fields import FloatConverter - +from odoo.addons.base.models.ir_qweb_fields import FloatConverter, MonetaryConverter +from markupsafe import Markup, escape +from odoo.tools.misc import formatLang as formatLangOdoo def record_to_html(self, record, field_name, options): if 'precision' not in options and 'decimal_precision' not in options: @@ -10,8 +11,74 @@ def record_to_html(self, record, field_name, options): record._fields[field_name].get_description(self.env)['digits'] or \ (None, None) options = dict(options, precision=precision) + #raise Exception(options) return super(FloatConverter, self).record_to_html( record, field_name, options) +def record_to_html_monetary(self, record, field_name, options): + options = dict(options) + #currency should be specified by monetary field + field = record._fields[field_name] + + if not options.get('display_currency') and field.type == 'monetary' and field.get_currency_field(record): + options['display_currency'] = record[field.get_currency_field(record)] + if not options.get('display_currency'): + # search on the model if they are a res.currency field to set as default + fields = record._fields.items() + currency_fields = [k for k, v in fields if v.type == 'many2one' and v.comodel_name == 'res.currency'] + if currency_fields: + options['display_currency'] = record[currency_fields[0]] + if 'date' not in options: + options['date'] = record._context.get('date') + if 'company_id' not in options: + options['company_id'] = record._context.get('company_id') + if 'precision' not in options and 'decimal_precision' not in options and 'digits' in record._fields[field_name].get_description(self.env): + + _, precision = \ + record._fields[field_name].get_description(self.env)['digits'] or \ + (None, None) + options = dict(options, precision=precision) + return super(MonetaryConverter, self).record_to_html(record, field_name, options) +def value_to_html_monetary(self, value, options): + display_currency = options['display_currency'] + + if not isinstance(value, (int, float)): + raise ValueError(_("The value send to monetary field is not a number.")) + + # 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). + fmt = "%.{0}f".format(display_currency.display_decimal_places) + + if options.get('from_currency'): + date = options.get('date') or fields.Date.today() + company_id = options.get('company_id') + if company_id: + company = self.env['res.company'].browse(company_id) + else: + company = self.env.company + value = options['from_currency']._convert(value, display_currency, company, date) + + lang = self.user_lang() + formatted_amount = lang.format(fmt, display_currency.round(value), + grouping=True, monetary=True).replace(r' ', '\N{NO-BREAK SPACE}').replace(r'-', '-\N{ZERO WIDTH NO-BREAK SPACE}') + + pre = post = '' + if display_currency.position == 'before': + pre = '{symbol}\N{NO-BREAK SPACE}'.format(symbol=display_currency.symbol or '') + else: + post = '\N{NO-BREAK SPACE}{symbol}'.format(symbol=display_currency.symbol or '') + + if options.get('label_price') and lang.decimal_point in formatted_amount: + sep = lang.decimal_point + integer_part, decimal_part = formatted_amount.split(sep) + integer_part += sep + return Markup('{pre}{0}{1}{post}').format(integer_part, decimal_part, pre=pre, post=post) + + return Markup('{pre}{0}{post}').format(formatted_amount, pre=pre, post=post) FloatConverter.record_to_html = record_to_html +MonetaryConverter.value_to_html = value_to_html_monetary +MonetaryConverter.record_to_html = record_to_html_monetary \ No newline at end of file