From 4c90e9e015c8edeca579de2db9a8bed11ff53450 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 7 Sep 2021 00:42:41 +0200 Subject: [PATCH 01/58] Add module account_move_name_sequence This module restores the good old behavior where journal entry numbers were generated from a sequence configured on the journal. --- account_move_name_sequence/README.rst | 1 + account_move_name_sequence/__init__.py | 1 + account_move_name_sequence/__manifest__.py | 20 ++++ account_move_name_sequence/models/__init__.py | 2 + .../models/account_journal.py | 96 ++++++++++++++++ .../models/account_move.py | 32 ++++++ .../readme/CONFIGURE.rst | 3 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 14 +++ .../security/ir.model.access.csv | 2 + account_move_name_sequence/tests/__init__.py | 1 + .../tests/test_account_move_name_seq.py | 107 ++++++++++++++++++ .../views/account_journal.xml | 34 ++++++ 13 files changed, 314 insertions(+) create mode 100644 account_move_name_sequence/README.rst create mode 100644 account_move_name_sequence/__init__.py create mode 100644 account_move_name_sequence/__manifest__.py create mode 100644 account_move_name_sequence/models/__init__.py create mode 100644 account_move_name_sequence/models/account_journal.py create mode 100644 account_move_name_sequence/models/account_move.py create mode 100644 account_move_name_sequence/readme/CONFIGURE.rst create mode 100644 account_move_name_sequence/readme/CONTRIBUTORS.rst create mode 100644 account_move_name_sequence/readme/DESCRIPTION.rst create mode 100644 account_move_name_sequence/security/ir.model.access.csv create mode 100644 account_move_name_sequence/tests/__init__.py create mode 100644 account_move_name_sequence/tests/test_account_move_name_seq.py create mode 100644 account_move_name_sequence/views/account_journal.xml diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst new file mode 100644 index 00000000000..2627cab222e --- /dev/null +++ b/account_move_name_sequence/README.rst @@ -0,0 +1 @@ +Will be auto-generated from the readme subdir diff --git a/account_move_name_sequence/__init__.py b/account_move_name_sequence/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/account_move_name_sequence/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py new file mode 100644 index 00000000000..b0b62405c37 --- /dev/null +++ b/account_move_name_sequence/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Account Move Number Sequence", + "version": "14.0.1.0.0", + "category": "Accounting", + "license": "AGPL-3", + "summary": "Generate journal entry number from sequence", + "author": "Akretion,Odoo Community Association (OCA)", + "maintainers": ["alexis-via"], + "website": "https://github.com/OCA/account-financial-tools", + "depends": ["account"], + "data": [ + "views/account_journal.xml", + "security/ir.model.access.csv", + ], + "installable": True, +} diff --git a/account_move_name_sequence/models/__init__.py b/account_move_name_sequence/models/__init__.py new file mode 100644 index 00000000000..067db8c5faa --- /dev/null +++ b/account_move_name_sequence/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_journal +from . import account_move diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py new file mode 100644 index 00000000000..2d616d009eb --- /dev/null +++ b/account_move_name_sequence/models/account_journal.py @@ -0,0 +1,96 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class AccountJournal(models.Model): + _inherit = "account.journal" + + sequence_id = fields.Many2one( + "ir.sequence", + string="Entry Sequence", + copy=False, + check_company=True, + domain="[('company_id', '=', company_id)]", + help="This sequence will be used to generate the journal entry number.", + ) + refund_sequence = fields.Boolean( + string="Dedicated Credit Note Sequence", + default=True, + help="If enabled, you will be able to setup a sequence dedicated for refunds.", + ) + refund_sequence_id = fields.Many2one( + "ir.sequence", + string="Credit Note Entry Sequence", + copy=False, + check_company=True, + domain="[('company_id', '=', company_id)]", + help="This sequence will be used to generate the journal entry number for refunds.", + ) + + @api.constrains("refund_sequence_id", "sequence_id") + def _check_journal_sequence(self): + for journal in self: + if ( + journal.refund_sequence_id + and journal.sequence_id + and journal.refund_sequence_id == journal.sequence_id + ): + raise ValidationError( + _( + "On journal '%s', the same sequence is used as " + "Entry Sequence and Credit Note Entry Sequence." + ) + % journal.display_name + ) + if journal.sequence_id and not journal.sequence_id.company_id: + raise ValidationError( + _( + "The company is not set on sequence '%s' configured on " + "journal '%s'." + ) + % (journal.sequence_id.display_name, journal.display_name) + ) + if journal.refund_sequence_id and not journal.refund_sequence_id.company_id: + raise ValidationError( + _( + "The company is not set on sequence '%s' configured as " + "credit note sequence of journal '%s'." + ) + % (journal.refund_sequence_id.display_name, journal.display_name) + ) + + @api.model + def create(self, vals): + if not vals.get("sequence_id"): + vals["sequence_id"] = self._create_sequence(vals).id + if ( + vals.get("type") in ("sale", "purchase") + and vals.get("refund_sequence") + and not vals.get("refund_sequence_id") + ): + vals["refund_sequence_id"] = self._create_sequence(vals, refund=True).id + return super().create(vals) + + @api.model + def _prepare_sequence(self, vals, refund=False): + code = vals.get("code") and vals["code"].upper() or "" + prefix = "%s%s/%%(range_year)s/" % (refund and "R" or "", code) + seq_vals = { + "name": "%s%s" + % (vals.get("name", _("Sequence")), refund and _("Refund") + " " or ""), + "company_id": vals.get("company_id") or self.env.company.id, + "implementation": "no_gap", + "prefix": prefix, + "padding": 4, + "use_date_range": True, + } + return seq_vals + + @api.model + def _create_sequence(self, vals, refund=False): + seq_vals = self._prepare_sequence(vals, refund=refund) + return self.env["ir.sequence"].sudo().create(seq_vals) diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py new file mode 100644 index 00000000000..986d64dd1be --- /dev/null +++ b/account_move_name_sequence/models/account_move.py @@ -0,0 +1,32 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def _compute_name(self): + for move in self.filtered( + lambda m: (m.name == "/" or not m.name) + and m.state == "posted" + and m.journal_id + and m.journal_id.sequence_id + ): + if ( + move.move_type in ("out_refund", "in_refund") + and move.journal_id.type in ("sale", "purchase") + and move.journal_id.refund_sequence + and move.journal_id.refund_sequence_id + ): + seq = move.journal_id.refund_sequence_id + else: + seq = move.journal_id.sequence_id + move.name = seq.next_by_id(sequence_date=move.date) + super()._compute_name() + for move in self.filtered( + lambda m: m.name and m.name != "/" and m.state != "posted" + ): + move.name = "/" diff --git a/account_move_name_sequence/readme/CONFIGURE.rst b/account_move_name_sequence/readme/CONFIGURE.rst new file mode 100644 index 00000000000..1b4bf54bf1e --- /dev/null +++ b/account_move_name_sequence/readme/CONFIGURE.rst @@ -0,0 +1,3 @@ +On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal. + +On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds. diff --git a/account_move_name_sequence/readme/CONTRIBUTORS.rst b/account_move_name_sequence/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..ff65d68ce6d --- /dev/null +++ b/account_move_name_sequence/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Alexis de Lattre diff --git a/account_move_name_sequence/readme/DESCRIPTION.rst b/account_move_name_sequence/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..7ec4dd21973 --- /dev/null +++ b/account_move_name_sequence/readme/DESCRIPTION.rst @@ -0,0 +1,14 @@ +In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal. + +In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: + +* the available options for the sequence are limited, +* it is not possible to configure the sequence in advance before the deployment in production, +* as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, +* the `piece of code `_ that handle this is not easy to understand and quite difficult to debug. + +For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. + +The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used. + +The module removes access to the *Resequence* wizard on journal entries. diff --git a/account_move_name_sequence/security/ir.model.access.csv b/account_move_name_sequence/security/ir.model.access.csv new file mode 100644 index 00000000000..6247bc1e335 --- /dev/null +++ b/account_move_name_sequence/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +account.access_account_resequence,Remove rights on account.resequence.wizard,account.model_account_resequence_wizard,account.group_account_manager,0,0,0,0 diff --git a/account_move_name_sequence/tests/__init__.py b/account_move_name_sequence/tests/__init__.py new file mode 100644 index 00000000000..5de02aafcb0 --- /dev/null +++ b/account_move_name_sequence/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_move_name_seq diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py new file mode 100644 index 00000000000..1ba0f2ac7c7 --- /dev/null +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -0,0 +1,107 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from odoo import fields +from odoo.tests import tagged +from odoo.tests.common import TransactionCase + + +@tagged("post_install", "-at_install") +class TestAccountMoveNameSequence(TransactionCase): + def setUp(self): + super().setUp() + self.company = self.env.ref("base.main_company") + self.misc_journal = self.env["account.journal"].create( + { + "name": "Test Journal Move name seq", + "code": "ADLM", + "type": "general", + "company_id": self.company.id, + } + ) + self.purchase_journal = self.env["account.journal"].create( + { + "name": "Test Purchase Journal Move name seq", + "code": "ADLP", + "type": "purchase", + "company_id": self.company.id, + "refund_sequence": True, + } + ) + self.accounts = self.env["account.account"].search( + [("company_id", "=", self.company.id)], limit=2 + ) + self.account1 = self.accounts[0] + self.account2 = self.accounts[1] + self.date = datetime.now() + + def test_seq_creation(self): + self.assertTrue(self.misc_journal.sequence_id) + seq = self.misc_journal.sequence_id + self.assertEqual(seq.company_id, self.company) + self.assertEqual(seq.implementation, "no_gap") + self.assertEqual(seq.padding, 4) + self.assertTrue(seq.use_date_range) + self.assertTrue(self.purchase_journal.sequence_id) + self.assertTrue(self.purchase_journal.refund_sequence_id) + seq = self.purchase_journal.refund_sequence_id + self.assertEqual(seq.company_id, self.company) + self.assertEqual(seq.implementation, "no_gap") + self.assertEqual(seq.padding, 4) + self.assertTrue(seq.use_date_range) + + def test_misc_move_name(self): + move = self.env["account.move"].create( + { + "date": self.date, + "journal_id": self.misc_journal.id, + "line_ids": [ + (0, 0, {"account_id": self.account1.id, "debit": 10}), + (0, 0, {"account_id": self.account2.id, "credit": 10}), + ], + } + ) + self.assertEqual(move.name, "/") + move.action_post() + seq = self.misc_journal.sequence_id + move_name = "%s%s" % (seq.prefix, "1".zfill(seq.padding)) + move_name = move_name.replace("%(range_year)s", str(self.date.year)) + self.assertEqual(move.name, move_name) + self.assertTrue(seq.date_range_ids) + drange_count = self.env["ir.sequence.date_range"].search_count( + [ + ("sequence_id", "=", seq.id), + ("date_from", "=", fields.Date.add(self.date, month=1, day=1)), + ] + ) + self.assertEqual(drange_count, 1) + + def test_in_refund(self): + in_refund_invoice = self.env["account.move"].create( + { + "journal_id": self.purchase_journal.id, + "invoice_date": self.date, + "partner_id": self.env.ref("base.res_partner_3").id, + "move_type": "in_refund", + "invoice_line_ids": [ + ( + 0, + 0, + { + "account_id": self.account1.id, + "price_unit": 42.0, + "quantity": 12, + }, + ) + ], + } + ) + self.assertEqual(in_refund_invoice.name, "/") + in_refund_invoice.action_post() + seq = self.purchase_journal.refund_sequence_id + move_name = "%s%s" % (seq.prefix, "1".zfill(seq.padding)) + move_name = move_name.replace("%(range_year)s", str(self.date.year)) + self.assertEqual(in_refund_invoice.name, move_name) diff --git a/account_move_name_sequence/views/account_journal.xml b/account_move_name_sequence/views/account_journal.xml new file mode 100644 index 00000000000..8c557014a07 --- /dev/null +++ b/account_move_name_sequence/views/account_journal.xml @@ -0,0 +1,34 @@ + + + + + + account.journal + + + + + + + + + + + From a1ddd04181014a7c41ea7cbbe0e876a27a2c89a4 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 8 Sep 2021 14:21:43 +0200 Subject: [PATCH 02/58] sequence is now required on journals Add post-install script to create a sequence for all existing journals Update README accordingly --- account_move_name_sequence/__init__.py | 1 + account_move_name_sequence/__manifest__.py | 2 + .../models/account_journal.py | 1 + .../models/account_move.py | 55 ++++++++++++------- account_move_name_sequence/post_install.py | 25 +++++++++ .../readme/CONFIGURE.rst | 2 + .../tests/test_account_move_name_seq.py | 6 ++ .../views/account_journal.xml | 32 +++++------ .../views/account_move.xml | 33 +++++++++++ 9 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 account_move_name_sequence/post_install.py create mode 100644 account_move_name_sequence/views/account_move.xml diff --git a/account_move_name_sequence/__init__.py b/account_move_name_sequence/__init__.py index 0650744f6bc..f8149cf409f 100644 --- a/account_move_name_sequence/__init__.py +++ b/account_move_name_sequence/__init__.py @@ -1 +1,2 @@ +from .post_install import create_journal_sequences from . import models diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index b0b62405c37..2d131aab39c 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -14,7 +14,9 @@ "depends": ["account"], "data": [ "views/account_journal.xml", + "views/account_move.xml", "security/ir.model.access.csv", ], + "post_init_hook": "create_journal_sequences", "installable": True, } diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 2d616d009eb..a1e2014601e 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -13,6 +13,7 @@ class AccountJournal(models.Model): "ir.sequence", string="Entry Sequence", copy=False, + required=True, check_company=True, domain="[('company_id', '=', company_id)]", help="This sequence will be used to generate the journal entry number.", diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index 986d64dd1be..b090eb52b26 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -2,31 +2,44 @@ # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models +from odoo import api, fields, models class AccountMove(models.Model): _inherit = "account.move" - def _compute_name(self): - for move in self.filtered( - lambda m: (m.name == "/" or not m.name) - and m.state == "posted" - and m.journal_id - and m.journal_id.sequence_id - ): + name = fields.Char(compute="_compute_name_by_sequence") + # highest_name, sequence_prefix and sequence_number are not needed any more + # -> compute=False to improve perf + highest_name = fields.Char(compute=False) + sequence_prefix = fields.Char(compute=False) + sequence_number = fields.Integer(compute=False) + + @api.depends("state", "journal_id", "date") + def _compute_name_by_sequence(self): + for move in self: + name = move.name or "/" + # I can't use posted_before in this IF because + # posted_before is set to True in _post() at the same + # time as state is set to "posted" if ( - move.move_type in ("out_refund", "in_refund") - and move.journal_id.type in ("sale", "purchase") - and move.journal_id.refund_sequence - and move.journal_id.refund_sequence_id + move.state == "posted" + and (not move.name or move.name == "/") + and move.journal_id + and move.journal_id.sequence_id ): - seq = move.journal_id.refund_sequence_id - else: - seq = move.journal_id.sequence_id - move.name = seq.next_by_id(sequence_date=move.date) - super()._compute_name() - for move in self.filtered( - lambda m: m.name and m.name != "/" and m.state != "posted" - ): - move.name = "/" + if ( + move.move_type in ("out_refund", "in_refund") + and move.journal_id.type in ("sale", "purchase") + and move.journal_id.refund_sequence + and move.journal_id.refund_sequence_id + ): + seq = move.journal_id.refund_sequence_id + else: + seq = move.journal_id.sequence_id + name = seq.next_by_id(sequence_date=move.date) + move.name = name + + # We must by-pass this constraint of sequence.mixin + def _constrains_date_sequence(self): + return True diff --git a/account_move_name_sequence/post_install.py b/account_move_name_sequence/post_install.py new file mode 100644 index 00000000000..5384a8cb671 --- /dev/null +++ b/account_move_name_sequence/post_install.py @@ -0,0 +1,25 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api + + +def create_journal_sequences(cr, registry): + with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + journals = env["account.journal"].with_context(active_test=False).search([]) + for journal in journals: + vals = {} + journal_vals = { + "code": journal.code, + "name": journal.name, + "company_id": journal.company_id.id, + } + seq_vals = journal._prepare_sequence(journal_vals) + vals["sequence_id"] = env["ir.sequence"].create(seq_vals).id + if journal.type in ("sale", "purchase") and journal.refund_sequence: + rseq_vals = journal._prepare_sequence(journal_vals, refund=True) + vals["refund_sequence_id"] = env["ir.sequence"].create(rseq_vals).id + journal.write(vals) + return diff --git a/account_move_name_sequence/readme/CONFIGURE.rst b/account_move_name_sequence/readme/CONFIGURE.rst index 1b4bf54bf1e..b2998870acf 100644 --- a/account_move_name_sequence/readme/CONFIGURE.rst +++ b/account_move_name_sequence/readme/CONFIGURE.rst @@ -1,3 +1,5 @@ On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal. On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds. + +Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option *Dedicated Credit Note Sequence* on existing sale and purchase journals if you don't want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry. diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index 1ba0f2ac7c7..c6acf33c4ff 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -78,6 +78,9 @@ def test_misc_move_name(self): ] ) self.assertEqual(drange_count, 1) + move.button_draft() + move.action_post() + self.assertEqual(move.name, move_name) def test_in_refund(self): in_refund_invoice = self.env["account.move"].create( @@ -105,3 +108,6 @@ def test_in_refund(self): move_name = "%s%s" % (seq.prefix, "1".zfill(seq.padding)) move_name = move_name.replace("%(range_year)s", str(self.date.year)) self.assertEqual(in_refund_invoice.name, move_name) + in_refund_invoice.button_draft() + in_refund_invoice.action_post() + self.assertEqual(in_refund_invoice.name, move_name) diff --git a/account_move_name_sequence/views/account_journal.xml b/account_move_name_sequence/views/account_journal.xml index 8c557014a07..073d40be09f 100644 --- a/account_move_name_sequence/views/account_journal.xml +++ b/account_move_name_sequence/views/account_journal.xml @@ -6,29 +6,25 @@ --> - - account.journal - - - - + account.journal + + + + - - + + - - - + + + - + diff --git a/account_move_name_sequence/views/account_move.xml b/account_move_name_sequence/views/account_move.xml new file mode 100644 index 00000000000..cb9457315f3 --- /dev/null +++ b/account_move_name_sequence/views/account_move.xml @@ -0,0 +1,33 @@ + + + + + + account.move + + + + {'invisible': [('name', '=', '/')]} + + + {'readonly': 1} + + + {'invisible': 1} + + + + + From 21448f5391018e52c3770502949cdcbc70b4d70f Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Thu, 5 May 2022 15:18:14 +0000 Subject: [PATCH 03/58] [REF] account_move_name_sequence: Add number_next_actual and date range lines data based on current moves --- account_move_name_sequence/__manifest__.py | 4 +- .../models/account_journal.py | 158 +++++++++++++++++- account_move_name_sequence/post_install.py | 7 +- .../readme/CONTRIBUTORS.rst | 1 + .../views/account_journal.xml | 5 +- 5 files changed, 164 insertions(+), 11 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 2d131aab39c..1ce93e5f507 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -1,5 +1,7 @@ # Copyright 2021 Akretion France (http://www.akretion.com/) +# Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre +# @author: Moisés López # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { @@ -8,7 +10,7 @@ "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", - "author": "Akretion,Odoo Community Association (OCA)", + "author": "Akretion,Vauxoo,Odoo Community Association (OCA)", "maintainers": ["alexis-via"], "website": "https://github.com/OCA/account-financial-tools", "depends": ["account"], diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index a1e2014601e..740e01e94e7 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -1,10 +1,18 @@ # Copyright 2021 Akretion France (http://www.akretion.com/) +# Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre +# @author: Moisés López # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import logging + +from dateutil.relativedelta import relativedelta + from odoo import _, api, fields, models from odoo.exceptions import ValidationError +_logger = logging.getLogger(__name__) + class AccountJournal(models.Model): _inherit = "account.journal" @@ -13,16 +21,10 @@ class AccountJournal(models.Model): "ir.sequence", string="Entry Sequence", copy=False, - required=True, check_company=True, domain="[('company_id', '=', company_id)]", help="This sequence will be used to generate the journal entry number.", ) - refund_sequence = fields.Boolean( - string="Dedicated Credit Note Sequence", - default=True, - help="If enabled, you will be able to setup a sequence dedicated for refunds.", - ) refund_sequence_id = fields.Many2one( "ir.sequence", string="Credit Note Entry Sequence", @@ -31,6 +33,8 @@ class AccountJournal(models.Model): domain="[('company_id', '=', company_id)]", help="This sequence will be used to generate the journal entry number for refunds.", ) + # Redefine the default to True as <=v13.0 + refund_sequence = fields.Boolean(default=True) @api.constrains("refund_sequence_id", "sequence_id") def _check_journal_sequence(self): @@ -95,3 +99,145 @@ def _prepare_sequence(self, vals, refund=False): def _create_sequence(self, vals, refund=False): seq_vals = self._prepare_sequence(vals, refund=refund) return self.env["ir.sequence"].sudo().create(seq_vals) + + def _prepare_sequence_current_moves(self, refund=False): + """Get sequence dict values the journal based on current moves""" + self.ensure_one() + move_domain = [ + ("journal_id", "=", self.id), + ("name", "!=", "/"), + ] + if self.refund_sequence: + #  Based on original Odoo behavior + if refund: + move_domain.append(("move_type", "in", ("out_refund", "in_refund"))) + else: + move_domain.append(("move_type", "not in", ("out_refund", "in_refund"))) + last_move = self.env["account.move"].search( + move_domain, limit=1, order="id DESC" + ) + msg_err = ( + "Journal %s could not get sequence %s values based on current moves. " + "Using default values." % (self.id, refund and "refund" or "") + ) + if not last_move: + _logger.warning("%s %s", msg_err, "No moves found") + return {} + try: + with self.env.cr.savepoint(): + # get the current sequence values could be buggy to get + # But even we can use the default values + # or do manual changes instead of raising errors + last_sequence = last_move._get_last_sequence() + if not last_sequence: + last_sequence = ( + last_move._get_last_sequence(relaxed=True) + or last_move._get_starting_sequence() + ) + + __, seq_format_values = last_move._get_sequence_format_param( + last_sequence + ) + prefix1 = seq_format_values["prefix1"] + prefix = prefix1 + if seq_format_values["year_length"] == 4: + prefix += "%(range_year)s" + elif seq_format_values["year_length"] == 2: + prefix += "%(range_y)s" + else: + # If there is not year so current values are valid + seq_vals = { + "padding": seq_format_values["seq_length"], + "suffix": seq_format_values["suffix"], + "prefix": prefix, + "date_range_ids": [], + "use_date_range": False, + "number_next_actual": seq_format_values["seq"] + 1, + } + return seq_vals + prefix2 = seq_format_values.get("prefix2") or "" + prefix += prefix2 + month = seq_format_values.get("month") # It is 0 if only have year + if month: + prefix += "%(range_month)s" + prefix3 = seq_format_values.get("prefix3") or "" + where_name_value = "%s%s%s%s%s%%" % ( + prefix1, + "_" * seq_format_values["year_length"], + prefix2, + "_" * bool(month) * 2, + prefix3, + ) + prefixes = prefix1 + prefix2 + select_year = ( + "split_part(name, '%s', %d)" % (prefix2, prefixes.count(prefix2)) + if prefix2 + else "''" + ) + prefixes += prefix3 + select_month = ( + "split_part(name, '%s', %d)" % (prefix3, prefixes.count(prefix3)) + if prefix3 + else "''" + ) + select_max_number = ( + "MAX(split_part(name, '%s', %d)::INTEGER) AS max_number" + % (prefixes[-1], prefixes.count(prefixes[-1]) + 1) + ) + query = ( + "SELECT %s, %s, %s FROM account_move " + "WHERE name LIKE %%s AND journal_id=%%s GROUP BY 1,2" + ) % ( + select_year, + select_month, + select_max_number, + ) + # It is not using user input + # pylint: disable=sql-injection + self.env.cr.execute(query, (where_name_value, self.id)) + res = self.env.cr.fetchall() + prefix += prefix3 + seq_vals = { + "padding": seq_format_values["seq_length"], + "suffix": seq_format_values["suffix"], + "prefix": prefix, + "date_range_ids": [], + "use_date_range": True, + } + for year, month, max_number in res: + if not year and not month: + seq_vals.update( + { + "use_date_range": False, + "number_next_actual": max_number + 1, + } + ) + continue + if len(year) == 2: + # Year >=50 will be considered as last century 1950 + # Year <=49 will be considered as current century 2049 + if int(year) >= 50: + year = "19" + year + else: + year = "20" + year + if month: + date_from = fields.Date.to_date("%s-%s-1" % (year, month)) + date_to = date_from + relativedelta(day=31) + else: + date_from = fields.Date.to_date("%s-1-1" % year) + date_to = fields.Date.to_date("%s-12-31" % year) + seq_vals["date_range_ids"].append( + ( + 0, + 0, + { + "date_from": date_from, + "date_to": date_to, + "number_next_actual": max_number + 1, + }, + ) + ) + return seq_vals + except Exception as e: + _logger.warning("%s %s", msg_err, e) + return {} diff --git a/account_move_name_sequence/post_install.py b/account_move_name_sequence/post_install.py index 5384a8cb671..b4f8b9971c1 100644 --- a/account_move_name_sequence/post_install.py +++ b/account_move_name_sequence/post_install.py @@ -1,5 +1,7 @@ # Copyright 2021 Akretion France (http://www.akretion.com/) +# Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre +# @author: Moisés López # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import SUPERUSER_ID, api @@ -10,16 +12,17 @@ def create_journal_sequences(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) journals = env["account.journal"].with_context(active_test=False).search([]) for journal in journals: - vals = {} journal_vals = { "code": journal.code, "name": journal.name, "company_id": journal.company_id.id, } seq_vals = journal._prepare_sequence(journal_vals) - vals["sequence_id"] = env["ir.sequence"].create(seq_vals).id + seq_vals.update(journal._prepare_sequence_current_moves()) + vals = {"sequence_id": env["ir.sequence"].create(seq_vals).id} if journal.type in ("sale", "purchase") and journal.refund_sequence: rseq_vals = journal._prepare_sequence(journal_vals, refund=True) + rseq_vals.update(journal._prepare_sequence_current_moves(refund=True)) vals["refund_sequence_id"] = env["ir.sequence"].create(rseq_vals).id journal.write(vals) return diff --git a/account_move_name_sequence/readme/CONTRIBUTORS.rst b/account_move_name_sequence/readme/CONTRIBUTORS.rst index ff65d68ce6d..c3f90701445 100644 --- a/account_move_name_sequence/readme/CONTRIBUTORS.rst +++ b/account_move_name_sequence/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Alexis de Lattre +* Moisés López diff --git a/account_move_name_sequence/views/account_journal.xml b/account_move_name_sequence/views/account_journal.xml index 073d40be09f..6cc643a7369 100644 --- a/account_move_name_sequence/views/account_journal.xml +++ b/account_move_name_sequence/views/account_journal.xml @@ -14,14 +14,15 @@ From ed40f611d1df4f2d5f630f4b68675bbb47048fd5 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Tue, 10 May 2022 20:10:29 +0000 Subject: [PATCH 04/58] [FIX] ir_sequence: Fix creating date_range_seq with range_month and range_day More info about: - https://github.com/odoo/odoo/pull/91019 TODO: Revert this commit after it is merged --- account_move_name_sequence/models/__init__.py | 1 + .../models/ir_sequence.py | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 account_move_name_sequence/models/ir_sequence.py diff --git a/account_move_name_sequence/models/__init__.py b/account_move_name_sequence/models/__init__.py index 067db8c5faa..069c9b592b7 100644 --- a/account_move_name_sequence/models/__init__.py +++ b/account_move_name_sequence/models/__init__.py @@ -1,2 +1,3 @@ from . import account_journal from . import account_move +from . import ir_sequence diff --git a/account_move_name_sequence/models/ir_sequence.py b/account_move_name_sequence/models/ir_sequence.py new file mode 100644 index 00000000000..c7ee985f669 --- /dev/null +++ b/account_move_name_sequence/models/ir_sequence.py @@ -0,0 +1,58 @@ +from dateutil.relativedelta import relativedelta + +from odoo import fields, models + + +class IrSequence(models.Model): + _inherit = "ir.sequence" + + def _create_date_range_seq(self, date): + # Fix issue creating new date range for future dates + # It assigns more than one month + # TODO: Remove if odoo merge the following PR: + # https://github.com/odoo/odoo/pull/91019 + date_obj = fields.Date.from_string(date) + prefix_suffix = "%s %s" % (self.prefix, self.suffix) + if "%(range_day)s" in prefix_suffix: + date_from = date_obj + date_to = date_obj + elif "%(range_month)s" in prefix_suffix: + date_from = date_obj + relativedelta(day=1) + date_to = date_obj + relativedelta(day=31) + else: + date_from = date_obj + relativedelta(day=1, month=1) + date_to = date_obj + relativedelta(day=31, month=12) + date_range = self.env["ir.sequence.date_range"].search( + [ + ("sequence_id", "=", self.id), + ("date_from", ">=", date), + ("date_from", "<=", date_to), + ], + order="date_from desc", + limit=1, + ) + if date_range: + date_to = date_range.date_from + relativedelta(days=-1) + date_range = self.env["ir.sequence.date_range"].search( + [ + ("sequence_id", "=", self.id), + ("date_to", ">=", date_from), + ("date_to", "<=", date), + ], + order="date_to desc", + limit=1, + ) + if date_range: + date_from = date_range.date_to + relativedelta(days=1) + seq_date_range = ( + self.env["ir.sequence.date_range"] + .sudo() + .create( + { + "date_from": date_from, + "date_to": date_to, + "sequence_id": self.id, + } + ) + ) + return seq_date_range From eb2533f1e048a741f842336b3a85cab0cc4880b1 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Wed, 11 May 2022 17:18:36 +0000 Subject: [PATCH 05/58] [REF] account_move_name_sequence: Discard journals already configured --- account_move_name_sequence/README.rst | 106 ++++- .../i18n/account_move_name_sequence.pot | 141 ++++++ account_move_name_sequence/post_install.py | 6 +- .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 440 ++++++++++++++++++ 5 files changed, 691 insertions(+), 2 deletions(-) create mode 100644 account_move_name_sequence/i18n/account_move_name_sequence.pot create mode 100644 account_move_name_sequence/static/description/icon.png create mode 100644 account_move_name_sequence/static/description/index.html diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 2627cab222e..fe18caeb088 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -1 +1,105 @@ -Will be auto-generated from the readme subdir +============================ +Account Move Number Sequence +============================ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Faccount--financial--tools-lightgray.png?logo=github + :target: https://github.com/OCA/account-financial-tools/tree/14.0/account_move_name_sequence + :alt: OCA/account-financial-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-financial-tools-14-0/account-financial-tools-14-0-account_move_name_sequence + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/92/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal. + +In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: + +* the available options for the sequence are limited, +* it is not possible to configure the sequence in advance before the deployment in production, +* as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, +* the `piece of code `_ that handle this is not easy to understand and quite difficult to debug. + +For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. + +The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used. + +The module removes access to the *Resequence* wizard on journal entries. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal. + +On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds. + +Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option *Dedicated Credit Note Sequence* on existing sale and purchase journals if you don't want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry. + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Akretion +* Vauxoo + +Contributors +~~~~~~~~~~~~ + +* Alexis de Lattre +* Moisés López + +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. + +.. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px + :target: https://github.com/alexis-via + :alt: alexis-via + +Current `maintainer `__: + +|maintainer-alexis-via| + +This module is part of the `OCA/account-financial-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_name_sequence/i18n/account_move_name_sequence.pot b/account_move_name_sequence/i18n/account_move_name_sequence.pot new file mode 100644 index 00000000000..fdc841027e2 --- /dev/null +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -0,0 +1,141 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_name_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.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" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence +msgid "" +"Check this box if you don't want to share the same sequence for invoices and" +" credit notes made from this journal" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "Credit Note Entry Sequence" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence +msgid "Dedicated Credit Note Sequence" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name +msgid "Display Name" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id +msgid "Entry Sequence" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name +msgid "Highest Name" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id +#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id +msgid "ID" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_journal +msgid "Journal" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal____last_update +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update +#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update +msgid "Last Modified on" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__name +msgid "Number" +msgstr "" + +#. module: account_move_name_sequence +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" +" Entry Sequence." +msgstr "" + +#. module: account_move_name_sequence +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "Refund" +msgstr "" + +#. module: account_move_name_sequence +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#: model:ir.model,name:account_move_name_sequence.model_ir_sequence +#, python-format +msgid "Sequence" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number +msgid "Sequence Number" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix +msgid "Sequence Prefix" +msgstr "" + +#. module: account_move_name_sequence +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%s' configured as credit note sequence " +"of journal '%s'." +msgstr "" + +#. module: account_move_name_sequence +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "The company is not set on sequence '%s' configured on journal '%s'." +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "" +"This sequence will be used to generate the journal entry number for refunds." +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id +msgid "This sequence will be used to generate the journal entry number." +msgstr "" diff --git a/account_move_name_sequence/post_install.py b/account_move_name_sequence/post_install.py index b4f8b9971c1..807e4aa67e0 100644 --- a/account_move_name_sequence/post_install.py +++ b/account_move_name_sequence/post_install.py @@ -10,7 +10,11 @@ def create_journal_sequences(cr, registry): with api.Environment.manage(): env = api.Environment(cr, SUPERUSER_ID, {}) - journals = env["account.journal"].with_context(active_test=False).search([]) + journals = ( + env["account.journal"] + .with_context(active_test=False) + .search([("sequence_id", "!=", False)]) + ) for journal in journals: journal_vals = { "code": journal.code, diff --git a/account_move_name_sequence/static/description/icon.png b/account_move_name_sequence/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html new file mode 100644 index 00000000000..5b60fcff59e --- /dev/null +++ b/account_move_name_sequence/static/description/index.html @@ -0,0 +1,440 @@ + + + + + + +Account Move Number Sequence + + + +
+

Account Move Number Sequence

+ + +

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

+

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

+

In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks:

+
    +
  • the available options for the sequence are limited,
  • +
  • it is not possible to configure the sequence in advance before the deployment in production,
  • +
  • as it is error-prone, they added a Resequence wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries,
  • +
  • the piece of code that handle this is not easy to understand and quite difficult to debug.
  • +
+

For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare.

+

The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used.

+

The module removes access to the Resequence wizard on journal entries.

+

Table of contents

+ +
+

Configuration

+

On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal.

+

On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds.

+

Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option Dedicated Credit Note Sequence on existing sale and purchase journals if you don’t want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry.

+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
  • Vauxoo
  • +
+
+
+

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.

+

Current maintainer:

+

alexis-via

+

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

+

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

+
+
+
+ + From f5bc4bc657bccfca74e1fa13dd7fd4c3c749f122 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Fri, 13 May 2022 15:34:58 +0000 Subject: [PATCH 06/58] [FIX] account_move_name_sequence: Fix sequence domain to assign only if it is empty --- account_move_name_sequence/__manifest__.py | 2 +- account_move_name_sequence/post_install.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 1ce93e5f507..ff92d0b58da 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Account Move Number Sequence", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/post_install.py b/account_move_name_sequence/post_install.py index 807e4aa67e0..ef52eeeb4c9 100644 --- a/account_move_name_sequence/post_install.py +++ b/account_move_name_sequence/post_install.py @@ -13,7 +13,7 @@ def create_journal_sequences(cr, registry): journals = ( env["account.journal"] .with_context(active_test=False) - .search([("sequence_id", "!=", False)]) + .search([("sequence_id", "=", False)]) ) for journal in journals: journal_vals = { From 54cddb787f0424d9e9cfa8547d5c394175c3432c Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Fri, 13 May 2022 16:14:51 +0000 Subject: [PATCH 07/58] [REF] account_move_name_sequence: Moves with name '/' can not be posted After remove required=True for journal.sequence_id field it is possible to post an invoice with misconfigured journal with empty sequence So, this constraint will raise an error for this kind of cases since that using '/' could raise the unique constraint for all other moves --- account_move_name_sequence/__manifest__.py | 2 +- .../i18n/account_move_name_sequence.pot | 7 +++++++ account_move_name_sequence/models/account_move.py | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index ff92d0b58da..3a836fbd63b 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Account Move Number Sequence", - "version": "14.0.1.0.1", + "version": "14.0.1.1.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/i18n/account_move_name_sequence.pot b/account_move_name_sequence/i18n/account_move_name_sequence.pot index fdc841027e2..395f8e187d9 100644 --- a/account_move_name_sequence/i18n/account_move_name_sequence.pot +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -13,6 +13,13 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: account_move_name_sequence +#: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal +msgid "" +"A move can not be posted with name \"/\" or empty value\n" +"Check the journal sequence, please" +msgstr "" + #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence msgid "" diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index b090eb52b26..ff1dbc7599d 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -15,6 +15,15 @@ class AccountMove(models.Model): sequence_prefix = fields.Char(compute=False) sequence_number = fields.Integer(compute=False) + _sql_constraints = [ + ( + "name_state_diagonal", + "CHECK(COALESCE(name, '') NOT IN ('/', '') OR state!='posted')", + 'A move can not be posted with name "/" or empty value\n' + "Check the journal sequence, please", + ), + ] + @api.depends("state", "journal_id", "date") def _compute_name_by_sequence(self): for move in self: From e6f8198e0ab497aa65d1a6a5edc2c917cead3849 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Fri, 13 May 2022 17:14:30 +0000 Subject: [PATCH 08/58] [FIX] account_move_name_sequence: Fix required journal fields in view The required flag was wrong for sequence_id and refund_sequence_id So, it was not possible to store any change in journal for journal different to sale and purchase --- account_move_name_sequence/__manifest__.py | 2 +- account_move_name_sequence/views/account_journal.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 3a836fbd63b..a4960cd8361 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Account Move Number Sequence", - "version": "14.0.1.1.0", + "version": "14.0.1.2.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/views/account_journal.xml b/account_move_name_sequence/views/account_journal.xml index 6cc643a7369..d274975a626 100644 --- a/account_move_name_sequence/views/account_journal.xml +++ b/account_move_name_sequence/views/account_journal.xml @@ -13,15 +13,15 @@ From a8a7f537709eabf8777b3fb6238124f1325e37f4 Mon Sep 17 00:00:00 2001 From: Moises Lopez Date: Fri, 13 May 2022 17:46:35 +0000 Subject: [PATCH 09/58] [REF] account_move_name_sequence: Add maintainers to myself --- account_move_name_sequence/README.rst | 7 +++++-- account_move_name_sequence/__manifest__.py | 2 +- account_move_name_sequence/static/description/index.html | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index fe18caeb088..7a704a40136 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -95,10 +95,13 @@ promote its widespread use. .. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px :target: https://github.com/alexis-via :alt: alexis-via +.. |maintainer-moylop260| image:: https://github.com/moylop260.png?size=40px + :target: https://github.com/moylop260 + :alt: moylop260 -Current `maintainer `__: +Current `maintainers `__: -|maintainer-alexis-via| +|maintainer-alexis-via| |maintainer-moylop260| This module is part of the `OCA/account-financial-tools `_ project on GitHub. diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index a4960cd8361..46f9835b7cd 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -11,7 +11,7 @@ "license": "AGPL-3", "summary": "Generate journal entry number from sequence", "author": "Akretion,Vauxoo,Odoo Community Association (OCA)", - "maintainers": ["alexis-via"], + "maintainers": ["alexis-via", "moylop260"], "website": "https://github.com/OCA/account-financial-tools", "depends": ["account"], "data": [ diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 5b60fcff59e..adccba01ca4 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -429,8 +429,8 @@

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.

-

Current maintainer:

-

alexis-via

+

Current maintainers:

+

alexis-via moylop260

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

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

From 7c2b1f51baae7994855e87976f5c1f098159c535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20L=C3=B3pez?= Date: Thu, 19 May 2022 16:05:34 -0500 Subject: [PATCH 10/58] [REF] account_move_name_sequence: Adding concurrency cases in README --- account_move_name_sequence/README.rst | 54 ++++++++++++- account_move_name_sequence/__manifest__.py | 2 +- .../readme/DESCRIPTION.rst | 54 ++++++++++++- .../static/description/index.html | 75 +++++++++++++++---- 4 files changed, 163 insertions(+), 22 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 7a704a40136..07ddb325507 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -27,14 +27,62 @@ Account Move Number Sequence In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal. -In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: +In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for the next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: * the available options for the sequence are limited, * it is not possible to configure the sequence in advance before the deployment in production, * as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, -* the `piece of code `_ that handle this is not easy to understand and quite difficult to debug. +* the `piece of code `_ that handles this is not easy to understand and quite difficult to debug. -For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. +Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck +Even if you only are creating a draft journal entry it locks the last one +It applies to all accounting Journal Entries + +e.g. + + - Customer Invoices + - Credit Notes + - Customer Payments + - Vendor Bills + - Vendor Refunds + - Vendor Payment + - Manual Journal Entries + +Then, the following concurrency errors are being raised now frequently: + +* Editing the last record used to get the new number from another process +* Creating a new draft invoice/payment (not only when posting it) +* Creating a transaction to create an invoice then payment or vice versa raises a deadlock error +* Reconciling the last record it could be a heavy process +* Creating 2 or more Invoices/Bills at the same time +* Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard) +* Creating 2 or more Journal Entries at the same time + + +All these increases in concurrency errors bring more issues since that Odoo is not prepared: + +* Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges +* Using `subscription_template.payment_mode=success_payment` you will see subscriptions with tag "payment exception" +* Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user +* The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance + +The new accounting number is a significant bottleneck + +.. image:: https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 + + +If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0: + + - Passing unittest for `13.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ + - Concurrency errors for `14.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ + - `Stress testing and issue reported to Odoo `_ + - `[BUG] account: Concurrency errors increased considerably in account.move for Odoo>=v14.0 #91873 `_ + + +Using this module, you can configure what kind of documents the gap sequence may be relaxed +And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record + +For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who considers that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used. diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 46f9835b7cd..1f2f54aa5c4 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Account Move Number Sequence", - "version": "14.0.1.2.0", + "version": "14.0.1.2.1", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/readme/DESCRIPTION.rst b/account_move_name_sequence/readme/DESCRIPTION.rst index 7ec4dd21973..9bbf7306f59 100644 --- a/account_move_name_sequence/readme/DESCRIPTION.rst +++ b/account_move_name_sequence/readme/DESCRIPTION.rst @@ -1,13 +1,61 @@ In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal. -In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: +In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for the next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks: * the available options for the sequence are limited, * it is not possible to configure the sequence in advance before the deployment in production, * as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, -* the `piece of code `_ that handle this is not easy to understand and quite difficult to debug. +* the `piece of code `_ that handles this is not easy to understand and quite difficult to debug. -For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. +Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck +Even if you only are creating a draft journal entry it locks the last one +It applies to all accounting Journal Entries + +e.g. + + - Customer Invoices + - Credit Notes + - Customer Payments + - Vendor Bills + - Vendor Refunds + - Vendor Payment + - Manual Journal Entries + +Then, the following concurrency errors are being raised now frequently: + +* Editing the last record used to get the new number from another process +* Creating a new draft invoice/payment (not only when posting it) +* Creating a transaction to create an invoice then payment or vice versa raises a deadlock error +* Reconciling the last record it could be a heavy process +* Creating 2 or more Invoices/Bills at the same time +* Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard) +* Creating 2 or more Journal Entries at the same time + + +All these increases in concurrency errors bring more issues since that Odoo is not prepared: + +* Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges +* Using `subscription_template.payment_mode=success_payment` you will see subscriptions with tag "payment exception" +* Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user +* The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance + +The new accounting number is a significant bottleneck + +.. image:: https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 + + +If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0: + + - Passing unittest for `13.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ + - Concurrency errors for `14.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ + - `Stress testing and issue reported to Odoo `_ + - `[BUG] account: Concurrency errors increased considerably in account.move for Odoo>=v14.0 #91873 `_ + + +Using this module, you can configure what kind of documents the gap sequence may be relaxed +And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record + +For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who considers that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare. The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used. diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index adccba01ca4..1f7fcb0135d 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -369,37 +369,82 @@

Account Move Number Sequence

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

-

In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks:

+

In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for the next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks:

  • the available options for the sequence are limited,
  • it is not possible to configure the sequence in advance before the deployment in production,
  • as it is error-prone, they added a Resequence wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries,
  • -
  • the piece of code that handle this is not easy to understand and quite difficult to debug.
  • +
  • the piece of code that handles this is not easy to understand and quite difficult to debug.
-

For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who consider that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare.

+

Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck +Even if you only are creating a draft journal entry it locks the last one +It applies to all accounting Journal Entries

+

e.g.

+
+
    +
  • Customer Invoices
  • +
  • Credit Notes
  • +
  • Customer Payments
  • +
  • Vendor Bills
  • +
  • Vendor Refunds
  • +
  • Vendor Payment
  • +
  • Manual Journal Entries
  • +
+
+

Then, the following concurrency errors are being raised now frequently:

+
    +
  • Editing the last record used to get the new number from another process
  • +
  • Creating a new draft invoice/payment (not only when posting it)
  • +
  • Creating a transaction to create an invoice then payment or vice versa raises a deadlock error
  • +
  • Reconciling the last record it could be a heavy process
  • +
  • Creating 2 or more Invoices/Bills at the same time
  • +
  • Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard)
  • +
  • Creating 2 or more Journal Entries at the same time
  • +
+

All these increases in concurrency errors bring more issues since that Odoo is not prepared:

+
    +
  • Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges
  • +
  • Using subscription_template.payment_mode=success_payment you will see subscriptions with tag “payment exception”
  • +
  • Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user
  • +
  • The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance
  • +
+

The new accounting number is a significant bottleneck

+https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 +

If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0:

+
+ +
+

Using this module, you can configure what kind of documents the gap sequence may be relaxed +And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record

+

For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who considers that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare.

The field names used in this module to configure the sequence on the journal are exactly the same as in Odoo version 13.0 and previous versions. That way, if you migrate to Odoo version 14.0 and you install this module immediately after the migration, you should keep the previous behavior and the same sequences will continue to be used.

The module removes access to the Resequence wizard on journal entries.

Table of contents

-

Configuration

+

Configuration

On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal.

On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds.

Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option Dedicated Credit Note Sequence on existing sale and purchase journals if you don’t want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry.

-

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 smashing it by providing a detailed and welcomed @@ -407,23 +452,23 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
  • Vauxoo
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

OCA, or the Odoo Community Association, is a nonprofit organization whose From bb974cb99335600a9da3a41dfe968c9bfe7a2fc6 Mon Sep 17 00:00:00 2001 From: Francisco Javier Luna Vazquez Date: Thu, 26 May 2022 09:26:12 -0500 Subject: [PATCH 11/58] [REF] account_move_name_sequence: Use Odoo native methods + Typos --- account_move_name_sequence/README.rst | 8 +++-- account_move_name_sequence/__manifest__.py | 9 +++-- .../models/account_journal.py | 4 +-- .../models/ir_sequence.py | 36 ++++++++----------- .../readme/CONFIGURE.rst | 2 +- .../readme/CONTRIBUTORS.rst | 1 + .../static/description/index.html | 5 +-- .../views/account_journal.xml | 2 ++ .../views/account_move.xml | 18 +++++----- 9 files changed, 43 insertions(+), 42 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 07ddb325507..8811eb96f8b 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -98,7 +98,7 @@ Configuration On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal. -On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds. +On sale and purchase journals, you have an additional option to have another sequence dedicated to refunds. Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option *Dedicated Credit Note Sequence* on existing sale and purchase journals if you don't want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry. @@ -126,6 +126,7 @@ Contributors * Alexis de Lattre * Moisés López +* Francisco Luna Maintainers ~~~~~~~~~~~ @@ -146,10 +147,13 @@ promote its widespread use. .. |maintainer-moylop260| image:: https://github.com/moylop260.png?size=40px :target: https://github.com/moylop260 :alt: moylop260 +.. |maintainer-frahikLV| image:: https://github.com/frahikLV.png?size=40px + :target: https://github.com/frahikLV + :alt: frahikLV Current `maintainers `__: -|maintainer-alexis-via| |maintainer-moylop260| +|maintainer-alexis-via| |maintainer-moylop260| |maintainer-frahikLV| This module is part of the `OCA/account-financial-tools `_ project on GitHub. diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 1f2f54aa5c4..46ab257aad4 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -2,18 +2,21 @@ # Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre # @author: Moisés López +# @author: Francisco Luna # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Account Move Number Sequence", - "version": "14.0.1.2.1", + "version": "14.0.1.2.2", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", "author": "Akretion,Vauxoo,Odoo Community Association (OCA)", - "maintainers": ["alexis-via", "moylop260"], + "maintainers": ["alexis-via", "moylop260", "frahikLV"], "website": "https://github.com/OCA/account-financial-tools", - "depends": ["account"], + "depends": [ + "account", + ], "data": [ "views/account_journal.xml", "views/account_move.xml", diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 740e01e94e7..41755ee1ed7 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -6,8 +6,6 @@ import logging -from dateutil.relativedelta import relativedelta - from odoo import _, api, fields, models from odoo.exceptions import ValidationError @@ -222,7 +220,7 @@ def _prepare_sequence_current_moves(self, refund=False): year = "20" + year if month: date_from = fields.Date.to_date("%s-%s-1" % (year, month)) - date_to = date_from + relativedelta(day=31) + date_to = fields.Date.end_of(date_from, "month") else: date_from = fields.Date.to_date("%s-1-1" % year) date_to = fields.Date.to_date("%s-12-31" % year) diff --git a/account_move_name_sequence/models/ir_sequence.py b/account_move_name_sequence/models/ir_sequence.py index c7ee985f669..7dc7d265607 100644 --- a/account_move_name_sequence/models/ir_sequence.py +++ b/account_move_name_sequence/models/ir_sequence.py @@ -1,5 +1,3 @@ -from dateutil.relativedelta import relativedelta - from odoo import fields, models @@ -12,17 +10,18 @@ def _create_date_range_seq(self, date): # TODO: Remove if odoo merge the following PR: # https://github.com/odoo/odoo/pull/91019 date_obj = fields.Date.from_string(date) + sequence_range = self.env["ir.sequence.date_range"] prefix_suffix = "%s %s" % (self.prefix, self.suffix) if "%(range_day)s" in prefix_suffix: date_from = date_obj date_to = date_obj elif "%(range_month)s" in prefix_suffix: - date_from = date_obj + relativedelta(day=1) - date_to = date_obj + relativedelta(day=31) + date_from = fields.Date.start_of(date_obj, "month") + date_to = fields.Date.end_of(date_obj, "month") else: - date_from = date_obj + relativedelta(day=1, month=1) - date_to = date_obj + relativedelta(day=31, month=12) - date_range = self.env["ir.sequence.date_range"].search( + date_from = fields.Date.start_of(date_obj, "year") + date_to = fields.Date.end_of(date_obj, "year") + date_range = sequence_range.search( [ ("sequence_id", "=", self.id), ("date_from", ">=", date), @@ -32,8 +31,8 @@ def _create_date_range_seq(self, date): limit=1, ) if date_range: - date_to = date_range.date_from + relativedelta(days=-1) - date_range = self.env["ir.sequence.date_range"].search( + date_to = fields.Date.subtract(date_range.date_from, days=1) + date_range = sequence_range.search( [ ("sequence_id", "=", self.id), ("date_to", ">=", date_from), @@ -43,16 +42,11 @@ def _create_date_range_seq(self, date): limit=1, ) if date_range: - date_from = date_range.date_to + relativedelta(days=1) - seq_date_range = ( - self.env["ir.sequence.date_range"] - .sudo() - .create( - { - "date_from": date_from, - "date_to": date_to, - "sequence_id": self.id, - } - ) - ) + date_to = fields.Date.add(date_range.date_to, days=1) + sequence_range_vals = { + "date_from": date_from, + "date_to": date_to, + "sequence_id": self.id, + } + seq_date_range = sequence_range.sudo().create(sequence_range_vals) return seq_date_range diff --git a/account_move_name_sequence/readme/CONFIGURE.rst b/account_move_name_sequence/readme/CONFIGURE.rst index b2998870acf..830a5389e5a 100644 --- a/account_move_name_sequence/readme/CONFIGURE.rst +++ b/account_move_name_sequence/readme/CONFIGURE.rst @@ -1,5 +1,5 @@ On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal. -On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds. +On sale and purchase journals, you have an additional option to have another sequence dedicated to refunds. Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option *Dedicated Credit Note Sequence* on existing sale and purchase journals if you don't want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry. diff --git a/account_move_name_sequence/readme/CONTRIBUTORS.rst b/account_move_name_sequence/readme/CONTRIBUTORS.rst index c3f90701445..3e8712428e2 100644 --- a/account_move_name_sequence/readme/CONTRIBUTORS.rst +++ b/account_move_name_sequence/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Alexis de Lattre * Moisés López +* Francisco Luna diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 1f7fcb0135d..14a7905a9a7 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -440,7 +440,7 @@

Account Move Number Sequence

Configuration

On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal.

-

On sale and purchase journals, you have an additionnal option to have another sequence dedicated to refunds.

+

On sale and purchase journals, you have an additional option to have another sequence dedicated to refunds.

Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option Dedicated Credit Note Sequence on existing sale and purchase journals if you don’t want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry.

@@ -465,6 +465,7 @@

Contributors

@@ -475,7 +476,7 @@

Maintainers

mission is to support the collaborative development of Odoo features and promote its widespread use.

Current maintainers:

-

alexis-via moylop260

+

alexis-via moylop260 frahikLV

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

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

diff --git a/account_move_name_sequence/views/account_journal.xml b/account_move_name_sequence/views/account_journal.xml index d274975a626..e0a28adc1fc 100644 --- a/account_move_name_sequence/views/account_journal.xml +++ b/account_move_name_sequence/views/account_journal.xml @@ -2,6 +2,8 @@ diff --git a/account_move_name_sequence/views/account_move.xml b/account_move_name_sequence/views/account_move.xml index cb9457315f3..2536e906682 100644 --- a/account_move_name_sequence/views/account_move.xml +++ b/account_move_name_sequence/views/account_move.xml @@ -10,23 +10,21 @@ account.move - - {'invisible': [('name', '=', '/')]} - - {'invisible': [('name', '=', '/')]} + + - {'readonly': 1} - - + {'readonly': 1} + + {'invisible': 1} - + From 18ef8f2b6c032169a5b2c427443ec05c50c6df58 Mon Sep 17 00:00:00 2001 From: Francisco Javier Luna Vazquez Date: Thu, 26 May 2022 16:20:43 -0500 Subject: [PATCH 12/58] [MIG] account_move_name_sequence: Migration to 15.0 --- account_move_name_sequence/__manifest__.py | 2 +- .../models/account_journal.py | 34 ++++++++------- account_move_name_sequence/post_install.py | 42 +++++++++---------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 46ab257aad4..de8ebb9b79a 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "14.0.1.2.2", + "version": "15.0.1.0.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 41755ee1ed7..9038ec2a230 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -2,6 +2,7 @@ # Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre # @author: Moisés López +# @author: Francisco Luna # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging @@ -45,26 +46,26 @@ def _check_journal_sequence(self): raise ValidationError( _( "On journal '%s', the same sequence is used as " - "Entry Sequence and Credit Note Entry Sequence." + "Entry Sequence and Credit Note Entry Sequence.", + journal.display_name, ) - % journal.display_name ) if journal.sequence_id and not journal.sequence_id.company_id: - raise ValidationError( - _( - "The company is not set on sequence '%s' configured on " - "journal '%s'." - ) - % (journal.sequence_id.display_name, journal.display_name) + msg = _( + "The company is not set on sequence '%(sequence)s' configured on " + "journal '%(journal)s'.", + sequence=journal.sequence_id.display_name, + journal=journal.display_name, ) + raise ValidationError(msg) if journal.refund_sequence_id and not journal.refund_sequence_id.company_id: - raise ValidationError( - _( - "The company is not set on sequence '%s' configured as " - "credit note sequence of journal '%s'." - ) - % (journal.refund_sequence_id.display_name, journal.display_name) + msg = _( + "The company is not set on sequence '%(sequence)s' configured as " + "credit note sequence of journal '%(journal)s'.", + sequence=journal.refund_sequence_id.display_name, + journal=journal.display_name, ) + raise ValidationError(msg) @api.model def create(self, vals): @@ -180,7 +181,10 @@ def _prepare_sequence_current_moves(self, refund=False): ) select_max_number = ( "MAX(split_part(name, '%s', %d)::INTEGER) AS max_number" - % (prefixes[-1], prefixes.count(prefixes[-1]) + 1) + % ( + prefixes[-1], + prefixes.count(prefixes[-1]) + 1, + ) ) query = ( "SELECT %s, %s, %s FROM account_move " diff --git a/account_move_name_sequence/post_install.py b/account_move_name_sequence/post_install.py index ef52eeeb4c9..10a69f0e5f7 100644 --- a/account_move_name_sequence/post_install.py +++ b/account_move_name_sequence/post_install.py @@ -2,31 +2,31 @@ # Copyright 2022 Vauxoo (https://www.vauxoo.com/) # @author: Alexis de Lattre # @author: Moisés López +# @author: Francisco Luna # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import SUPERUSER_ID, api def create_journal_sequences(cr, registry): - with api.Environment.manage(): - env = api.Environment(cr, SUPERUSER_ID, {}) - journals = ( - env["account.journal"] - .with_context(active_test=False) - .search([("sequence_id", "=", False)]) - ) - for journal in journals: - journal_vals = { - "code": journal.code, - "name": journal.name, - "company_id": journal.company_id.id, - } - seq_vals = journal._prepare_sequence(journal_vals) - seq_vals.update(journal._prepare_sequence_current_moves()) - vals = {"sequence_id": env["ir.sequence"].create(seq_vals).id} - if journal.type in ("sale", "purchase") and journal.refund_sequence: - rseq_vals = journal._prepare_sequence(journal_vals, refund=True) - rseq_vals.update(journal._prepare_sequence_current_moves(refund=True)) - vals["refund_sequence_id"] = env["ir.sequence"].create(rseq_vals).id - journal.write(vals) + env = api.Environment(cr, SUPERUSER_ID, {}) + journals = ( + env["account.journal"] + .with_context(active_test=False) + .search([("sequence_id", "=", False)]) + ) + for journal in journals: + journal_vals = { + "code": journal.code, + "name": journal.name, + "company_id": journal.company_id.id, + } + seq_vals = journal._prepare_sequence(journal_vals) + seq_vals.update(journal._prepare_sequence_current_moves()) + vals = {"sequence_id": env["ir.sequence"].create(seq_vals).id} + if journal.type in ("sale", "purchase") and journal.refund_sequence: + rseq_vals = journal._prepare_sequence(journal_vals, refund=True) + rseq_vals.update(journal._prepare_sequence_current_moves(refund=True)) + vals["refund_sequence_id"] = env["ir.sequence"].create(rseq_vals).id + journal.write(vals) return From 3ea1f0701b51b838a3112dd93c71ab48b5a31e1e Mon Sep 17 00:00:00 2001 From: Francisco Javier Luna Vazquez Date: Wed, 25 May 2022 17:58:09 -0500 Subject: [PATCH 13/58] [FIX] account_move_name_sequence: Exclude no_gap sequences from _is_end_of_seq_chain --- account_move_name_sequence/README.rst | 10 +++--- .../i18n/account_move_name_sequence.pot | 31 ++++--------------- .../models/account_move.py | 9 ++++++ .../static/description/index.html | 6 ++-- .../tests/test_account_move_name_seq.py | 25 +++++++++++++++ 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 8811eb96f8b..0d9fe0a7843 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -14,13 +14,13 @@ Account Move Number Sequence :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github - :target: https://github.com/OCA/account-financial-tools/tree/14.0/account_move_name_sequence + :target: https://github.com/OCA/account-financial-tools/tree/15.0/account_move_name_sequence :alt: OCA/account-financial-tools .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-financial-tools-14-0/account-financial-tools-14-0-account_move_name_sequence + :target: https://translation.odoo-community.org/projects/account-financial-tools-15-0/account-financial-tools-15-0-account_move_name_sequence :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/92/14.0 + :target: https://runbot.odoo-community.org/runbot/92/15.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -108,7 +108,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 smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -155,6 +155,6 @@ Current `maintainers `__: |maintainer-alexis-via| |maintainer-moylop260| |maintainer-frahikLV| -This module is part of the `OCA/account-financial-tools `_ project on GitHub. +This module is part of the `OCA/account-financial-tools `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_name_sequence/i18n/account_move_name_sequence.pot b/account_move_name_sequence/i18n/account_move_name_sequence.pot index 395f8e187d9..b9aa2fba175 100644 --- a/account_move_name_sequence/i18n/account_move_name_sequence.pot +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 14.0\n" +"Project-Id-Version: Odoo Server 15.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -37,13 +37,6 @@ msgstr "" msgid "Dedicated Credit Note Sequence" msgstr "" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name -#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name -msgid "Display Name" -msgstr "" - #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id msgid "Entry Sequence" @@ -56,13 +49,6 @@ msgstr "" msgid "Highest Name" msgstr "" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id -#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id -msgid "ID" -msgstr "" - #. module: account_move_name_sequence #: model:ir.model,name:account_move_name_sequence.model_account_journal msgid "Journal" @@ -73,13 +59,6 @@ msgstr "" msgid "Journal Entry" msgstr "" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal____last_update -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update -#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update -msgid "Last Modified on" -msgstr "" - #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name @@ -126,14 +105,16 @@ msgstr "" #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "" -"The company is not set on sequence '%s' configured as credit note sequence " -"of journal '%s'." +"The company is not set on sequence '%(sequence)s' configured as credit note " +"sequence of journal '%(journal)s'." msgstr "" #. module: account_move_name_sequence #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format -msgid "The company is not set on sequence '%s' configured on journal '%s'." +msgid "" +"The company is not set on sequence '%(sequence)s' configured on journal " +"'%(journal)s'." msgstr "" #. module: account_move_name_sequence diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index ff1dbc7599d..6f63aab6670 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -52,3 +52,12 @@ def _compute_name_by_sequence(self): # We must by-pass this constraint of sequence.mixin def _constrains_date_sequence(self): return True + + def _is_end_of_seq_chain(self): + invoices_no_gap_sequences = self.filtered( + lambda inv: inv.journal_id.sequence_id.implementation == "no_gap" + ) + invoices_other_sequences = self - invoices_no_gap_sequences + if not invoices_other_sequences and invoices_no_gap_sequences: + return False + return super(AccountMove, invoices_other_sequences)._is_end_of_seq_chain() diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 14a7905a9a7..e022819835f 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -367,7 +367,7 @@

Account Move Number Sequence

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for the next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks:

    @@ -448,7 +448,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 smashing it by providing a detailed and welcomed -feedback.

    +feedback.

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

@@ -477,7 +477,7 @@

Maintainers

promote its widespread use.

Current maintainers:

alexis-via moylop260 frahikLV

-

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

+

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

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

diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index c6acf33c4ff..039cfc87ce5 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -1,10 +1,13 @@ # Copyright 2021 Akretion France (http://www.akretion.com/) # @author: Alexis de Lattre +# @author: Moisés López +# @author: Francisco Luna # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from datetime import datetime from odoo import fields +from odoo.exceptions import UserError from odoo.tests import tagged from odoo.tests.common import TransactionCase @@ -111,3 +114,25 @@ def test_in_refund(self): in_refund_invoice.button_draft() in_refund_invoice.action_post() self.assertEqual(in_refund_invoice.name, move_name) + + def test_remove_invoice_error(self): + invoice = self.env["account.move"].create( + { + "date": self.date, + "journal_id": self.misc_journal.id, + "line_ids": [ + (0, 0, {"account_id": self.account1.id, "debit": 10}), + (0, 0, {"account_id": self.account2.id, "credit": 10}), + ], + } + ) + self.assertEqual(invoice.name, "/") + invoice.action_post() + error_msg = "You cannot delete an item linked to a posted entry." + with self.assertRaisesRegex(UserError, error_msg): + invoice.unlink() + invoice.button_draft() + invoice.button_cancel() + error_msg = "You cannot delete this entry, as it has already consumed a" + with self.assertRaisesRegex(UserError, error_msg): + invoice.unlink() From 0784dd4d4fffc1c8edbb11c609221037f814f3d7 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 7 Jul 2022 16:56:27 +0200 Subject: [PATCH 14/58] [FIX] account_move_name_sequence: Use account move date to compute prefix In case you want name your invoice YYYY-MM-SEQ (ie: 2022-07-00001) where: * YYYY: is the account move year * MM: is the account move month * SEQ: is a numerical sequence that is continue along the fiscal year assuming fiscal year is over two years (ie: from july to june next year) Before this commit the sequence prefix use now() to be compute but the range is selected with the account move date. This commit make consistency computing prefix with the account move date as well. So account move manage the first janunary for the last day of the previous year will properly use the account move date. Co-authored-by: Alexis de Lattre --- account_move_name_sequence/__manifest__.py | 2 +- .../models/account_move.py | 5 +- .../tests/test_account_move_name_seq.py | 53 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index de8ebb9b79a..fec5f01f261 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "15.0.1.0.0", + "version": "15.0.1.1.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index 6f63aab6670..8813263f7f6 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -46,7 +46,10 @@ def _compute_name_by_sequence(self): seq = move.journal_id.refund_sequence_id else: seq = move.journal_id.sequence_id - name = seq.next_by_id(sequence_date=move.date) + # next_by_id(date) only applies on ir.sequence.date_range selection + # => we use with_context(ir_sequence_date=date).next_by_id() + # which applies on ir.sequence.date_range selection AND prefix + name = seq.with_context(ir_sequence_date=move.date).next_by_id() move.name = name # We must by-pass this constraint of sequence.mixin diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index 039cfc87ce5..207ca61398c 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -6,6 +6,8 @@ from datetime import datetime +from freezegun import freeze_time + from odoo import fields from odoo.exceptions import UserError from odoo.tests import tagged @@ -85,6 +87,57 @@ def test_misc_move_name(self): move.action_post() self.assertEqual(move.name, move_name) + def test_prefix_move_name_use_move_date(self): + seq = self.misc_journal.sequence_id + seq.prefix = "TEST-%(year)s-%(month)s-" + self.env["ir.sequence.date_range"].sudo().create( + { + "date_from": "2021-07-01", + "date_to": "2022-06-30", + "sequence_id": seq.id, + } + ) + with freeze_time("2022-01-01"): + move = self.env["account.move"].create( + { + "date": "2021-12-31", + "journal_id": self.misc_journal.id, + "line_ids": [ + (0, 0, {"account_id": self.account1.id, "debit": 10}), + (0, 0, {"account_id": self.account2.id, "credit": 10}), + ], + } + ) + move.action_post() + self.assertEqual(move.name, "TEST-2021-12-0001") + with freeze_time("2022-01-01"): + move = self.env["account.move"].create( + { + "date": "2022-06-30", + "journal_id": self.misc_journal.id, + "line_ids": [ + (0, 0, {"account_id": self.account1.id, "debit": 10}), + (0, 0, {"account_id": self.account2.id, "credit": 10}), + ], + } + ) + move.action_post() + self.assertEqual(move.name, "TEST-2022-06-0002") + + with freeze_time("2022-01-01"): + move = self.env["account.move"].create( + { + "date": "2022-07-01", + "journal_id": self.misc_journal.id, + "line_ids": [ + (0, 0, {"account_id": self.account1.id, "debit": 10}), + (0, 0, {"account_id": self.account2.id, "credit": 10}), + ], + } + ) + move.action_post() + self.assertEqual(move.name, "TEST-2022-07-0001") + def test_in_refund(self): in_refund_invoice = self.env["account.move"].create( { From 47481d156db14bb26d542dce7a1b7a838d3643cc Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 24 Nov 2022 12:55:29 +0100 Subject: [PATCH 15/58] [MIG] account_move_name_sequence: Migration to 16.0 --- account_move_name_sequence/__manifest__.py | 2 +- .../models/account_journal.py | 23 ++++---- .../readme/CONTRIBUTORS.rst | 15 ++++- .../tests/test_account_move_name_seq.py | 56 ++++++++++++++++++- .../views/account_move.xml | 16 +++--- 5 files changed, 87 insertions(+), 25 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index fec5f01f261..d35084b30da 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "15.0.1.1.0", + "version": "16.0.1.0.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 9038ec2a230..3cfd1531a39 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -67,17 +67,18 @@ def _check_journal_sequence(self): ) raise ValidationError(msg) - @api.model - def create(self, vals): - if not vals.get("sequence_id"): - vals["sequence_id"] = self._create_sequence(vals).id - if ( - vals.get("type") in ("sale", "purchase") - and vals.get("refund_sequence") - and not vals.get("refund_sequence_id") - ): - vals["refund_sequence_id"] = self._create_sequence(vals, refund=True).id - return super().create(vals) + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if not vals.get("sequence_id"): + vals["sequence_id"] = self._create_sequence(vals).id + if ( + vals.get("type") in ("sale", "purchase") + and vals.get("refund_sequence") + and not vals.get("refund_sequence_id") + ): + vals["refund_sequence_id"] = self._create_sequence(vals, refund=True).id + return super().create(vals_list) @api.model def _prepare_sequence(self, vals, refund=False): diff --git a/account_move_name_sequence/readme/CONTRIBUTORS.rst b/account_move_name_sequence/readme/CONTRIBUTORS.rst index 3e8712428e2..39d07df21df 100644 --- a/account_move_name_sequence/readme/CONTRIBUTORS.rst +++ b/account_move_name_sequence/readme/CONTRIBUTORS.rst @@ -1,3 +1,12 @@ -* Alexis de Lattre -* Moisés López -* Francisco Luna +* `Akretion `_: + + * Alexis de Lattre + +* `Vauxoo `_: + + * Moisés López + * Francisco Luna + +* `Factor Libre `_: + + * Rodrigo Bonilla Martinez diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index 207ca61398c..4538ccd5021 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -9,7 +9,7 @@ from freezegun import freeze_time from odoo import fields -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError from odoo.tests import tagged from odoo.tests.common import TransactionCase @@ -168,7 +168,7 @@ def test_in_refund(self): in_refund_invoice.action_post() self.assertEqual(in_refund_invoice.name, move_name) - def test_remove_invoice_error(self): + def test_remove_invoice_error_secuence_no_grap(self): invoice = self.env["account.move"].create( { "date": self.date, @@ -189,3 +189,55 @@ def test_remove_invoice_error(self): error_msg = "You cannot delete this entry, as it has already consumed a" with self.assertRaisesRegex(UserError, error_msg): invoice.unlink() + + def test_remove_invoice_error_secuence_standard(self): + implementation = {"implementation": "standard"} + self.purchase_journal.sequence_id.write(implementation) + self.purchase_journal.refund_sequence_id.write(implementation) + in_refund_invoice = self.env["account.move"].create( + { + "journal_id": self.purchase_journal.id, + "invoice_date": self.date, + "partner_id": self.env.ref("base.res_partner_3").id, + "move_type": "in_refund", + "invoice_line_ids": [ + ( + 0, + 0, + { + "account_id": self.account1.id, + "price_unit": 42.0, + "quantity": 12, + }, + ) + ], + } + ) + in_refund_invoice._compute_split_sequence() + self.assertEqual(in_refund_invoice.name, "/") + in_refund_invoice.action_post() + error_msg = "You cannot delete an item linked to a posted entry." + with self.assertRaisesRegex(UserError, error_msg): + in_refund_invoice.unlink() + in_refund_invoice.button_draft() + in_refund_invoice.button_cancel() + self.assertTrue(in_refund_invoice.unlink()) + + def test_journal_check_journal_sequence(self): + new_journal = self.purchase_journal.copy() + # same sequence_id and refund_sequence_id + with self.assertRaises(ValidationError): + new_journal.write({"refund_sequence_id": new_journal.sequence_id}) + + # company_id in sequence_id or refund_sequence_id to False + new_sequence_id = new_journal.sequence_id.copy({"company_id": False}) + new_refund_sequence_id = new_journal.refund_sequence_id.copy( + {"company_id": False} + ) + with self.assertRaises(ValidationError): + new_journal.write({"sequence_id": new_sequence_id.id}) + with self.assertRaises(ValidationError): + new_journal.write({"refund_sequence_id": new_refund_sequence_id.id}) + + def test_constrains_date_sequence_true(self): + self.assertTrue(self.env["account.move"]._constrains_date_sequence()) diff --git a/account_move_name_sequence/views/account_move.xml b/account_move_name_sequence/views/account_move.xml index 2536e906682..c537b17a740 100644 --- a/account_move_name_sequence/views/account_move.xml +++ b/account_move_name_sequence/views/account_move.xml @@ -10,20 +10,20 @@ account.move - - {'invisible': [('name', '=', '/')]} + + 1 - {'readonly': 1} + {'invisible': [('name', '=', '/')]} + 1 - - {'invisible': 1} + + {'invisible': ['|', ('state', '!=', 'draft'), ('name', '!=', '/')]} From a2cbd32c137454f6a1a2f0627b41c40c347545ab Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 24 Nov 2022 14:13:50 +0100 Subject: [PATCH 16/58] [FIX] account_move_name_sequence: return sequence names do not add a space between name and returns. --- account_move_name_sequence/models/account_journal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 3cfd1531a39..ab3e275c09b 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -86,7 +86,7 @@ def _prepare_sequence(self, vals, refund=False): prefix = "%s%s/%%(range_year)s/" % (refund and "R" or "", code) seq_vals = { "name": "%s%s" - % (vals.get("name", _("Sequence")), refund and _("Refund") + " " or ""), + % (vals.get("name", _("Sequence")), refund and " " + _("Refund") or ""), "company_id": vals.get("company_id") or self.env.company.id, "implementation": "no_gap", "prefix": prefix, From 45e4ea2175cf6d64212a5d6e1c2f47ceda408ca7 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 28 Nov 2022 10:46:08 +0100 Subject: [PATCH 17/58] [FIX] account_move_name_sequence: issue #1465 vals get refund_sequence true if value not get in vals --- account_move_name_sequence/models/account_journal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index ab3e275c09b..3531cb80f63 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -74,7 +74,7 @@ def create(self, vals_list): vals["sequence_id"] = self._create_sequence(vals).id if ( vals.get("type") in ("sale", "purchase") - and vals.get("refund_sequence") + and vals.get("refund_sequence", True) and not vals.get("refund_sequence_id") ): vals["refund_sequence_id"] = self._create_sequence(vals, refund=True).id From 91de5f1295166d3ad128be073e24fbac997313c3 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 2 Dec 2022 12:57:26 +0100 Subject: [PATCH 18/58] [FIX] account_move_name_sequence: call flush before _fetch_duplicate_supplier_reference method same issue https://github.com/OCA/account-financial-tools/issues/1501 this fix not working for v16 https://github.com/OCA/account-financial-tools/pull/1514 --- account_move_name_sequence/README.rst | 25 +++-- .../i18n/account_move_name_sequence.pot | 7 +- .../models/account_move.py | 6 ++ .../static/description/index.html | 16 +++- .../tests/test_account_move_name_seq.py | 96 +++++++++++++++++++ 5 files changed, 138 insertions(+), 12 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 0d9fe0a7843..d77bab031a1 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -14,13 +14,13 @@ Account Move Number Sequence :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github - :target: https://github.com/OCA/account-financial-tools/tree/15.0/account_move_name_sequence + :target: https://github.com/OCA/account-financial-tools/tree/16.0/account_move_name_sequence :alt: OCA/account-financial-tools .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-financial-tools-15-0/account-financial-tools-15-0-account_move_name_sequence + :target: https://translation.odoo-community.org/projects/account-financial-tools-16-0/account-financial-tools-16-0-account_move_name_sequence :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/92/15.0 + :target: https://runbot.odoo-community.org/runbot/92/16.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -108,7 +108,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 smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -124,9 +124,18 @@ Authors Contributors ~~~~~~~~~~~~ -* Alexis de Lattre -* Moisés López -* Francisco Luna +* `Akretion `_: + + * Alexis de Lattre + +* `Vauxoo `_: + + * Moisés López + * Francisco Luna + +* `Factor Libre `_: + + * Rodrigo Bonilla Martinez Maintainers ~~~~~~~~~~~ @@ -155,6 +164,6 @@ Current `maintainers `__: |maintainer-alexis-via| |maintainer-moylop260| |maintainer-frahikLV| -This module is part of the `OCA/account-financial-tools `_ project on GitHub. +This module is part of the `OCA/account-financial-tools `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_name_sequence/i18n/account_move_name_sequence.pot b/account_move_name_sequence/i18n/account_move_name_sequence.pot index b9aa2fba175..4b400c5d13f 100644 --- a/account_move_name_sequence/i18n/account_move_name_sequence.pot +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 15.0\n" +"Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -67,6 +67,7 @@ msgid "Number" msgstr "" #. module: account_move_name_sequence +#. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "" @@ -75,12 +76,14 @@ msgid "" msgstr "" #. module: account_move_name_sequence +#. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "Refund" msgstr "" #. module: account_move_name_sequence +#. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 #: model:ir.model,name:account_move_name_sequence.model_ir_sequence #, python-format @@ -102,6 +105,7 @@ msgid "Sequence Prefix" msgstr "" #. module: account_move_name_sequence +#. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "" @@ -110,6 +114,7 @@ msgid "" msgstr "" #. module: account_move_name_sequence +#. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "" diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index 8813263f7f6..8b43a629f15 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -64,3 +64,9 @@ def _is_end_of_seq_chain(self): if not invoices_other_sequences and invoices_no_gap_sequences: return False return super(AccountMove, invoices_other_sequences)._is_end_of_seq_chain() + + def _fetch_duplicate_supplier_reference(self, only_posted=False): + moves = self.filtered(lambda m: m.is_purchase_document() and m.ref) + if moves: + self.flush_model(["name", "journal_id", "move_type", "state"]) + return super()._fetch_duplicate_supplier_reference(only_posted=only_posted) diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index e022819835f..84b1cf9e64a 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -367,7 +367,7 @@

Account Move Number Sequence

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

In Odoo version 14.0, the number of journal entries can be manually set by the user. Then, the number attributed for the next journal entries in the same journal is computed by a complex piece of code that guesses the format of the journal entry number from the number of the journal entry which was manually entered by the user. It has several drawbacks:

    @@ -448,7 +448,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 smashing it by providing a detailed and welcomed -feedback.

    +feedback.

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

    @@ -463,10 +463,20 @@

    Authors

    Contributors

    Maintainers

    @@ -477,7 +487,7 @@

    Maintainers

    promote its widespread use.

    Current maintainers:

    alexis-via moylop260 frahikLV

    -

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

    +

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

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

    diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index 4538ccd5021..4457da0c05b 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -138,6 +138,102 @@ def test_prefix_move_name_use_move_date(self): move.action_post() self.assertEqual(move.name, "TEST-2022-07-0001") + def test_in_invoice_and_refund(self): + in_invoice = self.env["account.move"].create( + { + "journal_id": self.purchase_journal.id, + "invoice_date": self.date, + "partner_id": self.env.ref("base.res_partner_3").id, + "move_type": "in_invoice", + "invoice_line_ids": [ + ( + 0, + 0, + { + "account_id": self.account1.id, + "price_unit": 42.0, + "quantity": 12, + }, + ), + ( + 0, + 0, + { + "account_id": self.account1.id, + "price_unit": 48.0, + "quantity": 10, + }, + ), + ], + } + ) + self.assertEqual(in_invoice.name, "/") + in_invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=in_invoice.ids) + .create( + { + "journal_id": in_invoice.journal_id.id, + "reason": "no reason", + "refund_method": "cancel", + } + ) + ) + reversal = move_reversal.reverse_moves() + reversed_move = self.env["account.move"].browse(reversal["res_id"]) + self.assertTrue(reversed_move) + self.assertEqual(reversed_move.state, "posted") + + in_invoice = in_invoice.copy( + { + "invoice_date": self.date, + } + ) + in_invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=in_invoice.ids) + .create( + { + "journal_id": in_invoice.journal_id.id, + "reason": "no reason", + "refund_method": "modify", + } + ) + ) + reversal = move_reversal.reverse_moves() + draft_invoice = self.env["account.move"].browse(reversal["res_id"]) + self.assertTrue(draft_invoice) + self.assertEqual(draft_invoice.state, "draft") + self.assertEqual(draft_invoice.move_type, "in_invoice") + + in_invoice = in_invoice.copy( + { + "invoice_date": self.date, + } + ) + in_invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=in_invoice.ids) + .create( + { + "journal_id": in_invoice.journal_id.id, + "reason": "no reason", + "refund_method": "refund", + } + ) + ) + reversal = move_reversal.reverse_moves() + draft_reversed_move = self.env["account.move"].browse(reversal["res_id"]) + self.assertTrue(draft_reversed_move) + self.assertEqual(draft_reversed_move.state, "draft") + self.assertEqual(draft_reversed_move.move_type, "in_refund") + def test_in_refund(self): in_refund_invoice = self.env["account.move"].create( { From 6314ef0796b6b4e5ed6e094260114c4a6d35ec87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20L=C3=B3pez?= Date: Thu, 8 Dec 2022 15:54:22 -0600 Subject: [PATCH 19/58] [REF] account_move_name_sequence: Remove concurrency outdated cases from the readme --- account_move_name_sequence/README.rst | 45 ------------- account_move_name_sequence/__manifest__.py | 2 +- .../readme/DESCRIPTION.rst | 45 ------------- .../static/description/index.html | 67 ++++--------------- 4 files changed, 13 insertions(+), 146 deletions(-) diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index d77bab031a1..4314f993b01 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -34,51 +34,6 @@ In Odoo version 14.0, the number of journal entries can be manually set by the u * as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, * the `piece of code `_ that handles this is not easy to understand and quite difficult to debug. -Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck -Even if you only are creating a draft journal entry it locks the last one -It applies to all accounting Journal Entries - -e.g. - - - Customer Invoices - - Credit Notes - - Customer Payments - - Vendor Bills - - Vendor Refunds - - Vendor Payment - - Manual Journal Entries - -Then, the following concurrency errors are being raised now frequently: - -* Editing the last record used to get the new number from another process -* Creating a new draft invoice/payment (not only when posting it) -* Creating a transaction to create an invoice then payment or vice versa raises a deadlock error -* Reconciling the last record it could be a heavy process -* Creating 2 or more Invoices/Bills at the same time -* Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard) -* Creating 2 or more Journal Entries at the same time - - -All these increases in concurrency errors bring more issues since that Odoo is not prepared: - -* Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges -* Using `subscription_template.payment_mode=success_payment` you will see subscriptions with tag "payment exception" -* Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user -* The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance - -The new accounting number is a significant bottleneck - -.. image:: https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 - - -If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0: - - - Passing unittest for `13.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ - - Concurrency errors for `14.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ - - `Stress testing and issue reported to Odoo `_ - - `[BUG] account: Concurrency errors increased considerably in account.move for Odoo>=v14.0 #91873 `_ - - Using this module, you can configure what kind of documents the gap sequence may be relaxed And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index d35084b30da..7ae16f3c7d1 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/readme/DESCRIPTION.rst b/account_move_name_sequence/readme/DESCRIPTION.rst index 9bbf7306f59..0c6a8bf0b86 100644 --- a/account_move_name_sequence/readme/DESCRIPTION.rst +++ b/account_move_name_sequence/readme/DESCRIPTION.rst @@ -7,51 +7,6 @@ In Odoo version 14.0, the number of journal entries can be manually set by the u * as it is error-prone, they added a *Resequence* wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries, * the `piece of code `_ that handles this is not easy to understand and quite difficult to debug. -Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck -Even if you only are creating a draft journal entry it locks the last one -It applies to all accounting Journal Entries - -e.g. - - - Customer Invoices - - Credit Notes - - Customer Payments - - Vendor Bills - - Vendor Refunds - - Vendor Payment - - Manual Journal Entries - -Then, the following concurrency errors are being raised now frequently: - -* Editing the last record used to get the new number from another process -* Creating a new draft invoice/payment (not only when posting it) -* Creating a transaction to create an invoice then payment or vice versa raises a deadlock error -* Reconciling the last record it could be a heavy process -* Creating 2 or more Invoices/Bills at the same time -* Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard) -* Creating 2 or more Journal Entries at the same time - - -All these increases in concurrency errors bring more issues since that Odoo is not prepared: - -* Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges -* Using `subscription_template.payment_mode=success_payment` you will see subscriptions with tag "payment exception" -* Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user -* The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance - -The new accounting number is a significant bottleneck - -.. image:: https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 - - -If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0: - - - Passing unittest for `13.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ - - Concurrency errors for `14.0 - [REF] account: Adding unittests for concurrency issues in account_move sequences `_ - - `Stress testing and issue reported to Odoo `_ - - `[BUG] account: Concurrency errors increased considerably in account.move for Odoo>=v14.0 #91873 `_ - - Using this module, you can configure what kind of documents the gap sequence may be relaxed And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 84b1cf9e64a..3c86cc643b8 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -376,49 +376,6 @@

    Account Move Number Sequence

  • as it is error-prone, they added a Resequence wizard to re-generate the journal entry numbers, which can be considered as illegal in many countries,
  • the piece of code that handles this is not easy to understand and quite difficult to debug.
-

Odoo>=v14.0 raises new concurrency issues since it locks the last journal entry of the journal to get the new number causing a bottleneck -Even if you only are creating a draft journal entry it locks the last one -It applies to all accounting Journal Entries

-

e.g.

-
-
    -
  • Customer Invoices
  • -
  • Credit Notes
  • -
  • Customer Payments
  • -
  • Vendor Bills
  • -
  • Vendor Refunds
  • -
  • Vendor Payment
  • -
  • Manual Journal Entries
  • -
-
-

Then, the following concurrency errors are being raised now frequently:

-
    -
  • Editing the last record used to get the new number from another process
  • -
  • Creating a new draft invoice/payment (not only when posting it)
  • -
  • Creating a transaction to create an invoice then payment or vice versa raises a deadlock error
  • -
  • Reconciling the last record it could be a heavy process
  • -
  • Creating 2 or more Invoices/Bills at the same time
  • -
  • Creating 2 or more Payments at the same time (Even if your country allows to relax gaps in these kinds of documents, you are not able anymore to change the implementation to standard)
  • -
  • Creating 2 or more Journal Entries at the same time
  • -
-

All these increases in concurrency errors bring more issues since that Odoo is not prepared:

-
    -
  • Using e-commerce, configured with Invoicing Policy Ordered and Automatic Invoice, the portal users will see errors in the checkout even if the payment was done, the sale order could be in state draft and request a new payment, so double charges
  • -
  • Using subscription_template.payment_mode=success_payment you will see subscriptions with tag “payment exception”
  • -
  • Using accounting creating invoice or payment, you will see errors then you will need to start the process again and again until you get the lock before another user
  • -
  • The workers could be used for more time than before since that it could be waiting for release so less concurrent users supported or loading page is shown more frequently affecting the performance
  • -
-

The new accounting number is a significant bottleneck

-https://media.istockphoto.com/vectors/road-highways-with-many-different-vehicles-vector-id1328678690 -

If you do not believe all these issues are occurring, we have created the following issues and unittest to reproduce errors in v14.0 including the deadlock, but not v13.0:

-
- -

Using this module, you can configure what kind of documents the gap sequence may be relaxed And even if you must use no-gap in your company or country it will reduce the concurrency issues since the module is using an extra table (ir_sequence) instead of locking the last record

For those like me who think that the implementation before Odoo v14.0 was much better, for the accountants who think it should not be possible to manually enter the sequence of a customer invoice, for the auditor who considers that resequencing journal entries is prohibited by law, this module may be a solution to get out of the nightmare.

@@ -427,24 +384,24 @@

Account Move Number Sequence

Table of contents

-

Configuration

+

Configuration

On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created when you save the journal.

On sale and purchase journals, you have an additional option to have another sequence dedicated to refunds.

Upon module installation, all existing journals will be updated with a journal entry sequence (and also a credit note sequence for sale and purchase journals). You should update the configuration of the sequences to fit your needs. You can uncheck the option Dedicated Credit Note Sequence on existing sale and purchase journals if you don’t want it. For the journals which already have journal entries, you should update the sequence configuration to avoid a discontinuity in the numbering for the next journal entry.

-

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 smashing it by providing a detailed and welcomed @@ -452,16 +409,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
  • Vauxoo
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

OCA, or the Odoo Community Association, is a nonprofit organization whose From df2f6bfed91f425b6e570db7fd0d791112b8193e Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 20 Jan 2023 12:11:00 +0100 Subject: [PATCH 20/58] [FIX] account_move_name_sequence: With the "account_move_name_sequence" module the "_get_last_sequence" method does not have to propagate the with_prefix parameter. The sequence_prefix parameter will not be completed and will give error as it is False in this line of code. https://github.com/OCA/OCB/blob/16.0/addons/account/models/sequence_mixin.py#L169 --- account_move_name_sequence/__manifest__.py | 2 +- account_move_name_sequence/models/account_move.py | 3 +++ account_move_name_sequence/tests/test_account_move_name_seq.py | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 7ae16f3c7d1..80b1d8f7ee9 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "16.0.1.1.0", + "version": "16.0.1.1.1", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index 8b43a629f15..f7338dcf171 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -70,3 +70,6 @@ def _fetch_duplicate_supplier_reference(self, only_posted=False): if moves: self.flush_model(["name", "journal_id", "move_type", "state"]) return super()._fetch_duplicate_supplier_reference(only_posted=only_posted) + + def _get_last_sequence(self, relaxed=False, with_prefix=None, lock=True): + return super()._get_last_sequence(relaxed, None, lock) diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index 4457da0c05b..c548e028a89 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -309,7 +309,6 @@ def test_remove_invoice_error_secuence_standard(self): ], } ) - in_refund_invoice._compute_split_sequence() self.assertEqual(in_refund_invoice.name, "/") in_refund_invoice.action_post() error_msg = "You cannot delete an item linked to a posted entry." From 7608a4c317e115a09be0fb6c72d8f8008075401a Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 31 Jan 2023 11:37:36 +0100 Subject: [PATCH 21/58] [FIX] account_move_name_sequence: Now you can unlink moves without check sequence fix: https://github.com/odoo/odoo/commit/6112f4f59aeb5dc5a3b698edd861b19f25da7017 --- account_move_name_sequence/__manifest__.py | 2 +- .../tests/test_account_move_name_seq.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index 80b1d8f7ee9..b9b695b92d4 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "16.0.1.1.1", + "version": "16.0.1.1.2", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index c548e028a89..d698a32a496 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -282,9 +282,7 @@ def test_remove_invoice_error_secuence_no_grap(self): invoice.unlink() invoice.button_draft() invoice.button_cancel() - error_msg = "You cannot delete this entry, as it has already consumed a" - with self.assertRaisesRegex(UserError, error_msg): - invoice.unlink() + invoice.unlink() def test_remove_invoice_error_secuence_standard(self): implementation = {"implementation": "standard"} From e8678d60044227c31abdee1e5b36730650ab0e5a Mon Sep 17 00:00:00 2001 From: Bole Date: Sat, 11 Feb 2023 10:47:27 +0000 Subject: [PATCH 22/58] Added translation using Weblate (Croatian) --- account_move_name_sequence/i18n/hr.po | 149 ++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 account_move_name_sequence/i18n/hr.po diff --git a/account_move_name_sequence/i18n/hr.po b/account_move_name_sequence/i18n/hr.po new file mode 100644 index 00000000000..71e8a203c8e --- /dev/null +++ b/account_move_name_sequence/i18n/hr.po @@ -0,0 +1,149 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_name_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-02-16 10:09+0000\n" +"Last-Translator: Bole \n" +"Language-Team: none\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.14.1\n" + +#. module: account_move_name_sequence +#: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal +msgid "" +"A move can not be posted with name \"/\" or empty value\n" +"Check the journal sequence, please" +msgstr "" +"Temeljnicu nije moguće potvrditi sa nazivom \"/\" ili praznim poljem \n" +"Provjerite sekvencu dnevnika, molimo" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence +msgid "" +"Check this box if you don't want to share the same sequence for invoices and" +" credit notes made from this journal" +msgstr "" +"Označite ovu kućicu ako ne želite dijeliti istu sekvencu za račune i " +"odobrenja/storna napravljena iz ovog dnevnika" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "Credit Note Entry Sequence" +msgstr "Ulazna sekvenca za odobrenja" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence +msgid "Dedicated Credit Note Sequence" +msgstr "Dedicirana sekvenca za odobrenja" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id +msgid "Entry Sequence" +msgstr "Ulazna sekvenca" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name +msgid "Highest Name" +msgstr "Najviši broj" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_journal +msgid "Journal" +msgstr "Dnevnik" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_move +msgid "Journal Entry" +msgstr "Stavka dnevnika" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__name +msgid "Number" +msgstr "Broj" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" +" Entry Sequence." +msgstr "" +"Na dnevniku '%s', ista sekvenca se koristi za regularna i storno knjiženja." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "Refund" +msgstr "Storno/Odobrenje" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#: model:ir.model,name:account_move_name_sequence.model_ir_sequence +#, python-format +msgid "Sequence" +msgstr "Sekvenca" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number +msgid "Sequence Number" +msgstr "Broj sekvence" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix +msgid "Sequence Prefix" +msgstr "Prefiks sekvence" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured as credit note " +"sequence of journal '%(journal)s'." +msgstr "" +"Tvrtka nije postavljena na sekvenci '%(sequence)s' postavljenoj kao sekvenca " +"za storno/odobrenja na dnevniku '%(journal)s'." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured on journal " +"'%(journal)s'." +msgstr "" +"Tvrtka nije postavljena na sekvenci '%(sequence)s' postavljenoj na dnevniku " +"'%(journal)s'." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "" +"This sequence will be used to generate the journal entry number for refunds." +msgstr "" +"Ova sekvenca će biti korištena za generiranje broja knjiženja za odobrenja/" +"storno." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id +msgid "This sequence will be used to generate the journal entry number." +msgstr "Ova sekvenca će biti korištena za generiranje broja knjiženja dnevnika." From d485697b444a754cce42ceb8d83b43c059c44409 Mon Sep 17 00:00:00 2001 From: remi-filament <30716308+remi-filament@users.noreply.github.com> Date: Wed, 15 Mar 2023 11:45:31 +0100 Subject: [PATCH 23/58] [FIX] account_move_name_sequence: computed fields raising warning --- account_move_name_sequence/__manifest__.py | 2 +- .../i18n/account_move_name_sequence.pot | 12 ++++++++++ account_move_name_sequence/i18n/hr.po | 23 +++++++++++++++---- .../models/account_journal.py | 3 +++ .../models/account_move.py | 5 +++- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index b9b695b92d4..e6914cdef8a 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "16.0.1.1.2", + "version": "16.0.1.1.3", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/i18n/account_move_name_sequence.pot b/account_move_name_sequence/i18n/account_move_name_sequence.pot index 4b400c5d13f..0fbe285c569 100644 --- a/account_move_name_sequence/i18n/account_move_name_sequence.pot +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -42,6 +42,11 @@ msgstr "" msgid "Entry Sequence" msgstr "" +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes +msgid "Has Sequence Holes" +msgstr "" + #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name @@ -59,6 +64,13 @@ msgstr "" msgid "Journal Entry" msgstr "" +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__made_sequence_hole +msgid "Made Sequence Hole" +msgstr "" + #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name diff --git a/account_move_name_sequence/i18n/hr.po b/account_move_name_sequence/i18n/hr.po index 71e8a203c8e..06e5c7d9328 100644 --- a/account_move_name_sequence/i18n/hr.po +++ b/account_move_name_sequence/i18n/hr.po @@ -29,8 +29,8 @@ msgstr "" #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence msgid "" -"Check this box if you don't want to share the same sequence for invoices and" -" credit notes made from this journal" +"Check this box if you don't want to share the same sequence for invoices and " +"credit notes made from this journal" msgstr "" "Označite ovu kućicu ako ne želite dijeliti istu sekvencu za račune i " "odobrenja/storna napravljena iz ovog dnevnika" @@ -50,6 +50,11 @@ msgstr "Dedicirana sekvenca za odobrenja" msgid "Entry Sequence" msgstr "Ulazna sekvenca" +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes +msgid "Has Sequence Holes" +msgstr "" + #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name @@ -67,6 +72,13 @@ msgstr "Dnevnik" msgid "Journal Entry" msgstr "Stavka dnevnika" +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__made_sequence_hole +msgid "Made Sequence Hole" +msgstr "" + #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name @@ -79,8 +91,8 @@ msgstr "Broj" #: code:addons/account_move_name_sequence/models/account_journal.py:0 #, python-format msgid "" -"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" -" Entry Sequence." +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note " +"Entry Sequence." msgstr "" "Na dnevniku '%s', ista sekvenca se koristi za regularna i storno knjiženja." @@ -146,4 +158,5 @@ msgstr "" #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id msgid "This sequence will be used to generate the journal entry number." -msgstr "Ova sekvenca će biti korištena za generiranje broja knjiženja dnevnika." +msgstr "" +"Ova sekvenca će biti korištena za generiranje broja knjiženja dnevnika." diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 3531cb80f63..24c24198f86 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -34,6 +34,9 @@ class AccountJournal(models.Model): ) # Redefine the default to True as <=v13.0 refund_sequence = fields.Boolean(default=True) + # has_sequence_holes is not relevant anymore (since based on sequence_prefix/number) + # -> compute=False to improve perf and to avoid displaying warning + has_sequence_holes = fields.Boolean(compute=False) @api.constrains("refund_sequence_id", "sequence_id") def _check_journal_sequence(self): diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index f7338dcf171..2027e996f8a 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -9,11 +9,14 @@ class AccountMove(models.Model): _inherit = "account.move" name = fields.Char(compute="_compute_name_by_sequence") - # highest_name, sequence_prefix and sequence_number are not needed any more + # highest_name, sequence_prefix, sequence_number are not needed any more # -> compute=False to improve perf highest_name = fields.Char(compute=False) sequence_prefix = fields.Char(compute=False) sequence_number = fields.Integer(compute=False) + # made_sequence_hole is not relevant anymore (since based on sequence_prefix/number) + # -> compute=False to improve perf and to avoid displaying warning + made_sequence_hole = fields.Boolean(compute=False) _sql_constraints = [ ( From 761254ae06b96963d48354fbbe56f37dc7a16a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= Date: Tue, 4 Apr 2023 11:11:59 +0000 Subject: [PATCH 24/58] Added translation using Weblate (French) --- account_move_name_sequence/i18n/fr.po | 163 ++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 account_move_name_sequence/i18n/fr.po diff --git a/account_move_name_sequence/i18n/fr.po b/account_move_name_sequence/i18n/fr.po new file mode 100644 index 00000000000..d6148b243bb --- /dev/null +++ b/account_move_name_sequence/i18n/fr.po @@ -0,0 +1,163 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_name_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-04-04 13:23+0000\n" +"Last-Translator: Rémi \n" +"Language-Team: none\n" +"Language: fr\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" +"X-Generator: Weblate 4.14.1\n" + +#. module: account_move_name_sequence +#: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal +msgid "" +"A move can not be posted with name \"/\" or empty value\n" +"Check the journal sequence, please" +msgstr "" +"Une pièce comptable ne peut pas être comptabilisé car elle n'a pas de numéro " +"attribué.\n" +"Vérifier la configuration de la séquence sur le journal concerné." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence +msgid "" +"Check this box if you don't want to share the same sequence for invoices and" +" credit notes made from this journal" +msgstr "" +"Cocher cette case si vous souhaitez créer 2 séquences distinctes pour les " +"factures et avoirs pour ce journal" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "Credit Note Entry Sequence" +msgstr "Séquence pour les avoirs" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence +msgid "Dedicated Credit Note Sequence" +msgstr "Séquence des avoirs dédiée" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id +msgid "Entry Sequence" +msgstr "Séquence de la pièce comptable" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes +msgid "Has Sequence Holes" +msgstr "A des trous dans la séquence" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name +msgid "Highest Name" +msgstr "Plus grand numéro de séquence" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_journal +msgid "Journal" +msgstr "Journal" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_move +msgid "Journal Entry" +msgstr "Pièce comptable" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__made_sequence_hole +msgid "Made Sequence Hole" +msgstr "Cause un trou dans la séquence" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__name +msgid "Number" +msgstr "Nombre" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" +" Entry Sequence." +msgstr "" +"Pour le journal '%s', la même séquence est utilisée pour les pièces de " +"factures et d'avoirs." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "Refund" +msgstr "Avoir" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#: model:ir.model,name:account_move_name_sequence.model_ir_sequence +#, python-format +msgid "Sequence" +msgstr "Séquence" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number +msgid "Sequence Number" +msgstr "Nombre de la séquence" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix +msgid "Sequence Prefix" +msgstr "Préfixe de la séquence" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured as credit note " +"sequence of journal '%(journal)s'." +msgstr "" +"Aucune société n'est configurée sur la séquence '%(sequence)s' utilisée " +"comme séquence pour les avoirs sur le journal '%(journal)s'." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured on journal " +"'%(journal)s'." +msgstr "" +"Aucune société n'est configurée sur la séquence '%(sequence)s' configurée " +"sur le journal '%(journal)s'." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "" +"This sequence will be used to generate the journal entry number for refunds." +msgstr "" +"Cette séquence sera utilisée pour générer les références de pièce comptable " +"pour les avoirs." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id +msgid "This sequence will be used to generate the journal entry number." +msgstr "" +"Cette séquence sera utilisée pour générer les références de pièce comptable." From 3fd1b6627eacf81863b26d628d4d2198ffa3fd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gelo=20joga=20Rodr=C3=ADguez?= Date: Thu, 13 Apr 2023 09:28:35 +0000 Subject: [PATCH 25/58] Added translation using Weblate (Spanish) --- account_move_name_sequence/i18n/es.po | 163 ++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 account_move_name_sequence/i18n/es.po diff --git a/account_move_name_sequence/i18n/es.po b/account_move_name_sequence/i18n/es.po new file mode 100644 index 00000000000..d5674e2668d --- /dev/null +++ b/account_move_name_sequence/i18n/es.po @@ -0,0 +1,163 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_name_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-04-13 12:33+0000\n" +"Last-Translator: gelo joga Rodríguez \n" +"Language-Team: none\n" +"Language: es\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" +"X-Generator: Weblate 4.14.1\n" + +#. module: account_move_name_sequence +#: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal +msgid "" +"A move can not be posted with name \"/\" or empty value\n" +"Check the journal sequence, please" +msgstr "" +"Un asiento no puede ser publicado con el nombre \"/\" o vacío \n" +"Comprueba la secuencia de diario, por favor" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence +msgid "" +"Check this box if you don't want to share the same sequence for invoices and" +" credit notes made from this journal" +msgstr "" +"Marca esta casilla si no quieres compartir la misma secuencia para las " +"facturas y facturas rectificativas hechas en este diario" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "Credit Note Entry Sequence" +msgstr "Secuencia de facturas rectificativas" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence +msgid "Dedicated Credit Note Sequence" +msgstr "Secuencia de facturas rectificativas dedicada" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id +msgid "Entry Sequence" +msgstr "Secuencia de asiento" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes +msgid "Has Sequence Holes" +msgstr "Hay agujeros en la secuencia" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name +msgid "Highest Name" +msgstr "Número más alto" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_journal +msgid "Journal" +msgstr "Dario" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_move +msgid "Journal Entry" +msgstr "Asiento" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__made_sequence_hole +msgid "Made Sequence Hole" +msgstr "Creado agujero en secuencia" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__name +msgid "Number" +msgstr "Número" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" +" Entry Sequence." +msgstr "" +"En el diario '%s', se ha usado la misma secuencia para la Secuencia de " +"asiento y la Secuencia de facturas rectificativas." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "Refund" +msgstr "Rectificativa" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#: model:ir.model,name:account_move_name_sequence.model_ir_sequence +#, python-format +msgid "Sequence" +msgstr "Secuencia" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number +msgid "Sequence Number" +msgstr "Número de secuencia" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix +msgid "Sequence Prefix" +msgstr "Prefijo de la secuencia" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured as credit note " +"sequence of journal '%(journal)s'." +msgstr "" +"La compañía no tiene establecida la secuencia '%(sequence)s' configurada " +"como secuencia de facturas rectificativas del diario '%(journal)s'." + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured on journal " +"'%(journal)s'." +msgstr "" +"La compañía no tiene establecida la secuencia '%(sequence)s' configurada en " +"el diario '%(journal)s'." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "" +"This sequence will be used to generate the journal entry number for refunds." +msgstr "" +"Esta secuencia se utilizará para generar el número de asientos para " +"rectificaciones." + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id +msgid "This sequence will be used to generate the journal entry number." +msgstr "" +"Esta secuencia se usará para establecer para generar el número de asiento " +"contable." From 865b71f676b811b3a2d9e879fa906878ea4da115 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 8 Jun 2023 21:55:13 +0000 Subject: [PATCH 26/58] Translated using Weblate (French) Currently translated at 100.0% (20 of 20 strings) Translation: account-financial-tools-16.0/account-financial-tools-16.0-account_move_name_sequence Translate-URL: https://translation.odoo-community.org/projects/account-financial-tools-16-0/account-financial-tools-16-0-account_move_name_sequence/fr/ --- account_move_name_sequence/i18n/fr.po | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/account_move_name_sequence/i18n/fr.po b/account_move_name_sequence/i18n/fr.po index d6148b243bb..d6f3c74ffd2 100644 --- a/account_move_name_sequence/i18n/fr.po +++ b/account_move_name_sequence/i18n/fr.po @@ -6,15 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2023-04-04 13:23+0000\n" -"Last-Translator: Rémi \n" +"PO-Revision-Date: 2023-06-09 00:10+0000\n" +"Last-Translator: Alexis de Lattre \n" "Language-Team: none\n" "Language: fr\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" -"X-Generator: Weblate 4.14.1\n" +"X-Generator: Weblate 4.17\n" #. module: account_move_name_sequence #: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal @@ -24,7 +24,7 @@ msgid "" msgstr "" "Une pièce comptable ne peut pas être comptabilisé car elle n'a pas de numéro " "attribué.\n" -"Vérifier la configuration de la séquence sur le journal concerné." +"Vérifiez la configuration de la séquence sur le journal concerné." #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence @@ -43,12 +43,12 @@ msgstr "Séquence pour les avoirs" #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence msgid "Dedicated Credit Note Sequence" -msgstr "Séquence des avoirs dédiée" +msgstr "Séquence dédiée pour les avoirs" #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id msgid "Entry Sequence" -msgstr "Séquence de la pièce comptable" +msgstr "Séquence des pièces comptables" #. module: account_move_name_sequence #: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes @@ -94,8 +94,8 @@ msgid "" "On journal '%s', the same sequence is used as Entry Sequence and Credit Note" " Entry Sequence." msgstr "" -"Pour le journal '%s', la même séquence est utilisée pour les pièces de " -"factures et d'avoirs." +"Pour le journal '%s', la même séquence est utilisée pour les factures et les " +"avoirs." #. module: account_move_name_sequence #. odoo-python @@ -152,12 +152,10 @@ msgstr "" #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id msgid "" "This sequence will be used to generate the journal entry number for refunds." -msgstr "" -"Cette séquence sera utilisée pour générer les références de pièce comptable " -"pour les avoirs." +msgstr "Cette séquence sera utilisée pour générer les numéros des avoirs." #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id msgid "This sequence will be used to generate the journal entry number." msgstr "" -"Cette séquence sera utilisée pour générer les références de pièce comptable." +"Cette séquence sera utilisée pour générer les numéros des pièces comptables." From 40b077aea78d9f20d23c003b8b51dd6aa19b6ddd Mon Sep 17 00:00:00 2001 From: Andrea Stirpe Date: Thu, 24 Aug 2023 13:22:31 +0200 Subject: [PATCH 27/58] [FIX] account_move_name_sequence: do not create duplicated sequences --- account_move_name_sequence/__manifest__.py | 2 +- account_move_name_sequence/models/account_journal.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index e6914cdef8a..22ebe5daa6a 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "16.0.1.1.3", + "version": "16.0.1.1.4", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 24c24198f86..a8813a81ef1 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -101,6 +101,10 @@ def _prepare_sequence(self, vals, refund=False): @api.model def _create_sequence(self, vals, refund=False): seq_vals = self._prepare_sequence(vals, refund=refund) + domain = [(key, "=", value) for key, value in seq_vals.items()] + existing = self.env["ir.sequence"].search(domain, limit=1) + if existing: + return existing return self.env["ir.sequence"].sudo().create(seq_vals) def _prepare_sequence_current_moves(self, refund=False): From e78bcc51d71260526ad88fe7131c26ecc44778c6 Mon Sep 17 00:00:00 2001 From: Hussain Hammad Date: Tue, 29 Aug 2023 14:25:37 +0000 Subject: [PATCH 28/58] Added translation using Weblate (Arabic) --- account_move_name_sequence/README.rst | 15 +- account_move_name_sequence/i18n/ar.po | 154 ++++++++++++++++++ .../static/description/index.html | 40 ++--- 3 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 account_move_name_sequence/i18n/ar.po diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index 4314f993b01..b517b039a74 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -2,10 +2,13 @@ Account Move Number Sequence ============================ -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1455404114c5b4a6e1be95b599f8a272c0758315126959df13d0f3e6bc284737 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -19,11 +22,11 @@ Account Move Number Sequence .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/account-financial-tools-16-0/account-financial-tools-16-0-account_move_name_sequence :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/92/16.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&target_branch=16.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal. @@ -62,7 +65,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 smashing it by providing a detailed and welcomed +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. diff --git a/account_move_name_sequence/i18n/ar.po b/account_move_name_sequence/i18n/ar.po new file mode 100644 index 00000000000..977e8f13fdc --- /dev/null +++ b/account_move_name_sequence/i18n/ar.po @@ -0,0 +1,154 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_name_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-09-02 21:55+0000\n" +"Last-Translator: Hussain Hammad \n" +"Language-Team: none\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" +"X-Generator: Weblate 4.17\n" + +#. module: account_move_name_sequence +#: model:ir.model.constraint,message:account_move_name_sequence.constraint_account_move_name_state_diagonal +msgid "" +"A move can not be posted with name \"/\" or empty value\n" +"Check the journal sequence, please" +msgstr "" +"لا يمكن ترحيل قيد و اسمه \"/\" او فارغ\n" +"الرجاء التأكد من تسلسل اليومية" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence +msgid "" +"Check this box if you don't want to share the same sequence for invoices and" +" credit notes made from this journal" +msgstr "" +"استخدم هذه الخاصية ان كنت لا ترغب باستخدام نفس التسلسل للفواتير و اشعارات " +"الدائن" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "Credit Note Entry Sequence" +msgstr "تسلسل ادخال اشعار دائن" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence +msgid "Dedicated Credit Note Sequence" +msgstr "تسلسل خاص باشعار دائن" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id +msgid "Entry Sequence" +msgstr "تسلسل ادخال" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__has_sequence_holes +msgid "Has Sequence Holes" +msgstr "التسلسل يحتوي على فراغات" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name +msgid "Highest Name" +msgstr "ارفع اسم" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_journal +msgid "Journal" +msgstr "يومية" + +#. module: account_move_name_sequence +#: model:ir.model,name:account_move_name_sequence.model_account_move +msgid "Journal Entry" +msgstr "ادخال يومية" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__made_sequence_hole +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__made_sequence_hole +msgid "Made Sequence Hole" +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__name +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__name +msgid "Number" +msgstr "رقم" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" +" Entry Sequence." +msgstr "" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "Refund" +msgstr "مرتجع" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#: model:ir.model,name:account_move_name_sequence.model_ir_sequence +#, python-format +msgid "Sequence" +msgstr "تسلسل" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number +msgid "Sequence Number" +msgstr "رقم التسلسل" + +#. module: account_move_name_sequence +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix +#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix +msgid "Sequence Prefix" +msgstr "قبل التسلسل" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured as credit note " +"sequence of journal '%(journal)s'." +msgstr "" + +#. module: account_move_name_sequence +#. odoo-python +#: code:addons/account_move_name_sequence/models/account_journal.py:0 +#, python-format +msgid "" +"The company is not set on sequence '%(sequence)s' configured on journal " +"'%(journal)s'." +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id +msgid "" +"This sequence will be used to generate the journal entry number for refunds." +msgstr "" + +#. module: account_move_name_sequence +#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id +msgid "This sequence will be used to generate the journal entry number." +msgstr "" diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 3c86cc643b8..0cf4177b824 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -1,20 +1,20 @@ - + - + Account Move Number Sequence -

-

Account Move Number Sequence

+
+ + +Odoo Community Association + +
+

Account Move Number Sequence

-

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

+

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

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

In Odoo version 14.0, the number of journal entries can be manually set @@ -418,7 +423,7 @@

Account Move Number Sequence

-

Configuration

+

Configuration

On the form view of an account journal, in the first tab, there is a many2one link to the sequence. When you create a new journal, you can keep this field empty and a new sequence will be automatically created @@ -435,7 +440,7 @@

Configuration

the next journal entry.

-

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 @@ -443,16 +448,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
  • Vauxoo
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -485,5 +490,6 @@

Maintainers

+
diff --git a/account_move_name_sequence/tests/__init__.py b/account_move_name_sequence/tests/__init__.py index 7f2d011b8fc..49b19d8c3bb 100644 --- a/account_move_name_sequence/tests/__init__.py +++ b/account_move_name_sequence/tests/__init__.py @@ -1,3 +1,4 @@ from . import test_account_move_name_seq +from . import test_account_move_name_seq_hashed_journal from . import test_sequence_concurrency from . import test_account_incoming_supplier_invoice diff --git a/account_move_name_sequence/tests/test_account_incoming_supplier_invoice.py b/account_move_name_sequence/tests/test_account_incoming_supplier_invoice.py index fc6976b39ec..d321aa2086f 100644 --- a/account_move_name_sequence/tests/test_account_incoming_supplier_invoice.py +++ b/account_move_name_sequence/tests/test_account_incoming_supplier_invoice.py @@ -1,5 +1,7 @@ import json +from markupsafe import Markup + from odoo.tests import tagged from odoo.addons.account.tests.common import AccountTestInvoicingCommon @@ -86,7 +88,7 @@ def test_supplier_invoice_mailed_from_supplier(self): ) self.assertEqual( message_ids.body, - "

Vendor Bill Created

", + Markup("

Vendor Bill Created

"), "Only the invoice creation should be posted", ) diff --git a/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py b/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py new file mode 100644 index 00000000000..a8cef66624c --- /dev/null +++ b/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py @@ -0,0 +1,66 @@ +# Copyright 2025 Le Filament (https://le-filament.com) +# @author: Rémi - Le Filament +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from freezegun import freeze_time + +from odoo.tests import tagged + +from odoo.addons.account_move_name_sequence.tests.test_account_move_name_seq import ( + TestAccountMoveNameSequence, +) + + +@tagged("post_install", "-at_install") +class TestAccountMoveNameSequenceHashedJournal(TestAccountMoveNameSequence): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.sales_journal.restrict_mode_hash_table = True + + def test_account_move_hashed(self): + seq = self.sales_journal.sequence_id + seq.prefix = "TEST-%(range_year)s-" + with freeze_time("2022-05-31"): + move = self.env["account.move"].create( + { + "journal_id": self.sales_journal.id, + "partner_id": self.env.ref("base.res_partner_3").id, + "move_type": "out_invoice", + "invoice_line_ids": self.invoice_line, + } + ) + move2 = move.copy() + move.action_post() + move2.action_post() + self.assertEqual(move.name, "TEST-2022-0001") + self.assertEqual(move2.name, "TEST-2022-0002") + self.assertEqual(move.sequence_prefix, "TEST-2022-") + self.assertEqual(move2.sequence_prefix, "TEST-2022-") + self.assertEqual(move.sequence_number, 1) + self.assertEqual(move2.sequence_number, 2) + + def test_account_move_hashed_suffix(self): + seq = self.sales_journal.sequence_id + seq.prefix = "TEST-%(range_year)s-" + seq.suffix = "-TEST_SUFFIX" + with freeze_time("2022-05-31"): + move = self.env["account.move"].create( + { + "journal_id": self.sales_journal.id, + "partner_id": self.env.ref("base.res_partner_3").id, + "move_type": "out_invoice", + "invoice_line_ids": self.invoice_line, + } + ) + move2 = move.copy() + move.action_post() + move2.action_post() + self.assertEqual(move.name, "TEST-2022-0001-TEST_SUFFIX") + self.assertEqual(move2.name, "TEST-2022-0002-TEST_SUFFIX") + self.assertEqual(move.sequence_prefix, "TEST-2022-") + self.assertEqual(move2.sequence_prefix, "TEST-2022-") + self.assertEqual(move.sequence_number, 1) + self.assertEqual(move2.sequence_number, 2) From 4e60f8c5ec5bd88c946640f2f6f2f256b3a63cb6 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 14 Oct 2025 20:54:09 +0000 Subject: [PATCH 57/58] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: account-financial-tools-18.0/account-financial-tools-18.0-account_move_name_sequence Translate-URL: https://translation.odoo-community.org/projects/account-financial-tools-18-0/account-financial-tools-18-0-account_move_name_sequence/ --- account_move_name_sequence/i18n/ar.po | 18 ++++++------------ account_move_name_sequence/i18n/es.po | 18 ++++++------------ account_move_name_sequence/i18n/fr.po | 18 ++++++------------ account_move_name_sequence/i18n/hr.po | 18 ++++++------------ account_move_name_sequence/i18n/it.po | 18 ++++++------------ account_move_name_sequence/i18n/pt_BR.po | 20 ++++---------------- account_move_name_sequence/i18n/sl.po | 18 ++++++------------ 7 files changed, 40 insertions(+), 88 deletions(-) diff --git a/account_move_name_sequence/i18n/ar.po b/account_move_name_sequence/i18n/ar.po index acc075b1cd3..e4788ae6846 100644 --- a/account_move_name_sequence/i18n/ar.po +++ b/account_move_name_sequence/i18n/ar.po @@ -104,18 +104,6 @@ msgstr "مرتجع" msgid "Sequence" msgstr "تسلسل" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "رقم التسلسل" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "قبل التسلسل" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -152,3 +140,9 @@ msgstr "" #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id msgid "This sequence will be used to generate the journal entry number." msgstr "" + +#~ msgid "Sequence Number" +#~ msgstr "رقم التسلسل" + +#~ msgid "Sequence Prefix" +#~ msgstr "قبل التسلسل" diff --git a/account_move_name_sequence/i18n/es.po b/account_move_name_sequence/i18n/es.po index a828ade9788..a14b80dfd99 100644 --- a/account_move_name_sequence/i18n/es.po +++ b/account_move_name_sequence/i18n/es.po @@ -105,18 +105,6 @@ msgstr "Rectificativa" msgid "Sequence" msgstr "Secuencia" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "Número de secuencia" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "Prefijo de la secuencia" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -161,3 +149,9 @@ msgid "This sequence will be used to generate the journal entry number." msgstr "" "Esta secuencia se usará para establecer para generar el número de asiento " "contable." + +#~ msgid "Sequence Number" +#~ msgstr "Número de secuencia" + +#~ msgid "Sequence Prefix" +#~ msgstr "Prefijo de la secuencia" diff --git a/account_move_name_sequence/i18n/fr.po b/account_move_name_sequence/i18n/fr.po index 1ed65d7598e..7fef9f39243 100644 --- a/account_move_name_sequence/i18n/fr.po +++ b/account_move_name_sequence/i18n/fr.po @@ -106,18 +106,6 @@ msgstr "Avoir" msgid "Sequence" msgstr "Séquence" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "Nombre de la séquence" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "Préfixe de la séquence" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -159,3 +147,9 @@ msgstr "Cette séquence sera utilisée pour générer les numéros des avoirs." msgid "This sequence will be used to generate the journal entry number." msgstr "" "Cette séquence sera utilisée pour générer les numéros des pièces comptables." + +#~ msgid "Sequence Number" +#~ msgstr "Nombre de la séquence" + +#~ msgid "Sequence Prefix" +#~ msgstr "Préfixe de la séquence" diff --git a/account_move_name_sequence/i18n/hr.po b/account_move_name_sequence/i18n/hr.po index 673197aa0b1..d1d9937a5a7 100644 --- a/account_move_name_sequence/i18n/hr.po +++ b/account_move_name_sequence/i18n/hr.po @@ -105,18 +105,6 @@ msgstr "Storno/Odobrenje" msgid "Sequence" msgstr "Sekvenca" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "Broj sekvence" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "Prefiks sekvence" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -160,3 +148,9 @@ msgstr "" msgid "This sequence will be used to generate the journal entry number." msgstr "" "Ova sekvenca će biti korištena za generiranje broja knjiženja dnevnika." + +#~ msgid "Sequence Number" +#~ msgstr "Broj sekvence" + +#~ msgid "Sequence Prefix" +#~ msgstr "Prefiks sekvence" diff --git a/account_move_name_sequence/i18n/it.po b/account_move_name_sequence/i18n/it.po index c0097c50851..7689515d498 100644 --- a/account_move_name_sequence/i18n/it.po +++ b/account_move_name_sequence/i18n/it.po @@ -105,18 +105,6 @@ msgstr "Rimborso" msgid "Sequence" msgstr "Sequenza" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "Numero sequenza" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "Prefisso sequenza" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -161,3 +149,9 @@ msgid "This sequence will be used to generate the journal entry number." msgstr "" "Questa sequenza verrà utilizzata per generare il numero della registrazione " "contabile." + +#~ msgid "Sequence Number" +#~ msgstr "Numero sequenza" + +#~ msgid "Sequence Prefix" +#~ msgstr "Prefisso sequenza" diff --git a/account_move_name_sequence/i18n/pt_BR.po b/account_move_name_sequence/i18n/pt_BR.po index 15e536bc5db..e6e4ff5d104 100644 --- a/account_move_name_sequence/i18n/pt_BR.po +++ b/account_move_name_sequence/i18n/pt_BR.po @@ -24,8 +24,8 @@ msgstr "" #. module: account_move_name_sequence #: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence msgid "" -"Check this box if you don't want to share the same sequence for invoices and" -" credit notes made from this journal" +"Check this box if you don't want to share the same sequence for invoices and " +"credit notes made from this journal" msgstr "" #. module: account_move_name_sequence @@ -80,8 +80,8 @@ msgstr "" #. odoo-python #: code:addons/account_move_name_sequence/models/account_journal.py:0 msgid "" -"On journal '%s', the same sequence is used as Entry Sequence and Credit Note" -" Entry Sequence." +"On journal '%s', the same sequence is used as Entry Sequence and Credit Note " +"Entry Sequence." msgstr "" #. module: account_move_name_sequence @@ -97,18 +97,6 @@ msgstr "" msgid "Sequence" msgstr "" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" diff --git a/account_move_name_sequence/i18n/sl.po b/account_move_name_sequence/i18n/sl.po index 8b3374a7e1a..c4c8400f6ea 100644 --- a/account_move_name_sequence/i18n/sl.po +++ b/account_move_name_sequence/i18n/sl.po @@ -104,18 +104,6 @@ msgstr "Povračilo" msgid "Sequence" msgstr "Zaporedje" -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number -msgid "Sequence Number" -msgstr "Številka zaporedja" - -#. module: account_move_name_sequence -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix -#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix -msgid "Sequence Prefix" -msgstr "Predpona zaporedja" - #. module: account_move_name_sequence #: model:account.journal,name:account_move_name_sequence.journal_cash_std_demo msgid "Standard Cash Journal Demo" @@ -153,6 +141,12 @@ msgstr "To zaporedje bo v rabi za knjigovodske vnose dobropisov." msgid "This sequence will be used to generate the journal entry number." msgstr "To zaporedje bo v rabi za knjigovodske vnose dobropisov." +#~ msgid "Sequence Number" +#~ msgstr "Številka zaporedja" + +#~ msgid "Sequence Prefix" +#~ msgstr "Predpona zaporedja" + #~ msgid "Display Name" #~ msgstr "Prikazani naziv" From fe5c27439f486936bf29453facbf9303563467d8 Mon Sep 17 00:00:00 2001 From: Ryan Tran Date: Thu, 27 Nov 2025 17:57:37 +0700 Subject: [PATCH 58/58] [MIG] account_move_name_sequence: Migrate to 19.0 --- account_move_name_sequence/README.rst | 10 +- account_move_name_sequence/__manifest__.py | 2 +- .../migrations/18.0.2.0.0/post-migration.py | 45 --- .../models/account_journal.py | 19 +- .../models/account_move.py | 13 +- .../models/ir_sequence.py | 25 +- .../static/description/index.html | 6 +- .../tests/test_account_move_name_seq.py | 10 +- ...st_account_move_name_seq_hashed_journal.py | 6 +- .../tests/test_sequence_concurrency.py | 318 ++++++++++++------ .../views/account_journal_views.xml | 2 - .../views/account_move_views.xml | 2 - 12 files changed, 268 insertions(+), 190 deletions(-) delete mode 100644 account_move_name_sequence/migrations/18.0.2.0.0/post-migration.py diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst index b96c9fd3bfd..976fed118fc 100644 --- a/account_move_name_sequence/README.rst +++ b/account_move_name_sequence/README.rst @@ -21,13 +21,13 @@ Account Move Number Sequence :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github - :target: https://github.com/OCA/account-financial-tools/tree/18.0/account_move_name_sequence + :target: https://github.com/OCA/account-financial-tools/tree/19.0/account_move_name_sequence :alt: OCA/account-financial-tools .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-financial-tools-18-0/account-financial-tools-18-0-account_move_name_sequence + :target: https://translation.odoo-community.org/projects/account-financial-tools-19-0/account-financial-tools-19-0-account_move_name_sequence :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/account-financial-tools&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -102,7 +102,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. @@ -158,6 +158,6 @@ Current `maintainers `__: |maintainer-alexis-via| |maintainer-moylop260| |maintainer-luisg123v| -This module is part of the `OCA/account-financial-tools `_ project on GitHub. +This module is part of the `OCA/account-financial-tools `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py index badb1e5733c..cb173d05f5a 100644 --- a/account_move_name_sequence/__manifest__.py +++ b/account_move_name_sequence/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Account Move Number Sequence", - "version": "18.0.2.0.1", + "version": "19.0.1.0.0", "category": "Accounting", "license": "AGPL-3", "summary": "Generate journal entry number from sequence", diff --git a/account_move_name_sequence/migrations/18.0.2.0.0/post-migration.py b/account_move_name_sequence/migrations/18.0.2.0.0/post-migration.py deleted file mode 100644 index 6c1386d058c..00000000000 --- a/account_move_name_sequence/migrations/18.0.2.0.0/post-migration.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2025 Le Filament (https://www.le-filament.com) -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -import re - -from openupgradelib import openupgrade - - -@openupgrade.migrate() -def migrate(env, version): - for journal in env["account.journal"].search( - [("restrict_mode_hash_table", "=", True)] - ): - journal_moves = env["account.move"].search( - [ - ("state", "=", "posted"), - ("journal_id", "=", journal.id), - "|", - ("sequence_prefix", "=", False), - "|", - ("sequence_number", "=", False), - ("sequence_number", "=", 0), - ] - ) - for (move_type, year), moves in journal_moves.grouped( - lambda m: (m.move_type, m.date.year) - ).items(): - if ( - move_type in ["in_refund", "out_refund"] - and journal.refund_sequence - and journal.refund_sequence_id - ): - sequence = journal.refund_sequence_id - else: - sequence = journal.sequence_id - prefix, suffix = sequence._get_prefix_suffix( - date=f"{year}-01-01", date_range=f"{year}-01-01" - ) - pattern = re.compile(f"{prefix}[0-9]{{{sequence.padding}}}{suffix}") - filtered_moves = moves.filtered(lambda move: pattern.match(move.name)) # noqa: B023 - filtered_moves.sequence_prefix = prefix - for move in filtered_moves: - move.sequence_number = int( - move.name[len(prefix) : len(move.name) - len(suffix)] - ) - filtered_moves._compute_made_sequence_gap() diff --git a/account_move_name_sequence/models/account_journal.py b/account_move_name_sequence/models/account_journal.py index 6158ebeca85..a79c4cd8078 100644 --- a/account_move_name_sequence/models/account_journal.py +++ b/account_move_name_sequence/models/account_journal.py @@ -9,6 +9,7 @@ from odoo import Command, api, fields, models from odoo.exceptions import ValidationError +from odoo.fields import Domain _logger = logging.getLogger(__name__) @@ -104,7 +105,7 @@ def _prepare_sequence(self, vals, refund=False): @api.model def _create_sequence(self, vals, refund=False): seq_vals = self._prepare_sequence(vals, refund=refund) - domain = [(key, "=", value) for key, value in seq_vals.items()] + domain = Domain([(key, "=", value) for key, value in seq_vals.items()]) existing = self.env["ir.sequence"].search(domain, limit=1) if existing: return existing @@ -113,16 +114,20 @@ def _create_sequence(self, vals, refund=False): def _prepare_sequence_current_moves(self, refund=False): """Get sequence dict values the journal based on current moves""" self.ensure_one() - move_domain = [ - ("journal_id", "=", self.id), - ("name", "!=", "/"), - ] + move_domain = Domain( + [ + ("journal_id", "=", self.id), + ("name", "!=", "/"), + ] + ) if self.refund_sequence: #  Based on original Odoo behavior if refund: - move_domain.append(("move_type", "in", ("out_refund", "in_refund"))) + move_domain &= Domain("move_type", "in", ("out_refund", "in_refund")) else: - move_domain.append(("move_type", "not in", ("out_refund", "in_refund"))) + move_domain &= Domain( + "move_type", "not in", ("out_refund", "in_refund") + ) last_move = self.env["account.move"].search( move_domain, limit=1, order="id DESC" ) diff --git a/account_move_name_sequence/models/account_move.py b/account_move_name_sequence/models/account_move.py index 7c5f207a9c7..81a1cf8061a 100644 --- a/account_move_name_sequence/models/account_move.py +++ b/account_move_name_sequence/models/account_move.py @@ -15,14 +15,11 @@ class AccountMove(models.Model): # -> compute=False to improve perf and to avoid displaying warning made_sequence_hole = fields.Boolean(compute=False) - _sql_constraints = [ - ( - "name_state_diagonal", - "CHECK(COALESCE(name, '') NOT IN ('/', '') OR state!='posted')", - 'A move can not be posted with name "/" or empty value\n' - "Check the journal sequence, please", - ), - ] + _name_state_diagonal = models.Constraint( + "CHECK(COALESCE(name, '') NOT IN ('/', '') OR state!='posted')", + 'A move can not be posted with name "/" or empty value\n' + "Check the journal sequence, please", + ) @api.depends("name") def _compute_split_sequence(self): diff --git a/account_move_name_sequence/models/ir_sequence.py b/account_move_name_sequence/models/ir_sequence.py index 75c5265cf6f..a8442d39cb5 100644 --- a/account_move_name_sequence/models/ir_sequence.py +++ b/account_move_name_sequence/models/ir_sequence.py @@ -1,4 +1,5 @@ from odoo import fields, models +from odoo.fields import Domain class IrSequence(models.Model): @@ -22,22 +23,26 @@ def _create_date_range_seq(self, date): date_from = fields.Date.start_of(date_obj, "year") date_to = fields.Date.end_of(date_obj, "year") date_range = sequence_range.search( - [ - ("sequence_id", "=", self.id), - ("date_from", ">=", date), - ("date_from", "<=", date_to), - ], + Domain( + [ + ("sequence_id", "=", self.id), + ("date_from", ">=", date), + ("date_from", "<=", date_to), + ] + ), order="date_from desc", limit=1, ) if date_range: date_to = fields.Date.subtract(date_range.date_from, days=1) date_range = sequence_range.search( - [ - ("sequence_id", "=", self.id), - ("date_to", ">=", date_from), - ("date_to", "<=", date), - ], + Domain( + [ + ("sequence_id", "=", self.id), + ("date_to", ">=", date_from), + ("date_to", "<=", date), + ] + ), order="date_to desc", limit=1, ) diff --git a/account_move_name_sequence/static/description/index.html b/account_move_name_sequence/static/description/index.html index 3b50dc2e959..d207e61ca24 100644 --- a/account_move_name_sequence/static/description/index.html +++ b/account_move_name_sequence/static/description/index.html @@ -374,7 +374,7 @@

Account Move Number Sequence

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:0c2654e763b1efefa3bdde71142ff86c5b15b5bc1ade423a7b2af05b98a17c2d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.

In Odoo version 14.0, the number of journal entries can be manually set @@ -444,7 +444,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.

@@ -485,7 +485,7 @@

Maintainers

promote its widespread use.

Current maintainers:

alexis-via moylop260 luisg123v

-

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

+

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

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

diff --git a/account_move_name_sequence/tests/test_account_move_name_seq.py b/account_move_name_sequence/tests/test_account_move_name_seq.py index ed6513241a5..57c2482ce1f 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -20,7 +20,7 @@ class TestAccountMoveNameSequence(TransactionCase): def setUpClass(cls): super().setUpClass() cls.company = cls.env.ref("base.main_company") - cls.partner = cls.env.ref("base.res_partner_3") + cls.partner = cls.env["res.partner"].create({"name": "Demo User"}) cls.misc_journal = cls.env["account.journal"].create( { "name": "Test Journal Move name seq", @@ -210,7 +210,7 @@ def test_in_invoice_and_refund(self): { "journal_id": self.purchase_journal.id, "invoice_date": self.date, - "partner_id": self.env.ref("base.res_partner_3").id, + "partner_id": self.partner.id, "move_type": "in_invoice", "invoice_line_ids": self.invoice_line + [ @@ -272,7 +272,7 @@ def test_in_refund(self): { "journal_id": self.purchase_journal.id, "invoice_date": self.date, - "partner_id": self.env.ref("base.res_partner_3").id, + "partner_id": self.partner.id, "move_type": "in_refund", "invoice_line_ids": self.invoice_line, } @@ -316,7 +316,7 @@ def test_remove_invoice_error_secuence_standard(self): { "journal_id": self.purchase_journal.id, "invoice_date": self.date, - "partner_id": self.env.ref("base.res_partner_3").id, + "partner_id": self.partner.id, "move_type": "in_refund", "invoice_line_ids": self.invoice_line, } @@ -370,7 +370,7 @@ def test_prefix_move_name_journal_onchange(self): self.assertIn("TB2CSEQ/", invoice.name, "name was not based on sequence") def test_is_end_of_seq_chain(self): - self.env.user.groups_id -= self.env.ref("account.group_account_manager") + self.env.user.group_ids -= self.env.ref("account.group_account_manager") invoice = self.env["account.move"].create( { "date": self.date, diff --git a/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py b/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py index a8cef66624c..77785ebf226 100644 --- a/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py +++ b/account_move_name_sequence/tests/test_account_move_name_seq_hashed_journal.py @@ -17,7 +17,7 @@ class TestAccountMoveNameSequenceHashedJournal(TestAccountMoveNameSequence): @classmethod def setUpClass(cls): super().setUpClass() - + cls.partner = cls.env["res.partner"].create({"name": "Demo User"}) cls.sales_journal.restrict_mode_hash_table = True def test_account_move_hashed(self): @@ -27,7 +27,7 @@ def test_account_move_hashed(self): move = self.env["account.move"].create( { "journal_id": self.sales_journal.id, - "partner_id": self.env.ref("base.res_partner_3").id, + "partner_id": self.partner.id, "move_type": "out_invoice", "invoice_line_ids": self.invoice_line, } @@ -50,7 +50,7 @@ def test_account_move_hashed_suffix(self): move = self.env["account.move"].create( { "journal_id": self.sales_journal.id, - "partner_id": self.env.ref("base.res_partner_3").id, + "partner_id": self.partner.id, "move_type": "out_invoice", "invoice_line_ids": self.invoice_line, } diff --git a/account_move_name_sequence/tests/test_sequence_concurrency.py b/account_move_name_sequence/tests/test_sequence_concurrency.py index f1a6c0af29f..ad53253c0e2 100644 --- a/account_move_name_sequence/tests/test_sequence_concurrency.py +++ b/account_move_name_sequence/tests/test_sequence_concurrency.py @@ -6,6 +6,8 @@ import psycopg2 from odoo import SUPERUSER_ID, api, fields, tools +from odoo.fields import Domain +from odoo.modules.registry import DummyRLock, Registry from odoo.tests import Form, TransactionCase, tagged _logger = logging.getLogger(__name__) @@ -38,71 +40,188 @@ class TestSequenceConcurrency(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.product = cls.env.ref("product.product_delivery_01") - cls.partner = cls.env.ref("base.res_partner_12") - cls.partner2 = cls.env.ref("base.res_partner_1") - cls.date = fields.Date.to_date("1985-04-14") - cls.journal_sale_std = cls.env.ref( - "account_move_name_sequence.journal_sale_std_demo" - ) - cls.journal_cash_std = cls.env.ref( - "account_move_name_sequence.journal_cash_std_demo" - ) + cls._registry_lock_patcher = patch.object(Registry, "_lock", DummyRLock()) + cls.startClassPatcher(cls._registry_lock_patcher) + + with cls.env.registry.cursor() as cr: + env = api.Environment(cr, api.SUPERUSER_ID, {}) + + Product = env["product.product"] + Partner = env["res.partner"] + Sequence = env["ir.sequence"] + Journal = env["account.journal"] + + product = Product.create({"name": "Test Product"}) + partner = Partner.create({"name": "Test Partner 1"}) + partner2 = Partner.create({"name": "Test Partner 2"}) + date = fields.Date.to_date("1985-04-14") + journal_sale_seq = Sequence.create( + { + "name": "Standard Sale Sequence Demo", + "prefix": "SSS_demo/%(range_year)s/", + "use_date_range": True, + "number_next": 1, + "number_increment": 1, + "company_id": env.ref("base.main_company").id, + "implementation": "standard", + } + ) + journal_sale_std = Journal.create( + { + "name": "Standard Sale Journal Demo", + "code": "SSJD", + "type": "sale", + "refund_sequence": True, + "company_id": env.ref("base.main_company").id, + "sequence_id": journal_sale_seq.id, + } + ) + journal_cash_seq = Sequence.create( + { + "name": "Standard Cash Sequence Demo", + "prefix": "SCS_demo/%(range_year)s/", + "use_date_range": True, + "number_next": 1, + "number_increment": 1, + "company_id": env.ref("base.main_company").id, + "implementation": "standard", + } + ) + journal_cash_std = Journal.create( + { + "name": "Standard Cash Journal Demo", + "code": "SCJD", + "type": "cash", + "refund_sequence": True, + "company_id": env.ref("base.main_company").id, + "sequence_id": journal_cash_seq.id, + } + ) + cls.data = { + "date": date, + "product_id": product.id, + "partner_id": partner.id, + "partner2_id": partner2.id, + "journal_sale_seq_id": journal_sale_seq.id, + "journal_cash_seq_id": journal_cash_seq.id, + "journal_sale_id": journal_sale_std.id, + "journal_cash_id": journal_cash_std.id, + } + env.cr.commit() - cls.cr0 = cls.cursor(cls) + cls.cr0 = cls.registry.cursor() cls.env0 = api.Environment(cls.cr0, SUPERUSER_ID, {}) - cls.cr1 = cls.cursor(cls) + cls.cr1 = cls.registry.cursor() cls.env1 = api.Environment(cls.cr1, SUPERUSER_ID, {}) - cls.cr2 = cls.cursor(cls) + cls.cr2 = cls.registry.cursor() cls.env2 = api.Environment(cls.cr2, SUPERUSER_ID, {}) for cr in [cls.cr0, cls.cr1, cls.cr2]: # Set a 10-second timeout to avoid waiting too long for release locks cr.execute("SET LOCAL statement_timeout = '10s'") - cls.registry.enter_test_mode(cls.cursor(cls)) - cls.addClassCleanup(cls.registry.leave_test_mode) - cls.last_existing_move = cls.env["account.move"].search( - [], limit=1, order="id desc" + cls.last_existing_move_id = ( + cls.env["account.move"].search([], limit=1, order="id desc").id or 0 ) + cls.addClassCleanup(cls._cleanup) @classmethod - def _clean_moves_and_payments(cls, last_move): - """Delete moves and payments created after finish test.""" - moves = ( - cls.env["account.move"] - .with_context(force_delete=True) - .search([("id", ">=", last_move)]) - ) - payments = moves.payment_ids - moves_without_payments = moves - payments.move_id - if payments: - payments.action_draft() - payments.unlink() - if moves_without_payments: - moves_without_payments.filtered( - lambda move: move.state != "draft" - ).button_draft() - moves_without_payments.unlink() + def _cleanup(cls): + with cls.env.registry.cursor() as cr: + env = api.Environment(cr, api.SUPERUSER_ID, {}) + moves = ( + env["account.move"] + .with_context(force_delete=True) + .search(Domain("id", ">", cls.last_existing_move_id)) + ) + payments = moves.payment_ids + moves_without_payments = moves - payments.move_id + if payments: + payments.action_draft() + payments.unlink() + if moves_without_payments: + moves_without_payments.filtered( + lambda move: move.state != "draft" + ).button_draft() + moves_without_payments.unlink() + + try: + journals = env["account.journal"].browse( + [ + cls.data["journal_sale_id"], + cls.data["journal_cash_id"], + ] + ) + journals.unlink() + except Exception as e: + _logger.warning("Failed to delete journals: %s", e) + + try: + sequences = env["ir.sequence"].browse( + [ + cls.data["journal_sale_seq_id"], + cls.data["journal_cash_seq_id"], + ] + ) + sequences.unlink() + except Exception as e: + _logger.warning("Failed to delete sequences: %s", e) + + try: + partners = env["res.partner"].browse( + [ + cls.data["partner_id"], + cls.data["partner2_id"], + ] + ) + partners.unlink() + except Exception as e: + _logger.warning("Failed to delete partners: %s", e) + + try: + product = env["product.product"].browse( + [ + cls.data["product_id"], + ] + ) + product.unlink() + except Exception as e: + _logger.warning("Failed to delete products: %s", e) + env.cr.commit() + + for cr in [cls.cr0, cls.cr1, cls.cr2]: + if not cr.closed: + try: + cr.close() + except Exception as e: + _logger.warning("Failed to close cursor: %s", e) def _commit_crs(self, *envs): for env in envs: env.cr.commit() def _create_invoice_form( - self, env, post=True, partner=None, ir_sequence_standard=False + self, env, post=True, partner_id=None, ir_sequence_standard=False ): ctx = {"default_move_type": "out_invoice"} with Form(env["account.move"].with_context(**ctx)) as invoice_form: # Use another partner to bypass "increase_rank" lock error - invoice_form.partner_id = partner or self.partner - invoice_form.invoice_date = self.date + invoice_form.partner_id = ( + partner_id + and env["res.partner"].browse(partner_id) + or env["res.partner"].browse(self.data["partner_id"]) + ) + invoice_form.invoice_date = self.data["date"] with invoice_form.invoice_line_ids.new() as line_form: - line_form.product_id = self.product + line_form.product_id = env["product.product"].browse( + self.data["product_id"] + ) line_form.price_unit = 100.0 line_form.tax_ids.clear() invoice = invoice_form.save() if ir_sequence_standard: - invoice.journal_id = self.journal_sale_std + invoice.journal_id = env["account.journal"].browse( + self.data["journal_sale_id"] + ) if post: # This patch was added to avoid test failures in the CI pipeline caused by # the `account_journal_restrict_mode` module. It avoids errors when setting @@ -114,7 +233,7 @@ def _create_invoice_form( invoice.action_post() return invoice - def _create_payment_form(self, env, partner=None, ir_sequence_standard=False): + def _create_payment_form(self, env, partner_id=None, ir_sequence_standard=False): with Form( env["account.payment"].with_context( default_payment_type="inbound", @@ -122,11 +241,17 @@ def _create_payment_form(self, env, partner=None, ir_sequence_standard=False): default_move_journal_types=("bank", "cash"), ) ) as payment_form: - payment_form.partner_id = partner or self.partner + payment_form.partner_id = ( + partner_id + and env["res.partner"].browse(partner_id) + or env["res.partner"].browse(self.data["partner_id"]) + ) payment_form.amount = 100 - payment_form.date = self.date + payment_form.date = self.data["date"] if ir_sequence_standard: - payment_form.journal_id = self.journal_cash_std + payment_form.journal_id = env["account.journal"].browse( + self.data["journal_cash_id"] + ) payment = payment_form.save() # This patch was added to avoid test failures in the CI pipeline caused by # the `account_journal_restrict_mode` module. It avoids errors when setting @@ -139,45 +264,46 @@ def _create_payment_form(self, env, partner=None, ir_sequence_standard=False): def _create_invoice_payment( self, deadlock_timeout, payment_first=False, ir_sequence_standard=False ): - with self.cursor() as cr, cr.savepoint(): + with self.registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) cr_pid = cr.connection.get_backend_pid() # Avoid waiting for a long time and it needs to be less than deadlock cr.execute("SET LOCAL statement_timeout = '%ss'", (deadlock_timeout + 10,)) if payment_first: - _logger.info("Creating payment cr %s", cr_pid) + _logger.info("[PID %s] Creating payment", cr_pid) self._create_payment_form( env, ir_sequence_standard=ir_sequence_standard ) - _logger.info("Creating invoice cr %s", cr_pid) + _logger.info("[PID %s] Creating invoice", cr_pid) self._create_invoice_form( env, ir_sequence_standard=ir_sequence_standard ) else: - _logger.info("Creating invoice cr %s", cr_pid) + _logger.info("[PID %s] Creating invoice", cr_pid) self._create_invoice_form( env, ir_sequence_standard=ir_sequence_standard ) - _logger.info("Creating payment cr %s", cr_pid) + _logger.info("[PID %s] Creating payment", cr_pid) self._create_payment_form( env, ir_sequence_standard=ir_sequence_standard ) # sleep in order to avoid release the locks too faster # It could be many methods called after creating these # kind of records e.g. reconcile - _logger.info("Finishing waiting %s", (deadlock_timeout + 12)) + _logger.info( + "[PID %s] Finishing, wait %ss before release", cr_pid, deadlock_timeout + 12 + ) time.sleep(deadlock_timeout + 12) def test_sequence_concurrency_10_draft_invoices(self): """Creating 2 DRAFT invoices not should raises errors""" # Create "last move" to lock self._create_invoice_form(self.env0) - self.cr0.commit() - with self.cr1.savepoint(), self.cr2.savepoint(): - invoice1 = self._create_invoice_form(self.env1, post=False) - self.assertEqual(invoice1.state, "draft") - invoice2 = self._create_invoice_form(self.env2, post=False) - self.assertEqual(invoice2.state, "draft") + self.env0.cr.commit() + invoice1 = self._create_invoice_form(self.env1, post=False) + self.assertEqual(invoice1.state, "draft") + invoice2 = self._create_invoice_form(self.env2, post=False) + self.assertEqual(invoice2.state, "draft") self._commit_crs(self.env0, self.env1, self.env2) def test_sequence_concurrency_20_editing_last_invoice(self): @@ -185,12 +311,11 @@ def test_sequence_concurrency_20_editing_last_invoice(self): should not raises errors""" # Create "last move" to lock invoice = self._create_invoice_form(self.env0) - self.cr0.commit() - with self.cr0.savepoint(), self.cr1.savepoint(): - # Edit something in "last move" - invoice.write({"write_uid": self.env0.uid}) - self.env0.flush_all() - self._create_invoice_form(self.env1) + self.env0.cr.commit() + # Edit something in "last move" + invoice.write({"write_uid": self.env0.uid}) + self.env0.flush_all() + self._create_invoice_form(self.env1) self._commit_crs(self.env0, self.env1) def test_sequence_concurrency_30_editing_last_payment(self): @@ -199,12 +324,11 @@ def test_sequence_concurrency_30_editing_last_payment(self): # Create "last move" to lock payment = self._create_payment_form(self.env0) payment_move = payment.move_id - self.cr0.commit() - with self.cr0.savepoint(), self.cr1.savepoint(): - # Edit something in "last move" - payment_move.write({"write_uid": self.env0.uid}) - self.env0.flush_all() - self._create_payment_form(self.env1) + self.env0.cr.commit() + # Edit something in "last move" + payment_move.write({"write_uid": self.env0.uid}) + self.env0.flush_all() + self._create_payment_form(self.env1) self._commit_crs(self.env0, self.env1) @tools.mute_logger("odoo.sql_db") @@ -215,20 +339,19 @@ def test_sequence_concurrency_40_reconciling_last_invoice(self): invoice = self._create_invoice_form(self.env0) payment = self._create_payment_form(self.env0) payment_move = payment.move_id - self.cr0.commit() + self.env0.cr.commit() lines2reconcile = ( (payment_move | invoice) .mapped("line_ids") .filtered(lambda line: line.account_id.account_type == "asset_receivable") ) - with self.cr0.savepoint(), self.cr1.savepoint(): - # Reconciling "last move" - # reconcile a payment with many invoices spend a lot so it could - # lock records too many time - lines2reconcile.reconcile() - # Many pieces of code call flush directly - self.env0.flush_all() - self._create_invoice_form(self.env1) + # Reconciling "last move" + # reconcile a payment with many invoices spend a lot so it could + # lock records too many time + lines2reconcile.reconcile() + # Many pieces of code call flush directly + self.env0.flush_all() + self._create_invoice_form(self.env1) self._commit_crs(self.env0, self.env1) def test_sequence_concurrency_50_reconciling_last_payment(self): @@ -238,43 +361,40 @@ def test_sequence_concurrency_50_reconciling_last_payment(self): invoice = self._create_invoice_form(self.env0) payment = self._create_payment_form(self.env0) payment_move = payment.move_id - self.cr0.commit() + self.env0.cr.commit() lines2reconcile = ( (payment_move | invoice) .mapped("line_ids") .filtered(lambda line: line.account_id.account_type == "asset_receivable") ) - with self.cr0.savepoint(), self.cr1.savepoint(): - # Reconciling "last move" - # reconcile a payment with many invoices spend a lot so it could - # lock records too many time - lines2reconcile.reconcile() - # Many pieces of code call flush directly - self.env0.flush_all() - self._create_payment_form(self.env1) + # Reconciling "last move" + # reconcile a payment with many invoices spend a lot so it could + # lock records too many time + lines2reconcile.reconcile() + # Many pieces of code call flush directly + self.env0.flush_all() + self._create_payment_form(self.env1) self._commit_crs(self.env0, self.env1) def test_sequence_concurrency_90_payments(self): """Creating concurrent payments should not raises errors""" # Create "last move" to lock self._create_payment_form(self.env0, ir_sequence_standard=True) - self.cr0.commit() - with self.cr1.savepoint(), self.cr2.savepoint(): - self._create_payment_form(self.env1, ir_sequence_standard=True) - self._create_payment_form(self.env2, ir_sequence_standard=True) + self.env0.cr.commit() + self._create_payment_form(self.env1, ir_sequence_standard=True) + self._create_payment_form(self.env2, ir_sequence_standard=True) self._commit_crs(self.env0, self.env1, self.env2) def test_sequence_concurrency_92_invoices(self): """Creating concurrent invoices should not raises errors""" # Create "last move" to lock self._create_invoice_form(self.env0, ir_sequence_standard=True) - self.cr0.commit() - with self.cr1.savepoint(), self.cr2.savepoint(): - self._create_invoice_form(self.env1, ir_sequence_standard=True) - # Using another partner to bypass "increase_rank" lock error - self._create_invoice_form( - self.env2, partner=self.partner2, ir_sequence_standard=True - ) + self.env0.cr.commit() + self._create_invoice_form(self.env1, ir_sequence_standard=True) + # Using another partner to bypass "increase_rank" lock error + self._create_invoice_form( + self.env2, partner_id=self.data["partner2_id"], ir_sequence_standard=True + ) self._commit_crs(self.env0, self.env1, self.env2) @tools.mute_logger("odoo.sql_db") @@ -286,11 +406,11 @@ def test_sequence_concurrency_95_pay2inv_inv2pay(self): self._create_invoice_form(self.env0) # Create "last move" to lock self._create_payment_form(self.env0) - self.cr0.commit() - self.cr0.execute( + self.env0.cr.commit() + self.env0.cr.execute( "SELECT setting FROM pg_settings WHERE name = 'deadlock_timeout'" ) - deadlock_timeout = int(self.cr0.fetchone()[0]) # ms + deadlock_timeout = int(self.env0.cr.fetchone()[0]) # ms # You could not have permission to set this parameter # psycopg2.errors.InsufficientPrivilege self.assertTrue( diff --git a/account_move_name_sequence/views/account_journal_views.xml b/account_move_name_sequence/views/account_journal_views.xml index 9a5140a373f..282d48573de 100644 --- a/account_move_name_sequence/views/account_journal_views.xml +++ b/account_move_name_sequence/views/account_journal_views.xml @@ -7,7 +7,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> - account.journal @@ -43,5 +42,4 @@
- diff --git a/account_move_name_sequence/views/account_move_views.xml b/account_move_name_sequence/views/account_move_views.xml index 450e829c04c..69bddd022f7 100644 --- a/account_move_name_sequence/views/account_move_views.xml +++ b/account_move_name_sequence/views/account_move_views.xml @@ -5,7 +5,6 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> - account.move @@ -25,5 +24,4 @@ -