From 4e15e63732e2662a19a4ac8a3104d105dfd21793 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Mon, 26 Jun 2023 11:26:55 +0100 Subject: [PATCH] [FIX] account_journal_general_sequence: optimize recomputes when renumbering When calling `_next()` in a sequence, it issues calls to `search()`, especially if it is a no-gap or date-range-based sequence (which is common in this use case). When doing a search, Odoo triggers recomputations. Thus, when doing both a write and a call to `_next()` in the same loop, Odoo had to flush to DB too often, causing a bottleneck. Now, the process is more optimized: 1. Cache all new entry numbers. 2. Write them all. 3. Mark them all as modified at once, to batch-trigger recomputations. To reduce the amount of recomputations, tracking is disabled for the entry number. After all, before renumbering there's already a warning telling you that you shouldn't renumber if you already published those entry numbers to your fiscal authority. Another pseudo-improvement is that the info log is shorter. Enable debug logging to log the list of IDs changed. A test was failing because it was relying on the fact that computations were not getting as lazy as they should. Manual flushes are added to imitate a user doing different invoice creations. @moduon MT-3082 --- .../models/account_move.py | 12 +++++++++--- .../tests/test_numbering.py | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/account_journal_general_sequence/models/account_move.py b/account_journal_general_sequence/models/account_move.py index 28179d39..44887d16 100644 --- a/account_journal_general_sequence/models/account_move.py +++ b/account_journal_general_sequence/models/account_move.py @@ -23,7 +23,6 @@ class AccountMove(models.Model): entry_number = fields.Char( index=True, readonly=True, - tracking=True, store=True, compute="_compute_entry_number", help="Automatic numbering, based on journal configuration.", @@ -59,9 +58,16 @@ class AccountMove(models.Model): chosen = self.filtered_domain( [("state", "=", "posted"), ("entry_number", "=", False)] ) + # Cache all the new numbers to avoid wasting recomputations, caused by + # searches done by _next() in the loop below + chosen_map = {} for move in chosen.sorted(lambda one: (one.date, one.name, one.id)): - move.entry_number = move.journal_id.entry_number_sequence_id._next( + chosen_map[move.id] = move.journal_id.entry_number_sequence_id._next( move.date ) + # Write all the new numbers in the chosen moves + for move_id, new_number in chosen_map.items(): + self.browse(move_id).entry_number = new_number if chosen: - _logger.info("Added entry_number to %r", chosen) + _logger.info("Added entry_number to %d account moves", len(chosen)) + _logger.debug("Added entry_number to %r", chosen) diff --git a/account_journal_general_sequence/tests/test_numbering.py b/account_journal_general_sequence/tests/test_numbering.py index 6d15f2ba..b8c9f86b 100644 --- a/account_journal_general_sequence/tests/test_numbering.py +++ b/account_journal_general_sequence/tests/test_numbering.py @@ -42,12 +42,15 @@ class RenumberCase(TestAccountReconciliationCommon): next_year_invoice = self._create_invoice( date_invoice="2023-12-31", auto_validate=True ) + next_year_invoice.flush(["entry_number"], next_year_invoice) new_invoice = self._create_invoice( date_invoice="2022-05-10", auto_validate=True ) + new_invoice.flush(["entry_number"], new_invoice) old_invoice = self._create_invoice( date_invoice="2022-04-30", auto_validate=True ) + old_invoice.flush(["entry_number"], old_invoice) self.assertLess(new_invoice.entry_number, old_invoice.entry_number) # Fix entry number order with wizard; default values are OK wiz_f = Form(self.env["account.move.renumber.wizard"])