diff --git a/account_move_name_sequence/README.rst b/account_move_name_sequence/README.rst new file mode 100644 index 000000000..aa87a0ca1 --- /dev/null +++ b/account_move_name_sequence/README.rst @@ -0,0 +1,162 @@ +============================ +Account Move Number Sequence +============================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:b06670c2d2d2da46bb2adb03b7c40fd5cd9bf5bfd4000063131334effdb3fe7e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/17.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-17-0/account-financial-tools-17-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=17.0 + :alt: Try me on Runboat + +|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 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 handles this is not easy to understand and quite difficult to + debug. + +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** + +.. 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 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 +=========== + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion +* Vauxoo + +Contributors +------------ + +- `Akretion `__: + + - Alexis de Lattre + +- `Vauxoo `__: + + - Moisés López + - Francisco Luna + +- `Factor Libre `__: + + - Rodrigo Bonilla Martinez + +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 +.. |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 +.. |maintainer-luisg123v| image:: https://github.com/luisg123v.png?size=40px + :target: https://github.com/luisg123v + :alt: luisg123v + +Current `maintainers `__: + +|maintainer-alexis-via| |maintainer-moylop260| |maintainer-frahikLV| |maintainer-luisg123v| + +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/__init__.py b/account_move_name_sequence/__init__.py new file mode 100644 index 000000000..1d353d71e --- /dev/null +++ b/account_move_name_sequence/__init__.py @@ -0,0 +1,2 @@ +from .hooks import post_init_hook +from . import models diff --git a/account_move_name_sequence/__manifest__.py b/account_move_name_sequence/__manifest__.py new file mode 100644 index 000000000..0feb2f643 --- /dev/null +++ b/account_move_name_sequence/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# 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": "17.0.1.0.0", + "category": "Accounting", + "license": "AGPL-3", + "summary": "Generate journal entry number from sequence", + "author": "Akretion,Vauxoo,Odoo Community Association (OCA)", + "maintainers": ["alexis-via", "moylop260", "frahikLV", "luisg123v"], + "website": "https://github.com/OCA/account-financial-tools", + "depends": [ + "account", + ], + "data": [ + "views/account_journal.xml", + "views/account_move.xml", + "security/ir.model.access.csv", + ], + "post_init_hook": "post_init_hook", + "installable": True, +} diff --git a/account_move_name_sequence/hooks.py b/account_move_name_sequence/hooks.py new file mode 100644 index 000000000..86d330ef7 --- /dev/null +++ b/account_move_name_sequence/hooks.py @@ -0,0 +1,33 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# 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). + + +def post_init_hook(env): + create_journal_sequences(env) + + +def create_journal_sequences(env): + 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 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 000000000..0fbe285c5 --- /dev/null +++ b/account_move_name_sequence/i18n/account_move_name_sequence.pot @@ -0,0 +1,146 @@ +# 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" +"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.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 "" +"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/i18n/ar.po b/account_move_name_sequence/i18n/ar.po new file mode 100644 index 000000000..ab6950b2c --- /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/i18n/es.po b/account_move_name_sequence/i18n/es.po new file mode 100644 index 000000000..9e8159e0b --- /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." diff --git a/account_move_name_sequence/i18n/fr.po b/account_move_name_sequence/i18n/fr.po new file mode 100644 index 000000000..fd0b14f6f --- /dev/null +++ b/account_move_name_sequence/i18n/fr.po @@ -0,0 +1,161 @@ +# 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-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.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 "" +"Une pièce comptable ne peut pas être comptabilisé car elle n'a pas de numéro " +"attribué.\n" +"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 +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 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 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 +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 factures et les " +"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 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 numéros des pièces comptables." diff --git a/account_move_name_sequence/i18n/hr.po b/account_move_name_sequence/i18n/hr.po new file mode 100644 index 000000000..06e5c7d93 --- /dev/null +++ b/account_move_name_sequence/i18n/hr.po @@ -0,0 +1,162 @@ +# 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_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 "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__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 "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." diff --git a/account_move_name_sequence/models/__init__.py b/account_move_name_sequence/models/__init__.py new file mode 100644 index 000000000..069c9b592 --- /dev/null +++ b/account_move_name_sequence/models/__init__.py @@ -0,0 +1,3 @@ +from . import account_journal +from . import account_move +from . import ir_sequence 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 000000000..f5c855e9e --- /dev/null +++ b/account_move_name_sequence/models/account_journal.py @@ -0,0 +1,250 @@ +# Copyright 2021 Akretion France (http://www.akretion.com/) +# 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 + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +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_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.", + ) + # 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): + 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: + 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: + 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_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", True) + 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): + code = vals.get("code") and vals["code"].upper() or "" + prefix = "{}{}/%(range_year)s/".format(refund and "R" or "", code) + seq_vals = { + "name": "{}{}".format( + 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) + 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): + """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 {} could not get sequence {} values based on current moves. " + "Using default values.".format(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 = "{}{}{}{}{}%".format( + prefix1, + "_" * seq_format_values["year_length"], + prefix2, + "_" * bool(month) * 2, + prefix3, + ) + prefixes = prefix1 + prefix2 + select_year = ( + f"split_part(name, '{prefix2}', {prefixes.count(prefix2)})" + if prefix2 + else "''" + ) + prefixes += prefix3 + select_month = ( + f"split_part(name, '{prefix3}', {prefixes.count(prefix3)})" + if prefix3 + else "''" + ) + select_max_number = ( + "MAX(split_part(name, '{}', {})::INTEGER) AS max_number".format( + prefixes[-1], + prefixes.count(prefixes[-1]) + 1, + ) + ) + query = ( + "SELECT {}, {}, {} FROM account_move " + "WHERE name LIKE %s AND journal_id=%s GROUP BY 1,2" + ).format(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(f"{year}-{month}-1") + date_to = fields.Date.end_of(date_from, "month") + else: + date_from = fields.Date.to_date(f"{year}-1-1") + date_to = fields.Date.to_date(f"{year}-12-31") + 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/models/account_move.py b/account_move_name_sequence/models/account_move.py new file mode 100644 index 000000000..f99bc9fde --- /dev/null +++ b/account_move_name_sequence/models/account_move.py @@ -0,0 +1,79 @@ +# 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 + + +class AccountMove(models.Model): + _inherit = "account.move" + + name = fields.Char(compute="_compute_name_by_sequence") + # 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 = [ + ( + "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: + 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.state == "posted" + and (not move.name or move.name == "/") + and move.journal_id + and move.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 + # 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 + self._inverse_name() + + # 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() + + 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) + + def _get_last_sequence(self, relaxed=False, with_prefix=None): + return super()._get_last_sequence(relaxed, None) 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 000000000..75c5265cf --- /dev/null +++ b/account_move_name_sequence/models/ir_sequence.py @@ -0,0 +1,52 @@ +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) + sequence_range = self.env["ir.sequence.date_range"] + prefix_suffix = f"{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 = fields.Date.start_of(date_obj, "month") + date_to = fields.Date.end_of(date_obj, "month") + else: + 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), + ], + 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), + ], + order="date_to desc", + limit=1, + ) + if date_range: + 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/pyproject.toml b/account_move_name_sequence/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/account_move_name_sequence/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/account_move_name_sequence/readme/CONFIGURE.md b/account_move_name_sequence/readme/CONFIGURE.md new file mode 100644 index 000000000..f4332d94b --- /dev/null +++ b/account_move_name_sequence/readme/CONFIGURE.md @@ -0,0 +1,16 @@ +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. diff --git a/account_move_name_sequence/readme/CONTRIBUTORS.md b/account_move_name_sequence/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..588d502ea --- /dev/null +++ b/account_move_name_sequence/readme/CONTRIBUTORS.md @@ -0,0 +1,7 @@ +- [Akretion](https://www.akretion.com): + - Alexis de Lattre \<\> +- [Vauxoo](https://www.vauxoo.com): + - Moisés López \<\> + - Francisco Luna \<\> +- [Factor Libre](https://www.factorlibre.com): + - Rodrigo Bonilla Martinez \<\> diff --git a/account_move_name_sequence/readme/DESCRIPTION.md b/account_move_name_sequence/readme/DESCRIPTION.md new file mode 100644 index 000000000..cf1fb2315 --- /dev/null +++ b/account_move_name_sequence/readme/DESCRIPTION.md @@ -0,0 +1,38 @@ +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: + +- 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](https://github.com/odoo/odoo/blob/14.0/addons/account/models/sequence_mixin.py) + that handles this is not easy to understand and quite difficult to + debug. + +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. 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 000000000..6247bc1e3 --- /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/static/description/icon.png b/account_move_name_sequence/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/account_move_name_sequence/static/description/icon.png differ 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 000000000..72838faae --- /dev/null +++ b/account_move_name_sequence/static/description/index.html @@ -0,0 +1,487 @@ + + + + + + +Account Move Number Sequence + + + +
+

Account Move Number Sequence

+ + +

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 +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 handles this is not easy to understand and quite difficult to +debug.
  • +
+

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

+

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

+

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.

+

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 maintainers:

+

alexis-via moylop260 frahikLV luisg123v

+

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/__init__.py b/account_move_name_sequence/tests/__init__.py new file mode 100644 index 000000000..5de02aafc --- /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 000000000..5d3e0ac6f --- /dev/null +++ b/account_move_name_sequence/tests/test_account_move_name_seq.py @@ -0,0 +1,312 @@ +# 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 freezegun import freeze_time + +from odoo import fields +from odoo.exceptions import UserError, ValidationError +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 = "{}{}".format(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) + move.button_draft() + 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_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() + + in_invoice = in_invoice.copy( + { + "invoice_date": self.date, + } + ) + in_invoice.action_post() + + move_reversal = self.env["account.move.reversal"].create( + { + "move_ids": in_invoice.ids, + "journal_id": in_invoice.journal_id.id, + "reason": "no reason", + } + ) + reversal = move_reversal.modify_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"].create( + { + "move_ids": in_invoice.ids, + "journal_id": in_invoice.journal_id.id, + "reason": "no reason", + } + ) + reversal = move_reversal.refund_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( + { + "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 = "{}{}".format(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) + + def test_remove_invoice_error_secuence_no_grap(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 can't delete a posted journal item. Don’t play games with your accounting records; reset the journal entry to draft before deleting it." + with self.assertRaisesRegex(UserError, error_msg): + invoice.unlink() + invoice.button_draft() + invoice.button_cancel() + 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, + }, + ) + ], + } + ) + self.assertEqual(in_refund_invoice.name, "/") + in_refund_invoice.action_post() + error_msg = "You can't delete a posted journal item. Don’t play games with your accounting records; reset the journal entry to draft before deleting it." + 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_journal.xml b/account_move_name_sequence/views/account_journal.xml new file mode 100644 index 000000000..102f49273 --- /dev/null +++ b/account_move_name_sequence/views/account_journal.xml @@ -0,0 +1,33 @@ + + + + + + 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 000000000..450e829c0 --- /dev/null +++ b/account_move_name_sequence/views/account_move.xml @@ -0,0 +1,29 @@ + + + + + + account.move + + + + 1 + + + name == '/' + 1 + + + state != 'draft' or name != '/' + + + + +