diff --git a/account_journal_general_sequence/README.rst b/account_journal_general_sequence/README.rst new file mode 100644 index 00000000..fa0297bd --- /dev/null +++ b/account_journal_general_sequence/README.rst @@ -0,0 +1,121 @@ +==================================== +General sequence in account journals +==================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-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_journal_general_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_journal_general_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| + +This module extends the functionality of account to support sequenced entry +numbers and to allow you to renumber them if needed, on demand. + +It adds a new field called *Entry number*. This is independent from the *Number* +that Odoo adds by default, and has different purpose. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure journal sequences: + +#. Have full accounting permissions. +#. Go to *Invoicing > Configuration > Accounting > Journals*. +#. Select or create the journal you want to configure. +#. Use *Account entry number sequence* to configure a sequence. + +Note that: + +* Various journals can share the same sequence. +* All journals get a shared default sequence, per company. +* Entry numbers must be unique per company. So, if you use different sequences + per journal, make sure they don't produce colliding results. + +Usage +===== + +To see journal entry numbers: + +#. Go to *Invoicing > Accounting > Miscellaneous > Journal Entries*. +#. Notice the new field *Entry Number*. Only posted moves get an entry number. + +Note that: + +* You can use that new field in quick searches. +* You can see it also in *Invoicing > Accounting > Miscellaneous > Journal Items*. + +To renumber journal entries: + +#. Have full accounting permissions. +#. Have *Accounting / Invoicing / Billing Administrator* permissions. +#. Go to *Invoicing > Accounting > Actions > Renumber journal entries*. +#. Configure those parameters. +#. Click on *Renumber*. + +Note that: + +* You will only be able to select sequences related to journals. +* A sequence usually affects various journals, if not all. + +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 +~~~~~~~ + +* Moduon + +Contributors +~~~~~~~~~~~~ + +* Jairo Llopis (`Moduon `__) +* Rafael Blasco (`Moduon `__) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/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_journal_general_sequence/__init__.py b/account_journal_general_sequence/__init__.py new file mode 100644 index 00000000..aee8895e --- /dev/null +++ b/account_journal_general_sequence/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/account_journal_general_sequence/__manifest__.py b/account_journal_general_sequence/__manifest__.py new file mode 100644 index 00000000..2ca011f5 --- /dev/null +++ b/account_journal_general_sequence/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2022 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +{ + "name": "General sequence in account journals", + "summary": "Add configurable sequence to account moves, per journal", + "version": "14.0.1.0.0", + "category": "Accounting/Accounting", + "website": "https://github.com/OCA/account-financial-tools", + "author": "Moduon, Odoo Community Association (OCA)", + "license": "LGPL-3", + "external_dependencies": {"python": ["freezegun"]}, + "depends": [ + "account", + ], + "data": [ + "security/ir.model.access.csv", + "views/account_journal.xml", + "views/account_move_line.xml", + "views/account_move.xml", + "wizards/account_move_renumber_wizard_views.xml", + ], +} diff --git a/account_journal_general_sequence/i18n/account_journal_general_sequence.pot b/account_journal_general_sequence/i18n/account_journal_general_sequence.pot new file mode 100644 index 00000000..3fa5305f --- /dev/null +++ b/account_journal_general_sequence/i18n/account_journal_general_sequence.pot @@ -0,0 +1,188 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_journal_general_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-27 08:32+0000\n" +"PO-Revision-Date: 2022-05-27 08:32+0000\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_journal_general_sequence +#: code:addons/account_journal_general_sequence/models/account_journal.py:0 +#, python-format +msgid "Account entry default numbering" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__entry_number_sequence_id +msgid "Account entry number sequence" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move_renumber_wizard +msgid "Account move entry renumbering wizard" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_bank_statement_line__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_line__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_payment__entry_number +msgid "Automatic numbering, based on journal configuration." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__available_sequence_ids +msgid "Available sequences" +msgstr "" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Cancel" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__create_uid +msgid "Created by" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__create_date +msgid "Created on" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__display_name +msgid "Display Name" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_bank_statement_line__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_payment__entry_number +msgid "Entry Number" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.constraint,message:account_journal_general_sequence.constraint_account_move_entry_number_unique +msgid "Entry number must be unique per company." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__id +msgid "ID" +msgstr "" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "" +"If you have already filed and legalized your journals with the competent " +"authority, this action could change it. Continue?" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_journal +msgid "Journal" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move_line +msgid "Journal Item" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard____last_update +msgid "Last Modified on" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__write_date +msgid "Last Updated on" +msgstr "" + +#. module: account_journal_general_sequence +#: code:addons/account_journal_general_sequence/wizards/account_move_renumber_wizard.py:0 +#, python-format +msgid "No account moves found." +msgstr "" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Renumber" +msgstr "" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Renumber account entry numbers" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__starting_date +msgid "Renumber account moves starting this day." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.actions.act_window,name:account_journal_general_sequence.account_move_renumber_wizard_action +#: model:ir.ui.menu,name:account_journal_general_sequence.account_move_renumber_wizard_menu +msgid "Renumber journal entries" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__starting_number +msgid "Reset sequence to this number before starting." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__sequence_id +msgid "Sequence" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__sequence_id +msgid "" +"Sequence to use for renumbering. Affects all journals that use this " +"sequence." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_journal__entry_number_sequence_id +msgid "Sequence used for account entry numbering." +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__starting_date +msgid "Starting Date" +msgstr "" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__starting_number +msgid "Starting Number" +msgstr "" diff --git a/account_journal_general_sequence/i18n/es.po b/account_journal_general_sequence/i18n/es.po new file mode 100644 index 00000000..0870890a --- /dev/null +++ b/account_journal_general_sequence/i18n/es.po @@ -0,0 +1,193 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_move_numbered +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-27 08:32+0000\n" +"PO-Revision-Date: 2022-05-27 09:34+0100\n" +"Last-Translator: Jairo Llopis \n" +"Language-Team: \n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#. module: account_journal_general_sequence +#: code:addons/account_journal_general_sequence/models/account_journal.py:0 +#, python-format +msgid "Account entry default numbering" +msgstr "Numeración por defecto de asientos contables" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__entry_number_sequence_id +msgid "Account entry number sequence" +msgstr "Secuencia para numerar los asientos" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move_renumber_wizard +msgid "Account move entry renumbering wizard" +msgstr "Asistente para renumerar asientos contables" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_bank_statement_line__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_line__entry_number +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_payment__entry_number +msgid "Automatic numbering, based on journal configuration." +msgstr "Numeración automática, basada en la configuración por diario." + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__available_sequence_ids +msgid "Available sequences" +msgstr "Secuencias disponibles" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__display_name +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_bank_statement_line__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__entry_number +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_payment__entry_number +msgid "Entry Number" +msgstr "Número de asiento" + +#. module: account_journal_general_sequence +#: model:ir.model.constraint,message:account_journal_general_sequence.constraint_account_move_entry_number_unique +msgid "Entry number must be unique per company." +msgstr "El número de asiento debe ser único por compañía." + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line__id +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__id +msgid "ID" +msgstr "ID" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "" +"If you have already filed and legalized your journals with the competent " +"authority, this action could change it. Continue?" +msgstr "" +"Si ya ha presentado y legalizado sus diarios ante la autoridad competente, " +"esta acción podría modificarlo. ¿Continuar?" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_journal +msgid "Journal" +msgstr "Diario" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move +msgid "Journal Entry" +msgstr "Asiento contable" + +#. module: account_journal_general_sequence +#: model:ir.model,name:account_journal_general_sequence.model_account_move_line +msgid "Journal Item" +msgstr "Apunte contable" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_journal____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_line____last_update +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: account_journal_general_sequence +#: code:addons/account_journal_general_sequence/wizards/account_move_renumber_wizard.py:0 +#, python-format +msgid "No account moves found." +msgstr "No se ha encontrado ningún asiento contable." + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Renumber" +msgstr "Renumerar" + +#. module: account_journal_general_sequence +#: model_terms:ir.ui.view,arch_db:account_journal_general_sequence.account_move_renumber_wizard_view_form +msgid "Renumber account entry numbers" +msgstr "Renumerar asientos contables" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__starting_date +msgid "Renumber account moves starting this day." +msgstr "Renumerar asientos contables a partir de este día." + +#. module: account_journal_general_sequence +#: model:ir.actions.act_window,name:account_journal_general_sequence.account_move_renumber_wizard_action +#: model:ir.ui.menu,name:account_journal_general_sequence.account_move_renumber_wizard_menu +msgid "Renumber journal entries" +msgstr "Renumerar asientos contables" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__starting_number +msgid "Reset sequence to this number before starting." +msgstr "Reiniciar la secuencia a este número antes de empezar." + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__sequence_id +msgid "Sequence" +msgstr "Secuencia" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_move_renumber_wizard__sequence_id +msgid "" +"Sequence to use for renumbering. Affects all journals that use this sequence." +msgstr "" +"Secuencia usada al renumerar. Afectará a todos los diarios que usen esta " +"secuencia." + +#. module: account_journal_general_sequence +#: model:ir.model.fields,help:account_journal_general_sequence.field_account_journal__entry_number_sequence_id +msgid "Sequence used for account entry numbering." +msgstr "Secuencia usada para renumerar los asientos contables." + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__starting_date +msgid "Starting Date" +msgstr "Fecha de inicio" + +#. module: account_journal_general_sequence +#: model:ir.model.fields,field_description:account_journal_general_sequence.field_account_move_renumber_wizard__starting_number +msgid "Starting Number" +msgstr "Número inicial" diff --git a/account_journal_general_sequence/models/__init__.py b/account_journal_general_sequence/models/__init__.py new file mode 100644 index 00000000..3af26e9a --- /dev/null +++ b/account_journal_general_sequence/models/__init__.py @@ -0,0 +1,3 @@ +from . import account_journal +from . import account_move +from . import account_move_line diff --git a/account_journal_general_sequence/models/account_journal.py b/account_journal_general_sequence/models/account_journal.py new file mode 100644 index 00000000..c36eb153 --- /dev/null +++ b/account_journal_general_sequence/models/account_journal.py @@ -0,0 +1,39 @@ +# Copyright 2022 Moduon +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +import logging + +from odoo import _, fields, models + +_logger = logging.getLogger(__name__) + + +class AccountJournal(models.Model): + _inherit = "account.journal" + + entry_number_sequence_id = fields.Many2one( + comodel_name="ir.sequence", + string="Account entry number sequence", + default=lambda self: self._default_entry_number_sequence(), + copy=False, + help="Sequence used for account entry numbering.", + ) + + def _default_entry_number_sequence(self): + """Get the default sequence for all journals.""" + result = self.env["ir.sequence"].search( + [("code", "=", "account_journal_general_sequence.default")] + ) + if result: + return result + _logger.info("Creating default sequence for account move numbers") + result = self.env["ir.sequence"].create( + { + "name": _("Account entry default numbering"), + "code": "account_journal_general_sequence.default", + "implementation": "no_gap", + "prefix": "%(range_year)s/", + "padding": 10, + "use_date_range": True, + } + ) + return result diff --git a/account_journal_general_sequence/models/account_move.py b/account_journal_general_sequence/models/account_move.py new file mode 100644 index 00000000..c3c2c9c1 --- /dev/null +++ b/account_journal_general_sequence/models/account_move.py @@ -0,0 +1,56 @@ +# Copyright 2022 Moduon +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +import logging + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class AccountMove(models.Model): + _inherit = "account.move" + + _sql_constraints = [ + ( + "entry_number_unique", + "UNIQUE(entry_number, company_id)", + "Entry number must be unique per company.", + ), + ] + + entry_number = fields.Char( + index=True, + readonly=True, + tracking=True, + store=True, + compute="_compute_entry_number", + help="Automatic numbering, based on journal configuration.", + ) + + @api.depends("state") + def _compute_entry_number(self): + """Assign an entry number when posting.""" + canceled = self.filtered_domain( + [("state", "=", "cancel"), ("entry_number", "!=", False)] + ) + canceled.entry_number = False + if canceled: + no_gap_seqs = canceled.mapped( + "journal_id.entry_number_sequence_id" + ).filtered_domain([("implementation", "=", "no_gap")]) + if no_gap_seqs: + _logger.warning( + "Emptied entry_number for %r after cancellation. " + "This created gaps on %r.", + canceled, + no_gap_seqs, + ) + chosen = self.filtered_domain( + [("state", "=", "posted"), ("entry_number", "=", False)] + ) + for move in chosen.sorted(lambda one: (one.date, one.name, one.id)): + move.entry_number = move.journal_id.entry_number_sequence_id._next( + move.date + ) + if chosen: + _logger.info("Added entry_number to %r", chosen) diff --git a/account_journal_general_sequence/models/account_move_line.py b/account_journal_general_sequence/models/account_move_line.py new file mode 100644 index 00000000..e60e321c --- /dev/null +++ b/account_journal_general_sequence/models/account_move_line.py @@ -0,0 +1,10 @@ +# Copyright 2022 Moduon +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import fields, models + + +class AccountMoveLine(models.Model): + _inherit = "account.move.line" + + entry_number = fields.Char(related="move_id.entry_number") diff --git a/account_journal_general_sequence/readme/CONFIGURE.rst b/account_journal_general_sequence/readme/CONFIGURE.rst new file mode 100644 index 00000000..8f532758 --- /dev/null +++ b/account_journal_general_sequence/readme/CONFIGURE.rst @@ -0,0 +1,13 @@ +To configure journal sequences: + +#. Have full accounting permissions. +#. Go to *Invoicing > Configuration > Accounting > Journals*. +#. Select or create the journal you want to configure. +#. Use *Account entry number sequence* to configure a sequence. + +Note that: + +* Various journals can share the same sequence. +* All journals get a shared default sequence, per company. +* Entry numbers must be unique per company. So, if you use different sequences + per journal, make sure they don't produce colliding results. diff --git a/account_journal_general_sequence/readme/CONTRIBUTORS.rst b/account_journal_general_sequence/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..958ce345 --- /dev/null +++ b/account_journal_general_sequence/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Jairo Llopis (`Moduon `__) +* Rafael Blasco (`Moduon `__) diff --git a/account_journal_general_sequence/readme/DESCRIPTION.rst b/account_journal_general_sequence/readme/DESCRIPTION.rst new file mode 100644 index 00000000..ce756023 --- /dev/null +++ b/account_journal_general_sequence/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This module extends the functionality of account to support sequenced entry +numbers and to allow you to renumber them if needed, on demand. + +It adds a new field called *Entry number*. This is independent from the *Number* +that Odoo adds by default, and has different purpose. diff --git a/account_journal_general_sequence/readme/USAGE.rst b/account_journal_general_sequence/readme/USAGE.rst new file mode 100644 index 00000000..3b6cbe10 --- /dev/null +++ b/account_journal_general_sequence/readme/USAGE.rst @@ -0,0 +1,22 @@ +To see journal entry numbers: + +#. Go to *Invoicing > Accounting > Miscellaneous > Journal Entries*. +#. Notice the new field *Entry Number*. Only posted moves get an entry number. + +Note that: + +* You can use that new field in quick searches. +* You can see it also in *Invoicing > Accounting > Miscellaneous > Journal Items*. + +To renumber journal entries: + +#. Have full accounting permissions. +#. Have *Accounting / Invoicing / Billing Administrator* permissions. +#. Go to *Invoicing > Accounting > Actions > Renumber journal entries*. +#. Configure those parameters. +#. Click on *Renumber*. + +Note that: + +* You will only be able to select sequences related to journals. +* A sequence usually affects various journals, if not all. diff --git a/account_journal_general_sequence/security/ir.model.access.csv b/account_journal_general_sequence/security/ir.model.access.csv new file mode 100644 index 00000000..70a86e48 --- /dev/null +++ b/account_journal_general_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 +access_account_move_renumber_wizard,access_account_move_renumber_wizard,model_account_move_renumber_wizard,account.group_account_manager,1,1,1,1 diff --git a/account_journal_general_sequence/static/description/icon.png b/account_journal_general_sequence/static/description/icon.png new file mode 100644 index 00000000..553d700b Binary files /dev/null and b/account_journal_general_sequence/static/description/icon.png differ diff --git a/account_journal_general_sequence/static/description/index.html b/account_journal_general_sequence/static/description/index.html new file mode 100644 index 00000000..d8af41d8 --- /dev/null +++ b/account_journal_general_sequence/static/description/index.html @@ -0,0 +1,468 @@ + + + + + + +General sequence in account journals + + + +
+

General sequence in account journals

+ + +

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

+

This module extends the functionality of account to support sequenced entry +numbers and to allow you to renumber them if needed, on demand.

+

It adds a new field called Entry number. This is independent from the Number +that Odoo adds by default, and has different purpose.

+

Table of contents

+ +
+

Configuration

+

To configure journal sequences:

+
    +
  1. Have full accounting permissions.
  2. +
  3. Go to Invoicing > Configuration > Accounting > Journals.
  4. +
  5. Select or create the journal you want to configure.
  6. +
  7. Use Account entry number sequence to configure a sequence.
  8. +
+

Note that:

+
    +
  • Various journals can share the same sequence.
  • +
  • All journals get a shared default sequence, per company.
  • +
  • Entry numbers must be unique per company. So, if you use different sequences +per journal, make sure they don’t produce colliding results.
  • +
+
+
+

Usage

+

To see journal entry numbers:

+
    +
  1. Go to Invoicing > Accounting > Miscellaneous > Journal Entries.
  2. +
  3. Notice the new field Entry Number. Only posted moves get an entry number.
  4. +
+

Note that:

+
    +
  • You can use that new field in quick searches.
  • +
  • You can see it also in Invoicing > Accounting > Miscellaneous > Journal Items.
  • +
+

To renumber journal entries:

+
    +
  1. Have full accounting permissions.
  2. +
  3. Have Accounting / Invoicing / Billing Administrator permissions.
  4. +
  5. Go to Invoicing > Accounting > Actions > Renumber journal entries.
  6. +
  7. Configure those parameters.
  8. +
  9. Click on Renumber.
  10. +
+

Note that:

+
    +
  • You will only be able to select sequences related to journals.
  • +
  • A sequence usually affects various journals, if not all.
  • +
+
+
+

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

+
    +
  • Moduon
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

This module is part of the OCA/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_journal_general_sequence/tests/__init__.py b/account_journal_general_sequence/tests/__init__.py new file mode 100644 index 00000000..60360ad2 --- /dev/null +++ b/account_journal_general_sequence/tests/__init__.py @@ -0,0 +1 @@ +from . import test_numbering diff --git a/account_journal_general_sequence/tests/test_numbering.py b/account_journal_general_sequence/tests/test_numbering.py new file mode 100644 index 00000000..001a8d3a --- /dev/null +++ b/account_journal_general_sequence/tests/test_numbering.py @@ -0,0 +1,46 @@ +# Copyright 2022 Moduon +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from freezegun import freeze_time + +from odoo.tests.common import Form, tagged +from odoo.tools import mute_logger + +from odoo.addons.account.tests.common import TestAccountReconciliationCommon + + +@freeze_time("2022-05-11", tick=True) +@tagged("post_install", "-at_install") +class RenumberCase(TestAccountReconciliationCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + + def test_invoice_gets_entry_number(self): + # Draft invoice without entry number + invoice = self._create_invoice() + self.assertFalse(invoice.entry_number) + # Gets one once posted + invoice.action_post() + self.assertTrue(invoice.entry_number.startswith("2022/")) + # Lost number when canceled + with mute_logger( + "odoo.addons.account_journal_general_sequence.models.account_move" + ): + invoice.button_cancel() + self.assertFalse(invoice.entry_number) + + def test_renumber(self): + # Post invoices in wrong order + new_invoice = self._create_invoice( + date_invoice="2022-05-10", auto_validate=True + ) + old_invoice = self._create_invoice( + date_invoice="2022-04-30", auto_validate=True + ) + self.assertLess(new_invoice.entry_number, old_invoice.entry_number) + # Fix entry number order with wizard; default values are OK + wiz_f = Form(self.env["account.move.renumber.wizard"]) + self.assertEqual(len(wiz_f.available_sequence_ids), 1) + wiz = wiz_f.save() + wiz.action_renumber() + self.assertGreater(new_invoice.entry_number, old_invoice.entry_number) diff --git a/account_journal_general_sequence/views/account_journal.xml b/account_journal_general_sequence/views/account_journal.xml new file mode 100644 index 00000000..13f8e690 --- /dev/null +++ b/account_journal_general_sequence/views/account_journal.xml @@ -0,0 +1,28 @@ + + + + + + Add move number sequence to tree + account.journal + + + + + + + + + + Add move number sequence to form + account.journal + + + + + + + + + diff --git a/account_journal_general_sequence/views/account_move.xml b/account_journal_general_sequence/views/account_move.xml new file mode 100644 index 00000000..30151056 --- /dev/null +++ b/account_journal_general_sequence/views/account_move.xml @@ -0,0 +1,42 @@ + + + + + + Add move number to tree + account.move + + + + + + + + + + Add move number to form + account.move + + + + + + + + + + + + + Add move number to search + account.move + + + + + + + + + diff --git a/account_journal_general_sequence/views/account_move_line.xml b/account_journal_general_sequence/views/account_move_line.xml new file mode 100644 index 00000000..776313cc --- /dev/null +++ b/account_journal_general_sequence/views/account_move_line.xml @@ -0,0 +1,39 @@ + + + + + + Add move number to tree + account.move.line + + + + + + + + + + Add move number to form + account.move.line + + + + + + + + + + Add move number to search + account.move.line + + + + + + + + + diff --git a/account_journal_general_sequence/wizards/__init__.py b/account_journal_general_sequence/wizards/__init__.py new file mode 100644 index 00000000..08f746fc --- /dev/null +++ b/account_journal_general_sequence/wizards/__init__.py @@ -0,0 +1 @@ +from . import account_move_renumber_wizard diff --git a/account_journal_general_sequence/wizards/account_move_renumber_wizard.py b/account_journal_general_sequence/wizards/account_move_renumber_wizard.py new file mode 100644 index 00000000..e8fcc7bc --- /dev/null +++ b/account_journal_general_sequence/wizards/account_move_renumber_wizard.py @@ -0,0 +1,82 @@ +# Copyright 2022 Moduon +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import date + +from odoo import _, api, exceptions, fields, models + + +class AccountMoveRenumberWizard(models.TransientModel): + _name = "account.move.renumber.wizard" + _description = "Account move entry renumbering wizard" + + starting_date = fields.Date( + required=True, + default=lambda self: self._default_starting_date(), + help="Renumber account moves starting this day.", + ) + starting_number = fields.Integer( + default=1, help="Reset sequence to this number before starting." + ) + available_sequence_ids = fields.Many2many( + comodel_name="ir.sequence", + string="Available sequences", + default=lambda self: self._default_available_sequence_ids(), + ) + sequence_id = fields.Many2one( + comodel_name="ir.sequence", + string="Sequence", + required=True, + default=lambda self: self._default_entry_number_sequence(), + domain="[('id', 'in', available_sequence_ids)]", + help="Sequence to use for renumbering. Affects all journals that use this sequence.", + ) + + @api.model + def _default_starting_date(self): + """Start by default on day 1 of current year.""" + return date(date.today().year, 1, 1) + + @api.model + def _default_entry_number_sequence(self): + """Get default sequence if it exists.""" + return self.env["ir.sequence"].search( + [("code", "=", "account_journal_general_sequence.default")] + ) + + @api.model + def _default_available_sequence_ids(self): + """Let view display only journal-related sequences.""" + return self.env["account.journal"].search([]).mapped("entry_number_sequence_id") + + def action_renumber(self): + """Renumber moves. + + Makes sure moves exist. Sorts them. Resets sequences. Renumbers them. + """ + # Find posted moves that match wizard criteria + moves = self.env["account.move"].search( + [ + ("state", "=", "posted"), + ("date", ">=", self.starting_date), + ("journal_id.entry_number_sequence_id", "=", self.sequence_id.id), + ], + order="date, id", + ) + if not moves: + raise exceptions.UserError(_("No account moves found.")) + # Reset sequence + future_ranges = self.env["ir.sequence.date_range"].search( + [ + ("date_from", ">", self.starting_date), + ("sequence_id", "=", self.sequence_id.id), + ] + ) + future_ranges.unlink() + current_range = self.sequence_id._get_current_sequence(self.starting_date) + current_range.number_next_actual = self.starting_number + self.sequence_id.number_next_actual = self.starting_number + # Renumber the moves + moves.entry_number = False + moves.flush(["entry_number"]) + moves._compute_entry_number() diff --git a/account_journal_general_sequence/wizards/account_move_renumber_wizard_views.xml b/account_journal_general_sequence/wizards/account_move_renumber_wizard_views.xml new file mode 100644 index 00000000..ccb6f40e --- /dev/null +++ b/account_journal_general_sequence/wizards/account_move_renumber_wizard_views.xml @@ -0,0 +1,46 @@ + + + + + + Renumber form + account.move.renumber.wizard + +
+ + + + + + + + +
+
+
+
+
+ + + Renumber journal entries + account.move.renumber.wizard + form + new + + + + +