From 98ff30fff73ce3982ed46b7499c917d29d4633c4 Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Tue, 20 Jan 2026 15:32:26 +0700 Subject: [PATCH] feat: Update module to Odoo 19, adjust XPath selectors from `tree` to `list` in views and tests, and simplify readonly attribute logic. --- __manifest__.py | 2 +- tests/run_view_tests.py | 8 ++++---- tests/test_view_configuration.py | 12 ++++++------ views/account_move_views.xml | 10 ++++------ 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/__manifest__.py b/__manifest__.py index 3aaeb00..8113caf 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Vendor Bill Editable Totals", - "version": "17.0.1.0.2", + "version": "19.0.1.0.3", "summary": "Enable direct editing of tax excluded and tax included amounts on vendor bill lines with automatic unit price recalculation", "description": """ Vendor Bill Editable Totals diff --git a/tests/run_view_tests.py b/tests/run_view_tests.py index cc8efd1..921a560 100755 --- a/tests/run_view_tests.py +++ b/tests/run_view_tests.py @@ -80,7 +80,7 @@ def test_price_subtotal_field_editable(): # Find the xpath that modifies price_subtotal xpath_elements = root.xpath( - "//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_subtotal']\"]" + "//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_subtotal']\"]" ) if not xpath_elements: @@ -132,7 +132,7 @@ def test_price_total_field_editable(): # Find the xpath that modifies price_total xpath_elements = root.xpath( - "//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_total']\"]" + "//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_total']\"]" ) if not xpath_elements: @@ -184,7 +184,7 @@ def test_fields_readonly_conditions(): # Check price_subtotal attrs xpath_subtotal = root.xpath( - "//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_subtotal']\"]" + "//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_subtotal']\"]" ) if not xpath_subtotal: @@ -205,7 +205,7 @@ def test_fields_readonly_conditions(): # Check price_total attrs xpath_total = root.xpath( - "//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_total']\"]" + "//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_total']\"]" ) if not xpath_total: diff --git a/tests/test_view_configuration.py b/tests/test_view_configuration.py index 5eb0e9e..f6c3188 100755 --- a/tests/test_view_configuration.py +++ b/tests/test_view_configuration.py @@ -50,7 +50,7 @@ class TestViewConfiguration(TransactionCase): arch = etree.fromstring(self.view.arch) # Find the xpath that modifies price_subtotal - xpath_elements = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_subtotal']\"]") + xpath_elements = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_subtotal']\"]") self.assertTrue( len(xpath_elements) > 0, @@ -80,7 +80,7 @@ class TestViewConfiguration(TransactionCase): arch = etree.fromstring(self.view.arch) # Find the xpath that modifies price_total - xpath_elements = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_total']\"]") + xpath_elements = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_total']\"]") self.assertTrue( len(xpath_elements) > 0, @@ -110,7 +110,7 @@ class TestViewConfiguration(TransactionCase): arch = etree.fromstring(self.view.arch) # Check price_subtotal attrs - xpath_subtotal = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_subtotal']\"]") + xpath_subtotal = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_subtotal']\"]") self.assertTrue(len(xpath_subtotal) > 0, "price_subtotal xpath should exist") attrs_subtotal = xpath_subtotal[0].xpath(".//attribute[@name='attrs']") @@ -133,7 +133,7 @@ class TestViewConfiguration(TransactionCase): ) # Check price_total attrs - xpath_total = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_total']\"]") + xpath_total = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_total']\"]") self.assertTrue(len(xpath_total) > 0, "price_total xpath should exist") attrs_total = xpath_total[0].xpath(".//attribute[@name='attrs']") @@ -251,7 +251,7 @@ class TestViewConfiguration(TransactionCase): arch = etree.fromstring(self.view.arch) # Verify both fields have attrs that reference parent.state - xpath_subtotal = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_subtotal']\"]") + xpath_subtotal = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_subtotal']\"]") attrs_subtotal = xpath_subtotal[0].xpath(".//attribute[@name='attrs']") attrs_text_subtotal = attrs_subtotal[0].text @@ -262,7 +262,7 @@ class TestViewConfiguration(TransactionCase): "Attrs should reference parent.state for price_subtotal" ) - xpath_total = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/tree//field[@name='price_total']\"]") + xpath_total = arch.xpath("//xpath[@expr=\"//field[@name='invoice_line_ids']/list//field[@name='price_total']\"]") attrs_total = xpath_total[0].xpath(".//attribute[@name='attrs']") attrs_text_total = attrs_total[0].text diff --git a/views/account_move_views.xml b/views/account_move_views.xml index 7bc32c2..ecedec9 100755 --- a/views/account_move_views.xml +++ b/views/account_move_views.xml @@ -8,15 +8,13 @@ - - 0 - {'readonly': [('parent.state', '!=', 'draft')]} + + parent.state != 'draft' - - 0 - {'readonly': [('parent.state', '!=', 'draft')]} + + parent.state != 'draft'