Merge PR #1847 into 15.0

Signed-off-by moylop260
This commit is contained in:
OCA-git-bot
2024-04-17 16:30:06 +00:00
17 changed files with 1120 additions and 14 deletions

View File

@@ -1,7 +1,8 @@
# Do NOT update manually; changes here will be overwritten by Copier
_commit: v1.17.2
_commit: v1.20
_src_path: gh:oca/oca-addons-repo-template
ci: GitHub
convert_readme_fragments_to_markdown: false
generate_requirements_txt: true
github_check_license: true
github_ci_extra_env: {}
@@ -14,9 +15,13 @@ odoo_test_flavor: Both
odoo_version: 15.0
org_name: Odoo Community Association (OCA)
org_slug: OCA
rebel_module_groups: []
rebel_module_groups:
- account_move_name_sequence
- account_sequence_option
repo_description: 'TODO: add repo description.'
repo_name: account-financial-tools
repo_slug: account-financial-tools
repo_website: https://github.com/OCA/account-financial-tools
use_pyproject_toml: false
use_ruff: false

View File

@@ -36,8 +36,17 @@ jobs:
matrix:
include:
- container: ghcr.io/oca/oca-ci/py3.8-odoo15.0:latest
include: "account_move_name_sequence"
name: test with Odoo account_move_name_sequence
- container: ghcr.io/oca/oca-ci/py3.8-ocb15.0:latest
include: "account_move_name_sequence"
name: test with OCB account_move_name_sequence
makepot: "true"
- container: ghcr.io/oca/oca-ci/py3.8-odoo15.0:latest
exclude: "account_move_name_sequence"
name: test with Odoo
- container: ghcr.io/oca/oca-ci/py3.8-ocb15.0:latest
exclude: "account_move_name_sequence"
name: test with OCB
makepot: "true"
services:
@@ -49,6 +58,9 @@ jobs:
POSTGRES_DB: odoo
ports:
- 5432:5432
env:
INCLUDE: "${{ matrix.include }}"
EXCLUDE: "${{ matrix.exclude }}"
steps:
- uses: actions/checkout@v3
with:

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@ __pycache__/
*.py[cod]
/.venv
/.pytest_cache
/.ruff_cache
# C extensions
*.so

View File

@@ -14,6 +14,8 @@ exclude: |
^docs/_templates/.*\.html$|
# Don't bother non-technical authors with formatting issues in docs
readme/.*\.(rst|md)$|
# Ignore build and dist directories in addons
/build/|/dist/|
# You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*)
default_language_version:
@@ -35,7 +37,7 @@ repos:
language: fail
files: '[a-zA-Z0-9_]*/i18n/en\.po$'
- repo: https://github.com/oca/maintainer-tools
rev: 969238e47c07d0c40573acff81d170f63245d738
rev: 9a170331575a265c092ee6b24b845ec508e8ef75
hooks:
# update the NOT INSTALLABLE ADDONS section above
- id: oca-update-pre-commit-excluded-addons
@@ -48,6 +50,7 @@ repos:
- --org-name=OCA
- --repo-name=account-financial-tools
- --if-source-changed
- --keep-source-digest
- repo: https://github.com/OCA/odoo-pre-commit-hooks
rev: v0.0.25
hooks:

View File

@@ -7,7 +7,7 @@ Account Move Number Sequence
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:3afe6316cda51964c0745fadd7bf028ba9a478aaa5b193d9adedd793ba3bc0b3
!! source digest: sha256:c1d07b9193af5e79dba57128500d43c3fc7e5aba05233d305bc0cf8caf9e6806
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png

View File

@@ -17,6 +17,9 @@
"depends": [
"account",
],
"demo": [
"demo/ir_sequence_demo.xml",
],
"data": [
"views/account_journal.xml",
"views/account_move.xml",

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="ir_sequence_demo" model="ir.sequence">
<field name="name">Standard Sequence Demo</field>
<field name="prefix">demo/%(range_year)s/</field>
<field name="use_date_range" eval="True" />
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field name="company_id" ref="base.main_company" />
</record>
</odoo>

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-10-10 19:36+0000\n"
"PO-Revision-Date: 2024-02-21 18:34+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\n"
@@ -37,24 +37,38 @@ 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 "Secuencia de introducción de abonos"
msgstr "Secuencia de Entrada de Notas de Crédito"
#. 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 notas de crédito especializadas"
msgstr "Secuencia de Notas de Crédito Especializadas"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. 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 entrada"
msgstr "Secuencia de Entrada"
#. 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 "Nombre máximo"
msgstr "Nombre Máximo"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id
msgid "ID"
msgstr "ID"
#. module: account_move_name_sequence
#: model:ir.model,name:account_move_name_sequence.model_account_journal
@@ -64,7 +78,14 @@ msgstr "Diario"
#. module: account_move_name_sequence
#: model:ir.model,name:account_move_name_sequence.model_account_move
msgid "Journal Entry"
msgstr "Entrada Diaria"
msgstr "Entrada de Diario"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update
msgid "Last Modified on"
msgstr "Última Modificación el"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__name
@@ -87,7 +108,7 @@ msgstr ""
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "Refund"
msgstr "Reembolso"
msgstr "Devolución"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
@@ -135,8 +156,8 @@ msgstr ""
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."
"Esta secuencia se utilizará para generar el número de asiento de diario para "
"reembolsos."
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id

View File

@@ -0,0 +1,166 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_move_name_sequence
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-06-04 08:08+0000\n"
"Last-Translator: Claude R Perrin <claude@perrin.it>\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érifier la configuration de la séquence sur le journal concerné."
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence
msgid ""
"Check this box if you don't want to share the same sequence for invoices and "
"credit notes made from this journal"
msgstr ""
"Cocher cette case si vous souhaitez créer 2 séquences distinctes pour les "
"factures et avoirs pour ce journal"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id
msgid "Credit Note Entry Sequence"
msgstr "Séquence pour les avoirs"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence
msgid "Dedicated Credit Note Sequence"
msgstr "Séquence des avoirs dédiée"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id
msgid "Entry Sequence"
msgstr "Séquence de la pièce comptable"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_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 "Nom le plus haut"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id
msgid "ID"
msgstr "ID"
#. 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_journal____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. 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
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"On journal '%s', the same sequence is used as Entry Sequence and Credit Note "
"Entry Sequence."
msgstr ""
"Pour le journal '%s', la même séquence est utilisée pour les pièces de "
"factures et d'avoirs."
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "Refund"
msgstr "Avoir"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#: model:ir.model,name:account_move_name_sequence.model_ir_sequence
#, python-format
msgid "Sequence"
msgstr "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
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"The company is not set on sequence '%s' configured as credit note sequence "
"of journal '%s'."
msgstr ""
"La société n'est pas défini sur la séquence d'avoir '%s' configurée pour le "
"journal '%s'."
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "The company is not set on sequence '%s' configured on journal '%s'."
msgstr ""
"La société n'est pas défini sur la séquence (de facturation) '%s' configurée "
"sur le 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 le numéro de pièce comptable 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 le numéro de pièce comptable (des "
"factures)."

View File

@@ -0,0 +1,157 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_move_name_sequence
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2022-08-22 21:07+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>\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.3.2\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 ""
"Temeljnica nemože biti proknjižena sa nazivom \"/\" ili praznom vrijednosti\n"
"Projerite molim sekvencu na dnevniku"
#. 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 ovdje ako ne želite isti sekvencu za račune i odobrenja 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 "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__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id
msgid "Entry Sequence"
msgstr "Početna sekvenca"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name
msgid "Highest Name"
msgstr "Najviši naziv"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id
msgid "ID"
msgstr "ID"
#. 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_journal____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update
msgid "Last Modified on"
msgstr "Zadnje modificirano"
#. 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
#: 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 ""
"U dnevniku '%s', ista sekvenca se koristi kao glavna i sekvenca za odobrenja."
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "Refund"
msgstr "Povrat"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#: model:ir.model,name:account_move_name_sequence.model_ir_sequence
#, python-format
msgid "Sequence"
msgstr "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 "Prefix sekvence"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"The company is not set on sequence '%s' configured as credit note sequence "
"of journal '%s'."
msgstr ""
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "The company is not set on sequence '%s' configured on journal '%s'."
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id
msgid ""
"This sequence will be used to generate the journal entry number for refunds."
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id
msgid "This sequence will be used to generate the journal entry number."
msgstr ""

View File

@@ -0,0 +1,151 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_move_name_sequence
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-10-17 18:36+0000\n"
"Last-Translator: Francesco Foresti <francesco.foresti@ooops404.com>\n"
"Language-Team: none\n"
"Language: it\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 ""
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence
msgid ""
"Check this box if you don't want to share the same sequence for invoices and "
"credit notes made from this journal"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence_id
msgid "Credit Note Entry Sequence"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__refund_sequence
msgid "Dedicated Credit Note Sequence"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id
msgid "Entry Sequence"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__highest_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__highest_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__highest_name
msgid "Highest Name"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id
msgid "ID"
msgstr "ID"
#. module: account_move_name_sequence
#: model:ir.model,name:account_move_name_sequence.model_account_journal
msgid "Journal"
msgstr "Registro"
#. module: account_move_name_sequence
#: model:ir.model,name:account_move_name_sequence.model_account_move
msgid "Journal Entry"
msgstr "Registrazione contabile"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. 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 "Numero"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"On journal '%s', the same sequence is used as Entry Sequence and Credit Note "
"Entry Sequence."
msgstr ""
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "Refund"
msgstr ""
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#: model:ir.model,name:account_move_name_sequence.model_ir_sequence
#, python-format
msgid "Sequence"
msgstr "Sequenza"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number
msgid "Sequence Number"
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix
msgid "Sequence Prefix"
msgstr ""
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"The company is not set on sequence '%s' configured as credit note sequence "
"of journal '%s'."
msgstr ""
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "The company is not set on sequence '%s' configured on journal '%s'."
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__refund_sequence_id
msgid ""
"This sequence will be used to generate the journal entry number for refunds."
msgstr ""
#. module: account_move_name_sequence
#: model:ir.model.fields,help:account_move_name_sequence.field_account_journal__sequence_id
msgid "This sequence will be used to generate the journal entry number."
msgstr ""

View File

@@ -0,0 +1,156 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_move_name_sequence
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-03-30 12:22+0000\n"
"Last-Translator: Matjaz Mozetic <matjaz@luxim.si>\n"
"Language-Team: none\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3;\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 ""
"Temeljnice ni mogoče knjižiti z nazivom \"/\" ali prazno vrednostjo\n"
"Prosimo, da preverite zaporedje v dnevniku"
#. 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, če želite v tem dnevniku uporabljati isto zaporedje za račune in "
"dobropise"
#. 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 "Zaporedje za dobropise"
#. 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 "Ločeno zaporedje za dobropise"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__display_name
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__sequence_id
msgid "Entry Sequence"
msgstr "Zaporedje vnosa"
#. 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šji naziv"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__id
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence__id
msgid "ID"
msgstr "ID"
#. 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 "Dnevniški vnos"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_journal____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move____last_update
#: model:ir.model.fields,field_description:account_move_name_sequence.field_ir_sequence____last_update
msgid "Last Modified on"
msgstr "Zadnjič spremenjeno"
#. 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 "Številka"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"On journal '%s', the same sequence is used as Entry Sequence and Credit Note "
"Entry Sequence."
msgstr "V dnevniku '%s' se uporablja isto zaporedje za vnose in dobropise."
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "Refund"
msgstr "Povračilo"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#: model:ir.model,name:account_move_name_sequence.model_ir_sequence
#, python-format
msgid "Sequence"
msgstr "Zaporedje"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_number
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_number
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_number
msgid "Sequence Number"
msgstr "Številka zaporedja"
#. module: account_move_name_sequence
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_bank_statement_line__sequence_prefix
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_move__sequence_prefix
#: model:ir.model.fields,field_description:account_move_name_sequence.field_account_payment__sequence_prefix
msgid "Sequence Prefix"
msgstr "Predpona zaporedja"
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid ""
"The company is not set on sequence '%s' configured as credit note sequence "
"of journal '%s'."
msgstr "Pri zaporedju '%s' za dobropise v dnevniku '%s' ni nastavljena družba."
#. module: account_move_name_sequence
#: code:addons/account_move_name_sequence/models/account_journal.py:0
#, python-format
msgid "The company is not set on sequence '%s' configured on journal '%s'."
msgstr "Pri zaporedju '%s' nastavljenem v dnevniku '%s' ni nastavljena družba."
#. 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 "To zaporedje bo v rabi za knjigovodske vnose dobropisov."
#. 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 "To zaporedje bo v rabi za knjigovodske vnose dobropisov."

View File

@@ -71,3 +71,10 @@ class AccountMove(models.Model):
def _get_last_sequence(self, relaxed=False, with_prefix=None, lock=True):
return super()._get_last_sequence(relaxed, None, lock)
def _compute_name(self):
"""Overwrite account module method in order to
avoid side effect if legacy code call it directly
like when creating entry from email.
"""
return self._compute_name_by_sequence()

View File

@@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:3afe6316cda51964c0745fadd7bf028ba9a478aaa5b193d9adedd793ba3bc0b3
!! source digest: sha256:c1d07b9193af5e79dba57128500d43c3fc7e5aba05233d305bc0cf8caf9e6806
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-financial-tools/tree/15.0/account_move_name_sequence"><img alt="OCA/account-financial-tools" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-financial-tools-15-0/account-financial-tools-15-0-account_move_name_sequence"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&amp;target_branch=15.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>In Odoo version 13.0 and previous versions, the number of journal entries was generated from a sequence configured on the journal.</p>

View File

@@ -1 +1,3 @@
from . import test_account_move_name_seq
from . import test_sequence_concurrency
from . import test_account_incoming_supplier_invoice

View File

@@ -0,0 +1,87 @@
import json
from odoo.tests import tagged
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
@tagged("post_install", "-at_install")
class TestAccountIncomingSupplierInvoice(AccountTestInvoicingCommon):
"""Testing creating account move fetching mail.alias"""
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.env["ir.config_parameter"].sudo().set_param(
"mail.catchall.domain", "test-company.odoo.com"
)
cls.internal_user = cls.env["res.users"].create(
{
"name": "Internal User",
"login": "internal.user@test.odoo.com",
"email": "internal.user@test.odoo.com",
}
)
cls.supplier_partner = cls.env["res.partner"].create(
{
"name": "Your Supplier",
"email": "supplier@other.company.com",
"supplier_rank": 10,
}
)
cls.journal = cls.company_data["default_journal_purchase"]
journal_alias = cls.env["mail.alias"].create(
{
"alias_name": "test-bill",
"alias_model_id": cls.env.ref("account.model_account_move").id,
"alias_defaults": json.dumps(
{
"move_type": "in_invoice",
"company_id": cls.env.user.company_id.id,
"journal_id": cls.journal.id,
}
),
}
)
cls.journal.write({"alias_id": journal_alias.id})
def test_supplier_invoice_mailed_from_supplier(self):
"""this test is mainly inspired from
addons.account.tests.test_account_incoming_supplier_invoice
python module but we make sure account move is draft without
name
"""
message_parsed = {
"message_id": "message-id-dead-beef",
"subject": "Incoming bill",
"from": "%s <%s>"
% (self.supplier_partner.name, self.supplier_partner.email),
"to": "%s@%s"
% (self.journal.alias_id.alias_name, self.journal.alias_id.alias_domain),
"body": "You know, that thing that you bought.",
"attachments": [b"Hello, invoice"],
}
invoice = self.env["account.move"].message_new(
message_parsed, {"move_type": "in_invoice", "journal_id": self.journal.id}
)
message_ids = invoice.message_ids
self.assertEqual(
len(message_ids), 1, "Only one message should be posted in the chatter"
)
self.assertEqual(
message_ids.body,
"<p>Vendor Bill Created</p>",
"Only the invoice creation should be posted",
)
following_partners = invoice.message_follower_ids.mapped("partner_id")
self.assertEqual(following_partners, self.env.user.partner_id)
self.assertEqual(invoice.state, "draft")
self.assertEqual(invoice.name, "/")

View File

@@ -0,0 +1,324 @@
import logging
import threading
import time
import psycopg2
import odoo
from odoo import SUPERUSER_ID, api, fields, tools
from odoo.tests import tagged
from odoo.tests.common import Form, TransactionCase
_logger = logging.getLogger(__name__)
class ThreadRaiseJoin(threading.Thread):
"""Custom Thread Class to raise the exception to main thread in the join"""
def run(self, *args, **kwargs):
self.exc = None
try:
return super().run(*args, **kwargs)
except BaseException as e:
self.exc = e
def join(self, *args, **kwargs):
res = super().join(*args, **kwargs)
# Wait for the thread finishes
while self.is_alive():
pass
# raise exception in the join
# to raise it in the main thread
if self.exc:
raise self.exc
return res
@tagged("post_install", "-at_install", "test_move_sequence")
class TestSequenceConcurrency(TransactionCase):
def setUp(self):
super().setUp()
self.product = self.env.ref("product.product_delivery_01")
self.partner = self.env.ref("base.res_partner_12")
self.date = fields.Date.to_date("1985-04-14")
def _new_cr(self):
return self.env.registry.cursor()
def _create_invoice_form(self, env, post=True):
ctx = {"default_move_type": "out_invoice"}
with Form(env["account.move"].with_context(**ctx)) as invoice_form:
invoice_form.partner_id = self.partner
invoice_form.invoice_date = self.date
with invoice_form.invoice_line_ids.new() as line_form:
line_form.product_id = self.product
line_form.price_unit = 100.0
line_form.tax_ids.clear()
invoice = invoice_form.save()
if post:
invoice.action_post()
return invoice
def _create_payment_form(self, env, ir_sequence_standard=False):
with Form(
env["account.payment"].with_context(
default_payment_type="inbound",
default_partner_type="customer",
default_move_journal_types=("bank", "cash"),
)
) as payment_form:
payment_form.partner_id = env.ref("base.res_partner_12")
payment_form.amount = 100
payment_form.date = self.date
payment = payment_form.save()
if ir_sequence_standard:
payment.move_id.journal_id.sequence_id = self.env.ref(
"account_move_name_sequence.ir_sequence_demo"
)
payment.action_post()
return payment
def _clean_moves(self, move_ids, payment=None):
"""Delete moves created after finish unittest using
self.addCleanup(
self._clean_moves, self.env, (invoices | payments.mapped('move_id')).ids
)"""
with self._new_cr() as cr:
env = api.Environment(cr, SUPERUSER_ID, {})
moves = env["account.move"].browse(move_ids)
moves.button_draft()
moves = moves.with_context(force_delete=True)
moves.unlink()
# TODO: Delete payment and journal
env.cr.commit()
def _create_invoice_payment(
self, deadlock_timeout, payment_first=False, ir_sequence_standard=False
):
odoo.registry(self.env.cr.dbname)
with self._new_cr() as cr, cr.savepoint():
env = api.Environment(cr, SUPERUSER_ID, {})
cr_pid = cr.connection.get_backend_pid()
# Avoid waiting for a long time and it needs to be less than deadlock
cr.execute("SET LOCAL statement_timeout = '%ss'", (deadlock_timeout + 10,))
if payment_first:
_logger.info("Creating payment cr %s", cr_pid)
self._create_payment_form(
env, ir_sequence_standard=ir_sequence_standard
)
_logger.info("Creating invoice cr %s", cr_pid)
self._create_invoice_form(env)
else:
_logger.info("Creating invoice cr %s", cr_pid)
self._create_invoice_form(env)
_logger.info("Creating payment cr %s", cr_pid)
self._create_payment_form(
env, ir_sequence_standard=ir_sequence_standard
)
# sleep in order to avoid release the locks too faster
# It could be many methods called after creating these
# kind of records e.g. reconcile
_logger.info("Finishing waiting %s" % (deadlock_timeout + 12))
time.sleep(deadlock_timeout + 12)
def test_sequence_concurrency_10_draft_invoices(self):
"""Creating 2 DRAFT invoices not should raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1, self._new_cr() as cr2:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
env2 = api.Environment(cr2, SUPERUSER_ID, {})
for cr in [cr0, cr1, cr2]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
invoice = self._create_invoice_form(env0)
self.addCleanup(self._clean_moves, invoice.ids)
env0.cr.commit()
with env1.cr.savepoint(), env2.cr.savepoint():
invoice1 = self._create_invoice_form(env1, post=False)
self.assertEqual(invoice1.state, "draft")
invoice2 = self._create_invoice_form(env2, post=False)
self.assertEqual(invoice2.state, "draft")
def test_sequence_concurrency_20_editing_last_invoice(self):
"""Edit last invoice and create a new invoice
should not raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
for cr in [cr0, cr1]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
invoice = self._create_invoice_form(env0)
self.addCleanup(self._clean_moves, invoice.ids)
env0.cr.commit()
with env0.cr.savepoint(), env1.cr.savepoint():
# Edit something in "last move"
invoice.write({"write_uid": env0.uid})
invoice.flush()
self._create_invoice_form(env1)
def test_sequence_concurrency_30_editing_last_payment(self):
"""Edit last payment and create a new payment
should not raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
for cr in [cr0, cr1]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
payment = self._create_payment_form(env0)
payment_move = payment.move_id
self.addCleanup(self._clean_moves, payment_move.ids)
env0.cr.commit()
with env0.cr.savepoint(), env1.cr.savepoint():
# Edit something in "last move"
payment_move.write({"write_uid": env0.uid})
payment_move.flush()
self._create_payment_form(env1)
@tools.mute_logger("odoo.sql_db")
def test_sequence_concurrency_40_reconciling_last_invoice(self):
"""Reconcile last invoice and create a new one
should not raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
for cr in [cr0, cr1]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
invoice = self._create_invoice_form(env0)
payment = self._create_payment_form(env0)
payment_move = payment.move_id
self.addCleanup(self._clean_moves, invoice.ids + payment_move.ids)
env0.cr.commit()
lines2reconcile = (
(payment_move | invoice)
.mapped("line_ids")
.filtered(lambda l: l.account_id.internal_type == "receivable")
)
with env0.cr.savepoint(), env1.cr.savepoint():
# Reconciling "last move"
# reconcile a payment with many invoices spend a lot so it could
# lock records too many time
lines2reconcile.reconcile()
# Many pieces of code call flush directly
lines2reconcile.flush()
self._create_invoice_form(env1)
def test_sequence_concurrency_50_reconciling_last_payment(self):
"""Reconcile last payment and create a new one
should not raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
for cr in [cr0, cr1]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
invoice = self._create_invoice_form(env0)
payment = self._create_payment_form(env0)
payment_move = payment.move_id
self.addCleanup(self._clean_moves, invoice.ids + payment_move.ids)
env0.cr.commit()
lines2reconcile = (
(payment_move | invoice)
.mapped("line_ids")
.filtered(lambda l: l.account_id.internal_type == "receivable")
)
with env0.cr.savepoint(), env1.cr.savepoint():
# Reconciling "last move"
# reconcile a payment with many invoices spend a lot so it could
# lock records too many time
lines2reconcile.reconcile()
# Many pieces of code call flush directly
lines2reconcile.flush()
self._create_payment_form(env1)
def test_sequence_concurrency_90_payments(self):
"""Creating concurrent payments should not raises errors"""
with self._new_cr() as cr0, self._new_cr() as cr1, self._new_cr() as cr2:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
env1 = api.Environment(cr1, SUPERUSER_ID, {})
env2 = api.Environment(cr2, SUPERUSER_ID, {})
for cr in [cr0, cr1, cr2]:
# Set 10s timeout in order to avoid waiting for release locks a long time
cr.execute("SET LOCAL statement_timeout = '10s'")
# Create "last move" to lock
payment = self._create_payment_form(env0, ir_sequence_standard=True)
payment_move_ids = payment.move_id.ids
self.addCleanup(self._clean_moves, payment_move_ids)
env0.cr.commit()
with env1.cr.savepoint(), env2.cr.savepoint():
self._create_payment_form(env1)
self._create_payment_form(env2)
@tools.mute_logger("odoo.sql_db")
def test_sequence_concurrency_95_pay2inv_inv2pay(self):
"""Creating concurrent payment then invoice and invoice then payment
should not raises errors
It raises deadlock sometimes"""
with self._new_cr() as cr0:
env0 = api.Environment(cr0, SUPERUSER_ID, {})
# Create "last move" to lock
invoice = self._create_invoice_form(env0)
# Create "last move" to lock
payment = self._create_payment_form(env0)
payment_move_ids = payment.move_id.ids
self.addCleanup(self._clean_moves, invoice.ids + payment_move_ids)
env0.cr.commit()
env0.cr.execute(
"SELECT setting FROM pg_settings WHERE name = 'deadlock_timeout'"
)
deadlock_timeout = int(env0.cr.fetchone()[0]) # ms
# You could not have permission to set this parameter
# psycopg2.errors.InsufficientPrivilege
self.assertTrue(
deadlock_timeout,
"You need to configure PG parameter deadlock_timeout='1s'",
)
deadlock_timeout = int(deadlock_timeout / 1000) # s
try:
t_pay_inv = ThreadRaiseJoin(
target=self._create_invoice_payment,
args=(deadlock_timeout, True, True),
name="Thread payment invoice",
)
t_inv_pay = ThreadRaiseJoin(
target=self._create_invoice_payment,
args=(deadlock_timeout, False, True),
name="Thread invoice payment",
)
t_pay_inv.start()
t_inv_pay.start()
# the thread could raise the error before to wait for it so disable coverage
t_pay_inv.join(timeout=deadlock_timeout + 15) # pragma: no cover
t_inv_pay.join(timeout=deadlock_timeout + 15) # pragma: no cover
except psycopg2.OperationalError as e:
if e.pgcode in [
psycopg2.errorcodes.SERIALIZATION_FAILURE,
psycopg2.errorcodes.LOCK_NOT_AVAILABLE,
]: # pragma: no cover
# Concurrency error is expected but not deadlock so ok
pass
elif (
e.pgcode == psycopg2.errorcodes.DEADLOCK_DETECTED
): # pragma: no cover
self.assertFalse(True, "Deadlock detected.")
else: # pragma: no cover
raise