From 9fb6819cc1b3541996d4da52a89aef42ac13de49 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Mon, 15 Sep 2025 22:06:41 +0200 Subject: [PATCH 1/8] [ADD] test_auditlog --- test_auditlog/README.rst | 74 ++++ test_auditlog/__init__.py | 0 test_auditlog/__manifest__.py | 16 + test_auditlog/pyproject.toml | 3 + test_auditlog/readme/CONTRIBUTORS.md | 1 + test_auditlog/readme/DESCRIPTION.md | 4 + test_auditlog/static/description/index.html | 419 ++++++++++++++++++ test_auditlog/tests/__init__.py | 2 + .../tests/test_account_move_reverse.py | 172 +++++++ .../tests/test_product_tax_multicompany.py | 75 ++++ 10 files changed, 766 insertions(+) create mode 100644 test_auditlog/README.rst create mode 100644 test_auditlog/__init__.py create mode 100644 test_auditlog/__manifest__.py create mode 100644 test_auditlog/pyproject.toml create mode 100644 test_auditlog/readme/CONTRIBUTORS.md create mode 100644 test_auditlog/readme/DESCRIPTION.md create mode 100644 test_auditlog/static/description/index.html create mode 100644 test_auditlog/tests/__init__.py create mode 100644 test_auditlog/tests/test_account_move_reverse.py create mode 100644 test_auditlog/tests/test_product_tax_multicompany.py diff --git a/test_auditlog/README.rst b/test_auditlog/README.rst new file mode 100644 index 00000000000..c6c9f2001e8 --- /dev/null +++ b/test_auditlog/README.rst @@ -0,0 +1,74 @@ +=============== +Audit Log Tests +=============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:83ebaaf9f4e2f1f13c0b3e1ffb3e18050e9210af4707305c780fb85c5f587961 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/18.0/test_auditlog + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-test_auditlog + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module does not add any business or technical functionality. It +only contains tests for the ``auditlog`` module that depend on models +from modules that are not a dependency of ``auditlog`` itself. Don't +install this module on your database unless you want to run its tests. + +**Table of contents** + +.. contents:: + :local: + +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Contributors +------------ + +- Stefan Rijnhart stefan@opener.amsterdam + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/test_auditlog/__init__.py b/test_auditlog/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_auditlog/__manifest__.py b/test_auditlog/__manifest__.py new file mode 100644 index 00000000000..82899eb8502 --- /dev/null +++ b/test_auditlog/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2025 Opener B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Audit Log Tests", + "summary": "Additional unit tests for Audit Log based on accounting models", + "version": "18.0.1.0.0", + "author": "Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools", + "category": "Tools", + "depends": ["account", "auditlog"], + "data": [], + "application": False, + "installable": True, +} diff --git a/test_auditlog/pyproject.toml b/test_auditlog/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/test_auditlog/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/test_auditlog/readme/CONTRIBUTORS.md b/test_auditlog/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..3a29acd033f --- /dev/null +++ b/test_auditlog/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +* Stefan Rijnhart diff --git a/test_auditlog/readme/DESCRIPTION.md b/test_auditlog/readme/DESCRIPTION.md new file mode 100644 index 00000000000..cfd2ee960d6 --- /dev/null +++ b/test_auditlog/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This module does not add any business or technical functionality. It only +contains tests for the `auditlog` module that depend on models from modules +that are not a dependency of `auditlog` itself. Don't install this module on +your database unless you want to run its tests. diff --git a/test_auditlog/static/description/index.html b/test_auditlog/static/description/index.html new file mode 100644 index 00000000000..9360bb84b3b --- /dev/null +++ b/test_auditlog/static/description/index.html @@ -0,0 +1,419 @@ + + + + + +Audit Log Tests + + + +
+

Audit Log Tests

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

This module does not add any business or technical functionality. It +only contains tests for the auditlog module that depend on models +from modules that are not a dependency of auditlog itself. Don’t +install this module on your database unless you want to run its tests.

+

Table of contents

+ +
+

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 +feedback.

+

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

+
+
+

Credits

+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/test_auditlog/tests/__init__.py b/test_auditlog/tests/__init__.py new file mode 100644 index 00000000000..febd48f594d --- /dev/null +++ b/test_auditlog/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_account_move_reverse +from . import test_product_tax_multicompany diff --git a/test_auditlog/tests/test_account_move_reverse.py b/test_auditlog/tests/test_account_move_reverse.py new file mode 100644 index 00000000000..67d08e16c3b --- /dev/null +++ b/test_auditlog/tests/test_account_move_reverse.py @@ -0,0 +1,172 @@ +from odoo import fields +from odoo.tests import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon + + +@tagged("post_install", "-at_install") +class TestAccountMoveReverse(AccountTestInvoicingCommon): + @classmethod + def setUpClass(cls): + # Class setup taken from account/tests/test_account_move_in_invoice.py + super().setUpClass() + + cls.other_currency = cls.setup_other_currency("EUR") + + cls.invoice = cls.init_invoice( + "in_invoice", products=cls.product_a + cls.product_b + ) + + cls.product_line_vals_1 = { + "name": "product_a", + "product_id": cls.product_a.id, + "account_id": cls.product_a.property_account_expense_id.id, + "partner_id": cls.partner_a.id, + "product_uom_id": cls.product_a.uom_id.id, + "quantity": 1.0, + "discount": 0.0, + "price_unit": 800.0, + "price_subtotal": 800.0, + "price_total": 920.0, + "tax_ids": cls.product_a.supplier_taxes_id.ids, + "tax_line_id": False, + "currency_id": cls.company_data["currency"].id, + "amount_currency": 800.0, + "debit": 800.0, + "credit": 0.0, + "date_maturity": False, + } + cls.product_line_vals_2 = { + "name": "product_b", + "product_id": cls.product_b.id, + "account_id": cls.product_b.property_account_expense_id.id, + "partner_id": cls.partner_a.id, + "product_uom_id": cls.product_b.uom_id.id, + "quantity": 1.0, + "discount": 0.0, + "price_unit": 160.0, + "price_subtotal": 160.0, + "price_total": 208.0, + "tax_ids": cls.product_b.supplier_taxes_id.ids, + "tax_line_id": False, + "currency_id": cls.company_data["currency"].id, + "amount_currency": 160.0, + "debit": 160.0, + "credit": 0.0, + "date_maturity": False, + } + cls.tax_line_vals_1 = { + "name": cls.tax_purchase_a.name, + "product_id": False, + "account_id": cls.company_data["default_account_tax_purchase"].id, + "partner_id": cls.partner_a.id, + "product_uom_id": False, + "quantity": False, + "discount": 0.0, + "price_unit": 0.0, + "price_subtotal": 0.0, + "price_total": 0.0, + "tax_ids": [], + "tax_line_id": cls.tax_purchase_a.id, + "currency_id": cls.company_data["currency"].id, + "amount_currency": 144.0, + "debit": 144.0, + "credit": 0.0, + "date_maturity": False, + } + cls.tax_line_vals_2 = { + "name": cls.tax_purchase_b.name, + "product_id": False, + "account_id": cls.company_data["default_account_tax_purchase"].id, + "partner_id": cls.partner_a.id, + "product_uom_id": False, + "quantity": False, + "discount": 0.0, + "price_unit": 0.0, + "price_subtotal": 0.0, + "price_total": 0.0, + "tax_ids": [], + "tax_line_id": cls.tax_purchase_b.id, + "currency_id": cls.company_data["currency"].id, + "amount_currency": 24.0, + "debit": 24.0, + "credit": 0.0, + "date_maturity": False, + } + cls.term_line_vals_1 = { + "name": False, + "product_id": False, + "account_id": cls.company_data["default_account_payable"].id, + "partner_id": cls.partner_a.id, + "product_uom_id": False, + "quantity": False, + "discount": 0.0, + "price_unit": 0.0, + "price_subtotal": 0.0, + "price_total": 0.0, + "tax_ids": [], + "tax_line_id": False, + "currency_id": cls.company_data["currency"].id, + "amount_currency": -1128.0, + "debit": 0.0, + "credit": 1128.0, + "date_maturity": fields.Date.from_string("2019-01-01"), + } + cls.move_vals = { + "partner_id": cls.partner_a.id, + "currency_id": cls.company_data["currency"].id, + "journal_id": cls.company_data["default_journal_purchase"].id, + "date": fields.Date.from_string("2019-01-01"), + "fiscal_position_id": False, + "payment_reference": False, + "invoice_payment_term_id": cls.pay_terms_a.id, + "amount_untaxed": 960.0, + "amount_tax": 168.0, + "amount_total": 1128.0, + } + cls.env.user.groups_id += cls.env.ref("uom.group_uom") + + def setUp(self): + super().setUp() + rules = self.env["auditlog.rule"].search([]) + rules.unsubscribe() + rules.unlink() + self.rule = self.env["auditlog.rule"].create( + { + "name": __name__, + "model_id": self.env.ref("account.model_account_move_line").id, + "log_read": True, + "log_create": True, + "log_write": True, + "log_unlink": True, + "log_type": "full", + } + ) + self.rule.subscribe() + + def tearDown(self): + self.rule.unsubscribe() + super().tearDown() + + def test_in_invoice_create_refund(self): + """Test creating a refund from a vendor bill. + + If auditlog does not carefully separate the main transaction cache from + the cache that it uses to fetch the logged values, this test would fail + on the loss of values related to the dynamic syncing of invoice and + journal entry lines. + """ + self.invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=self.invoice.ids) + .create( + { + "date": fields.Date.from_string("2019-02-01"), + "reason": "no reason", + "journal_id": self.invoice.journal_id.id, + } + ) + ) + move_reversal.refund_moves() diff --git a/test_auditlog/tests/test_product_tax_multicompany.py b/test_auditlog/tests/test_product_tax_multicompany.py new file mode 100644 index 00000000000..cee7fa8193e --- /dev/null +++ b/test_auditlog/tests/test_product_tax_multicompany.py @@ -0,0 +1,75 @@ +from odoo import fields +from odoo.tests import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon + + +@tagged("post_install", "-at_install") +class TestProductTaxMulticompany(AccountTestInvoicingCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company1 = cls.company_data["company"] + cls.tax1 = cls.company_data["default_tax_sale"] + cls.company_data_2 = cls.setup_other_company() + cls.company2 = cls.company_data_2["company"] + cls.tax2 = cls.company_data_2["default_tax_sale"] + cls.product_a.sudo().taxes_id = cls.tax1 + cls.tax2 + cls.env.user.company_ids = cls.company1 + + def setUp(self): + super().setUp() + rules = self.env["auditlog.rule"].search([]) + rules.unsubscribe() + rules.unlink() + self.rule = self.env["auditlog.rule"].create( + { + "name": __name__, + "model_id": self.env.ref("product.model_product_template").id, + "log_read": True, + "log_create": True, + "log_write": True, + "log_unlink": True, + "log_type": "full", + } + ) + self.rule.subscribe() + + def tearDown(self): + self.rule.unsubscribe() + super().tearDown() + + def test_cache_accesserror(self): + """No AccessError occurs reading the product after writing taxes. + + The current user only has access to one of the taxes assigned to the + product. If auditlog does sanitize the cache after fetching old and + new values for the log lines, the other company's tax may remain in the + product's cache which will raise an AccessError when it is read. + """ + product = self.product_a.product_tmpl_id + product.write( + {"taxes_id": [fields.Command.unlink(self.tax1.id)]}, + ) + self.tax1.invalidate_model() + product.read(["taxes_id"]) + + def test_product_tax_multicompany_result(self): + """The value from the other company is preserved""" + product = self.product_a.product_tmpl_id + product.write( + {"taxes_id": [fields.Command.unlink(self.tax1.id)]}, + ) + self.assertFalse(product.taxes_id) + product.invalidate_recordset() + self.assertEqual(product.sudo().taxes_id, self.tax2) + + def test_product_tax_multicompany_log(self): + """The log covers the taxes across all companies.""" + product = self.product_a.product_tmpl_id + product.write( + {"taxes_id": [fields.Command.unlink(self.tax1.id)]}, + ) + log = self.env["auditlog.log"].search([], order="id desc", limit=1) + self.assertEqual(log.line_ids.old_value, f"[{self.tax1.id}, {self.tax2.id}]") + self.assertEqual(log.line_ids.new_value, f"[{self.tax2.id}]") From 6194c9bc30dcf29f5181f473ce7f387f4cd50724 Mon Sep 17 00:00:00 2001 From: Adam Heinz Date: Wed, 24 Sep 2025 19:31:23 +0200 Subject: [PATCH 2/8] [FIX] auditlog: Ensure unit tests unpatch methods. Though TransactionCase rolls back database changes, it does not call `unlink` on `auditlog.rule` records, meaning that `unsubscribe` is never called to unpatch model methods. This causes subsequent tests in other modules to unexpectedly execute patched methods. This commit adds the `AuditLogRuleCommon` test class in an attempt to identify and prevent patched methods from contaminating the test environment. --- test_auditlog/README.rst | 10 +++++--- test_auditlog/__manifest__.py | 2 +- test_auditlog/i18n/test_auditlog.pot | 13 ++++++++++ test_auditlog/static/description/icon.png | Bin 0 -> 10254 bytes test_auditlog/static/description/index.html | 24 +++++++++++------- .../tests/test_account_move_reverse.py | 7 ++--- .../tests/test_product_tax_multicompany.py | 7 ++--- 7 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 test_auditlog/i18n/test_auditlog.pot create mode 100644 test_auditlog/static/description/icon.png diff --git a/test_auditlog/README.rst b/test_auditlog/README.rst index c6c9f2001e8..dc1b34e4383 100644 --- a/test_auditlog/README.rst +++ b/test_auditlog/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + =============== Audit Log Tests =============== @@ -7,13 +11,13 @@ Audit Log Tests !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:83ebaaf9f4e2f1f13c0b3e1ffb3e18050e9210af4707305c780fb85c5f587961 + !! source digest: sha256:8a3a6a49ac231887d7512b2ec1cf5be2c0751698c97228a7aa6d90d2dd03e820 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |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/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-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%2Fserver--tools-lightgray.png?logo=github @@ -54,7 +58,7 @@ Credits Contributors ------------ -- Stefan Rijnhart stefan@opener.amsterdam +- Stefan Rijnhart stefan@opener.amsterdam Maintainers ----------- diff --git a/test_auditlog/__manifest__.py b/test_auditlog/__manifest__.py index 82899eb8502..a4ba941d813 100644 --- a/test_auditlog/__manifest__.py +++ b/test_auditlog/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Audit Log Tests", "summary": "Additional unit tests for Audit Log based on accounting models", - "version": "18.0.1.0.0", + "version": "18.0.1.0.1", "author": "Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/server-tools", diff --git a/test_auditlog/i18n/test_auditlog.pot b/test_auditlog/i18n/test_auditlog.pot new file mode 100644 index 00000000000..aadee09bfed --- /dev/null +++ b/test_auditlog/i18n/test_auditlog.pot @@ -0,0 +1,13 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" diff --git a/test_auditlog/static/description/icon.png b/test_auditlog/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 -Audit Log Tests +README.rst -
-

Audit Log Tests

+
+ + +Odoo Community Association + +
+

Audit Log Tests

-

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module does not add any business or technical functionality. It only contains tests for the auditlog module that depend on models from modules that are not a dependency of auditlog itself. Don’t @@ -386,7 +391,7 @@

Audit Log Tests

-

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 @@ -394,15 +399,15 @@

Bug Tracker

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

+
diff --git a/test_auditlog/tests/test_account_move_reverse.py b/test_auditlog/tests/test_account_move_reverse.py index 67d08e16c3b..aa62f32778a 100644 --- a/test_auditlog/tests/test_account_move_reverse.py +++ b/test_auditlog/tests/test_account_move_reverse.py @@ -2,10 +2,11 @@ from odoo.tests import tagged from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.addons.auditlog.tests.common import AuditLogRuleCommon @tagged("post_install", "-at_install") -class TestAccountMoveReverse(AccountTestInvoicingCommon): +class TestAccountMoveReverse(AccountTestInvoicingCommon, AuditLogRuleCommon): @classmethod def setUpClass(cls): # Class setup taken from account/tests/test_account_move_in_invoice.py @@ -144,10 +145,6 @@ def setUp(self): ) self.rule.subscribe() - def tearDown(self): - self.rule.unsubscribe() - super().tearDown() - def test_in_invoice_create_refund(self): """Test creating a refund from a vendor bill. diff --git a/test_auditlog/tests/test_product_tax_multicompany.py b/test_auditlog/tests/test_product_tax_multicompany.py index cee7fa8193e..6f2dc2eb8de 100644 --- a/test_auditlog/tests/test_product_tax_multicompany.py +++ b/test_auditlog/tests/test_product_tax_multicompany.py @@ -2,10 +2,11 @@ from odoo.tests import tagged from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.addons.auditlog.tests.common import AuditLogRuleCommon @tagged("post_install", "-at_install") -class TestProductTaxMulticompany(AccountTestInvoicingCommon): +class TestProductTaxMulticompany(AccountTestInvoicingCommon, AuditLogRuleCommon): @classmethod def setUpClass(cls): super().setUpClass() @@ -35,10 +36,6 @@ def setUp(self): ) self.rule.subscribe() - def tearDown(self): - self.rule.unsubscribe() - super().tearDown() - def test_cache_accesserror(self): """No AccessError occurs reading the product after writing taxes. From 0d66d5e5e4ba80a2c3f458f1ff2ce5d0a2a4a753 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 2 Oct 2025 19:17:48 +0000 Subject: [PATCH 3/8] Added translation using Weblate (Italian) --- test_auditlog/i18n/it.po | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test_auditlog/i18n/it.po diff --git a/test_auditlog/i18n/it.po b/test_auditlog/i18n/it.po new file mode 100644 index 00000000000..c0d5085374b --- /dev/null +++ b/test_auditlog/i18n/it.po @@ -0,0 +1,14 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" From 3c61ac7ce626dad3b551b6ea23cba2a4068e97e6 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Mon, 6 Oct 2025 14:47:26 +0200 Subject: [PATCH 4/8] [FIX] auditlog: swap out tocompute in ThrowAwayCache as well Steps to Reproduce: Install auditlog and purchase_tier_validation. Create an auditlog rule on the Tier Exception model. Create a new tier exception record for the purchase order model without any fields. In an export, check the value for the stored computed field `model_name`. Desired outcome: The value for `model_name` is 'purchase.order'. Actual outcome: There is no value for the stored computed field `model_name`. When trying to edit the `Fields` model, which depends on a valid value for this field, an error occurs saying 'Compute method failed to assign tier.validation.exception(1,).valid_model_field_ids'. Analysis: When `read` is executed under the scope of the new `ThrowAwayCache` decorator (#3374), recomputes may be performed and dequeued from `self.env.cache.transaction.tocompute`. To make sure the recomputed values still end up in the non-volatile as well, we need to preserve the tocompute attribute from the original transaction. --- test_auditlog/README.rst | 2 +- test_auditlog/__manifest__.py | 2 +- test_auditlog/static/description/index.html | 2 +- test_auditlog/tests/test_account_move_reverse.py | 14 ++++++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/test_auditlog/README.rst b/test_auditlog/README.rst index dc1b34e4383..1d5aac4d9fb 100644 --- a/test_auditlog/README.rst +++ b/test_auditlog/README.rst @@ -11,7 +11,7 @@ Audit Log Tests !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:8a3a6a49ac231887d7512b2ec1cf5be2c0751698c97228a7aa6d90d2dd03e820 + !! source digest: sha256:b0537bd80eb5a3d24aef4fd1cb72d66f7b384ba71861dbec738aa6695abbc539 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/test_auditlog/__manifest__.py b/test_auditlog/__manifest__.py index a4ba941d813..aca77a1184e 100644 --- a/test_auditlog/__manifest__.py +++ b/test_auditlog/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Audit Log Tests", "summary": "Additional unit tests for Audit Log based on accounting models", - "version": "18.0.1.0.1", + "version": "18.0.1.0.2", "author": "Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/server-tools", diff --git a/test_auditlog/static/description/index.html b/test_auditlog/static/description/index.html index bed7a9c6a64..c58059d52bd 100644 --- a/test_auditlog/static/description/index.html +++ b/test_auditlog/static/description/index.html @@ -372,7 +372,7 @@

Audit Log Tests

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:8a3a6a49ac231887d7512b2ec1cf5be2c0751698c97228a7aa6d90d2dd03e820 +!! source digest: sha256:b0537bd80eb5a3d24aef4fd1cb72d66f7b384ba71861dbec738aa6695abbc539 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module does not add any business or technical functionality. It diff --git a/test_auditlog/tests/test_account_move_reverse.py b/test_auditlog/tests/test_account_move_reverse.py index aa62f32778a..ff68ab7df0f 100644 --- a/test_auditlog/tests/test_account_move_reverse.py +++ b/test_auditlog/tests/test_account_move_reverse.py @@ -145,6 +145,20 @@ def setUp(self): ) self.rule.subscribe() + def test_in_invoice_stored_related_field(self): + """Stored related fields are computed properly""" + self.invoice.name = "TEST" + line = self.env["account.move.line"].create( + { + "display_type": "line_note", + "name": __name__, + "move_id": self.invoice.id, + } + ) + self.assertEqual(line.move_name, "TEST") + self.invoice.name = "TEST2" + self.assertEqual(line.move_name, "TEST2") + def test_in_invoice_create_refund(self): """Test creating a refund from a vendor bill. From e30f6d5d17b56d629a406ac82e32a4816bac11f3 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Thu, 18 Dec 2025 15:32:00 +0100 Subject: [PATCH 5/8] [FIX] auditlog: drop tocompute register entirely from ThrowAwayCache Fixes #3424 Previous approach was to create a copy, so that the recomputes were also applied to the real world cache. However, this causes an issue when a field is required that is only available in the real world cache, such as the `date` field in ``` @api.depends('date', 'sequence') def _compute_internal_index(self): for st_line in self.filtered(lambda line: line._origin.id): st_line.internal_index = f'{st_line.date.strftime("%Y%m%d")}' ... ``` It actually makes sense to avoid recomputes in this isolated environment that is meant to retrieve the original values from before the write. Fixes ``` File "/odoo/odoo/addons/account/models/account_bank_statement_line.py", line 427, in create st_line.move_id.write(to_write) File "/odoo/server-tools/auditlog/models/rule.py", line 464, in write_full old_values = {d["id"]: d for d in records_write.read(fields_list)} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/server-tools/auditlog/models/rule.py", line 406, in read result = read.origin(self, fields, load, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/odoo/odoo/models.py", line 3857, in read self._origin.fetch(fields) File "/odoo/odoo/odoo/models.py", line 4153, in fetch fetched = self._fetch_query(query, fields_to_fetch) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/odoo/odoo/models.py", line 4264, in _fetch_query field.read(fetched) File "/odoo/odoo/odoo/fields.py", line 4654, in read lines = comodel.search_fetch(domain, field_names) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/odoo/odoo/models.py", line 1781, in search_fetch return self._fetch_query(query, fields_to_fetch) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/odoo/odoo/models.py", line 4240, in _fetch_query rows = self.env.execute_query(query.select(*sql_terms)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/odoo/odoo/odoo/api.py", line 992, in execute_query self.flush_query(query) File "/odoo/odoo/odoo/api.py", line 984, in flush_query self[model_name].flush_model(field_names) File "/odoo/odoo/odoo/models.py", line 6768, in flush_model self._recompute_model(fnames) File "/odoo/odoo/odoo/models.py", line 7332, in _recompute_model self._recompute_field(field) File "/odoo/odoo/odoo/models.py", line 7360, in _recompute_field field.recompute(records) File "/odoo/odoo/odoo/fields.py", line 1471, in recompute apply_except_missing(self.compute_value, recs) File "/odoo/odoo/odoo/fields.py", line 1444, in apply_except_missing func(records) File "/odoo/odoo/odoo/fields.py", line 1493, in compute_value records._compute_field_value(self) File "/odoo/odoo/odoo/models.py", line 5297, in _compute_field_value fields.determine(field.compute, self) File "/odoo/odoo/odoo/fields.py", line 110, in determine return needle(*args) ^^^^^^^^^^^^^ File "/odoo/odoo/addons/account/models/account_bank_statement_line.py", line 295, in _compute_internal_index st_line.internal_index = f'{st_line.date.strftime("%Y%m%d")}' \ ^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'bool' object has no attribute 'strftime' ``` --- test_auditlog/README.rst | 2 +- test_auditlog/__manifest__.py | 2 +- test_auditlog/static/description/index.html | 2 +- test_auditlog/tests/__init__.py | 1 + .../tests/test_account_bank_statement_line.py | 52 +++++++++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test_auditlog/tests/test_account_bank_statement_line.py diff --git a/test_auditlog/README.rst b/test_auditlog/README.rst index 1d5aac4d9fb..7f01ea6d3ea 100644 --- a/test_auditlog/README.rst +++ b/test_auditlog/README.rst @@ -11,7 +11,7 @@ Audit Log Tests !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:b0537bd80eb5a3d24aef4fd1cb72d66f7b384ba71861dbec738aa6695abbc539 + !! source digest: sha256:ae0a5ae9d572925bd0b2083f4d0a20734e00d384183a843b0c04ccc202deb904 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/test_auditlog/__manifest__.py b/test_auditlog/__manifest__.py index aca77a1184e..50aaabee8a0 100644 --- a/test_auditlog/__manifest__.py +++ b/test_auditlog/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Audit Log Tests", "summary": "Additional unit tests for Audit Log based on accounting models", - "version": "18.0.1.0.2", + "version": "18.0.1.0.3", "author": "Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/server-tools", diff --git a/test_auditlog/static/description/index.html b/test_auditlog/static/description/index.html index c58059d52bd..91ff928ea16 100644 --- a/test_auditlog/static/description/index.html +++ b/test_auditlog/static/description/index.html @@ -372,7 +372,7 @@

Audit Log Tests

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:b0537bd80eb5a3d24aef4fd1cb72d66f7b384ba71861dbec738aa6695abbc539 +!! source digest: sha256:ae0a5ae9d572925bd0b2083f4d0a20734e00d384183a843b0c04ccc202deb904 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module does not add any business or technical functionality. It diff --git a/test_auditlog/tests/__init__.py b/test_auditlog/tests/__init__.py index febd48f594d..9678814e1ad 100644 --- a/test_auditlog/tests/__init__.py +++ b/test_auditlog/tests/__init__.py @@ -1,2 +1,3 @@ +from . import test_account_bank_statement_line from . import test_account_move_reverse from . import test_product_tax_multicompany diff --git a/test_auditlog/tests/test_account_bank_statement_line.py b/test_auditlog/tests/test_account_bank_statement_line.py new file mode 100644 index 00000000000..01d724212de --- /dev/null +++ b/test_auditlog/tests/test_account_bank_statement_line.py @@ -0,0 +1,52 @@ +from odoo.tests import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.addons.auditlog.tests.common import AuditLogRuleCommon + + +@tagged("post_install", "-at_install") +class TestAccountBankStatementLine(AccountTestInvoicingCommon, AuditLogRuleCommon): + def setUp(self): + super().setUp() + self.rule = self.env["auditlog.rule"].create( + { + "name": __name__, + "model_id": self.env.ref("account.model_account_move").id, + "log_read": True, + "log_create": True, + "log_write": True, + "log_unlink": True, + "log_type": "full", + } + ) + self.rule.subscribe() + + def test_create_statement_line(self): + """Statement line can be created with logging on journal entries enabled. + + Because we swap out the cache when fetching previous values during full + logging using the ThrowAwayCache, some values that are assumed by + compute methods (c.q. 'date' in account.bank.statement.line's + _compute_internal_index) might be missing. If a recompute of those fields + is inadvertently triggered when using the ThrowAwayCache, the missing + values will raise an exception (in this case: `AttributeError: 'bool' + object has no attribute 'strftime'`). This test verifies that the queued + recomputes are consistent with the values in the cache such that this + exception does not occur. + """ + partner = self.env["res.partner"].create({"name": "test"}) + stmt = self.env["account.bank.statement"].create( + {"journal_id": self.company_data["default_journal_bank"].id} + ) + line = self.env["account.bank.statement.line"].create( + { + "date": "2023-04-01", + "account_number": "NL45 TRIO 0198100000", + "amount": 5.75, + "journal_id": self.company_data["default_journal_bank"].id, + "payment_ref": "1234", + "partner_id": partner.id, + "statement_id": stmt.id, + }, + ) + line.flush_recordset() From 9e5f0548ce192bf32c4bfea4bc6954f2a61b521e Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Fri, 2 Jan 2026 19:33:51 +0100 Subject: [PATCH 6/8] [MIG] test_auditlog: Migration to 19.0 --- test_auditlog/README.rst | 12 ++++++------ test_auditlog/__manifest__.py | 2 +- test_auditlog/static/description/index.html | 6 +++--- test_auditlog/tests/test_account_move_reverse.py | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test_auditlog/README.rst b/test_auditlog/README.rst index 7f01ea6d3ea..b1153530c2b 100644 --- a/test_auditlog/README.rst +++ b/test_auditlog/README.rst @@ -21,13 +21,13 @@ Audit Log Tests :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github - :target: https://github.com/OCA/server-tools/tree/18.0/test_auditlog + :target: https://github.com/OCA/server-tools/tree/19.0/test_auditlog :alt: OCA/server-tools .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/server-tools-18-0/server-tools-18-0-test_auditlog + :target: https://translation.odoo-community.org/projects/server-tools-19-0/server-tools-19-0-test_auditlog :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-tools&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -48,7 +48,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -58,7 +58,7 @@ Credits Contributors ------------ -- Stefan Rijnhart stefan@opener.amsterdam +- Stefan Rijnhart stefan@opener.amsterdam Maintainers ----------- @@ -73,6 +73,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/server-tools `_ project on GitHub. +This module is part of the `OCA/server-tools `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/test_auditlog/__manifest__.py b/test_auditlog/__manifest__.py index 50aaabee8a0..900cb9b13c5 100644 --- a/test_auditlog/__manifest__.py +++ b/test_auditlog/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Audit Log Tests", "summary": "Additional unit tests for Audit Log based on accounting models", - "version": "18.0.1.0.3", + "version": "19.0.1.0.0", "author": "Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/server-tools", diff --git a/test_auditlog/static/description/index.html b/test_auditlog/static/description/index.html index 91ff928ea16..269eaf171ad 100644 --- a/test_auditlog/static/description/index.html +++ b/test_auditlog/static/description/index.html @@ -374,7 +374,7 @@

Audit Log Tests

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:ae0a5ae9d572925bd0b2083f4d0a20734e00d384183a843b0c04ccc202deb904 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module does not add any business or technical functionality. It only contains tests for the auditlog module that depend on models from modules that are not a dependency of auditlog itself. Don’t @@ -395,7 +395,7 @@

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 -feedback.

+feedback.

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

@@ -415,7 +415,7 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/server-tools project on GitHub.

+

This module is part of the OCA/server-tools project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/test_auditlog/tests/test_account_move_reverse.py b/test_auditlog/tests/test_account_move_reverse.py index ff68ab7df0f..dfdd9ff0da4 100644 --- a/test_auditlog/tests/test_account_move_reverse.py +++ b/test_auditlog/tests/test_account_move_reverse.py @@ -125,7 +125,7 @@ def setUpClass(cls): "amount_tax": 168.0, "amount_total": 1128.0, } - cls.env.user.groups_id += cls.env.ref("uom.group_uom") + cls.env.user.group_ids += cls.env.ref("uom.group_uom") def setUp(self): super().setUp() From 0cc2ebb607a4dfb1754e6e6fd0eb85c33bdd3758 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Fri, 2 Jan 2026 21:21:21 +0100 Subject: [PATCH 7/8] [IMP] test_auditlog: adapt to terminology change in auditlog --- test_auditlog/tests/test_account_bank_statement_line.py | 2 +- test_auditlog/tests/test_account_move_reverse.py | 4 ++-- test_auditlog/tests/test_product_tax_multicompany.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test_auditlog/tests/test_account_bank_statement_line.py b/test_auditlog/tests/test_account_bank_statement_line.py index 01d724212de..ecbccbef37d 100644 --- a/test_auditlog/tests/test_account_bank_statement_line.py +++ b/test_auditlog/tests/test_account_bank_statement_line.py @@ -19,7 +19,7 @@ def setUp(self): "log_type": "full", } ) - self.rule.subscribe() + self.rule.set_to_confirmed() def test_create_statement_line(self): """Statement line can be created with logging on journal entries enabled. diff --git a/test_auditlog/tests/test_account_move_reverse.py b/test_auditlog/tests/test_account_move_reverse.py index dfdd9ff0da4..bf9a8bef824 100644 --- a/test_auditlog/tests/test_account_move_reverse.py +++ b/test_auditlog/tests/test_account_move_reverse.py @@ -130,7 +130,7 @@ def setUpClass(cls): def setUp(self): super().setUp() rules = self.env["auditlog.rule"].search([]) - rules.unsubscribe() + rules.set_to_confirmed() rules.unlink() self.rule = self.env["auditlog.rule"].create( { @@ -143,7 +143,7 @@ def setUp(self): "log_type": "full", } ) - self.rule.subscribe() + self.rule.set_to_confirmed() def test_in_invoice_stored_related_field(self): """Stored related fields are computed properly""" diff --git a/test_auditlog/tests/test_product_tax_multicompany.py b/test_auditlog/tests/test_product_tax_multicompany.py index 6f2dc2eb8de..83ef204d4cd 100644 --- a/test_auditlog/tests/test_product_tax_multicompany.py +++ b/test_auditlog/tests/test_product_tax_multicompany.py @@ -21,7 +21,7 @@ def setUpClass(cls): def setUp(self): super().setUp() rules = self.env["auditlog.rule"].search([]) - rules.unsubscribe() + rules.set_to_draft() rules.unlink() self.rule = self.env["auditlog.rule"].create( { @@ -34,7 +34,7 @@ def setUp(self): "log_type": "full", } ) - self.rule.subscribe() + self.rule.set_to_confirmed() def test_cache_accesserror(self): """No AccessError occurs reading the product after writing taxes. From 06f69628dae67713937a938a212818fa366c58ee Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Fri, 2 Jan 2026 21:21:42 +0100 Subject: [PATCH 8/8] [TST] Test requirement: dependency on unmerged auditlog --- test-requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test-requirements.txt diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000000..09828639ff5 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +git+https://github.com/stefanrijnhart/server-tools@19.0-mig-auditlog#subdirectory=auditlog