From e44a4d9a047989c13d584122db4de31db00b8cb8 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Mon, 2 Mar 2026 04:17:41 +0000 Subject: [PATCH] [IMP] report_qweb_field_option: add domain field for better controlling the decimal places Add domain field in report config for better control of decimal places. --- report_qweb_field_option/README.rst | 33 ++++++------ .../models/qweb_field_options.py | 50 ++++++++++++++++++- report_qweb_field_option/readme/CONFIGURE.md | 3 ++ .../static/description/index.html | 33 ++++++------ .../tests/test_report_qweb_field_options.py | 36 +++++++++++++ .../views/qweb_field_options_views.xml | 7 +++ 6 files changed, 126 insertions(+), 36 deletions(-) diff --git a/report_qweb_field_option/README.rst b/report_qweb_field_option/README.rst index ee4a44ca34..be13222d0d 100644 --- a/report_qweb_field_option/README.rst +++ b/report_qweb_field_option/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ======================== Report Qweb Field Option ======================== @@ -17,7 +13,7 @@ Report Qweb Field Option .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github @@ -49,15 +45,18 @@ create records according to your needs. For each record: -- Set **Model** and **Field** (required) -- Set **UoM** and **UoM Field**, or **Currency** and **Currency Field** - only for fields of float type (optional) -- Set **Company** (optional) -- Set **Options** as a string representation of a dictionary. E.g., - ``{"widget": "date"}``, ``{"widget": "monetary"}``, or - ``{"widget": "contact", "fields": ["name", "phone"]}`` -- Set **Digits** (only for float-type fields). The value is ignored if - Options is set +- Set **Model** and **Field** (required) +- Set **UoM** and **UoM Field**, or **Currency** and **Currency Field** + only for fields of float type (optional) +- Set **Domain** to specify a domain for more specific filtering (e.g., + ``[('secondary_uom_id', '=', 1)]`` to apply only when a specific + secondary UoM is used) (optional) +- Set **Company** (optional) +- Set **Options** as a string representation of a dictionary. E.g., + ``{"widget": "date"}``, ``{"widget": "monetary"}``, or + ``{"widget": "contact", "fields": ["name", "phone"]}`` +- Set **Digits** (only for float-type fields). The value is ignored if + Options is set Usage ===== @@ -115,10 +114,10 @@ Authors Contributors ------------ -- `Quartile `__: +- `Quartile `__: - - Yoshi Tashiro - - Aung Ko Ko Lin + - Yoshi Tashiro + - Aung Ko Ko Lin Maintainers ----------- diff --git a/report_qweb_field_option/models/qweb_field_options.py b/report_qweb_field_option/models/qweb_field_options.py index 91c4b35e0a..2dc62519a2 100644 --- a/report_qweb_field_option/models/qweb_field_options.py +++ b/report_qweb_field_option/models/qweb_field_options.py @@ -4,8 +4,10 @@ import ast import logging -from odoo import _, api, fields, models +from odoo import _, api, fields, models, tools from odoo.exceptions import ValidationError +from odoo.osv.expression import normalize_domain +from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -52,6 +54,14 @@ class QwebFieldOptions(models.Model): ) digits = fields.Integer() company_id = fields.Many2one("res.company", string="Company") + domain = fields.Char( + help="Optional domain for additional filtering conditions.\n" + "This is evaluated in addition to UoM/Currency conditions.\n" + "Examples:\n" + "[('secondary_uom_id', '=', 1)]\n" + "[('secondary_uom_id.name', '=', 'Box')]\n" + "[('state', 'in', ['sale', 'done'])]", + ) @api.constrains("field_options") def _check_field_options_format(self): @@ -74,6 +84,28 @@ def _check_field_options_format(self): _("Options must be a dictionary, but got %s") % type(field_options) ) + def _get_eval_context(self): + return { + "time": tools.safe_eval.time, + "datetime": tools.safe_eval.datetime, + "dateutil": tools.safe_eval.dateutil, + "timezone": tools.safe_eval.pytz.timezone, + "context_today": lambda: fields.Date.context_today(self), + } + + @api.constrains("domain") + def _check_domain_format(self): + for rec in self: + if not rec.domain: + continue + try: + normalize_domain(safe_eval(rec.domain, rec._get_eval_context())) + except Exception as e: + raise ValidationError( + _("Invalid domain format: %(domain)s.\n" "Error: %(error)s") + % {"domain": rec.domain, "error": e} + ) from e + def _get_score(self, record): self.ensure_one() score = 1 @@ -91,6 +123,22 @@ def _get_score(self, record): score += 1 else: return -1 + if self.domain: + try: + domain = normalize_domain( + safe_eval(self.domain, self._get_eval_context()) + ) + if not record.filtered_domain(domain): + return -1 + score += 1 + except Exception as e: + _logger.warning( + "Failed to evaluate domain %s for record %s: %s", + self.domain, + record, + e, + ) + return -1 return score def _update_field_options(self, record, field_options): diff --git a/report_qweb_field_option/readme/CONFIGURE.md b/report_qweb_field_option/readme/CONFIGURE.md index e8532ad73a..35be0963da 100644 --- a/report_qweb_field_option/readme/CONFIGURE.md +++ b/report_qweb_field_option/readme/CONFIGURE.md @@ -6,6 +6,9 @@ For each record: - Set **Model** and **Field** (required) - Set **UoM** and **UoM Field**, or **Currency** and **Currency Field** only for fields of float type (optional) +- Set **Domain** to specify a domain for more specific filtering + (e.g., `[('secondary_uom_id', '=', 1)]` to apply only when + a specific secondary UoM is used) (optional) - Set **Company** (optional) - Set **Options** as a string representation of a dictionary. E.g., `{"widget": "date"}`, `{"widget": "monetary"}`, or diff --git a/report_qweb_field_option/static/description/index.html b/report_qweb_field_option/static/description/index.html index 65f598bd40..aebd39dc87 100644 --- a/report_qweb_field_option/static/description/index.html +++ b/report_qweb_field_option/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Report Qweb Field Option -
+
+

Report Qweb Field Option

- - -Odoo Community Association - -
-

Report Qweb Field Option

-

Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

This module allows administrators to define the decimal precision of float fields and add option values to fields (e.g., adding a date widget option to datetime fields) for QWeb report and view presentation.

@@ -394,7 +389,7 @@

Report Qweb Field Option

-

Configuration

+

Configuration

Go to Settings > Technical > Reporting > Qweb Field Options, and create records according to your needs.

For each record:

@@ -402,6 +397,9 @@

Configuration

  • Set Model and Field (required)
  • Set UoM and UoM Field, or Currency and Currency Field only for fields of float type (optional)
  • +
  • Set Domain to specify a domain for more specific filtering (e.g., +[('secondary_uom_id', '=', 1)] to apply only when a specific +secondary UoM is used) (optional)
  • Set Company (optional)
  • Set Options as a string representation of a dictionary. E.g., {"widget": "date"}, {"widget": "monetary"}, or @@ -411,7 +409,7 @@

    Configuration

  • -

    Usage

    +

    Usage

    Print a QWeb report (quotation, invoice, purchase order, etc.), and the value presentation for fields like line quantity, price unit and date order are adjusted according to the Qweb Field Options configuration.

    @@ -419,7 +417,7 @@

    Usage

    strictest condition will be applied.

    -

    Known issues / Roadmap

    +

    Known issues / Roadmap

    #. QWeb field option settings only apply to fields rendered with t-field.
    @@ -441,7 +439,7 @@

    Known issues / Roadmap

    https://github.com/odoo/odoo/blob/5eec379/addons/purchase/views/portal_templates.xml#L101-L102

    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -449,15 +447,15 @@

    Bug Tracker

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • Quartile
    -

    Contributors

    +

    Contributors

    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association @@ -480,6 +478,5 @@

    Maintainers

    -
    diff --git a/report_qweb_field_option/tests/test_report_qweb_field_options.py b/report_qweb_field_option/tests/test_report_qweb_field_options.py index e55e439a6a..c5670abfbe 100644 --- a/report_qweb_field_option/tests/test_report_qweb_field_options.py +++ b/report_qweb_field_option/tests/test_report_qweb_field_options.py @@ -153,3 +153,39 @@ def test_qweb_field_option_with_uom(self): self.test_record, "quantity", False, False, {}, values ) self.assertEqual(content, "1.0") + + def test_domain_validation(self): + """Test that invalid domain raises validation error""" + with self.assertRaises(ValidationError): + self.env["qweb.field.options"].create( + { + "res_model_id": self.test_model.id, + "field_id": self.value_field.id, + "domain": "invalid domain", + "digits": 2, + } + ) + + def test_qweb_field_option_with_domain(self): + values = {"report_type": "pdf"} + jpy_currency = self.env.ref("base.JPY") + jpy_currency.active = True + self.qweb_options_rec.digits = 2 + self.env["qweb.field.options"].create( + { + "res_model_id": self.test_model.id, + "field_id": self.value_field.id, + "domain": f"[('currency_id', '=', {jpy_currency.id})]", + "digits": 0, + } + ) + _, content, _ = self.IrQweb._get_field( + self.test_record, "value", False, False, {}, values + ) + self.assertEqual(content, "1.00") + # Test with JPY: domain matches, uses JPY-specific option (0 digits) + self.test_record.currency_id = jpy_currency.id + _, content, _ = self.IrQweb._get_field( + self.test_record, "value", False, False, {}, values + ) + self.assertEqual(content, "1") diff --git a/report_qweb_field_option/views/qweb_field_options_views.xml b/report_qweb_field_option/views/qweb_field_options_views.xml index 679477d4d5..776a4c1fdf 100644 --- a/report_qweb_field_option/views/qweb_field_options_views.xml +++ b/report_qweb_field_option/views/qweb_field_options_views.xml @@ -27,6 +27,13 @@ readonly="currency_id == False" required="currency_id != False" /> + +