From 982bd56679c23dc153fa124570c16dd801c81223 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Wed, 16 Sep 2020 09:52:35 +0000 Subject: [PATCH] [FIX] base: clearer message in case of conflict for no_gap sequences The raw error message from psycopg2 wasn't clear for users and led to multiple support tickets. In case of such "concurrency" errors, the user should retry later, it's not a "real" bug. closes odoo/odoo#57851 X-original-commit: 9f7f1db5add5b8a940e53707091133c0bcadd350 Signed-off-by: Victor Feyens (vfe) --- odoo/addons/base/models/ir_sequence.py | 12 +++++++++--- odoo/addons/base/tests/test_ir_sequence.py | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/odoo/addons/base/models/ir_sequence.py b/odoo/addons/base/models/ir_sequence.py index a356ddfaa47..3e13dccdade 100644 --- a/odoo/addons/base/models/ir_sequence.py +++ b/odoo/addons/base/models/ir_sequence.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta import logging import pytz -from psycopg2 import sql +from psycopg2 import sql, OperationalError, errorcodes from odoo import api, fields, models, _ from odoo.exceptions import UserError @@ -53,8 +53,14 @@ def _select_nextval(cr, seq_name): def _update_nogap(self, number_increment): number_next = self.number_next - self._cr.execute("SELECT number_next FROM %s WHERE id=%%s FOR UPDATE NOWAIT" % self._table, [self.id]) - self._cr.execute("UPDATE %s SET number_next=number_next+%%s WHERE id=%%s " % self._table, (number_increment, self.id)) + try: + self._cr.execute("SELECT number_next FROM %s WHERE id=%%s FOR UPDATE NOWAIT" % self._table, [self.id]) + self._cr.execute("UPDATE %s SET number_next=number_next+%%s WHERE id=%%s " % self._table, (number_increment, self.id)) + except OperationalError as e: + if e.pgcode == errorcodes.LOCK_NOT_AVAILABLE: + raise UserError(_("This transaction wasn't executed because another transaction is already using the same no-gap sequence. Please try again later.")) + else: + raise self.invalidate_cache(['number_next'], [self.id]) return number_next diff --git a/odoo/addons/base/tests/test_ir_sequence.py b/odoo/addons/base/tests/test_ir_sequence.py index 0fc53012b48..8c27dc18d74 100644 --- a/odoo/addons/base/tests/test_ir_sequence.py +++ b/odoo/addons/base/tests/test_ir_sequence.py @@ -7,6 +7,7 @@ import psycopg2 import psycopg2.errorcodes import odoo +from odoo.exceptions import UserError from odoo.tests import common from odoo.tests.common import BaseCase @@ -92,11 +93,10 @@ class TestIrSequenceNoGap(BaseCase): with environment() as env0: with environment() as env1: env1.cr._default_log_exceptions = False # Prevent logging a traceback - with self.assertRaises(psycopg2.OperationalError) as e: + with self.assertRaises(UserError) as e: n0 = env0['ir.sequence'].next_by_code('test_sequence_type_2') self.assertTrue(n0) n1 = env1['ir.sequence'].next_by_code('test_sequence_type_2') - self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode") @classmethod def tearDownClass(cls):