From 15530bbd7657e4b6d19abd505c50c756fa6400ed Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Thu, 18 Dec 2025 15:32:00 +0100 Subject: [PATCH 1/2] [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' ``` --- auditlog/models/rule.py | 10 ++-- test_auditlog/tests/__init__.py | 1 + .../tests/test_account_bank_statement_line.py | 52 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 test_auditlog/tests/test_account_bank_statement_line.py diff --git a/auditlog/models/rule.py b/auditlog/models/rule.py index 0336ed3e551..32ff17c746c 100644 --- a/auditlog/models/rule.py +++ b/auditlog/models/rule.py @@ -71,10 +71,12 @@ def __enter__(self): don't swap them all out here. """ self._original_cache = self._transaction.cache - # Copy the sets of records, which are popped on recompute but do not - # copy the keys because they do not match the original field object - # afterwards. - self._original_tocompute = defaultdict(OrderedSet) + # Also swap out the list of fields to recompute. Their compute methods + # may depend on fields in the cache that are not yet flushed, and as is + # the case with account.bank.statement.line's _compute_internal_index, + # may not be resilient to some of the values (c.q. 'date') missing. + self._original_tocompute = self._transaction.tocompute + self._transaction.tocompute = defaultdict(OrderedSet) for key, value in self._transaction.tocompute.items(): self._original_tocompute[key] = OrderedSet(value) temporary_cache = api.Cache() 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 6df81fedb7274364d303793c96e6132aed895875 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 2 Jan 2026 05:26:44 +0000 Subject: [PATCH 2/2] [BOT] post-merge updates --- README.md | 4 ++-- auditlog/README.rst | 2 +- auditlog/__manifest__.py | 2 +- auditlog/static/description/index.html | 2 +- test_auditlog/README.rst | 2 +- test_auditlog/__manifest__.py | 2 +- test_auditlog/static/description/index.html | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f7bb1e913ba..e4892df7417 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ addon | version | maintainers | summary [attachment_queue](attachment_queue/) | 18.0.1.0.0 | florian-dacosta sebastienbeau | Base module adding the concept of queue for processing files [attachment_synchronize](attachment_synchronize/) | 18.0.1.0.0 | florian-dacosta sebastienbeau GSLabIt bealdav | Attachment Synchronize [attachment_unindex_content](attachment_unindex_content/) | 18.0.1.0.0 | moylop260 ebirbe luisg123v | Disable indexing of attachments -[auditlog](auditlog/) | 18.0.2.0.4 | | Audit Log +[auditlog](auditlog/) | 18.0.2.0.5 | | Audit Log [auto_backup](auto_backup/) | 18.0.1.0.1 | | Backups database [autovacuum_message_attachment](autovacuum_message_attachment/) | 18.0.1.0.1 | florian-dacosta | Automatically delete old mail messages and attachments [base_cron_exclusion](base_cron_exclusion/) | 18.0.1.0.1 | LoisRForgeFlow ChrisOForgeFlow | Allow you to select scheduled actions that should not run simultaneously. @@ -63,7 +63,7 @@ addon | version | maintainers | summary [scheduler_error_mailer](scheduler_error_mailer/) | 18.0.1.0.0 | | Scheduler Error Mailer [sentry](sentry/) | 18.0.1.0.3 | barsi naglis versada moylop260 fernandahf | Report Odoo errors to Sentry [session_db](session_db/) | 18.0.1.0.1 | sbidoul | Store sessions in DB -[test_auditlog](test_auditlog/) | 18.0.1.0.2 | | Additional unit tests for Audit Log based on accounting models +[test_auditlog](test_auditlog/) | 18.0.1.0.3 | | Additional unit tests for Audit Log based on accounting models [test_base_time_window](test_base_time_window/) | 18.0.1.0.0 | | Test Base model to handle time windows [tracking_manager](tracking_manager/) | 18.0.1.1.0 | Kev-Roche sebastienbeau | This module tracks all fields of a model, including one2many and many2many ones. [tracking_manager_domain](tracking_manager_domain/) | 18.0.1.0.1 | CRogos | This module extends the tracking manager to allow to define a domain on fields to track changes only when certain conditions apply. diff --git a/auditlog/README.rst b/auditlog/README.rst index 362cd93c1aa..37615e91c2d 100644 --- a/auditlog/README.rst +++ b/auditlog/README.rst @@ -11,7 +11,7 @@ Audit Log !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:128a623839f266a13080072b8ee934467414cee354aff1afe25f078729621f52 + !! source digest: sha256:5d80401c7f72e7744b093dc1e4ee6fc2eec010879861d75c844494808dc0e867 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/auditlog/__manifest__.py b/auditlog/__manifest__.py index 8c0a5d6ea22..990eefc417e 100644 --- a/auditlog/__manifest__.py +++ b/auditlog/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Audit Log", - "version": "18.0.2.0.4", + "version": "18.0.2.0.5", "author": "ABF OSIELL, Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/server-tools", diff --git a/auditlog/static/description/index.html b/auditlog/static/description/index.html index b8b68c6f177..09bfb84c421 100644 --- a/auditlog/static/description/index.html +++ b/auditlog/static/description/index.html @@ -372,7 +372,7 @@

Audit Log

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:128a623839f266a13080072b8ee934467414cee354aff1afe25f078729621f52 +!! source digest: sha256:5d80401c7f72e7744b093dc1e4ee6fc2eec010879861d75c844494808dc0e867 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This module allows the administrator to log user operations performed on 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