From 6ab0a4cecdd826fc81e28e738483e919839c784d Mon Sep 17 00:00:00 2001
From: Simone Orsi
Date: Mon, 27 Nov 2023 10:14:15 +0100
Subject: [PATCH 1/5] fix test
---
edi_webservice_oca/demo/edi_backend.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/edi_webservice_oca/demo/edi_backend.xml b/edi_webservice_oca/demo/edi_backend.xml
index 37dd503fda..8f9f4dd35c 100644
--- a/edi_webservice_oca/demo/edi_backend.xml
+++ b/edi_webservice_oca/demo/edi_backend.xml
@@ -6,6 +6,9 @@
http
https://foo.test/{endpoint}
application/xml
+ user_pwd
+ user
+ pwd
Demo backend type ws
From 0af198ff212509502f13a86be7a7e9fc67237fca Mon Sep 17 00:00:00 2001
From: pcastelovigo
Date: Mon, 27 Nov 2023 10:16:28 +0100
Subject: [PATCH 2/5] base_business_document_import setup files
---
.../odoo/addons/base_business_document_import | 1 +
setup/base_business_document_import/setup.py | 6 ++++++
2 files changed, 7 insertions(+)
create mode 120000 setup/base_business_document_import/odoo/addons/base_business_document_import
create mode 100644 setup/base_business_document_import/setup.py
diff --git a/setup/base_business_document_import/odoo/addons/base_business_document_import b/setup/base_business_document_import/odoo/addons/base_business_document_import
new file mode 120000
index 0000000000..5e41f0a0b5
--- /dev/null
+++ b/setup/base_business_document_import/odoo/addons/base_business_document_import
@@ -0,0 +1 @@
+../../../../base_business_document_import
\ No newline at end of file
diff --git a/setup/base_business_document_import/setup.py b/setup/base_business_document_import/setup.py
new file mode 100644
index 0000000000..28c57bb640
--- /dev/null
+++ b/setup/base_business_document_import/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
From 927c008426dc04bec44928d1e2defee03faf0eed Mon Sep 17 00:00:00 2001
From: pcastelovigo
Date: Mon, 27 Nov 2023 10:16:55 +0100
Subject: [PATCH 3/5] fix test requirements
---
test-requirements.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/test-requirements.txt b/test-requirements.txt
index 43172676f0..9349b88b08 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1 +1,2 @@
odoo-test-helper>=2.0.1
+responses
From c0fbb81ec30c0e70bea556c167eb8ac22a03229c Mon Sep 17 00:00:00 2001
From: Goncalo Brito
Date: Mon, 27 Nov 2023 10:23:26 +0100
Subject: [PATCH 4/5] backport from 16
---
base_business_document_import/README.rst | 93 ++
base_business_document_import/__init__.py | 1 +
base_business_document_import/__manifest__.py | 20 +
.../i18n/base_business_document_import.pot | 372 +++++
base_business_document_import/i18n/cs_CZ.po | 445 ++++++
base_business_document_import/i18n/es.po | 498 ++++++
base_business_document_import/i18n/fr.po | 554 +++++++
base_business_document_import/i18n/fr_FR.po | 598 +++++++
base_business_document_import/i18n/nl.po | 598 +++++++
.../models/__init__.py | 1 +
.../models/business_document_import.py | 1398 +++++++++++++++++
.../readme/CONTRIBUTORS.rst | 5 +
.../readme/DESCRIPTION.rst | 5 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 432 +++++
.../tests/__init__.py | 1 +
.../tests/test_business_document_import.py | 482 ++++++
17 files changed, 5503 insertions(+)
create mode 100644 base_business_document_import/README.rst
create mode 100644 base_business_document_import/__init__.py
create mode 100644 base_business_document_import/__manifest__.py
create mode 100644 base_business_document_import/i18n/base_business_document_import.pot
create mode 100644 base_business_document_import/i18n/cs_CZ.po
create mode 100644 base_business_document_import/i18n/es.po
create mode 100644 base_business_document_import/i18n/fr.po
create mode 100644 base_business_document_import/i18n/fr_FR.po
create mode 100644 base_business_document_import/i18n/nl.po
create mode 100644 base_business_document_import/models/__init__.py
create mode 100644 base_business_document_import/models/business_document_import.py
create mode 100644 base_business_document_import/readme/CONTRIBUTORS.rst
create mode 100644 base_business_document_import/readme/DESCRIPTION.rst
create mode 100644 base_business_document_import/static/description/icon.png
create mode 100644 base_business_document_import/static/description/index.html
create mode 100644 base_business_document_import/tests/__init__.py
create mode 100644 base_business_document_import/tests/test_business_document_import.py
diff --git a/base_business_document_import/README.rst b/base_business_document_import/README.rst
new file mode 100644
index 0000000000..a0dbd9e366
--- /dev/null
+++ b/base_business_document_import/README.rst
@@ -0,0 +1,93 @@
+=============================
+Base Business Document Import
+=============================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:e0687319afa4e196bd4d8087afd6a7f63b64265200a8e5837fb7658d8ef8dd95
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |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%2Fedi-lightgray.png?logo=github
+ :target: https://github.com/OCA/edi/tree/16.0/base_business_document_import
+ :alt: OCA/edi
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-base_business_document_import
+ :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/edi&target_branch=16.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This is a technical module ; it doesn't bring any useful feature by itself. This module is the base modules for 2 other modules :
+
+* *account_invoice_import* which imports supplier invoices as PDF or XML files (this module also requires some additional modules such as *account_invoice_import_invoice2data*, *account_invoice_import_ubl*, etc... to support specific invoice formats),
+
+* *sale_invoice_import* which imports sale orders as CSV, XML or PDF files (this module also requires some additional modules such as *sale_invoice_import_csv* or *sale_invoice_import_ubl* to support specific order formats)
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+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
+* Nicolas JEUDY
+
+Contributors
+~~~~~~~~~~~~
+
+* Alexis de Lattre
+* Nicolas JEUDY
+* Jacques-Etienne Baudoux
+* Phuc (Tran Thanh)
+* Simone Orsi
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-alexis-via| image:: https://github.com/alexis-via.png?size=40px
+ :target: https://github.com/alexis-via
+ :alt: alexis-via
+
+Current `maintainer `__:
+
+|maintainer-alexis-via|
+
+This module is part of the `OCA/edi `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/base_business_document_import/__init__.py b/base_business_document_import/__init__.py
new file mode 100644
index 0000000000..0650744f6b
--- /dev/null
+++ b/base_business_document_import/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/base_business_document_import/__manifest__.py b/base_business_document_import/__manifest__.py
new file mode 100644
index 0000000000..aea2e4c4a6
--- /dev/null
+++ b/base_business_document_import/__manifest__.py
@@ -0,0 +1,20 @@
+# Copyright 2016-2021 Akretion France (http://www.akretion.com/)
+# @author: Alexis de Lattre
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+ "name": "Base Business Document Import",
+ "version": "15.0.1.0.0",
+ "category": "Tools",
+ "license": "AGPL-3",
+ "summary": "Provides technical tools to import sale orders or supplier invoices",
+ "author": "Akretion, Nicolas JEUDY, Odoo Community Association (OCA)",
+ "maintainers": ["alexis-via"],
+ "website": "https://github.com/OCA/edi",
+ "depends": [
+ # OCA/community-data-files
+ "account_tax_unece",
+ "uom_unece",
+ "pdf_helper",
+ ],
+}
diff --git a/base_business_document_import/i18n/base_business_document_import.pot b/base_business_document_import/i18n/base_business_document_import.pot
new file mode 100644
index 0000000000..7faebfefee
--- /dev/null
+++ b/base_business_document_import/i18n/base_business_document_import.pot
@@ -0,0 +1,372 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+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: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "(fixed)"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been "
+"updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax Included in Price' = '%(price)s' which correspond to the following information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company '%(company)s' "
+"(%(vat)s) in which you are trying to import this document."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the "
+"symbol/ISO code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is "
+"disabled."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier %(partner)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr ""
diff --git a/base_business_document_import/i18n/cs_CZ.po b/base_business_document_import/i18n/cs_CZ.po
new file mode 100644
index 0000000000..a7795f89cf
--- /dev/null
+++ b/base_business_document_import/i18n/cs_CZ.po
@@ -0,0 +1,445 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+# Translators:
+# Lukáš Spurný , 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-02-22 03:40+0000\n"
+"PO-Revision-Date: 2018-02-22 03:40+0000\n"
+"Last-Translator: Lukáš Spurný , 2018\n"
+"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/"
+"teams/23907/cs_CZ/)\n"
+"Language: cs_CZ\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "(fixed)"
+msgstr "(Úprávy)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr "Poznámky v souboru %s:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr "Poznámky v importovaném dokumentu:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr "Společné metody importu obchodních dokumentů"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been updated"
+"b>."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr "IBAN %s není platný, takže byl ignorován."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr "Není uvedena žádná měna, takže Odoo použil měnu společnosti (%s)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information "
+"extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information "
+"extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following "
+"information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information "
+"extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information "
+"extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following "
+"information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+"Included in Price' = '%(price)s' which correspond to the following "
+"information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company "
+"'%(company)s' (%(vat)s) in which you are trying to import this document."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the symbol/"
+"ISO code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+"Analýza obchodního dokladu vrátila jako symbol měny symbol '%s'. Ale v Odoo "
+"neexistuje žádný nebo několik měn s tímto symbolem."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is disabled."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier "
+"%(partner)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"Existující řádek '%s' nemá žádný produkt, takže 1 řádky nebyly aktualizovány."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Produkt '%s' se používá na několika existujících linkách, takže řádky nebyly "
+"aktualizovány."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Produkt '%s' se používá na několika importovaných řádcích, takže 1 řádky "
+"nebyly aktualizovány."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr "zákazník"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr "partner"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr "dodavatele"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any unit of measure corresponding to the following "
+#~ "information extracted from the business document:
- UNECE code: "
+#~ "%s
- Name of the unit of measure: %s
So the unit of "
+#~ "measure 'Unit(s)' has been used. You may have to change it manually."
+#~ "em>
"
+#~ msgstr ""
+#~ "Společnost Odoo nemohla najít žádnou měrnou jednotku, která by odpovídala "
+#~ "těmto informacím získaným z obchodního dokladu: Kód UNECE %s Náměrová "
+#~ "jednotka: %s Je použita měrná jednotka 'Jednotky)' Musíte ji ručně změnit."
+
+#, python-format
+#~ msgid "Approximate match: account %s has been matched with account %s"
+#~ msgstr "Přibližná shoda: účet %s byl přiřazen účtu %s"
+
+#~ msgid "Display Name"
+#~ msgstr "Zobrazovaný název"
+
+#, python-format
+#~ msgid ""
+#~ "For product '%s', the unit of measure is %s on the existing line, but it "
+#~ "is %s on the imported line. We don't support this scenario for the "
+#~ "moment, so the lines haven't been updated."
+#~ msgstr ""
+#~ "U produktu '%s' je měrnou jednotkou %s na existujícím řádku, ale na "
+#~ "importované řádce je %s. Momentálně nepodporujeme tento scénář, takže 1 "
+#~ "řádky nebyly aktualizovány."
+
+#~ msgid "ID"
+#~ msgstr "ID"
+
+#~ msgid "Last Modified on"
+#~ msgstr "Poslední změna dne"
+
+#, fuzzy, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the currency "
+#~ "symbol or ISO code. But there are none or several currencies with the "
+#~ "symbol/ISO code in Odoo."
+#~ msgstr ""
+#~ "Analýza obchodního dokladu vrátila hodnotu \"%s\" jako symbol měny nebo "
+#~ "kód ISO. Neexistuje však žádná měna se symbolem ani kódem ISO v Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the unit of "
+#~ "measure UNECE code, but there is no unit of measure with that UNECE code "
+#~ "in Odoo. Please check the configuration of the units of measures in Odoo."
+#~ msgstr ""
+#~ "Analýza obchodního dokladu vrátila \"%s\" jako měrnou jednotku UNECE, "
+#~ "avšak s tímto kódem UNECE v Odoo neexistuje žádná měrná jednotka. "
+#~ "Zkontrolujte prosím konfiguraci jednotek opatření v Odoo."
diff --git a/base_business_document_import/i18n/es.po b/base_business_document_import/i18n/es.po
new file mode 100644
index 0000000000..121da667fb
--- /dev/null
+++ b/base_business_document_import/i18n/es.po
@@ -0,0 +1,498 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2023-11-03 20:37+0000\n"
+"Last-Translator: Ivorra78 \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.17\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "(fixed)"
+msgstr "(fijado)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr "Notas en el archivo %s:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr "Notas en el documento importado:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+"Odoo no pudo encontrar ninguna unidad de medida correspondiente a la "
+"siguiente información extraída del documento comercial:
- Código "
+"UNECE: %(code)s
- Nombre de la unidad de medida: %(name)s
"
+"ul>Entonces se ha utilizado la unidad de medida 'Unidad(es)'. Puede "
+"que tenga que cambiarlo manualmente.
"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+"Coincidencia aproximada: la cuenta %(account)s ha coincidido con la cuenta "
+"%(matched_account)s"
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr "Métodos habituales para importar documentos comerciales"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr "No se pudo encontrar ningún Incotérmino en Odoo que corresponda a '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been updated"
+"b>."
+msgstr ""
+"Para el producto '%(product)s', la unidad de medida es %(uom_product)s en la "
+"línea existente, pero es %(uom_imported)s en la línea importada. No "
+"admitimos este escenario por el momento, por lo que las líneas no se han "
+"actualizado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr "El IBAN %s no es válido, por lo que se ha ignorado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr "La ID {id} de '{model}' no existe en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr "Falta el número de IVA de la compañía \"%s\""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr ""
+"No se especificó la moneda, por lo que Odoo utilizó la moneda de la compañía "
+"(%s)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information "
+"extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+"Odoo no pudo encontrar ningún %(label)s correspondiente a la siguiente "
+"información extraída del documento comercial:\n"
+"Nombre: %(name)s\n"
+"Número de IVA: %(vat)s\n"
+"Referencia: %(ref)s\n"
+"Correo electrónico: %(email)s\n"
+"Sitio web: %(website)s\n"
+"Código de estado: %(state)s\n"
+"Código de país: %(country)s \n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information "
+"extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+"Odoo no pudo encontrar ninguna cuenta correspondiente a la siguiente "
+"información extraída del documento comercial:\n"
+"Código de cuenta: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following "
+"information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+"Odoo no pudo encontrar ninguna cuenta analítica correspondiente a la "
+"siguiente información extraída del documento comercial:\n"
+"Código de cuenta analítica: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information "
+"extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+"Odoo no pudo encontrar ningún diario correspondiente a la siguiente "
+"información extraída del documento comercial:\n"
+"Código de diario: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information "
+"extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+"Odoo no pudo encontrar ningún producto correspondiente a la siguiente "
+"información extraída del documento comercial:\n"
+"Código de barras: %(barcode)s\n"
+"Código de producto: %(product_code)s\n"
+"Proveedor: %(supplier)s\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following "
+"information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+"Odoo no pudo encontrar ningún socio de envío correspondiente a la siguiente "
+"información extraída del documento comercial:\n"
+"Nombre: %(name)s\n"
+"Número de IVA: %(vat)s\n"
+"Referencia: %(ref)s\n"
+"Correo electrónico: %(email)s\n"
+"Sitio web: %(website)s\n"
+"Calle: %(street)s\n"
+"Calle2: %(street2)s\n"
+"Ciudad: %(city)s\n"
+"Código postal: %(zip)s\n"
+"Código de estado: %(state)s\n"
+"Código de país: %(country)s\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+"Included in Price' = '%(price)s' which correspond to the following "
+"information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+"Odoo no pudo encontrar ningún impuesto con 'Aplicación de impuestos' = "
+"'%(tax)s' e 'Impuesto incluido en el precio' = '%(price)s' que corresponden "
+"a la siguiente información extraída del documento comercial:\n"
+"Código de tipo de impuesto CEPE: %(tax_type)s\n"
+"Código de categoría fiscal de la CEPE: %(tax_cat)s\n"
+"Código de fecha de vencimiento de la CEPE: %(tax_due_date)s\n"
+"Monto del impuesto: %(amount)s %(amount_type)s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"Una de las líneas importadas no tiene ningún producto, por lo que las "
+"líneas no se han actualizado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+"El %(label)s ha sido identificado por el nombre de dominio '%(domain)s' así "
+"que por favor compruebe cuidadosamente que el %(label)s es correcto."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company "
+"'%(company)s' (%(vat)s) in which you are trying to import this document."
+msgstr ""
+"El número de IVA del cliente escrito en el documento comercial "
+"(%(parsed_vat)s) no coincide con el número de IVA de la empresa "
+"'%(company)s' (%(vat)s) en la que intenta importar esto documento."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr "El XMLID '%s' no existe en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+"El análisis del documento comercial arrojó '%(code)s' como el código de país "
+"para encontrar la moneda relacionada. Pero el país '%(name)s' no tiene "
+"ninguna moneda relacionada configurada en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the symbol/"
+"ISO code in Odoo."
+msgstr ""
+"El análisis del documento comercial arrojó '%(code)s' como símbolo de moneda "
+"o código ISO. Pero no hay ninguna o varias monedas con el símbolo/código ISO "
+"en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+"El análisis del documento comercial arrojó '%(code)s' como la unidad de "
+"medida del código UNECE, pero no hay ninguna unidad de medida con ese código "
+"UNECE en Odoo. Por favor revise la configuración de las unidades de medidas "
+"en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+"El análisis del documento de negocio devolvió '%s' como código de país. Pero "
+"no hay ningún país con ese código en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+"El análisis del documento comercial arrojó '%s' como código de país para "
+"encontrar la moneda relacionada. Pero no hay ningún país con ese código en "
+"Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+"El análisis del documento comercial devolvió '%s' como el código ISO de "
+"divisa. Pero no hay divisa con ese código en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+"El análisis del documento comercial arrojó '%s' como símbolo de divisa. Pero "
+"no hay ninguna o varias divisas con ese símbolo en Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is disabled."
+msgstr ""
+"El análisis del documento comercial deolvió IBAN %(iban)s como cuenta "
+"bancaria, pero no existe tal cuenta bancaria en Odoo vinculada al socio %(partner)s y "
+"la opción de crear automáticamente cuentas bancarias al importar está "
+"deshabilitada."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier "
+"%(partner)s"
+msgstr ""
+"La cuenta bancaria IBAN %(iban)s se ha añadido automáticamente al "
+"proveedor "
+"%(partner)s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"La línea existente '%s' no tiene ningún producto, por lo que las líneas "
+"no se han actualizado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+"El producto '%s' se utiliza en varias líneas existentes, por lo que las "
+"líneas no se han actualizado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+"El producto '%s' se utiliza en varias líneas importadas, por lo que las "
+"líneas no se han actualizado."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+"El registro '{record}' es una instancia de '{record_model}', no de "
+"'{target_model}'."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr "Cliente"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr "socio"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr "proveedor"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+#~ "Included in Price' = '%(price)s' which correspond to the following "
+#~ "information extracted from the business document:\n"
+#~ "UNECE Tax Type code: %(tax_type)s\n"
+#~ "UNECE Tax Category code: %(tax_cat)s\n"
+#~ "UNECE Due Date code: %s(tax_due_date)\n"
+#~ "Tax amount: %(amount)s %(amount_type)s"
+#~ msgstr ""
+#~ "Odoo no pudo encontrar ningún impuesto con 'Aplicación de impuestos' = "
+#~ "'%(tax)s' e 'Impuestos incluidos en el precio' = '%(price)s' que "
+#~ "corresponden a la siguiente información extraída del documento "
+#~ "comercial:\n"
+#~ "Código de tipo de impuesto de la UNECE (CEPE): %(tax_type)s\n"
+#~ "Código de categoría fiscal de la UNECE (CEPE): %(tax_cat)s\n"
+#~ "Código de fecha de vencimiento de la UNECE (CEPE): %s(tax_due_date)\n"
+#~ "Monto del impuesto: %(amount)s %(amount_type)s"
diff --git a/base_business_document_import/i18n/fr.po b/base_business_document_import/i18n/fr.po
new file mode 100644
index 0000000000..b0e5f8deba
--- /dev/null
+++ b/base_business_document_import/i18n/fr.po
@@ -0,0 +1,554 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+# Translators:
+# OCA Transbot , 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-02-22 03:40+0000\n"
+"PO-Revision-Date: 2022-08-07 07:06+0000\n"
+"Last-Translator: Claude R Perrin \n"
+"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\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.3.2\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "(fixed)"
+msgstr "(fixe)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr "Notes dans le fichier %s:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr "Notes dans le document importé :"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr "Méthodes courantes d'importation de documents commerciaux"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr "Impossible de trouver un Incoterm dans Odoo correspondant à '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been updated"
+"b>."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr "IBAN %s n’est pas valide, il a donc été ignoré."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr "Numéro de TVA manquant pour la société \"%s\""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr ""
+"Aucune devise n'a été spécifiée, Odoo a donc utilisé la devise de la société "
+"(%s)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information "
+"extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information "
+"extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de compte correspondant aux informations suivantes "
+"extraites du document commercial :\n"
+"Code du compte : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following "
+"information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de compte analytique correspondant aux informations "
+"suivantes extraites du document commercial :\n"
+"Code du compte analytique : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information "
+"extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de journal correspondant aux informations suivantes "
+"extraites du document commercial :\n"
+"Code journal : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information "
+"extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following "
+"information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+"Included in Price' = '%(price)s' which correspond to the following "
+"information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"Une des lignes importées n'a pas de produit, donc les lignes n'ont pas "
+"été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company "
+"'%(company)s' (%(vat)s) in which you are trying to import this document."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the symbol/"
+"ISO code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a retourné '%s' comme code de pays. Mais il "
+"n'y a pas de pays avec ce code dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a renvoyé '%s' comme code de pays pour "
+"trouver la devise correspondante. Mais il n'y a pas de pays avec ce code "
+"dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a renvoyé '%s' comme code de pays pour "
+"trouver la devise correspondante. Mais il n'y a pas de pays avec ce code "
+"dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+"L'analyse du document commercial a donné '%s' comme symbole de devise. Mais "
+"il n'y a pas ou plusieurs devises avec ce symbole dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is disabled."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier "
+"%(partner)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"La ligne existante '%s' n'a pas de produit, donc les lignes n'ont pas été "
+"mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Le produit '%s' est utilisé sur plusieurs lignes existantes, donc les "
+"lignes n'ont pas été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Le produit '%s' est utilisé sur plusieurs lignes importées, donc les "
+"lignes n'ont pas été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr "client"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr "partenaire"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr "sournisseur"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any unit of measure corresponding to the following "
+#~ "information extracted from the business document:
- UNECE code: "
+#~ "%s
- Name of the unit of measure: %s
So the unit of "
+#~ "measure 'Unit(s)' has been used. You may have to change it manually."
+#~ "em>
"
+#~ msgstr ""
+#~ "Odoo n'a pas trouvé d'unité de mesure correspondant aux informations "
+#~ "suivantes extraites du document métier :
- Code UNECE : %s"
+#~ "li>
- Nom de l'unité de mesure : %s
L'unité de mesure "
+#~ "'Unité(s)' a donc été utilisée. Vous devrez peut-être la modifier "
+#~ "manuellement.
"
+
+#, python-format
+#~ msgid "Approximate match: account %s has been matched with account %s"
+#~ msgstr ""
+#~ "Correspondance approximative : le compte %s a été mis en correspondance "
+#~ "avec le compte %s"
+
+#~ msgid "Display Name"
+#~ msgstr "Afficher Nom"
+
+#, python-format
+#~ msgid ""
+#~ "For product '%s', the unit of measure is %s on the existing line, but it "
+#~ "is %s on the imported line. We don't support this scenario for the "
+#~ "moment, so the lines haven't been updated."
+#~ msgstr ""
+#~ "Pour le produit ' %s ', l’unité de mesure est %s sur la ligne existante, "
+#~ "mais elle est sur %s la ligne importée. Nous ne prenons pas en charge ce "
+#~ "scénario pour le moment, donc les lignes n’ont pas été mises à jour"
+#~ "b>."
+
+#~ msgid "ID"
+#~ msgstr "ID"
+
+#~ msgid "Last Modified on"
+#~ msgstr "Dernière modification le"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any product corresponding to the following information "
+#~ "extracted from the business document:\n"
+#~ "Barcode: %s\n"
+#~ "Product code: %s\n"
+#~ "Supplier: %s\n"
+#~ msgstr ""
+#~ "Odoo n'a pas pu trouver de produit correspondant aux informations "
+#~ "suivantes extraites du document commercial :\n"
+#~ "Barcode : %s\n"
+#~ "Code produit : %s\n"
+#~ "Fournisseur : %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any tax with 'Tax Application' = '%s' and 'Tax "
+#~ "Included in Price' = '%s' which correspond to the following information "
+#~ "extracted from the business document:\n"
+#~ "UNECE Tax Type code: %s\n"
+#~ "UNECE Tax Category code: %s\n"
+#~ "UNECE Due Date code: %s\n"
+#~ "Tax amount: %s %s"
+#~ msgstr ""
+#~ "Odoo n'a pas trouvé de taxe avec 'Tax Application' = '%s' et 'Tax "
+#~ "Included in Price' = '%s' qui correspondent aux informations suivantes "
+#~ "extraites du document commercial :\n"
+#~ "Code de type de taxe CEE-ONU : %s\n"
+#~ "Code de catégorie de taxe CEE-ONU : %s\n"
+#~ "Code de la date d'échéance CEE-ONU : %s\n"
+#~ "Montant de la taxe : %s %s"
+
+#, python-format
+#~ msgid ""
+#~ "The %s has been identified by the domain name '%s' so please check "
+#~ "carefully that the %s is correct."
+#~ msgstr ""
+#~ "Le %s a été identifié par le nom de domaine '%s'. Veuillez vérifier "
+#~ "soigneusement que le %s est correct."
+
+#, python-format
+#~ msgid ""
+#~ "The VAT number of the customer written in the business document (%s) "
+#~ "doesn't match the VAT number of the company '%s' (%s) in which you are "
+#~ "trying to import this document."
+#~ msgstr ""
+#~ "Le numéro de TVA du client indiqué dans le document commercial (%s) ne "
+#~ "correspond pas au numéro de TVA de la société '%s' (%s) dans laquelle "
+#~ "vous essayez d'importer ce document."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the country code "
+#~ "to find the related currency. But the country '%s' doesn't have any "
+#~ "related currency configured in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a retourné '%s' comme code de pays pour "
+#~ "trouver la devise associée. Mais le pays '%s' n'a pas de devise associée "
+#~ "configurée dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the currency "
+#~ "symbol or ISO code. But there are none or several currencies with the "
+#~ "symbol/ISO code in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a donné '%s' comme symbole monétaire ou "
+#~ "code ISO. Mais il n'y a pas ou plusieurs devises avec ce symbole/code ISO "
+#~ "dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the unit of "
+#~ "measure UNECE code, but there is no unit of measure with that UNECE code "
+#~ "in Odoo. Please check the configuration of the units of measures in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a donné '%s' comme code d'unité de "
+#~ "mesure UNECE, mais il n'y a pas d'unité de mesure avec ce code UNECE dans "
+#~ "Odoo. Veuillez vérifier la configuration des unités de mesure dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned IBAN %s as bank "
+#~ "account, but there is no such bank account in Odoo linked to partner %s and the option to "
+#~ "automatically create bank accounts upon import is disabled."
+#~ msgstr ""
+#~ "L'analyse du document commercial a renvoyé IBAN %s comme compte "
+#~ "bancaire, mais il n'y a pas de tel compte bancaire dans Odoo lié au "
+#~ "partenaire %s et "
+#~ "l'option de création automatique de comptes bancaires à l'importation est "
+#~ "désactivée."
+
+#, python-format
+#~ msgid ""
+#~ "The bank account IBAN %s has been automatically added on the "
+#~ "supplier %s"
+#~ msgstr ""
+#~ "Le compte bancaire IBAN %s a été automatiquement ajouté sur le "
+#~ "fournisseur %s"
diff --git a/base_business_document_import/i18n/fr_FR.po b/base_business_document_import/i18n/fr_FR.po
new file mode 100644
index 0000000000..9f10c2c1c6
--- /dev/null
+++ b/base_business_document_import/i18n/fr_FR.po
@@ -0,0 +1,598 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2021-04-15 17:46+0000\n"
+"Last-Translator: Yves Le Doeuff \n"
+"Language-Team: none\n"
+"Language: fr_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.3.2\n"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "(fixed)"
+msgstr "(fixe)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr "Notes dans le fichier %s:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr "Notes dans le document importé:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr "Méthodes courantes d'importation de documents commerciaux"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr "Impossible de trouver un Incoterm dans Odoo correspondant à '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been updated"
+"b>."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr "L'IBAN %s n'est pas valide, il a donc été ignoré."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr "Numéro de TVA manquant pour la société '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr ""
+"Pas de devise précisée, donc Odoo a utilisé la devise (%s) de la société"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information "
+"extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information "
+"extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de compte correspondant aux informations suivantes "
+"extraites du document commercial :\n"
+"Code du compte : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following "
+"information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de compte analytique correspondant aux informations "
+"suivantes extraites du document commercial :\n"
+"Code du compte analytique : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information "
+"extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+"Odoo n'a pas trouvé de journal correspondant aux informations suivantes "
+"extraites du document commercial :\n"
+"Code journal : %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information "
+"extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following "
+"information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+"Included in Price' = '%(price)s' which correspond to the following "
+"information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"Une des lignes importées n'a pas de produit, donc les lignes n'ont pas "
+"été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company "
+"'%(company)s' (%(vat)s) in which you are trying to import this document."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the symbol/"
+"ISO code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a retourné '%s' comme code de pays. Mais il "
+"n'y a pas de pays avec ce code dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a renvoyé '%s' comme code de pays pour "
+"trouver la devise correspondante. Mais il n'y a pas de pays avec ce code "
+"dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+"L'analyse du document commercial a donné '%s' comme code ISO de la devise. "
+"Mais il n'y a pas de devise avec ce code dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+"L'analyse du document commercial a donné '%s' comme symbole de devise. Mais "
+"il n'y a pas ou plusieurs devises avec ce symbole dans Odoo."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is disabled."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier "
+"%(partner)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"La ligne existante '%s' n'a pas de produit, donc les lignes n'ont pas été "
+"mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Le produit '%s' est utilisé sur plusieurs lignes existantes, donc les "
+"lignes n'ont pas été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Le produit '%s' est utilisé sur plusieurs lignes importées, donc les "
+"lignes n'ont pas été mises à jour."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr "client"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr "partenaire"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr "fournisseur"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any unit of measure corresponding to the following "
+#~ "information extracted from the business document:
- UNECE code: "
+#~ "%s
- Name of the unit of measure: %s
So the unit of "
+#~ "measure 'Unit(s)' has been used. You may have to change it manually."
+#~ "em>
"
+#~ msgstr ""
+#~ "Odoo n'a pas trouvé d'unité de mesure correspondant aux informations "
+#~ "suivantes extraites du document métier :
- Code UNECE : %s"
+#~ "li>
- Nom de l'unité de mesure : %s
L'unité de mesure "
+#~ "'Unité(s)' a donc été utilisée. Vous devrez peut-être la modifier "
+#~ "manuellement.
"
+
+#, python-format
+#~ msgid "Approximate match: account %s has been matched with account %s"
+#~ msgstr ""
+#~ "Correspondance approximative : le compte %s a été mis en correspondance "
+#~ "avec le compte %s"
+
+#~ msgid "Display Name"
+#~ msgstr "Nom affiché"
+
+#, python-format
+#~ msgid ""
+#~ "For product '%s', the unit of measure is %s on the existing line, but it "
+#~ "is %s on the imported line. We don't support this scenario for the "
+#~ "moment, so the lines haven't been updated."
+#~ msgstr ""
+#~ "Pour le produit '%s', l'unité de mesure est %s sur la ligne existante, "
+#~ "mais elle est %s sur la ligne importée. Nous ne supportons pas ce "
+#~ "scénario pour le moment, donc les lignes n'ont pas été mises à jour"
+#~ "b>."
+
+#~ msgid "Last Modified on"
+#~ msgstr "Dernière modification"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any %s corresponding to the following information "
+#~ "extracted from the business document:\n"
+#~ "Name: %s\n"
+#~ "VAT number: %s\n"
+#~ "Reference: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "State code: %s\n"
+#~ "Country code: %s\n"
+#~ msgstr ""
+#~ "Odoo n'a pas trouvé de %s correspondant aux informations suivantes "
+#~ "extraites du document commercial :\n"
+#~ "Nom : %s\n"
+#~ "Numéro de TVA : %s\n"
+#~ "Référence : %s\n"
+#~ "E-mail : %s\n"
+#~ "Site web : %s\n"
+#~ "Code de l'État : %s\n"
+#~ "Code du pays : %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any product corresponding to the following information "
+#~ "extracted from the business document:\n"
+#~ "Barcode: %s\n"
+#~ "Product code: %s\n"
+#~ "Supplier: %s\n"
+#~ msgstr ""
+#~ "Odoo n'a pas pu trouver de produit correspondant aux informations "
+#~ "suivantes extraites du document commercial :\n"
+#~ "Code barres : %s\n"
+#~ "Code produit : %s\n"
+#~ "Fournisseur : %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any shipping partner corresponding to the following "
+#~ "information extracted from the business document:\n"
+#~ "Name: %s\n"
+#~ "VAT number: %s\n"
+#~ "Reference: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "Street: %s\n"
+#~ "Street2: %s\n"
+#~ "City: %s\n"
+#~ "ZIP: %s\n"
+#~ "State code: %s\n"
+#~ "Country code: %s\n"
+#~ msgstr ""
+#~ "Odoo n'a pas pu trouver de partenaire d'expédition correspondant aux "
+#~ "informations suivantes extraites du document commercial :\n"
+#~ "Nom : %s\n"
+#~ "Numéro de TVA : %s\n"
+#~ "Référence : %s\n"
+#~ "E-mail : %s\n"
+#~ "Site web : %s\n"
+#~ "Rue : %s\n"
+#~ "Rue2 : %s\n"
+#~ "Ville : %s\n"
+#~ "Code postal : %s\n"
+#~ "Code d'état : %s\n"
+#~ "Code du pays : %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any tax with 'Tax Application' = '%s' and 'Tax "
+#~ "Included in Price' = '%s' which correspond to the following information "
+#~ "extracted from the business document:\n"
+#~ "UNECE Tax Type code: %s\n"
+#~ "UNECE Tax Category code: %s\n"
+#~ "UNECE Due Date code: %s\n"
+#~ "Tax amount: %s %s"
+#~ msgstr ""
+#~ "Odoo n'a pas trouvé de taxe avec 'Application de taxe' = '%s' et 'Taxe "
+#~ "Incluse dans le prix' = '%s' qui correspondent aux informations suivantes "
+#~ "extraites du document commercial :\n"
+#~ "Code de type de taxe CEE-ONU : %s\n"
+#~ "Code de catégorie de taxe CEE-ONU : %s\n"
+#~ "Code de la date d'échéance CEE-ONU : %s\n"
+#~ "Montant de la taxe : %s %s"
+
+#, python-format
+#~ msgid ""
+#~ "The %s has been identified by the domain name '%s' so please check "
+#~ "carefully that the %s is correct."
+#~ msgstr ""
+#~ "Le %s a été identifié par le nom de domaine '%s'. Veuillez vérifier "
+#~ "soigneusement que le %s est correct."
+
+#, python-format
+#~ msgid ""
+#~ "The VAT number of the customer written in the business document (%s) "
+#~ "doesn't match the VAT number of the company '%s' (%s) in which you are "
+#~ "trying to import this document."
+#~ msgstr ""
+#~ "Le numéro de TVA du client indiqué dans le document commercial (%s) ne "
+#~ "correspond pas au numéro de TVA de la société '%s' (%s) dans laquelle "
+#~ "vous essayez d'importer ce document."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the country code "
+#~ "to find the related currency. But the country '%s' doesn't have any "
+#~ "related currency configured in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a retourné '%s' comme code de pays pour "
+#~ "trouver la devise associée. Mais le pays '%s' n'a pas de devise associée "
+#~ "configurée dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the currency "
+#~ "symbol or ISO code. But there are none or several currencies with the "
+#~ "symbol/ISO code in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a donné '%s' comme symbole monétaire ou "
+#~ "code ISO. Mais il n'y a pas ou plusieurs devises avec ce symbole/code ISO "
+#~ "dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the unit of "
+#~ "measure UNECE code, but there is no unit of measure with that UNECE code "
+#~ "in Odoo. Please check the configuration of the units of measures in Odoo."
+#~ msgstr ""
+#~ "L'analyse du document commercial a donné '%s' comme code d'unité de "
+#~ "mesure UNECE, mais il n'y a pas d'unité de mesure avec ce code UNECE dans "
+#~ "Odoo. Veuillez vérifier la configuration des unités de mesure dans Odoo."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned IBAN %s as bank "
+#~ "account, but there is no such bank account in Odoo linked to partner %s and the option to "
+#~ "automatically create bank accounts upon import is disabled."
+#~ msgstr ""
+#~ "L'analyse du document commercial a retourné IBAN %s comme compte "
+#~ "bancaire, mais il n'y a pas de tel compte bancaire dans Odoo lié au "
+#~ "partenaire %s et "
+#~ "l'option de création automatique de comptes bancaires lors de "
+#~ "l'importation est désactivée."
+
+#, python-format
+#~ msgid ""
+#~ "The bank account IBAN %s has been automatically added on the "
+#~ "supplier %s"
+#~ msgstr ""
+#~ "Le compte bancaire IBAN %s a été automatiquement ajouté sur le "
+#~ "fournisseur %s"
diff --git a/base_business_document_import/i18n/nl.po b/base_business_document_import/i18n/nl.po
new file mode 100644
index 0000000000..15d0d8aa2f
--- /dev/null
+++ b/base_business_document_import/i18n/nl.po
@@ -0,0 +1,598 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * base_business_document_import
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2023-02-07 12:22+0000\n"
+"Last-Translator: Bosd \n"
+"Language-Team: none\n"
+"Language: nl\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: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, fuzzy, python-format
+msgid "(fixed)"
+msgstr "(fixed)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in file %s:"
+msgstr "Notities in bestand %s:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Notes in imported document:"
+msgstr "Notities in geimporteerd document:"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any unit of measure corresponding to the following "
+"information extracted from the business document:
- UNECE code: "
+"%(code)s
- Name of the unit of measure: %(name)s
So the "
+"unit of measure 'Unit(s)' has been used. You may have to change it "
+"manually.
"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Approximate match: account %(account)s has been matched with account "
+"%(matched_account)s"
+msgstr ""
+
+#. module: base_business_document_import
+#: model:ir.model,name:base_business_document_import.model_business_document_import
+msgid "Common methods to import business documents"
+msgstr "Algemene procedures voor het importeren van bedrijfsdocumenten"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Could not find any Incoterm in Odoo corresponding to '%s'"
+msgstr "Er kong geen Incoterm gevonden worden overeenkomstig met '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"For product '%(product)s', the unit of measure is %(uom_product)s on the "
+"existing line, but it is %(uom_imported)s on the imported line.We don't "
+"support this scenario for the moment, so the lines haven't been updated"
+"b>."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "IBAN %s is not valid, so it has been ignored."
+msgstr "IBAN %s is ongeldig, dus genegeerd."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "ID {id} of '{model}' doesn't exist in Odoo."
+msgstr "ID {id} van '{model}' bestaat niet."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "Missing VAT number on company '%s'"
+msgstr "Ontbrekent BTW nummer voor bedrijf '%s'"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "No currency specified, so Odoo used the company currency (%s)"
+msgstr ""
+"Er is geen valuta gespicificeerd, dus de bedrijfsvaluta wordt gebruikt (%s)"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any %(label)s corresponding to the following information "
+"extracted from the business document:\n"
+"Name: %(name)s \n"
+"VAT number: %(vat)s \n"
+"Reference: %(ref)s \n"
+"E-mail: %(email)s \n"
+"Website: %(website)s \n"
+"State code: %(state)s \n"
+"Country code: %(country)s \n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any account corresponding to the following information "
+"extracted from the business document:\n"
+"Account code: %s"
+msgstr ""
+"kon geen rekening vinden welke overeenkomt met de verkregen informatie uit "
+"dit bedrijfsdocument:\n"
+"Rekening code: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any analytic account corresponding to the following "
+"information extracted from the business document:\n"
+"Analytic account code: %s"
+msgstr ""
+"kon geen analytisch account vinden welke overeenkomt met de verkregen "
+"informatie uit dit bedrijfsdocument:\n"
+"Analytisch account code: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any journal corresponding to the following information "
+"extracted from the business document:\n"
+"Journal code: %s"
+msgstr ""
+"kon geen dagboek vinden welke overeenkomt met de verkregen informatie uit "
+"dit bedrijfsdocument:\n"
+"Dagboek code: %s"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any product corresponding to the following information "
+"extracted from the business document:\n"
+"Barcode: %(barcode)s\n"
+"Product code: %(product_code)s\n"
+"Supplier: %(supplier)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any shipping partner corresponding to the following "
+"information extracted from the business document:\n"
+"Name: %(name)s\n"
+"VAT number: %(vat)s\n"
+"Reference: %(ref)s\n"
+"E-mail: %(email)s\n"
+"Website: %(website)s\n"
+"Street: %(street)s\n"
+"Street2: %(street2)s\n"
+"City: %(city)s\n"
+"ZIP: %(zip)s\n"
+"State code: %(state)s\n"
+"Country code: %(country)s\n"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' and 'Tax "
+"Included in Price' = '%(price)s' which correspond to the following "
+"information extracted from the business document:\n"
+"UNECE Tax Type code: %(tax_type)s\n"
+"UNECE Tax Category code: %(tax_cat)s\n"
+"UNECE Due Date code: %(tax_due_date)s\n"
+"Tax amount: %(amount)s %(amount_type)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"One of the imported lines doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"Een van de geimporteede regels bevat geen product, dus de regels zijn "
+"niet bijgewerkt."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The %(label)s has been identified by the domain name '%(domain)s' so please "
+"check carefully that the %(label)s is correct."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The VAT number of the customer written in the business document "
+"(%(parsed_vat)s) doesn't match the VAT number of the company "
+"'%(company)s' (%(vat)s) in which you are trying to import this document."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "The XMLID '%s' doesn't exist in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the country "
+"code to find the related currency. But the country '%(name)s' doesn't have "
+"any related currency configured in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the currency "
+"symbol or ISO code. But there are none or several currencies with the symbol/"
+"ISO code in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%(code)s' as the unit of "
+"measure UNECE code, but there is no unit of measure with that UNECE code in "
+"Odoo. Please check the configuration of the units of measures in Odoo."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as country code. But "
+"there are no country with that code in Odoo."
+msgstr ""
+"De analyse van het bedrijfsdocument leverde landcode '%s' op. Deze landcode "
+"is niet bekend in het systeem."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the country code to "
+"find the related currency. But there is no country with that code in Odoo."
+msgstr ""
+"De analyse van het bedrijfsdocument leverde '%s' op als de landcode om de "
+"bijbehorende valuta te vinden. Maar deze landcode is niet bekend in het "
+"systeem."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency ISO "
+"code. But there are no currency with that code in Odoo."
+msgstr ""
+"De analyse van het bedrijfsdocument leverde '%s' op als de valuta ISO code. "
+"Er is geen valuta met deze code bekend in het systeem."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned '%s' as the currency symbol. "
+"But there are none or several currencies with that symbol in Odoo."
+msgstr ""
+"De analyse van het bedrijfsdocument leverde '%s' op als de valutateken. Er "
+"zijn geen of meerdre valutas met dat valutateken in het systeem."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The analysis of the business document returned IBAN %(iban)s as bank "
+"account, but there is no such bank account in Odoo linked to partner %(partner)s "
+"and the option to automatically create bank accounts upon import is disabled."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The bank account IBAN %(iban)s has been automatically added on the "
+"supplier "
+"%(partner)s"
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The existing line '%s' doesn't have any product, so the lines haven't "
+"been updated."
+msgstr ""
+"De bestaande regel '%s' heeft geen product, dus de regel is niet "
+"bijgewerkt."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several existing lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Het product '%s' is gebruikt op meerdere bestaande regels, dus de regels "
+"zijn niet bijgewerkt."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The product '%s' is used on several imported lines, so the lines haven't "
+"been updated."
+msgstr ""
+"Het product '%s' is gebruikt op meerdere geimporteerde regels, dus de "
+"regels zijn niet bijgewerkt."
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid ""
+"The record '{record}' is an instance of '{record_model}', not of "
+"'{target_model}'."
+msgstr ""
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "customer"
+msgstr "klant"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "partner"
+msgstr "relatie"
+
+#. module: base_business_document_import
+#. odoo-python
+#: code:addons/base_business_document_import/models/business_document_import.py:0
+#, python-format
+msgid "supplier"
+msgstr "leverancier"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any unit of measure corresponding to the following "
+#~ "information extracted from the business document:
- UNECE code: "
+#~ "%s
- Name of the unit of measure: %s
So the unit of "
+#~ "measure 'Unit(s)' has been used. You may have to change it manually."
+#~ "em>
"
+#~ msgstr ""
+#~ "Er kon geen eenheid gevonden worden welke overeenkomt met de volgende "
+#~ "informatie verkregen uit het bedrijfsdocument:
- UNECE code: %s"
+#~ "li>
- Eenheidsnaam: %s
dus de 'Unit(s)' eenheid is gebruikt. "
+#~ "Wellicht wilt u dit handmatig wijzigen.
"
+
+#, python-format
+#~ msgid "Approximate match: account %s has been matched with account %s"
+#~ msgstr "Geschatte overeenkomst: rekening %s is gematched met rekening %s"
+
+#~ msgid "Display Name"
+#~ msgstr "Weergavenaam"
+
+#, python-format
+#~ msgid ""
+#~ "For product '%s', the unit of measure is %s on the existing line, but it "
+#~ "is %s on the imported line. We don't support this scenario for the "
+#~ "moment, so the lines haven't been updated."
+#~ msgstr ""
+#~ "voor product '%s', is de eenheid %s op de bestaande regel, maar is %s op "
+#~ "de geimporteerde regel. Dit wordt op dit moment niet ondersteund, de "
+#~ "regels zijnnietbijgewerkt."
+
+#, fuzzy
+#~ msgid "ID"
+#~ msgstr "ID"
+
+#~ msgid "Last Modified on"
+#~ msgstr "Laatst bijgewerkt op"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any %s corresponding to the following information "
+#~ "extracted from the business document:\n"
+#~ "Name: %s\n"
+#~ "VAT number: %s\n"
+#~ "Reference: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "State code: %s\n"
+#~ "Country code: %s\n"
+#~ msgstr ""
+#~ "Er kon geen %s gevonden worden welke overeenkomt met de informatie "
+#~ "verkregen uit het document:\n"
+#~ "Naam: %s\n"
+#~ "BTW nummer: %s\n"
+#~ "Referentie: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "State code: %s\n"
+#~ "Land code: %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any product corresponding to the following information "
+#~ "extracted from the business document:\n"
+#~ "Barcode: %s\n"
+#~ "Product code: %s\n"
+#~ "Supplier: %s\n"
+#~ msgstr ""
+#~ "Er kon geen product gevonden worden welke overeenkomt met de verkregen "
+#~ "informatie uit het document:\n"
+#~ "Barcode: %s\n"
+#~ "Product code: %s\n"
+#~ "Leverancier: %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any shipping partner corresponding to the following "
+#~ "information extracted from the business document:\n"
+#~ "Name: %s\n"
+#~ "VAT number: %s\n"
+#~ "Reference: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "Street: %s\n"
+#~ "Street2: %s\n"
+#~ "City: %s\n"
+#~ "ZIP: %s\n"
+#~ "State code: %s\n"
+#~ "Country code: %s\n"
+#~ msgstr ""
+#~ "Er kon geen geadresseerde relatie gevonden worden welke overeenkomt met "
+#~ "de verkregen informatie uit dit bedrijfsdocument:\n"
+#~ "Naam: %s\n"
+#~ "BTW nummer: %s\n"
+#~ "Referentie: %s\n"
+#~ "E-mail: %s\n"
+#~ "Website: %s\n"
+#~ "Straat: %s\n"
+#~ "Straat2: %s\n"
+#~ "Woonplaats: %s\n"
+#~ "Postcode: %s\n"
+#~ "State code: %s\n"
+#~ "Land code: %s\n"
+
+#, python-format
+#~ msgid ""
+#~ "Odoo couldn't find any tax with 'Tax Application' = '%s' and 'Tax "
+#~ "Included in Price' = '%s' which correspond to the following information "
+#~ "extracted from the business document:\n"
+#~ "UNECE Tax Type code: %s\n"
+#~ "UNECE Tax Category code: %s\n"
+#~ "UNECE Due Date code: %s\n"
+#~ "Tax amount: %s %s"
+#~ msgstr ""
+#~ "Er kon geen belastingsregel gevonden worden 'Tax Application' = '%s' en "
+#~ "'prijs inclusief btw' = '%s' welke overeenkomt met de volgende informatie "
+#~ "verkregen uit dit bedrijfsdocument:\n"
+#~ "UNECE Tax Type code: %s\n"
+#~ "UNECE Tax Category code: %s\n"
+#~ "UNECE Due Date code: %s\n"
+#~ "Belast bedrag: %s %s"
+
+#, python-format
+#~ msgid ""
+#~ "The %s has been identified by the domain name '%s' so please check "
+#~ "carefully that the %s is correct."
+#~ msgstr ""
+#~ "Het %s is geidentificeerd op de domeinnaam '%s' controleer zorgvuldig "
+#~ "daat de %s juist is."
+
+#, python-format
+#~ msgid ""
+#~ "The VAT number of the customer written in the business document (%s) "
+#~ "doesn't match the VAT number of the company '%s' (%s) in which you are "
+#~ "trying to import this document."
+#~ msgstr ""
+#~ "Het BTW nummer van de klant in het bedrijfsdocument (%s) komt niet "
+#~ "overeen met het BTW nummer van het bedrijf '%s' (%s) waarvoor je een "
+#~ "document probeert te importeren."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the country code "
+#~ "to find the related currency. But the country '%s' doesn't have any "
+#~ "related currency configured in Odoo."
+#~ msgstr ""
+#~ "De analyse van het bedrijfsdocument leverde '%s' op als de landcode om de "
+#~ "bijbehorende valuta te vinden. Maar voor het land '%s' zijn geen "
+#~ "bijbehorende valuta's geconfigureerd."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the currency "
+#~ "symbol or ISO code. But there are none or several currencies with the "
+#~ "symbol/ISO code in Odoo."
+#~ msgstr ""
+#~ "De analyse van het bedrijfsdocument leverde '%s' op als het valuta "
+#~ "symbool of ISO code. Er zijn geen of meerdere valuta met dit symbool/code "
+#~ "bekend in het systeem."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned '%s' as the unit of "
+#~ "measure UNECE code, but there is no unit of measure with that UNECE code "
+#~ "in Odoo. Please check the configuration of the units of measures in Odoo."
+#~ msgstr ""
+#~ "De analyse van het bedrijfsdocument leverde '%s' als eenheids UNECE code, "
+#~ "maar er is geen eenheid met die UNECE code in het systeem. Controleer de "
+#~ "eenheidsinstellingen."
+
+#, python-format
+#~ msgid ""
+#~ "The analysis of the business document returned IBAN %s as bank "
+#~ "account, but there is no such bank account in Odoo linked to partner %s and the option to "
+#~ "automatically create bank accounts upon import is disabled."
+#~ msgstr ""
+#~ "De analyse van het bedrijfsdocument leverde IBAN %s op als "
+#~ "bankrekening, maar het bankrekeningnummer is niet toegewezen aan relatie "
+#~ "%s en de "
+#~ "mogelijkheid om automatisch bankrekeningen aan te maken tijdens de import "
+#~ "van bedrijfsdocumenten is uitgeschakeld."
+
+#, python-format
+#~ msgid ""
+#~ "The bank account IBAN %s has been automatically added on the "
+#~ "supplier %s"
+#~ msgstr ""
+#~ "Het bankrekeningnummerIBAN %s is automatisch toegevoegd aan de "
+#~ "leverancier %s"
diff --git a/base_business_document_import/models/__init__.py b/base_business_document_import/models/__init__.py
new file mode 100644
index 0000000000..d695bc5f59
--- /dev/null
+++ b/base_business_document_import/models/__init__.py
@@ -0,0 +1 @@
+from . import business_document_import
diff --git a/base_business_document_import/models/business_document_import.py b/base_business_document_import/models/business_document_import.py
new file mode 100644
index 0000000000..75932a0d48
--- /dev/null
+++ b/base_business_document_import/models/business_document_import.py
@@ -0,0 +1,1398 @@
+# Copyright 2015-2021 Akretion France
+# @author: Alexis de Lattre
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+import logging
+from urllib.parse import urlparse
+
+from odoo import _, api, models
+from odoo.exceptions import UserError
+from odoo.osv import expression
+from odoo.tools import float_compare
+
+from odoo.addons.base_iban.models.res_partner_bank import validate_iban
+
+logger = logging.getLogger(__name__)
+
+
+class BusinessDocumentImport(models.AbstractModel):
+ _name = "business.document.import"
+ _description = "Common methods to import business documents"
+
+ @api.model
+ def user_error_wrap(self, method, data_dict, error_msg):
+ """The method and data_dict arguments are useful when you want to
+ inherit this method to update the error messag_match_currencye"""
+ assert error_msg
+ raise UserError(error_msg)
+
+ def _direct_match(self, data_dict, model, raise_exception=True):
+ if data_dict.get("recordset"):
+ record = data_dict["recordset"]
+ if isinstance(record, type(model)):
+ return record
+ elif raise_exception:
+ raise UserError(
+ _(
+ "The record '{record}' is an instance of '{record_model}', "
+ "not of '{target_model}'."
+ ).format(
+ record=record.display_name,
+ record_model=record._name,
+ target_model=model._name,
+ )
+ )
+ if data_dict.get("id"):
+ record = model.browse(data_dict["id"]).exists()
+ if not record and raise_exception:
+ raise UserError(
+ _("ID {id} of '{model}' doesn't exist in Odoo.").format(
+ id=data_dict["id"], model=model._name
+ )
+ )
+ if record:
+ return record
+ if data_dict.get("xmlid"):
+ xmlid = data_dict["xmlid"]
+ record = False
+ try:
+ record = self.env.ref(xmlid, raise_if_not_found=True)
+ except Exception as e:
+ if raise_exception:
+ raise UserError(
+ _("The XMLID '%s' doesn't exist in Odoo.") % xmlid
+ ) from e
+ if record:
+ if isinstance(record, type(model)):
+ return record
+ elif raise_exception:
+ raise UserError(
+ _(
+ "The record '{record}' is an instance of '{record_model}', "
+ "not of '{target_model}'."
+ ).format(
+ record=record.display_name,
+ record_model=record._name,
+ target_model=model._name,
+ )
+ )
+ return None
+
+ @api.model
+ def _strip_cleanup_dict(self, match_dict):
+ if not match_dict:
+ return
+
+ for key, value in match_dict.items():
+ if value and isinstance(value, str):
+ match_dict[key] = value.strip()
+ if match_dict.get("country_code"):
+ match_dict["country_code"] = match_dict["country_code"].upper()
+ if match_dict.get("state_code"):
+ match_dict["state_code"] = match_dict["state_code"].upper()
+
+ @api.model
+ def _get_match_partner_order(self, partner_type):
+ if partner_type == "supplier":
+ return "supplier_rank desc"
+ if partner_type == "customer":
+ return "customer_rank desc"
+ return ""
+
+ @api.model
+ def _get_match_partner_type_label(self, partner_type):
+ if partner_type == "supplier":
+ return _("supplier")
+ if partner_type == "customer":
+ return _("customer")
+ return _("partner")
+
+ @api.model
+ def _get_country_filter(self, partner_dict, chatter_msg):
+ """Generate filter by country"""
+ if partner_dict.get("country_code"):
+ country = self.env["res.country"].search(
+ [("code", "=", partner_dict["country_code"])], limit=1
+ )
+ if country:
+ return [
+ "|",
+ ("country_id", "=", False),
+ ("country_id", "=", country.id),
+ ]
+ chatter_msg.append(
+ _(
+ "The analysis of the business document returned '%s' as "
+ "country code. But there are no country with that code "
+ "in Odoo."
+ )
+ % partner_dict["country_code"]
+ )
+ return False
+
+ @api.model
+ def _get_country_state_filter(self, partner_dict, chatter_msg):
+ if partner_dict.get("state_code"):
+ country = self.env["res.country"].search(
+ [("code", "=", partner_dict["country_code"])], limit=1
+ )
+ if state := self.env["res.country.state"].search(
+ [
+ ("code", "=", partner_dict["state_code"]),
+ ("country_id", "=", country.id),
+ ],
+ limit=1,
+ ):
+ return ["|", ("state_id", "=", False), ("state_id", "=", state.id)]
+ return False
+
+ @api.model
+ def _match_partner_ref(self, partner_dict, chatter_msg, domain, order):
+ """If a ref is explicitly given, we just want to match that partner"""
+ if partner_dict.get("ref"):
+ domain = expression.AND(
+ [
+ domain,
+ [("ref", "=", partner_dict["ref"])],
+ ]
+ )
+ return self.env["res.partner"].search(domain, limit=1, order=order)
+ return False
+
+ @api.model
+ def _match_partner_contact(self, partner_dict, chatter_msg, domain, order):
+ rpo = self.env["res.partner"]
+ if partner_dict.get("email") and "@" in partner_dict["email"]:
+ if partner := rpo.search(
+ expression.AND(
+ [
+ domain,
+ [("email", "=ilike", partner_dict["email"])],
+ ]
+ ),
+ limit=1,
+ order=order,
+ ):
+ return partner
+ if partner_dict.get("contact"):
+ if partner := rpo.search(
+ expression.AND(
+ [
+ domain,
+ [("name", "=ilike", partner_dict["contact"])],
+ ]
+ ),
+ limit=1,
+ order=order,
+ ):
+ return partner
+ if partner_dict.get("phone"):
+ if partner := rpo.search(
+ expression.AND(
+ [
+ domain,
+ [
+ "|",
+ ("mobile", "=", partner_dict["phone"]),
+ ("phone", "=", partner_dict["phone"]),
+ ],
+ ]
+ ),
+ limit=1,
+ order=order,
+ ):
+ return partner
+ return False
+
+ @api.model
+ def _match_partner_name(self, partner_dict, chatter_msg, domain, order):
+ if partner_dict.get("name"):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("name", "=ilike", partner_dict["name"]),
+ ],
+ ]
+ )
+ return self.env["res.partner"].search(domain, limit=1, order=order)
+ return False
+
+ @api.model
+ def _get_partner_website_domain(self, partner_dict):
+ if not partner_dict.get("website"):
+ return False
+
+ urlp = urlparse(partner_dict["website"])
+ netloc = urlp.netloc
+ if not urlp.scheme and not netloc:
+ netloc = urlp.path
+ if netloc and len(netloc.split(".")) >= 2:
+ return ".".join(netloc.split(".")[-2:])
+
+ @api.model
+ def _match_partner_website(self, partner_dict, chatter_msg, domain, order):
+ if website_domain := self._get_partner_website_domain(partner_dict):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("website", "=ilike", "%" + website_domain + "%"),
+ ],
+ ]
+ )
+ return self.env["res.partner"].search(domain, limit=1, order=order)
+ return False
+
+ @api.model
+ def _get_partner_email_domain(self, partner_dict):
+ return (
+ partner_dict.get("email")
+ and "@" in partner_dict["email"]
+ and partner_dict["email"].split("@")[1]
+ )
+
+ @api.model
+ def _match_partner_email(self, partner_dict, chatter_msg, domain, order):
+ email_domain = self._get_partner_email_domain(partner_dict)
+ # I can't search on email addresses with
+ # email_domain because of the emails such as
+ # @gmail.com, @yahoo.com that may match random partners
+ if email_domain:
+ partner = self.env["res.partner"].search(
+ expression.AND(
+ [domain, [("website", "=ilike", "%" + email_domain + "%")]]
+ ),
+ limit=1,
+ order=order,
+ )
+ if not partner:
+ partner = self.env["res.partner"].search(
+ expression.AND(
+ [domain, [("email", "=ilike", "%@" + email_domain)]]
+ ),
+ limit=1,
+ order=order,
+ )
+ if partner:
+ partner_type_label = partner_dict["type_label"]
+ chatter_msg.append(
+ _(
+ "The %(label)s has been identified by the domain name "
+ "'%(domain)s' so please check carefully that the "
+ "%(label)s is correct.",
+ label=partner_type_label,
+ domain=domain,
+ )
+ )
+ return partner
+
+ @api.model
+ def _match_partner( # noqa: C901
+ self,
+ partner_dict,
+ chatter_msg,
+ partner_type="supplier",
+ domain=None,
+ raise_exception=True,
+ ):
+ """Example:
+ partner_dict = {
+ 'country_code': 'FR',
+ 'state_code': False,
+ 'vat': 'FR12448890432',
+ 'email': 'roger.lemaire@akretion.com',
+ 'website': 'www.akretion.com',
+ 'name': 'Akretion France',
+ 'ref': 'C1242',
+ 'phone': '01.41.98.12.42',
+ }
+ """
+ rpo = self.env["res.partner"]
+ partner_dict = partner_dict.copy()
+ self._strip_cleanup_dict(partner_dict)
+ partner = self._direct_match(partner_dict, rpo, raise_exception=raise_exception)
+ if partner:
+ return partner
+ company_id = self._context.get("force_company") or self.env.company.id
+ domain = domain or []
+ domain = expression.AND(
+ [
+ domain,
+ [
+ "|",
+ ("company_id", "=", False),
+ ("company_id", "=", company_id),
+ ],
+ ]
+ )
+ order = self._get_match_partner_order(partner_type)
+ partner_type_label = self._get_match_partner_type_label(partner_type)
+ partner_dict["type"] = partner_type
+ partner_dict["type_label"] = partner_type_label
+
+ partner = self._match_partner_ref(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ if country_domain := self._get_country_filter(partner_dict, chatter_msg):
+ domain = expression.AND([domain, country_domain])
+
+ if state_domain := self._get_country_state_filter(
+ partner_dict, chatter_msg
+ ):
+ domain = expression.AND([domain, state_domain])
+
+ # Search on VAT
+ if partner_dict.get("vat"):
+ vat = partner_dict["vat"].replace(" ", "").upper()
+ partner = rpo.search(
+ expression.AND([domain, [("vat", "=", vat)]]),
+ limit=1,
+ order=order,
+ )
+ if partner:
+ return partner
+
+ # Hook to plug alternative matching methods
+ partner = self._hook_match_partner(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ # Search for partner contact
+ partner = self._match_partner_contact(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ # Search for partner name
+ partner = self._match_partner_name(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ # Search for partner website
+ partner = self._match_partner_website(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ # Search for partner website
+ partner = self._match_partner_email(partner_dict, chatter_msg, domain, order)
+ if partner:
+ return partner
+
+ if not raise_exception:
+ return None
+ raise self.user_error_wrap(
+ "_match_partner",
+ partner_dict,
+ _(
+ "Odoo couldn't find any %(label)s corresponding to the following "
+ "information extracted from the business document:\n"
+ "Name: %(name)s \n"
+ "VAT number: %(vat)s \n"
+ "Reference: %(ref)s \n"
+ "E-mail: %(email)s \n"
+ "Website: %(website)s \n"
+ "State code: %(state)s \n"
+ "Country code: %(country)s \n",
+ label=partner_type_label,
+ name=partner_dict.get("name") or "",
+ vat=partner_dict.get("vat") or "",
+ ref=partner_dict.get("ref") or "",
+ email=partner_dict.get("email") or "",
+ website=partner_dict.get("website") or "",
+ state=partner_dict.get("state_code") or "",
+ country=partner_dict.get("country_code") or "",
+ ),
+ )
+
+ @api.model
+ def _hook_match_partner(self, partner_dict, chatter_msg, domain, order):
+ return False
+
+ @api.model
+ def _match_shipping_partner(
+ self, partner_dict, partner, chatter_msg, domain=None, raise_exception=True
+ ):
+ """Example:
+ shipping_dict = {
+ 'email': 'contact@akretion.com',
+ 'name': 'Akretion France',
+ 'street': 'Long Avenue',
+ 'street2': 'Building 2A',
+ 'city': 'Paris',
+ 'zip': '69100',
+ 'country_code': 'FR',
+ }
+ The shipping partner can be any partner, not especially related to the
+ customer/supplier (partner argument)
+ """
+ domain = domain or []
+ if partner_dict.get("street"):
+ if partner_dict.get("street_number"):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ (
+ "street",
+ "in",
+ [
+ "{} {}".format(
+ partner_dict.get("street"),
+ partner_dict.get("street_number"),
+ ),
+ "{} {}".format(
+ partner_dict.get("street_number"),
+ partner_dict.get("street"),
+ ),
+ "{}, {}".format(
+ partner_dict.get("street"),
+ partner_dict.get("street_number"),
+ ),
+ "{}, {}".format(
+ partner_dict.get("street_number"),
+ partner_dict.get("street"),
+ ),
+ ],
+ )
+ ],
+ ]
+ )
+ else:
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("street", "=", partner_dict.get("street")),
+ ],
+ ]
+ )
+
+ if partner_dict.get("street2"):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("street2", "=", partner_dict.get("street2")),
+ ],
+ ]
+ )
+ if partner_dict.get("city"):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("city", "=", partner_dict.get("city")),
+ ],
+ ]
+ )
+ if partner_dict.get("zip"):
+ domain = expression.AND(
+ [
+ domain,
+ [
+ ("zip", "=", partner_dict.get("zip")),
+ ],
+ ]
+ )
+
+ domain_delivery = expression.AND([domain, [("type", "=", "delivery")]])
+ partner = self._match_partner(
+ partner_dict,
+ chatter_msg,
+ partner_type=False,
+ domain=domain_delivery,
+ raise_exception=False,
+ )
+ if partner:
+ return partner
+ if not partner_dict.get("vat") and not partner_dict.get("email"):
+ partner = self.env["res.partner"].search(domain_delivery, limit=1)
+ if partner:
+ return partner
+ partner = self._match_partner(
+ partner_dict,
+ chatter_msg,
+ partner_type=False,
+ domain=domain,
+ raise_exception=False,
+ )
+ if partner:
+ return partner
+ if not partner_dict.get("vat"):
+ partner = self.env["res.partner"].search(domain, limit=1)
+ if partner:
+ return partner
+
+ if not raise_exception:
+ return
+ raise self.user_error_wrap(
+ "_match_shipping_partner",
+ partner_dict,
+ _(
+ "Odoo couldn't find any shipping partner corresponding to the "
+ "following information extracted from the business document:\n"
+ "Name: %(name)s\n"
+ "VAT number: %(vat)s\n"
+ "Reference: %(ref)s\n"
+ "E-mail: %(email)s\n"
+ "Website: %(website)s\n"
+ "Street: %(street)s\n"
+ "Street2: %(street2)s\n"
+ "City: %(city)s\n"
+ "ZIP: %(zip)s\n"
+ "State code: %(state)s\n"
+ "Country code: %(country)s\n",
+ name=partner_dict.get("name") or "",
+ vat=partner_dict.get("vat") or "",
+ ref=partner_dict.get("ref") or "",
+ email=partner_dict.get("email") or "",
+ website=partner_dict.get("website") or "",
+ street=partner_dict.get("street") or "",
+ street2=partner_dict.get("street2") or "",
+ city=partner_dict.get("city") or "",
+ zip=partner_dict.get("zip") or "",
+ state=partner_dict.get("state_code") or "",
+ country=partner_dict.get("country_code") or "",
+ ),
+ )
+
+ @api.model
+ def _match_partner_bank(
+ self, partner, iban, bic, chatter_msg, create_if_not_found=False
+ ):
+ assert iban, "iban is a required arg"
+ assert partner, "partner is a required arg"
+ partner = partner.commercial_partner_id
+ iban = iban.replace(" ", "").upper()
+ rpbo = self.env["res.partner.bank"]
+ rbo = self.env["res.bank"]
+ try:
+ validate_iban(iban)
+ except Exception:
+ chatter_msg.append(
+ _("IBAN %s is not valid, so it has been ignored.") % iban
+ )
+ return False
+ company_id = self._context.get("force_company") or self.env.company.id
+ bankaccount = rpbo.search(
+ [
+ "|",
+ ("company_id", "=", False),
+ ("company_id", "=", company_id),
+ ("sanitized_acc_number", "=", iban),
+ ("partner_id", "=", partner.id),
+ ],
+ limit=1,
+ )
+ if bankaccount:
+ return bankaccount
+ elif create_if_not_found:
+ bank_id = False
+ if bic:
+ bic = bic.replace(" ", "").upper()
+ bank = rbo.search([("bic", "=", bic)], limit=1)
+ if bank:
+ bank_id = bank.id
+ else:
+ bank = rbo.create(
+ {"bic": bic, "name": bic} # TODO: see if we could do better
+ )
+ bank_id = bank.id
+ partner_bank = rpbo.create(
+ {"partner_id": partner.id, "acc_number": iban, "bank_id": bank_id}
+ )
+ chatter_msg.append(
+ _(
+ "The bank account IBAN %(iban)s has been automatically "
+ "added on the supplier "
+ "%(partner)s",
+ iban=iban,
+ partner_id=partner.id,
+ partner=partner.display_name,
+ )
+ )
+ return partner_bank
+ else:
+ chatter_msg.append(
+ _(
+ "The analysis of the business document returned "
+ "IBAN %(iban)s as bank account, but there is no such "
+ "bank account in Odoo linked to partner "
+ "%(partner)s and "
+ "the option to automatically create bank "
+ "accounts upon import is disabled.",
+ iban=iban,
+ partner_id=partner.id,
+ partner=partner.display_name,
+ )
+ )
+
+ @api.model
+ def _match_product(self, product_dict, chatter_msg, seller=False):
+ """Retrieve product.
+
+ Matching sequence:
+
+ 1. ID
+ 2. barcode
+ 3. packaging barcode
+ 4. default_code
+ 5. seller code
+
+ :param product_dict: dictionary w/ product info.
+
+ Example: {'barcode': '5449000054227', 'code': 'COCA1L'}
+
+ :param chatter_msg: list of msgs to append to chatter (if any)
+ :param seller: optional product.supplierinfo record
+ """
+ ppo = self.env["product.product"]
+ self._strip_cleanup_dict(product_dict)
+ product = self._direct_match(product_dict, ppo)
+ if product:
+ return product
+ product = self._match_product_search(product_dict)
+ if product:
+ return product
+ elif seller:
+ # WARNING: Won't work for multi-variant products
+ # because product.supplierinfo is attached to product template
+ sinfo = self.env["product.supplierinfo"].search(
+ self._match_company_domain()
+ + [
+ ("partner_id", "=", seller.id),
+ ("product_code", "=", product_dict["code"]),
+ ],
+ limit=1,
+ )
+ if (
+ sinfo
+ and sinfo.product_tmpl_id.product_variant_ids
+ and len(sinfo.product_tmpl_id.product_variant_ids) == 1
+ ):
+ return sinfo.product_tmpl_id.product_variant_ids[0]
+ raise self.user_error_wrap(
+ "_match_product",
+ product_dict,
+ _(
+ "Odoo couldn't find any product corresponding to the "
+ "following information extracted from the business document:\n"
+ "Barcode: %(barcode)s\n"
+ "Product code: %(product_code)s\n"
+ "Supplier: %(supplier)s\n",
+ barcode=product_dict.get("barcode") or "",
+ product_code=product_dict.get("code") or "",
+ supplier=seller and seller.name or "",
+ ),
+ )
+
+ @api.model
+ def _match_product_search(self, product_dict):
+ product = self.env["product.product"].browse()
+ cdomain = self._match_company_domain()
+ if product_dict.get("barcode"):
+ domain = expression.AND(
+ [
+ cdomain,
+ [
+ "|",
+ ("barcode", "=", product_dict["barcode"]),
+ ("packaging_ids.barcode", "=", product_dict["barcode"]),
+ ],
+ ]
+ )
+ product = product.search(domain, limit=1)
+ if not product and product_dict.get("code"):
+ # TODO: this domain could be probably included in the former one
+ domain = expression.AND(
+ [
+ cdomain,
+ [
+ "|",
+ ("barcode", "=", product_dict["code"]),
+ ("default_code", "=", product_dict["code"]),
+ ],
+ ]
+ )
+ product = product.search(domain, limit=1)
+ return product
+
+ @api.model
+ def _match_company_domain(self):
+ company_id = self._context.get("force_company") or self.env.user.company_id.id
+ return ["|", ("company_id", "=", False), ("company_id", "=", company_id)]
+
+ @api.model
+ def _match_currency(self, currency_dict, chatter_msg):
+ """Example:
+ currency_dict = {
+ 'iso': 'USD', # If we have ISO, no need to have more keys
+ 'symbol': '$',
+ 'country_code': 'US',
+ 'iso_or_symbol': '$',
+ }
+ """
+ if not currency_dict:
+ currency_dict = {}
+ rco = self.env["res.currency"]
+ self._strip_cleanup_dict(currency_dict)
+ currency = self._direct_match(currency_dict, rco)
+ if currency:
+ return currency
+ if currency_dict.get("iso"):
+ currency_iso = currency_dict["iso"].upper()
+ currency = rco.search([("name", "=", currency_iso)], limit=1)
+ if currency:
+ return currency
+ else:
+ raise self.user_error_wrap(
+ "_match_currency",
+ currency_dict,
+ _(
+ "The analysis of the business document returned '%s' as "
+ "the currency ISO code. But there are no currency "
+ "with that code in Odoo."
+ )
+ % currency_iso,
+ )
+ if currency_dict.get("symbol"):
+ currencies = rco.search([("symbol", "=", currency_dict["symbol"])])
+ if len(currencies) == 1:
+ return currencies
+ else:
+ chatter_msg.append(
+ _(
+ "The analysis of the business document returned '%s' as "
+ "the currency symbol. But there are none or several "
+ "currencies with that symbol in Odoo."
+ )
+ % currency_dict["symbol"]
+ )
+ if currency_dict.get("iso_or_symbol"):
+ currencies = rco.search(
+ [
+ "|",
+ ("name", "=", currency_dict["iso_or_symbol"].upper()),
+ ("symbol", "=", currency_dict["iso_or_symbol"]),
+ ]
+ )
+ if len(currencies) == 1:
+ return currencies[0]
+ else:
+ raise self.user_error_wrap(
+ "_match_currency",
+ currency_dict,
+ _(
+ "The analysis of the business document returned '%(code)s' as "
+ "the currency symbol or ISO code. But there are none or "
+ "several currencies with the symbol/ISO code in Odoo.",
+ code=currency_dict["iso_or_symbol"],
+ ),
+ )
+ if currency_dict.get("country_code"):
+ country_code = currency_dict["country_code"]
+ country = self.env["res.country"].search(
+ [("code", "=", country_code)], limit=1
+ )
+ if country:
+ if country.currency_id:
+ return country.currency_id
+ else:
+ raise self.user_error_wrap(
+ "_match_currency",
+ currency_dict,
+ _(
+ "The analysis of the business document returned '%(code)s' "
+ "as the country code to find the related currency. "
+ "But the country '%(name)s' doesn't have any related "
+ "currency configured in Odoo.",
+ code=country_code,
+ name=country.name,
+ ),
+ )
+ else:
+ raise self.user_error_wrap(
+ "_match_currency",
+ currency_dict,
+ _(
+ "The analysis of the business document returned '%s' "
+ "as the country code to find the related currency. "
+ "But there is no country with that code in Odoo."
+ )
+ % country_code,
+ )
+ if self._context.get("force_company"):
+ company = self.env["res.company"].browse(self._context["force_company"])
+ else:
+ company = self.env.company
+ company_cur = company.currency_id
+ chatter_msg.append(
+ _("No currency specified, so Odoo used the company currency (%s)")
+ % company_cur.name
+ )
+ return company_cur
+
+ @api.model
+ def _match_uom(self, uom_dict, chatter_msg, product=False):
+ """Example:
+ uom_dict = {
+ 'unece_code': 'LTR',
+ 'name': 'Liter',
+ }
+ """
+ uuo = self.env["uom.uom"]
+ if not uom_dict:
+ uom_dict = {}
+ self._strip_cleanup_dict(uom_dict)
+ uom = self._direct_match(uom_dict, uuo)
+ if uom:
+ return uom
+ if uom_dict.get("unece_code"):
+ # Map NIU to Unit
+ if uom_dict["unece_code"] == "NIU":
+ uom_dict["unece_code"] = "C62"
+ uom = uuo.search([("unece_code", "=", uom_dict["unece_code"])], limit=1)
+ if uom:
+ return uom
+ else:
+ chatter_msg.append(
+ _(
+ "The analysis of the business document returned '%(code)s' "
+ "as the unit of measure UNECE code, but there is no "
+ "unit of measure with that UNECE code in Odoo. Please "
+ "check the configuration of the units of measures in "
+ "Odoo.",
+ code=uom_dict["unece_code"],
+ )
+ )
+ if uom_dict.get("name"):
+ uom = uuo.search([("name", "=ilike", uom_dict["name"] + "%")], limit=1)
+ if uom:
+ return uom
+ if product:
+ return product.uom_id
+ chatter_msg.append(
+ _(
+ "Odoo couldn't find any unit of measure corresponding to the "
+ "following information extracted from the business document:
"
+ "- UNECE code: %(code)s
"
+ "- Name of the unit of measure: %(name)s
"
+ "So the unit of measure 'Unit(s)' has been used. You may "
+ "have to change it manually.
",
+ code=uom_dict.get("unece_code"),
+ name=uom_dict.get("name"),
+ )
+ )
+ return self.env.ref("uom.product_uom_unit")
+
+ @api.model
+ def _match_taxes(
+ self, taxes_list, chatter_msg, type_tax_use="purchase", price_include=False
+ ):
+ """taxes_list must be a list of tax_dict"""
+ taxes_recordset = self.env["account.tax"].browse(False)
+ for tax_dict in taxes_list:
+ taxes_recordset += self._match_tax(
+ tax_dict,
+ chatter_msg,
+ type_tax_use=type_tax_use,
+ price_include=price_include,
+ )
+ return taxes_recordset
+
+ @api.model
+ def _prepare_match_tax_domain(
+ self, tax_dict, type_tax_use="purchase", price_include=False
+ ):
+ ato = self.env["account.tax"]
+ company_id = self._context.get("force_company") or self.env.company.id
+ domain = [("company_id", "=", company_id)]
+ if type_tax_use == "purchase":
+ domain.append(("type_tax_use", "=", "purchase"))
+ elif type_tax_use == "sale":
+ domain.append(("type_tax_use", "=", "sale"))
+ if price_include is False:
+ domain.append(("price_include", "=", False))
+ elif price_include is True:
+ domain.append(("price_include", "=", True))
+ # with the code above, if you set price_include=None, it will
+ # won't depend on the value of the price_include parameter
+ assert tax_dict.get("amount_type") in [
+ "fixed",
+ "percent",
+ ], "bad tax type, has to be fixed or percent"
+ assert "amount" in tax_dict, "Missing amount key in tax_dict"
+ domain.append(("amount_type", "=", tax_dict["amount_type"]))
+ if tax_dict.get("unece_type_code"):
+ domain.append(("unece_type_code", "=", tax_dict["unece_type_code"]))
+ if tax_dict.get("unece_categ_code"):
+ domain.append(("unece_categ_code", "=", tax_dict["unece_categ_code"]))
+ if tax_dict.get("unece_due_date_code"):
+ tax_exigibility = ato._get_tax_exigibility_from_unece_code(
+ tax_dict["unece_due_date_code"]
+ )
+ if tax_exigibility:
+ domain = expression.AND(
+ [domain, [("tax_exigibility", "=", tax_exigibility)]]
+ )
+ return domain
+
+ @api.model
+ def _match_tax(
+ self,
+ tax_dict,
+ chatter_msg,
+ type_tax_use="purchase",
+ price_include=False,
+ ):
+ """Example:
+ tax_dict = {
+ 'amount_type': 'percent', # required param, 'fixed' or 'percent'
+ 'amount': 20.0, # required
+ 'unece_type_code': 'VAT',
+ 'unece_categ_code': 'S',
+ 'unece_due_date_code': '72',
+ }
+ """
+ ato = self.env["account.tax"]
+ self._strip_cleanup_dict(tax_dict)
+ tax = self._direct_match(tax_dict, ato)
+ if tax:
+ return tax
+ domain = self._prepare_match_tax_domain(
+ tax_dict, type_tax_use=type_tax_use, price_include=price_include
+ )
+ taxes = ato.search(domain)
+ for tax in taxes:
+ tax_amount = tax.amount # 'amount' field : digits=(16, 4)
+ if not float_compare(tax_dict["amount"], tax_amount, precision_digits=4):
+ return tax
+ raise self.user_error_wrap(
+ "_match_tax",
+ tax_dict,
+ _(
+ "Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' "
+ "and 'Tax Included in Price' = '%(price)s' which correspond to the "
+ "following information extracted from the business document:\n"
+ "UNECE Tax Type code: %(tax_type)s\n"
+ "UNECE Tax Category code: %(tax_cat)s\n"
+ "UNECE Due Date code: %(tax_due_date)s\n"
+ "Tax amount: %(amount)s %(amount_type)s",
+ tax=type_tax_use,
+ price=price_include,
+ tax_type=tax_dict.get("unece_type_code") or "",
+ tax_cat=tax_dict.get("unece_categ_code") or "",
+ tax_due_date=tax_dict.get("unece_due_date_code") or "",
+ amount=tax_dict["amount"],
+ amount_type=tax_dict["amount_type"] == "percent"
+ and "%"
+ or _("(fixed)"),
+ ),
+ )
+
+ def compare_lines(
+ self,
+ existing_lines,
+ import_lines,
+ chatter_msg,
+ qty_precision=None,
+ price_precision=None,
+ seller=False,
+ ):
+ """Example:
+ existing_lines = [{
+ 'product': odoo_recordset,
+ 'name': 'USB Adapter',
+ 'qty': 1.5,
+ 'price_unit': 23.43, # without taxes
+ 'uom': uom,
+ 'line': recordset,
+ # Add taxes
+ }]
+ import_lines = [{
+ 'product': {
+ 'barcode': '2100002000003',
+ 'code': 'EAZY1',
+ },
+ 'quantity': 2,
+ 'price_unit': 12.42, # without taxes
+ 'uom': {'unece_code': 'C62'},
+ }]
+
+ Result of the method:
+ {
+ 'to_remove': line_multirecordset,
+ 'to_add': [
+ {
+ 'product': recordset1,
+ 'uom', recordset,
+ 'import_line': {import dict},
+ # We provide product and uom as recordset to avoid the
+ # need to compute a second match
+ ]
+ 'to_update': {
+ 'line1_recordset': {'qty': [1, 2], 'price_unit': [4.5, 4.6]},
+ # qty must be updated from 1 to 2
+ # price must be updated from 4.5 to 4.6
+ 'line2_recordset': {'qty': [12, 13]},
+ # only qty must be updated
+ }
+ }
+
+ The check existing_currency == import_currency must be done before
+ the call to compare_lines()
+ """
+ dpo = self.env["decimal.precision"]
+ if qty_precision is None:
+ qty_precision = dpo.precision_get("Product Unit of Measure")
+ if price_precision is None:
+ price_precision = dpo.precision_get("Product Price")
+ existing_lines_dict = {}
+ for eline in existing_lines:
+ if not eline.get("product"):
+ chatter_msg.append(
+ _(
+ "The existing line '%s' doesn't have any product, "
+ "so the lines haven't been updated."
+ )
+ % eline.get("name")
+ )
+ return False
+ if eline["product"] in existing_lines_dict:
+ chatter_msg.append(
+ _(
+ "The product '%s' is used on several existing "
+ "lines, so the lines haven't been updated."
+ )
+ % eline["product"].display_name
+ )
+ return False
+ existing_lines_dict[eline["product"]] = eline
+ unique_import_products = []
+ res = {
+ "to_remove": False,
+ "to_add": [],
+ "to_update": {},
+ }
+ for iline in import_lines:
+ if not iline.get("product"):
+ chatter_msg.append(
+ _(
+ "One of the imported lines doesn't have any product, "
+ "so the lines haven't been updated."
+ )
+ )
+ return False
+ product = self._match_product(iline["product"], chatter_msg, seller=seller)
+ uom = self._match_uom(iline.get("uom"), chatter_msg, product)
+ if product in unique_import_products:
+ chatter_msg.append(
+ _(
+ "The product '%s' is used on several imported lines, "
+ "so the lines haven't been updated."
+ )
+ % product.display_name
+ )
+ return False
+ unique_import_products.append(product)
+ if product in existing_lines_dict:
+ if uom != existing_lines_dict[product]["uom"]:
+ chatter_msg.append(
+ _(
+ "For product '%(product)s', the unit of measure is "
+ "%(uom_product)s on the existing line, but it is "
+ "%(uom_imported)s on the imported line."
+ "We don't support this scenario for the moment, so "
+ "the lines haven't been updated.",
+ product=product.display_name,
+ uom_product=existing_lines_dict[product]["uom"].name,
+ uom_imported=uom.name,
+ )
+ )
+ return False
+ # used for to_remove
+ existing_lines_dict[product]["import"] = True
+ oline = existing_lines_dict[product]["line"]
+ res["to_update"][oline] = self._prepare_order_line_update_values(
+ existing_lines_dict[product], iline, qty_precision, price_precision
+ )
+ else:
+ res["to_add"].append(
+ {"product": product, "uom": uom, "import_line": iline}
+ )
+ for exiting_dict in existing_lines_dict.values():
+ if not exiting_dict.get("import"):
+ if res["to_remove"]:
+ res["to_remove"] += exiting_dict["line"]
+ else:
+ res["to_remove"] = exiting_dict["line"]
+ return res
+
+ def _prepare_order_line_update_values(
+ self, existing_line, iline, qty_precision, price_precision
+ ):
+ values = {}
+ if float_compare(
+ iline["qty"],
+ existing_line["qty"],
+ precision_digits=qty_precision,
+ ):
+ values["qty"] = [existing_line["qty"], iline["qty"]]
+ if "price_unit" in iline and float_compare(
+ iline["price_unit"],
+ existing_line["price_unit"],
+ precision_digits=price_precision,
+ ):
+ values["price_unit"] = [
+ existing_line["price_unit"],
+ iline["price_unit"],
+ ]
+ return values
+
+ def _prepare_account_speed_dict(self):
+ company_id = self._context.get("force_company") or self.env.company.id
+ res = self.env["account.account"].search_read(
+ [("company_id", "=", company_id), ("deprecated", "=", False)], ["code"]
+ )
+ speed_dict = {}
+ for line in res:
+ speed_dict[line["code"].upper()] = line["id"]
+ return speed_dict
+
+ @api.model
+ def _match_account(self, account_dict, chatter_msg, speed_dict=None):
+ """Example:
+ account_dict = {
+ 'code': '411100',
+ }
+ speed_dict is usefull to gain performance when you have a lot of
+ accounts to match
+ """
+ if not account_dict:
+ account_dict = {}
+ aao = self.env["account.account"]
+ if speed_dict is None:
+ speed_dict = self._prepare_account_speed_dict()
+ self._strip_cleanup_dict(account_dict)
+ account = self._direct_match(account_dict, aao)
+ if account:
+ return account
+ if account_dict.get("code"):
+ acc_code = account_dict["code"].upper()
+ if acc_code in speed_dict:
+ return aao.browse(speed_dict[acc_code])
+ # Match when account_dict['code'] is longer than Odoo's account
+ # codes because of trailing '0'
+ # I don't think we need a warning for this kind of match
+ acc_code_tmp = acc_code
+ while acc_code_tmp and acc_code_tmp[-1] == "0":
+ acc_code_tmp = acc_code_tmp[:-1]
+ if acc_code_tmp and acc_code_tmp in speed_dict:
+ return aao.browse(speed_dict[acc_code_tmp])
+ # Match when account_dict['code'] is shorter than Odoo's accounts
+ # -> warns the user about this
+ for code, account_id in speed_dict.items():
+ if code.startswith(acc_code):
+ chatter_msg.append(
+ _(
+ "Approximate match: account %(account)s has been matched "
+ "with account %(matched_account)s",
+ account=account_dict["code"],
+ matched_account=code,
+ )
+ )
+ return aao.browse(account_id)
+ raise self.user_error_wrap(
+ "_match_account",
+ account_dict,
+ _(
+ "Odoo couldn't find any account corresponding to the "
+ "following information extracted from the business document:\n"
+ "Account code: %s"
+ )
+ % (account_dict.get("code") or ""),
+ )
+
+ def _prepare_analytic_account_speed_dict(self):
+ company_id = self._context.get("force_company") or self.env.company.id
+ res = self.env["account.analytic.account"].search_read(
+ [("company_id", "=", company_id)], ["code"]
+ )
+ speed_dict = {}
+ for line in res:
+ if line["code"]:
+ speed_dict[line["code"].upper()] = line["id"]
+ return speed_dict
+
+ @api.model
+ def _match_analytic_account(self, aaccount_dict, chatter_msg, speed_dict=None):
+ """Example:
+ aaccount_dict = {
+ 'code': '627',
+ }
+ speed_dict is usefull to gain performance when you have a lot of
+ analytic accounts to match
+ """
+ if not aaccount_dict:
+ aaccount_dict = {}
+ aaao = self.env["account.analytic.account"]
+ if speed_dict is None:
+ speed_dict = self._prepare_analytic_account_speed_dict()
+ self._strip_cleanup_dict(aaccount_dict)
+ aaccount = self._direct_match(aaccount_dict, aaao)
+ if aaccount:
+ return aaccount
+ if aaccount_dict.get("code"):
+ aacode = aaccount_dict["code"].upper()
+ if aacode in speed_dict:
+ return aaao.browse(speed_dict[aacode])
+ raise self.user_error_wrap(
+ "_match_analytic_account",
+ aaccount_dict,
+ _(
+ "Odoo couldn't find any analytic account corresponding to the "
+ "following information extracted from the business document:\n"
+ "Analytic account code: %s"
+ )
+ % (aaccount_dict.get("code") or ""),
+ )
+
+ def _prepare_journal_speed_dict(self):
+ company_id = self._context.get("force_company") or self.env.company.id
+ res = self.env["account.journal"].search_read(
+ [("company_id", "=", company_id)], ["code"]
+ )
+ speed_dict = {}
+ for line in res:
+ speed_dict[line["code"].upper()] = line["id"]
+ return speed_dict
+
+ @api.model
+ def _match_journal(self, journal_dict, chatter_msg, speed_dict=None):
+ """Example:
+ journal_dict = {
+ 'code': 'MISC',
+ }
+ speed_dict is usefull to gain performance when you have a lot of
+ journals to match
+ """
+ if not journal_dict:
+ journal_dict = {}
+ ajo = self.env["account.journal"]
+ if speed_dict is None:
+ speed_dict = self._prepare_journal_speed_dict()
+ self._strip_cleanup_dict(journal_dict)
+ journal = self._direct_match(journal_dict, ajo)
+ if journal:
+ return journal
+ if journal_dict.get("code"):
+ jcode = journal_dict["code"].upper()
+ if jcode in speed_dict:
+ return ajo.browse(speed_dict[jcode])
+ # case insensitive
+ raise self.user_error_wrap(
+ "_match_journal",
+ journal_dict,
+ _(
+ "Odoo couldn't find any journal corresponding to the "
+ "following information extracted from the business document:\n"
+ "Journal code: %s"
+ )
+ % (journal_dict.get("code") or ""),
+ )
+
+ # Code moved from base_business_document_import_stock
+ # Now that the incoterm obj (account.incoterms) is defined in
+ # the 'account' module (since Odoo v12) instead of 'stock'
+ @api.model
+ def _match_incoterm(self, incoterm_dict, chatter_msg):
+ aio = self.env["account.incoterms"]
+ if not incoterm_dict:
+ incoterm_dict = {}
+ self._strip_cleanup_dict(incoterm_dict)
+ incoterm = self._direct_match(incoterm_dict, aio)
+ if incoterm:
+ return incoterm
+ if incoterm_dict.get("code"):
+ incoterm = aio.search(
+ [
+ "|",
+ ("name", "=ilike", incoterm_dict["code"]),
+ ("code", "=ilike", incoterm_dict["code"]),
+ ],
+ limit=1,
+ )
+ if incoterm:
+ return incoterm
+ else:
+ self.user_error_wrap(
+ "_match_incoterm",
+ incoterm_dict,
+ _("Could not find any Incoterm in Odoo corresponding " "to '%s'")
+ % incoterm_dict["code"],
+ )
+ return False
+
+ @api.model
+ def _check_company(self, company_dict, chatter_msg):
+ if not company_dict:
+ company_dict = {}
+ rco = self.env["res.company"]
+ if self._context.get("force_company"):
+ company = rco.browse(self._context["force_company"])
+ else:
+ company = self.env.company
+ if company_dict.get("vat"):
+ parsed_company_vat = company_dict["vat"].replace(" ", "").upper()
+ if company.partner_id.vat:
+ if company.partner_id.vat != parsed_company_vat:
+ raise self.user_error_wrap(
+ "_check_company",
+ company_dict,
+ _(
+ "The VAT number of the customer written in the "
+ "business document (%(parsed_vat)s) doesn't match "
+ "the VAT number of the company '%(company)s' (%(vat)s) "
+ "in which you are trying to import this document.",
+ parsed_vat=parsed_company_vat,
+ company=company.display_name,
+ vat=company.partner_id.vat,
+ ),
+ )
+ else:
+ chatter_msg.append(
+ _("Missing VAT number on company '%s'") % company.display_name
+ )
+
+ def get_xml_files_from_pdf(self, pdf_file):
+ """Returns a dict with key = filename, value = XML file obj"""
+ logger.warning(
+ "`get_xml_files_from_pdf` deprecated: use `pdf.helper.pdf_get_xml_files`"
+ )
+ return self.env["pdf.helper"].pdf_get_xml_files(pdf_file)
+
+ @api.model
+ def post_create_or_update(self, parsed_dict, record, doc_filename=None):
+ if parsed_dict.get("attachments"):
+ for filename, data_base64 in parsed_dict["attachments"].items():
+ self.env["ir.attachment"].create(
+ {
+ "name": filename,
+ "res_id": record.id,
+ "res_model": str(record._name),
+ "datas": data_base64,
+ }
+ )
+ for msg in parsed_dict["chatter_msg"]:
+ record.message_post(body=msg)
+ if parsed_dict.get("note"):
+ if doc_filename:
+ msg = _("Notes in file %s:") % doc_filename
+ else:
+ msg = _("Notes in imported document:")
+ record.message_post( # pylint: disable=translation-required
+ body="{} {}".format(msg, parsed_dict["note"])
+ )
diff --git a/base_business_document_import/readme/CONTRIBUTORS.rst b/base_business_document_import/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000000..2aa685f8ae
--- /dev/null
+++ b/base_business_document_import/readme/CONTRIBUTORS.rst
@@ -0,0 +1,5 @@
+* Alexis de Lattre
+* Nicolas JEUDY
+* Jacques-Etienne Baudoux
+* Phuc (Tran Thanh)
+* Simone Orsi
diff --git a/base_business_document_import/readme/DESCRIPTION.rst b/base_business_document_import/readme/DESCRIPTION.rst
new file mode 100644
index 0000000000..a5b1f2cc73
--- /dev/null
+++ b/base_business_document_import/readme/DESCRIPTION.rst
@@ -0,0 +1,5 @@
+This is a technical module ; it doesn't bring any useful feature by itself. This module is the base modules for 2 other modules :
+
+* *account_invoice_import* which imports supplier invoices as PDF or XML files (this module also requires some additional modules such as *account_invoice_import_invoice2data*, *account_invoice_import_ubl*, etc... to support specific invoice formats),
+
+* *sale_invoice_import* which imports sale orders as CSV, XML or PDF files (this module also requires some additional modules such as *sale_invoice_import_csv* or *sale_invoice_import_ubl* to support specific order formats)
diff --git a/base_business_document_import/static/description/icon.png b/base_business_document_import/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~!
zVpnB`o+K7|Al`Q_U;eD$B
zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA
z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__
zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_
zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I
z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U
z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)(
z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH
zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW
z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx
zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h
zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9
zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz#
z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA
zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K=
z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS
zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C
zuVl&0duN<;uOsB3%T9Fp8t{ED108)`y_~Hnd9AUX7h-H?jVuU|}My+C=TjH(jKz
zqMVr0re3S$H@t{zI95qa)+Crz*5Zj}Ao%4Z><+W(nOZd?gDnfNBC3>M8WE61$So|P
zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO
z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1
zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_
zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8
zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ>
zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN
z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h
zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d
zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB
zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz
z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I
zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X
zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD
z#z-)AXwSRY?OPefw^iI+
z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd
z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs
z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I
z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$
z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV
z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s
zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6
zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u
zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q
zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH
zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c
zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT
zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+
z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ
zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy
zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC)
zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a
zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x!
zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X
zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8
z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A
z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H
zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n=
z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK
z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z
zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h
z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD
z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW
zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@
zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz
z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y<
zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X
zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6
zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6%
z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(|
z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ
z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H
zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6
z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d}
z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A
zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB
z
z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp
zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zls4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6#
z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f#
zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC
zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv!
zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG
z-wfS
zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9
z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE#
z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz
zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t
z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN
zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q
ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k
zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG
z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff
z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1
zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO
zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$
zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV(
z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb
zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4
z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{
zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx}
z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov
zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22
zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq
zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t<
z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k
z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp
z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{}
zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/base_business_document_import/static/description/index.html b/base_business_document_import/static/description/index.html
new file mode 100644
index 0000000000..8cf028bdc3
--- /dev/null
+++ b/base_business_document_import/static/description/index.html
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+Base Business Document Import
+
+
+
+
+
Base Business Document Import
+
+
+
+
This is a technical module ; it doesn’t bring any useful feature by itself. This module is the base modules for 2 other modules :
+
+- account_invoice_import which imports supplier invoices as PDF or XML files (this module also requires some additional modules such as account_invoice_import_invoice2data, account_invoice_import_ubl, etc… to support specific invoice formats),
+- sale_invoice_import which imports sale orders as CSV, XML or PDF files (this module also requires some additional modules such as sale_invoice_import_csv or sale_invoice_import_ubl to support specific order formats)
+
+
Table of contents
+
+
+
+
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.
+
+
+
+
+
+
+- Akretion
+- Nicolas JEUDY
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
Current maintainer:
+
+
This module is part of the OCA/edi project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/base_business_document_import/tests/__init__.py b/base_business_document_import/tests/__init__.py
new file mode 100644
index 0000000000..12d28211d4
--- /dev/null
+++ b/base_business_document_import/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_business_document_import
diff --git a/base_business_document_import/tests/test_business_document_import.py b/base_business_document_import/tests/test_business_document_import.py
new file mode 100644
index 0000000000..90ddbedcf6
--- /dev/null
+++ b/base_business_document_import/tests/test_business_document_import.py
@@ -0,0 +1,482 @@
+# Copyright 2016-2021 Akretion France (http://www.akretion.com/)
+# Copyright 2020-2021 Jacques-Etienne Baudoux (BCIM)
+# @author: Alexis de Lattre
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+import logging
+
+from odoo.exceptions import UserError
+from odoo.tests import tagged
+from odoo.tests.common import TransactionCase
+
+logger = logging.getLogger(__name__)
+
+
+@tagged("post_install", "-at_install")
+class TestBaseBusinessDocumentImport(TransactionCase):
+ def test_match_partner(self):
+ partner1 = self.env["res.partner"].create(
+ {"name": "COGIP", "ref": "COGIP", "website": "http://example.com/"}
+ )
+ bdio = self.env["business.document.import"]
+ # match on domain extracted from email with warning
+ partner_dict = {"email": "alexis.delattre@example.com"}
+ warn = []
+ res = bdio._match_partner(partner_dict, warn, partner_type=False)
+ self.assertEqual(res, partner1)
+ self.assertTrue(warn)
+ partner_dict = {"name": "ready mat "}
+ partner_ready_mat = self.env.ref("base.res_partner_4")
+ partner_ready_mat.supplier_rank = 1 # to be considered as a supplier
+ res = bdio._match_partner(partner_dict, [], partner_type="supplier")
+ self.assertEqual(res, partner_ready_mat)
+ partner_dict = {"ref": "COGIP"}
+ res = bdio._match_partner(partner_dict, [], partner_type=False)
+ self.assertEqual(res, partner1)
+
+ def test_direct_match_recordset(self):
+ partner = self.env["res.partner"].create(
+ {
+ "name": "Alexis Delattre",
+ "email": "alexis.delattre@example.com",
+ "ref": "C1242",
+ }
+ )
+ partner_dict = {
+ "recordset": partner,
+ }
+ bdio = self.env["business.document.import"]
+ partner_match = bdio._direct_match(partner_dict, self.env["res.partner"], True)
+ self.assertEqual(partner, partner_match)
+
+ with self.assertRaises(UserError):
+ bdio._direct_match(partner_dict, self.env["res.partner.bank"], True)
+
+ partner_match = bdio._direct_match(
+ partner_dict, self.env["res.partner.bank"], False
+ )
+ self.assertEqual(None, partner_match)
+
+ def test_direct_match_id(self):
+ partner = self.env["res.partner"].create(
+ {
+ "name": "Alexis Delattre",
+ "email": "alexis.delattre@example.com",
+ "ref": "C1242",
+ }
+ )
+ partner_dict = {
+ "id": partner.id,
+ }
+ bdio = self.env["business.document.import"]
+ partner_match = bdio._direct_match(partner_dict, self.env["res.partner"], True)
+ self.assertEqual(partner, partner_match)
+
+ partner_dict = {
+ "id": 234234234234231,
+ }
+ with self.assertRaises(UserError):
+ bdio._direct_match(partner_dict, self.env["res.partner"], True)
+
+ def test_direct_match_xmlid(self):
+ partner_dict = {
+ "xmlid": "i.dont.exist.odoo",
+ }
+ bdio = self.env["business.document.import"]
+ with self.assertRaises(UserError):
+ bdio._direct_match(partner_dict, self.env["res.partner"], True)
+
+ partner_dict = {
+ "xmlid": "base.fr",
+ }
+ with self.assertRaises(UserError):
+ bdio._direct_match(partner_dict, self.env["res.partner"], True)
+
+ partner_dict = {
+ "xmlid": "base.main_partner",
+ }
+ partner = bdio._direct_match(partner_dict, self.env["res.partner"], True)
+ self.assertEqual(partner.name, "YourCompany")
+
+ def test_match_partner_ref(self):
+ partner1 = self.env["res.partner"].create(
+ {
+ "name": "Alexis Delattre",
+ "email": "alexis.delattre@example.com",
+ "ref": "C1242",
+ }
+ )
+ bdio = self.env["business.document.import"]
+ partner_dict = {
+ "name": "Alexis Delattre",
+ "email": "alexis.delattre@example.com",
+ "ref": "C1242",
+ }
+ chatter_msg = []
+ domain = []
+ order = ""
+ partner = bdio._match_partner_ref(partner_dict, chatter_msg, domain, order)
+ self.assertEqual(partner, partner1)
+
+ def test_match_partner_contact(self):
+ partner_email = self.env["res.partner"].create(
+ {
+ "email": "alexis.email@example.com",
+ "name": "Alexis email",
+ }
+ )
+ partner_contact = self.env["res.partner"].create(
+ {
+ "email": "alexis.name@example.com",
+ "name": "Alexis name",
+ }
+ )
+ partner_phone = self.env["res.partner"].create(
+ {
+ "email": "alexis.phone@example.com",
+ "phone": "01.41.98.12.42",
+ "name": "Alexis phone",
+ }
+ )
+ bdio = self.env["business.document.import"]
+ chatter_msg = []
+ domain = []
+ order = ""
+
+ partner_dict = {
+ "name": "Alexis email",
+ "email": "alexis.email@example.com",
+ }
+ partner = bdio._match_partner_contact(partner_dict, chatter_msg, domain, order)
+ self.assertEqual(partner, partner_email)
+
+ partner_dict = {
+ "contact": "Alexis name",
+ "email": "alexis.name@example.com",
+ }
+ partner = bdio._match_partner_contact(partner_dict, chatter_msg, domain, order)
+ self.assertEqual(partner, partner_contact)
+
+ partner_dict = {
+ "name": "Alexis phone",
+ "email": "alexis.phone@example.com",
+ "phone": "01.41.98.12.42",
+ }
+ partner = bdio._match_partner_contact(partner_dict, chatter_msg, domain, order)
+ self.assertEqual(partner, partner_phone)
+
+ def test_match_partner_name(self):
+ partner_name = self.env["res.partner"].create(
+ {
+ "email": "alexis.name@example.com",
+ "name": "Alexis name",
+ }
+ )
+ bdio = self.env["business.document.import"]
+ chatter_msg = []
+ domain = []
+ order = ""
+
+ partner_dict = {
+ "name": "Alexis name",
+ "email": "alexis.name@example.com",
+ }
+ partner = bdio._match_partner_name(partner_dict, chatter_msg, domain, order)
+ self.assertEqual(partner, partner_name)
+
+ def test_get_partner_website_domain(self):
+ bdio = self.env["business.document.import"]
+
+ www_website = {"website": "www.example.com"}
+ website_domain = bdio._get_partner_website_domain(www_website)
+ self.assertEqual(website_domain, "example.com")
+
+ no_website = bdio._get_partner_website_domain({})
+ self.assertEqual(False, no_website)
+
+ https_www_website = {"website": "https://www.example.com"}
+ website_domain = bdio._get_partner_website_domain(https_www_website)
+ self.assertEqual(website_domain, "example.com")
+
+ https_website = {"website": "https://example.com"}
+ website_domain = bdio._get_partner_website_domain(https_website)
+ self.assertEqual(website_domain, "example.com")
+
+ https_path_website = {"website": "https://subdomain.example.com/bla/bla"}
+ website_domain = bdio._get_partner_website_domain(https_path_website)
+ self.assertEqual(website_domain, "example.com")
+
+ https_big_subdomain_website = {
+ "website": "https://just.a.big.subdomain.example.com"
+ }
+ website_domain = bdio._get_partner_website_domain(https_big_subdomain_website)
+ self.assertEqual(website_domain, "example.com")
+
+ def test_match_shipping_partner(self):
+ rpo = self.env["res.partner"]
+ bdio = self.env["business.document.import"]
+ partner1 = rpo.create(
+ {
+ "name": "Akretion France",
+ "street": "27 rue Henri Rolland",
+ "zip": "69100",
+ "country_id": self.env.ref("base.fr").id,
+ "email": "contact@akretion.com",
+ }
+ )
+ rpo.create(
+ {
+ "parent_id": partner1.id,
+ "name": "Sébastien BEAU",
+ "email": "sebastien.beau@akretion.com",
+ "type": "contact",
+ }
+ )
+ cpartner3 = rpo.create(
+ {
+ "parent_id": partner1.id,
+ "name": "Flo",
+ "email": "flo@akretion.com",
+ "street": "42 rue des lilas d'Espagne",
+ "zip": "92400",
+ "city": "Courbevoie",
+ "country_id": self.env.ref("base.fr").id,
+ "type": "invoice",
+ }
+ )
+ shipping_dict = {
+ "email": "contact@akretion.com",
+ }
+ res = bdio._match_shipping_partner(shipping_dict, None, [])
+ self.assertEqual(res, partner1)
+ shipping_dict = {
+ "street": "42 rue des lilas d'Espagne",
+ "zip": "92400",
+ "country_code": "fr",
+ }
+ res = bdio._match_shipping_partner(shipping_dict, None, [])
+ self.assertEqual(res, cpartner3)
+ shipping_dict["zip"] = "92500"
+ with self.assertRaises(UserError):
+ bdio._match_shipping_partner(shipping_dict, None, [])
+
+ no_error = bdio._match_shipping_partner(
+ shipping_dict, None, [], raise_exception=False
+ )
+ self.assertEqual(no_error, None)
+
+ partner2 = rpo.create(
+ {
+ "name": "Alex Corp",
+ "zip": "69009",
+ "country_id": self.env.ref("base.fr").id,
+ "email": "contact@alex.com",
+ }
+ )
+ shipping_dict = {
+ "email": "contact@alex.com",
+ "zip": "69009",
+ "country_code": "FR",
+ }
+ res = bdio._match_shipping_partner(shipping_dict, None, [])
+ self.assertEqual(res, partner2)
+
+ def test_match_currency(self):
+ bdio = self.env["business.document.import"]
+ currency_dict = {"xmlid": "base.USD"}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.USD"))
+ first_cur = self.env["res.currency"].search([], limit=1)
+ currency_dict = {"id": first_cur.id}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, first_cur)
+ currency_dict = {"recordset": first_cur}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, first_cur)
+ currency_dict = {"iso": "EUR"}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.EUR"))
+ currency_dict = {"symbol": "€"}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.EUR"))
+ currency_dict = {"country_code": "fr "}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.EUR"))
+ currency_dict = {"iso_or_symbol": "€"}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.EUR"))
+ currency_id = self.env.ref("base.KRW").id
+ self.cr.execute(
+ "UPDATE res_company SET currency_id = %s WHERE id = 1", (currency_id,)
+ )
+ currency_dict = {}
+ res = bdio._match_currency(currency_dict, [])
+ self.assertEqual(res, self.env.ref("base.KRW"))
+
+ def test_match_product(self):
+ bdio = self.env["business.document.import"]
+ ppo = self.env["product.product"]
+ product1 = ppo.create(
+ {
+ "name": "Test Product",
+ "barcode": "9782203121102",
+ "seller_ids": [
+ (
+ 0,
+ 0,
+ {
+ "partner_id": self.env.ref("base.res_partner_2").id,
+ "product_code": "TEST1242",
+ },
+ ),
+ ],
+ "packaging_ids": [(0, 0, {"name": "Big Pack", "barcode": "BIG-PACK"})],
+ }
+ )
+ # Match by code
+ product_dict = {"code": "FURN_7777 "}
+ res = bdio._match_product(product_dict, [])
+ self.assertEqual(res, self.env.ref("product.product_delivery_01"))
+ # Match by barcode
+ product_dict = {"barcode": "9782203121102"}
+ res = bdio._match_product(product_dict, [])
+ self.assertEqual(res, product1)
+ # Match by packaging barcode
+ product_dict = {"barcode": "BIG-PACK"}
+ res = bdio._match_product(product_dict, [])
+ self.assertEqual(res, product1)
+ # Match by seller
+ product_dict = {"code": "TEST1242"}
+ res = bdio._match_product(
+ product_dict, [], seller=self.env.ref("base.res_partner_2")
+ )
+ self.assertEqual(res, product1)
+ raise_test = True
+ try:
+ bdio._match_product(product_dict, [], seller=False)
+ raise_test = False
+ except Exception:
+ logger.info("Exception catched.")
+
+ self.assertTrue(raise_test)
+
+ def test_match_uom(self):
+ bdio = self.env["business.document.import"]
+ uom_dict = {"unece_code": "KGM"}
+ res = bdio._match_uom(uom_dict, [])
+ self.assertEqual(res, self.env.ref("uom.product_uom_kgm"))
+ uom_dict = {"unece_code": "NIU"}
+ res = bdio._match_uom(uom_dict, [])
+ self.assertEqual(res, self.env.ref("uom.product_uom_unit"))
+ uom_dict = {"name": "day"}
+ res = bdio._match_uom(uom_dict, [])
+ self.assertEqual(res, self.env.ref("uom.product_uom_day"))
+ uom_dict = {"name": "lb"}
+ res = bdio._match_uom(uom_dict, [])
+ self.assertEqual(res, self.env.ref("uom.product_uom_lb"))
+ uom_dict = {}
+ product = self.env.ref("product.product_product_1")
+ res = bdio._match_uom(uom_dict, [], product=product)
+ self.assertEqual(res, product.uom_id)
+
+ def test_match_tax(self):
+ # on purpose, I use a rate that doesn't exist
+ # so that this test works even if the l10n_de is installed
+ de_tax_21 = self.env["account.tax"].create(
+ {
+ "name": "German VAT purchase 18.0%",
+ "description": "DE-VAT-buy-18.0",
+ "type_tax_use": "purchase",
+ "price_include": False,
+ "amount": 18,
+ "amount_type": "percent",
+ "tax_exigibility": "on_invoice",
+ "unece_type_id": self.env.ref("account_tax_unece.tax_type_vat").id,
+ "unece_categ_id": self.env.ref("account_tax_unece.tax_categ_s").id,
+ }
+ )
+ de_tax_21_onpayment = self.env["account.tax"].create(
+ {
+ "name": "German VAT purchase 18.0%",
+ "description": "DE-VAT-buy-18.0",
+ "type_tax_use": "purchase",
+ "price_include": False,
+ "amount": 18,
+ "amount_type": "percent",
+ "tax_exigibility": "on_payment",
+ "unece_type_id": self.env.ref("account_tax_unece.tax_type_vat").id,
+ "unece_categ_id": self.env.ref("account_tax_unece.tax_categ_s").id,
+ }
+ )
+ de_tax_21_ttc = self.env["account.tax"].create(
+ {
+ "name": "German VAT purchase 18.0% TTC",
+ "description": "DE-VAT-buy-18.0-TTC",
+ "type_tax_use": "purchase",
+ "price_include": True,
+ "amount": 18,
+ "amount_type": "percent",
+ "tax_exigibility": "on_invoice",
+ "unece_type_id": self.env.ref("account_tax_unece.tax_type_vat").id,
+ "unece_categ_id": self.env.ref("account_tax_unece.tax_categ_s").id,
+ }
+ )
+ bdio = self.env["business.document.import"]
+ tax_dict = {
+ "amount_type": "percent",
+ "amount": 18,
+ "unece_type_code": "VAT",
+ "unece_categ_code": "S",
+ "unece_due_date_code": "5",
+ }
+ res = bdio._match_tax(tax_dict, [], type_tax_use="purchase")
+ self.assertEqual(res, de_tax_21)
+ tax_dict.pop("unece_categ_code")
+ res = bdio._match_tax(tax_dict, [], type_tax_use="purchase")
+ self.assertEqual(res, de_tax_21)
+ res = bdio._match_tax(tax_dict, [], type_tax_use="purchase", price_include=True)
+ self.assertEqual(res, de_tax_21_ttc)
+ res = bdio._match_taxes([tax_dict], [], type_tax_use="purchase")
+ self.assertEqual(res, de_tax_21)
+ res = bdio._match_taxes(
+ [dict(tax_dict, unece_due_date_code=72)], [], type_tax_use="purchase"
+ )
+ self.assertEqual(res, de_tax_21_onpayment)
+
+ def test_match_account_exact(self):
+ bdio = self.env["business.document.import"]
+ acc = self.env["account.account"].create(
+ {
+ "name": "Test 898999",
+ "code": "898999",
+ "account_type": "expense",
+ }
+ )
+ res = bdio._match_account({"code": "898999"}, [])
+ self.assertEqual(acc, res)
+
+ def test_match_account_bigger_in(self):
+ bdio = self.env["business.document.import"]
+ acc = self.env["account.account"].create(
+ {
+ "name": "Test 898999",
+ "code": "898999",
+ "account_type": "expense",
+ }
+ )
+ res = bdio._match_account({"code": "89899900"}, [])
+ self.assertEqual(acc, res)
+
+ def test_match_account_smaller_in(self):
+ bdio = self.env["business.document.import"]
+ acc = self.env["account.account"].create(
+ {
+ "name": "Test 89899910",
+ "code": "89899910",
+ "account_type": "expense",
+ }
+ )
+ chatter = []
+ res = bdio._match_account({"code": "898999"}, chatter)
+ self.assertEqual(acc, res)
+ self.assertEqual(len(chatter), 1)
From bef47f5a0e2b84fab82c01826378b155e566bb40 Mon Sep 17 00:00:00 2001
From: pcastelovigo
Date: Mon, 27 Nov 2023 11:34:24 +0100
Subject: [PATCH 5/5] fixes
---
.../models/business_document_import.py | 625 ++++++++----------
1 file changed, 266 insertions(+), 359 deletions(-)
diff --git a/base_business_document_import/models/business_document_import.py b/base_business_document_import/models/business_document_import.py
index 75932a0d48..af38486340 100644
--- a/base_business_document_import/models/business_document_import.py
+++ b/base_business_document_import/models/business_document_import.py
@@ -7,7 +7,6 @@
from odoo import _, api, models
from odoo.exceptions import UserError
-from odoo.osv import expression
from odoo.tools import float_compare
from odoo.addons.base_iban.models.res_partner_bank import validate_iban
@@ -22,7 +21,7 @@ class BusinessDocumentImport(models.AbstractModel):
@api.model
def user_error_wrap(self, method, data_dict, error_msg):
"""The method and data_dict arguments are useful when you want to
- inherit this method to update the error messag_match_currencye"""
+ inherit this method to update the error message"""
assert error_msg
raise UserError(error_msg)
@@ -43,13 +42,19 @@ def _direct_match(self, data_dict, model, raise_exception=True):
)
)
if data_dict.get("id"):
- record = model.browse(data_dict["id"]).exists()
- if not record and raise_exception:
- raise UserError(
- _("ID {id} of '{model}' doesn't exist in Odoo.").format(
- id=data_dict["id"], model=model._name
- )
- )
+ record = False
+ try:
+ record = model.browse(data_dict["id"])
+ # Browsing an unexisting ID doesn't make Odoo crash
+ # So I read create_date to make it crash
+ record.create_date # pylint: disable=pointless-statement
+ except Exception:
+ if raise_exception:
+ raise UserError(
+ _("ID {id} of '{model}' doesn't exist in Odoo.").format(
+ id=data_dict["id"], model=model._name
+ )
+ ) from None
if record:
return record
if data_dict.get("xmlid"):
@@ -57,11 +62,12 @@ def _direct_match(self, data_dict, model, raise_exception=True):
record = False
try:
record = self.env.ref(xmlid, raise_if_not_found=True)
- except Exception as e:
+ except Exception:
if raise_exception:
raise UserError(
- _("The XMLID '%s' doesn't exist in Odoo.") % xmlid
- ) from e
+ _("The XMLID '%(xmlid)s' doesn't exist in Odoo.")
+ % {"xmlid": xmlid}
+ ) from None
if record:
if isinstance(record, type(model)):
return record
@@ -80,16 +86,14 @@ def _direct_match(self, data_dict, model, raise_exception=True):
@api.model
def _strip_cleanup_dict(self, match_dict):
- if not match_dict:
- return
-
- for key, value in match_dict.items():
- if value and isinstance(value, str):
- match_dict[key] = value.strip()
- if match_dict.get("country_code"):
- match_dict["country_code"] = match_dict["country_code"].upper()
- if match_dict.get("state_code"):
- match_dict["state_code"] = match_dict["state_code"].upper()
+ if match_dict:
+ for key, value in match_dict.items():
+ if value and isinstance(value, str):
+ match_dict[key] = value.strip()
+ if match_dict.get("country_code"):
+ match_dict["country_code"] = match_dict["country_code"].upper()
+ if match_dict.get("state_code"):
+ match_dict["state_code"] = match_dict["state_code"].upper()
@api.model
def _get_match_partner_order(self, partner_type):
@@ -110,6 +114,7 @@ def _get_match_partner_type_label(self, partner_type):
@api.model
def _get_country_filter(self, partner_dict, chatter_msg):
"""Generate filter by country"""
+ country = False
if partner_dict.get("country_code"):
country = self.env["res.country"].search(
[("code", "=", partner_dict["country_code"])], limit=1
@@ -122,11 +127,11 @@ def _get_country_filter(self, partner_dict, chatter_msg):
]
chatter_msg.append(
_(
- "The analysis of the business document returned '%s' as "
+ "The analysis of the business document returned '%(cc)s' as "
"country code. But there are no country with that code "
"in Odoo."
)
- % partner_dict["country_code"]
+ % {"cc": partner_dict["country_code"]}
)
return False
@@ -136,13 +141,14 @@ def _get_country_state_filter(self, partner_dict, chatter_msg):
country = self.env["res.country"].search(
[("code", "=", partner_dict["country_code"])], limit=1
)
- if state := self.env["res.country.state"].search(
+ state = self.env["res.country.state"].search(
[
("code", "=", partner_dict["state_code"]),
("country_id", "=", country.id),
],
limit=1,
- ):
+ )
+ if state:
return ["|", ("state_id", "=", False), ("state_id", "=", state.id)]
return False
@@ -150,98 +156,75 @@ def _get_country_state_filter(self, partner_dict, chatter_msg):
def _match_partner_ref(self, partner_dict, chatter_msg, domain, order):
"""If a ref is explicitly given, we just want to match that partner"""
if partner_dict.get("ref"):
- domain = expression.AND(
- [
- domain,
- [("ref", "=", partner_dict["ref"])],
- ]
+ return self.env["res.partner"].search(
+ domain + [("ref", "=", partner_dict["ref"])], limit=1, order=order
)
- return self.env["res.partner"].search(domain, limit=1, order=order)
return False
@api.model
def _match_partner_contact(self, partner_dict, chatter_msg, domain, order):
rpo = self.env["res.partner"]
if partner_dict.get("email") and "@" in partner_dict["email"]:
- if partner := rpo.search(
- expression.AND(
- [
- domain,
- [("email", "=ilike", partner_dict["email"])],
- ]
- ),
+ partner = rpo.search(
+ domain + [("email", "=ilike", partner_dict["email"])],
limit=1,
order=order,
- ):
+ )
+ if partner:
return partner
if partner_dict.get("contact"):
- if partner := rpo.search(
- expression.AND(
- [
- domain,
- [("name", "=ilike", partner_dict["contact"])],
- ]
- ),
+ partner = rpo.search(
+ domain + [("name", "=ilike", partner_dict["contact"])],
limit=1,
order=order,
- ):
+ )
+ if partner:
return partner
if partner_dict.get("phone"):
- if partner := rpo.search(
- expression.AND(
- [
- domain,
- [
- "|",
- ("mobile", "=", partner_dict["phone"]),
- ("phone", "=", partner_dict["phone"]),
- ],
- ]
- ),
+ partner = rpo.search(
+ domain
+ + [
+ "|",
+ ("mobile", "=", partner_dict["phone"]),
+ ("phone", "=", partner_dict["phone"]),
+ ],
limit=1,
order=order,
- ):
+ )
+ if partner:
return partner
return False
@api.model
def _match_partner_name(self, partner_dict, chatter_msg, domain, order):
if partner_dict.get("name"):
- domain = expression.AND(
- [
- domain,
- [
- ("name", "=ilike", partner_dict["name"]),
- ],
- ]
+ return self.env["res.partner"].search(
+ domain + [("name", "=ilike", partner_dict["name"])],
+ limit=1,
+ order=order,
)
- return self.env["res.partner"].search(domain, limit=1, order=order)
return False
@api.model
def _get_partner_website_domain(self, partner_dict):
- if not partner_dict.get("website"):
- return False
-
- urlp = urlparse(partner_dict["website"])
- netloc = urlp.netloc
- if not urlp.scheme and not netloc:
- netloc = urlp.path
- if netloc and len(netloc.split(".")) >= 2:
- return ".".join(netloc.split(".")[-2:])
+ if partner_dict.get("website"):
+ urlp = urlparse(partner_dict["website"])
+ netloc = urlp.netloc
+ if not urlp.scheme and not netloc:
+ netloc = urlp.path
+ if netloc and len(netloc.split(".")) >= 2:
+ return ".".join(netloc.split(".")[-2:])
+ return False
@api.model
def _match_partner_website(self, partner_dict, chatter_msg, domain, order):
- if website_domain := self._get_partner_website_domain(partner_dict):
- domain = expression.AND(
- [
- domain,
- [
- ("website", "=ilike", "%" + website_domain + "%"),
- ],
- ]
+ website_domain = self._get_partner_website_domain(partner_dict)
+ if website_domain:
+ return self.env["res.partner"].search(
+ domain + [("website", "=ilike", "%" + website_domain + "%")],
+ limit=1,
+ order=order,
)
- return self.env["res.partner"].search(domain, limit=1, order=order)
return False
@api.model
@@ -260,17 +243,13 @@ def _match_partner_email(self, partner_dict, chatter_msg, domain, order):
# @gmail.com, @yahoo.com that may match random partners
if email_domain:
partner = self.env["res.partner"].search(
- expression.AND(
- [domain, [("website", "=ilike", "%" + email_domain + "%")]]
- ),
+ domain + [("website", "=ilike", "%" + email_domain + "%")],
limit=1,
order=order,
)
if not partner:
partner = self.env["res.partner"].search(
- expression.AND(
- [domain, [("email", "=ilike", "%@" + email_domain)]]
- ),
+ domain + [("email", "=ilike", "%@" + email_domain)],
limit=1,
order=order,
)
@@ -278,12 +257,11 @@ def _match_partner_email(self, partner_dict, chatter_msg, domain, order):
partner_type_label = partner_dict["type_label"]
chatter_msg.append(
_(
- "The %(label)s has been identified by the domain name "
- "'%(domain)s' so please check carefully that the "
- "%(label)s is correct.",
- label=partner_type_label,
- domain=domain,
+ "The %(p_type_label)s has been identified "
+ "by the domain name '%(domain)s' so please check carefully "
+ "that the %(p_type_label)s is correct."
)
+ % {"p_type_label": partner_type_label, "domain": domain}
)
return partner
@@ -314,18 +292,8 @@ def _match_partner( # noqa: C901
partner = self._direct_match(partner_dict, rpo, raise_exception=raise_exception)
if partner:
return partner
- company_id = self._context.get("force_company") or self.env.company.id
domain = domain or []
- domain = expression.AND(
- [
- domain,
- [
- "|",
- ("company_id", "=", False),
- ("company_id", "=", company_id),
- ],
- ]
- )
+ domain += self._match_company_domain()
order = self._get_match_partner_order(partner_type)
partner_type_label = self._get_match_partner_type_label(partner_type)
partner_dict["type"] = partner_type
@@ -335,22 +303,19 @@ def _match_partner( # noqa: C901
if partner:
return partner
- if country_domain := self._get_country_filter(partner_dict, chatter_msg):
- domain = expression.AND([domain, country_domain])
+ country_domain = self._get_country_filter(partner_dict, chatter_msg)
- if state_domain := self._get_country_state_filter(
- partner_dict, chatter_msg
- ):
- domain = expression.AND([domain, state_domain])
+ if country_domain:
+ domain += country_domain
+
+ state_domain = self._get_country_state_filter(partner_dict, chatter_msg)
+ if state_domain:
+ domain += state_domain
# Search on VAT
if partner_dict.get("vat"):
vat = partner_dict["vat"].replace(" ", "").upper()
- partner = rpo.search(
- expression.AND([domain, [("vat", "=", vat)]]),
- limit=1,
- order=order,
- )
+ partner = rpo.search(domain + [("vat", "=", vat)], limit=1, order=order)
if partner:
return partner
@@ -387,22 +352,24 @@ def _match_partner( # noqa: C901
_(
"Odoo couldn't find any %(label)s corresponding to the following "
"information extracted from the business document:\n"
- "Name: %(name)s \n"
- "VAT number: %(vat)s \n"
- "Reference: %(ref)s \n"
- "E-mail: %(email)s \n"
- "Website: %(website)s \n"
- "State code: %(state)s \n"
- "Country code: %(country)s \n",
- label=partner_type_label,
- name=partner_dict.get("name") or "",
- vat=partner_dict.get("vat") or "",
- ref=partner_dict.get("ref") or "",
- email=partner_dict.get("email") or "",
- website=partner_dict.get("website") or "",
- state=partner_dict.get("state_code") or "",
- country=partner_dict.get("country_code") or "",
- ),
+ "Name: %(name)s\n"
+ "VAT number: %(vat)s\n"
+ "Reference: %(ref)s\n"
+ "E-mail: %(mail)s\n"
+ "Website: %(web)s\n"
+ "State code: %(state)s\n"
+ "Country code: %(country)s\n"
+ )
+ % {
+ "label": partner_type_label,
+ "name": partner_dict.get("name") or "",
+ "vat": partner_dict.get("vat") or "",
+ "ref": partner_dict.get("ref") or "",
+ "mail": partner_dict.get("email") or "",
+ "web": partner_dict.get("website") or "",
+ "state": partner_dict.get("state_code") or "",
+ "country": partner_dict.get("country_code") or "",
+ },
)
@api.model
@@ -429,74 +396,40 @@ def _match_shipping_partner(
domain = domain or []
if partner_dict.get("street"):
if partner_dict.get("street_number"):
- domain = expression.AND(
- [
- domain,
+ domain += [
+ (
+ "street",
+ "in",
[
- (
- "street",
- "in",
- [
- "{} {}".format(
- partner_dict.get("street"),
- partner_dict.get("street_number"),
- ),
- "{} {}".format(
- partner_dict.get("street_number"),
- partner_dict.get("street"),
- ),
- "{}, {}".format(
- partner_dict.get("street"),
- partner_dict.get("street_number"),
- ),
- "{}, {}".format(
- partner_dict.get("street_number"),
- partner_dict.get("street"),
- ),
- ],
- )
+ "{} {}".format(
+ partner_dict.get("street"),
+ partner_dict.get("street_number"),
+ ),
+ "{} {}".format(
+ partner_dict.get("street_number"),
+ partner_dict.get("street"),
+ ),
+ "{}, {}".format(
+ partner_dict.get("street"),
+ partner_dict.get("street_number"),
+ ),
+ "{}, {}".format(
+ partner_dict.get("street_number"),
+ partner_dict.get("street"),
+ ),
],
- ]
- )
+ )
+ ]
else:
- domain = expression.AND(
- [
- domain,
- [
- ("street", "=", partner_dict.get("street")),
- ],
- ]
- )
-
+ domain += [("street", "=", partner_dict.get("street"))]
if partner_dict.get("street2"):
- domain = expression.AND(
- [
- domain,
- [
- ("street2", "=", partner_dict.get("street2")),
- ],
- ]
- )
+ domain += [("street2", "=", partner_dict.get("street2"))]
if partner_dict.get("city"):
- domain = expression.AND(
- [
- domain,
- [
- ("city", "=", partner_dict.get("city")),
- ],
- ]
- )
+ domain += [("city", "=", partner_dict.get("city"))]
if partner_dict.get("zip"):
- domain = expression.AND(
- [
- domain,
- [
- ("zip", "=", partner_dict.get("zip")),
- ],
- ]
- )
+ domain += [("zip", "=", partner_dict.get("zip"))]
- domain_delivery = expression.AND([domain, [("type", "=", "delivery")]])
+ domain_delivery = domain + [("type", "=", "delivery")]
partner = self._match_partner(
partner_dict,
chatter_msg,
@@ -535,26 +468,28 @@ def _match_shipping_partner(
"Name: %(name)s\n"
"VAT number: %(vat)s\n"
"Reference: %(ref)s\n"
- "E-mail: %(email)s\n"
- "Website: %(website)s\n"
- "Street: %(street)s\n"
- "Street2: %(street2)s\n"
+ "E-mail: %(mail)s\n"
+ "Website: %(web)s\n"
+ "Street: %(str)s\n"
+ "Street2: %(str2)s\n"
"City: %(city)s\n"
"ZIP: %(zip)s\n"
"State code: %(state)s\n"
- "Country code: %(country)s\n",
- name=partner_dict.get("name") or "",
- vat=partner_dict.get("vat") or "",
- ref=partner_dict.get("ref") or "",
- email=partner_dict.get("email") or "",
- website=partner_dict.get("website") or "",
- street=partner_dict.get("street") or "",
- street2=partner_dict.get("street2") or "",
- city=partner_dict.get("city") or "",
- zip=partner_dict.get("zip") or "",
- state=partner_dict.get("state_code") or "",
- country=partner_dict.get("country_code") or "",
- ),
+ "Country code: %(country)s\n"
+ )
+ % {
+ "name": partner_dict.get("name") or "",
+ "vat": partner_dict.get("vat") or "",
+ "ref": partner_dict.get("ref") or "",
+ "mail": partner_dict.get("email") or "",
+ "web": partner_dict.get("website") or "",
+ "str": partner_dict.get("street") or "",
+ "str2": partner_dict.get("street2") or "",
+ "city": partner_dict.get("city") or "",
+ "zip": partner_dict.get("zip") or "",
+ "state": partner_dict.get("state_code") or "",
+ "country": partner_dict.get("country_code") or "",
+ },
)
@api.model
@@ -571,18 +506,13 @@ def _match_partner_bank(
validate_iban(iban)
except Exception:
chatter_msg.append(
- _("IBAN %s is not valid, so it has been ignored.") % iban
+ _("IBAN %(iban)s is not valid, so it has been ignored.")
+ % {"iban": iban}
)
return False
- company_id = self._context.get("force_company") or self.env.company.id
bankaccount = rpbo.search(
- [
- "|",
- ("company_id", "=", False),
- ("company_id", "=", company_id),
- ("sanitized_acc_number", "=", iban),
- ("partner_id", "=", partner.id),
- ],
+ self._match_company_domain()
+ + [("sanitized_acc_number", "=", iban), ("partner_id", "=", partner.id)],
limit=1,
)
if bankaccount:
@@ -606,12 +536,9 @@ def _match_partner_bank(
_(
"The bank account IBAN %(iban)s has been automatically "
"added on the supplier "
- "%(partner)s",
- iban=iban,
- partner_id=partner.id,
- partner=partner.display_name,
+ "%(n)s"
)
+ % {"iban": iban, "i": partner.id, "n": partner.display_name}
)
return partner_bank
else:
@@ -620,14 +547,11 @@ def _match_partner_bank(
"The analysis of the business document returned "
"IBAN %(iban)s as bank account, but there is no such "
"bank account in Odoo linked to partner "
- "%(partner)s and "
- "the option to automatically create bank "
- "accounts upon import is disabled.",
- iban=iban,
- partner_id=partner.id,
- partner=partner.display_name,
+ "%(n)s "
+ "and the option to automatically create bank "
+ "accounts upon import is disabled."
)
+ % {"iban": iban, "p": partner.id, "n": partner.display_name}
)
@api.model
@@ -663,7 +587,7 @@ def _match_product(self, product_dict, chatter_msg, seller=False):
sinfo = self.env["product.supplierinfo"].search(
self._match_company_domain()
+ [
- ("partner_id", "=", seller.id),
+ ("name", "=", seller.id),
("product_code", "=", product_dict["code"]),
],
limit=1,
@@ -681,12 +605,14 @@ def _match_product(self, product_dict, chatter_msg, seller=False):
"Odoo couldn't find any product corresponding to the "
"following information extracted from the business document:\n"
"Barcode: %(barcode)s\n"
- "Product code: %(product_code)s\n"
- "Supplier: %(supplier)s\n",
- barcode=product_dict.get("barcode") or "",
- product_code=product_dict.get("code") or "",
- supplier=seller and seller.name or "",
- ),
+ "Product code: %(product)s\n"
+ "Supplier: %(supplier)s\n"
+ )
+ % {
+ "barcode": product_dict.get("barcode") or "",
+ "product": product_dict.get("code") or "",
+ "supplier": seller and seller.name or "",
+ },
)
@api.model
@@ -694,35 +620,25 @@ def _match_product_search(self, product_dict):
product = self.env["product.product"].browse()
cdomain = self._match_company_domain()
if product_dict.get("barcode"):
- domain = expression.AND(
- [
- cdomain,
- [
- "|",
- ("barcode", "=", product_dict["barcode"]),
- ("packaging_ids.barcode", "=", product_dict["barcode"]),
- ],
- ]
- )
+ domain = cdomain + [
+ "|",
+ ("barcode", "=", product_dict["barcode"]),
+ ("packaging_ids.barcode", "=", product_dict["barcode"]),
+ ]
product = product.search(domain, limit=1)
if not product and product_dict.get("code"):
# TODO: this domain could be probably included in the former one
- domain = expression.AND(
- [
- cdomain,
- [
- "|",
- ("barcode", "=", product_dict["code"]),
- ("default_code", "=", product_dict["code"]),
- ],
- ]
- )
+ domain = cdomain + [
+ "|",
+ ("barcode", "=", product_dict["code"]),
+ ("default_code", "=", product_dict["code"]),
+ ]
product = product.search(domain, limit=1)
return product
@api.model
def _match_company_domain(self):
- company_id = self._context.get("force_company") or self.env.user.company_id.id
+ company_id = self._context.get("force_company") or self.env.company.id
return ["|", ("company_id", "=", False), ("company_id", "=", company_id)]
@api.model
@@ -752,24 +668,24 @@ def _match_currency(self, currency_dict, chatter_msg):
"_match_currency",
currency_dict,
_(
- "The analysis of the business document returned '%s' as "
+ "The analysis of the business document returned '%(currency)s' as "
"the currency ISO code. But there are no currency "
"with that code in Odoo."
)
- % currency_iso,
+ % {"currency": currency_iso},
)
if currency_dict.get("symbol"):
currencies = rco.search([("symbol", "=", currency_dict["symbol"])])
if len(currencies) == 1:
- return currencies
+ return currencies[0]
else:
chatter_msg.append(
_(
- "The analysis of the business document returned '%s' as "
+ "The analysis of the business document returned '%(symbol)s' as "
"the currency symbol. But there are none or several "
"currencies with that symbol in Odoo."
)
- % currency_dict["symbol"]
+ % {"symbol": currency_dict["symbol"]}
)
if currency_dict.get("iso_or_symbol"):
currencies = rco.search(
@@ -786,11 +702,11 @@ def _match_currency(self, currency_dict, chatter_msg):
"_match_currency",
currency_dict,
_(
- "The analysis of the business document returned '%(code)s' as "
+ "The analysis of the business document returned '%(isoorsymbol)s' as "
"the currency symbol or ISO code. But there are none or "
- "several currencies with the symbol/ISO code in Odoo.",
- code=currency_dict["iso_or_symbol"],
- ),
+ "several currencies with the symbol/ISO code in Odoo."
+ )
+ % {"isoorsymbol": currency_dict["iso_or_symbol"]},
)
if currency_dict.get("country_code"):
country_code = currency_dict["country_code"]
@@ -805,24 +721,23 @@ def _match_currency(self, currency_dict, chatter_msg):
"_match_currency",
currency_dict,
_(
- "The analysis of the business document returned '%(code)s' "
+ "The analysis of the business document returned '%(cc)s' "
"as the country code to find the related currency. "
- "But the country '%(name)s' doesn't have any related "
- "currency configured in Odoo.",
- code=country_code,
- name=country.name,
- ),
+ "But the country '%(cn)s' doesn't have any related "
+ "currency configured in Odoo."
+ )
+ % {"cc": country_code, "cn": country.name},
)
else:
raise self.user_error_wrap(
"_match_currency",
currency_dict,
_(
- "The analysis of the business document returned '%s' "
+ "The analysis of the business document returned '%(cc)s' "
"as the country code to find the related currency. "
"But there is no country with that code in Odoo."
)
- % country_code,
+ % {"cc": country_code},
)
if self._context.get("force_company"):
company = self.env["res.company"].browse(self._context["force_company"])
@@ -830,8 +745,8 @@ def _match_currency(self, currency_dict, chatter_msg):
company = self.env.company
company_cur = company.currency_id
chatter_msg.append(
- _("No currency specified, so Odoo used the company currency (%s)")
- % company_cur.name
+ _("No currency specified, so Odoo used the company currency (%(company)s)")
+ % {"company": company_cur.name}
)
return company_cur
@@ -860,16 +775,16 @@ def _match_uom(self, uom_dict, chatter_msg, product=False):
else:
chatter_msg.append(
_(
- "The analysis of the business document returned '%(code)s' "
+ "The analysis of the business document returned '%(unece)s' "
"as the unit of measure UNECE code, but there is no "
"unit of measure with that UNECE code in Odoo. Please "
"check the configuration of the units of measures in "
- "Odoo.",
- code=uom_dict["unece_code"],
+ "Odoo."
)
+ % {"unece": uom_dict["unece_code"]}
)
if uom_dict.get("name"):
- uom = uuo.search([("name", "=ilike", uom_dict["name"] + "%")], limit=1)
+ uom = uuo.search([("name", "=", uom_dict["name"])], limit=1)
if uom:
return uom
if product:
@@ -878,13 +793,12 @@ def _match_uom(self, uom_dict, chatter_msg, product=False):
_(
"Odoo couldn't find any unit of measure corresponding to the "
"following information extracted from the business document:
"
- "- UNECE code: %(code)s
"
- "- Name of the unit of measure: %(name)s
"
+ "- UNECE code: %(unece)s
"
+ "- Name of the unit of measure: %(dict)s
"
"So the unit of measure 'Unit(s)' has been used. You may "
- "have to change it manually.
",
- code=uom_dict.get("unece_code"),
- name=uom_dict.get("name"),
+ "have to change it manually.
"
)
+ % {"unece": uom_dict.get("unece_code"), "dict": uom_dict.get("name")}
)
return self.env.ref("uom.product_uom_unit")
@@ -899,7 +813,7 @@ def _match_taxes(
tax_dict,
chatter_msg,
type_tax_use=type_tax_use,
- price_include=price_include,
+ price_include=tax_dict.get("price_include", price_include),
)
return taxes_recordset
@@ -935,18 +849,12 @@ def _prepare_match_tax_domain(
tax_dict["unece_due_date_code"]
)
if tax_exigibility:
- domain = expression.AND(
- [domain, [("tax_exigibility", "=", tax_exigibility)]]
- )
+ domain += [("tax_exigibility", "=", tax_exigibility)]
return domain
@api.model
def _match_tax(
- self,
- tax_dict,
- chatter_msg,
- type_tax_use="purchase",
- price_include=False,
+ self, tax_dict, chatter_msg, type_tax_use="purchase", price_include=False
):
"""Example:
tax_dict = {
@@ -977,20 +885,20 @@ def _match_tax(
"Odoo couldn't find any tax with 'Tax Application' = '%(tax)s' "
"and 'Tax Included in Price' = '%(price)s' which correspond to the "
"following information extracted from the business document:\n"
- "UNECE Tax Type code: %(tax_type)s\n"
- "UNECE Tax Category code: %(tax_cat)s\n"
- "UNECE Due Date code: %(tax_due_date)s\n"
- "Tax amount: %(amount)s %(amount_type)s",
- tax=type_tax_use,
- price=price_include,
- tax_type=tax_dict.get("unece_type_code") or "",
- tax_cat=tax_dict.get("unece_categ_code") or "",
- tax_due_date=tax_dict.get("unece_due_date_code") or "",
- amount=tax_dict["amount"],
- amount_type=tax_dict["amount_type"] == "percent"
- and "%"
- or _("(fixed)"),
- ),
+ "UNECE Tax Type code: %(tc)s\n"
+ "UNECE Tax Category code: %(tcc)s\n"
+ "UNECE Due Date code: %(ddc)s\n"
+ "Tax amount: %(amt)s %(amtt)s"
+ )
+ % {
+ "tax": type_tax_use,
+ "price": price_include,
+ "tc": tax_dict.get("unece_type_code") or "",
+ "tcc": tax_dict.get("unece_categ_code") or "",
+ "ddc": tax_dict.get("unece_due_date_code") or "",
+ "amt": tax_dict["amount"],
+ "amtt": tax_dict["amount_type"] == "percent" and "%" or _("(fixed)"),
+ },
)
def compare_lines(
@@ -1055,28 +963,24 @@ def compare_lines(
if not eline.get("product"):
chatter_msg.append(
_(
- "The existing line '%s' doesn't have any product, "
+ "The existing line '%(eline)s' doesn't have any product, "
"so the lines haven't been updated."
)
- % eline.get("name")
+ % {"eline": eline.get("name")}
)
return False
if eline["product"] in existing_lines_dict:
chatter_msg.append(
_(
- "The product '%s' is used on several existing "
+ "The product '%(eline)s' is used on several existing "
"lines, so the lines haven't been updated."
)
- % eline["product"].display_name
+ % {"eline": eline["product"].display_name}
)
return False
existing_lines_dict[eline["product"]] = eline
unique_import_products = []
- res = {
- "to_remove": False,
- "to_add": [],
- "to_update": {},
- }
+ res = {"to_remove": False, "to_add": [], "to_update": {}}
for iline in import_lines:
if not iline.get("product"):
chatter_msg.append(
@@ -1091,10 +995,10 @@ def compare_lines(
if product in unique_import_products:
chatter_msg.append(
_(
- "The product '%s' is used on several imported lines, "
+ "The product '%(product)s' is used on several imported lines, "
"so the lines haven't been updated."
)
- % product.display_name
+ % {"product": product.display_name}
)
return False
unique_import_products.append(product)
@@ -1102,15 +1006,16 @@ def compare_lines(
if uom != existing_lines_dict[product]["uom"]:
chatter_msg.append(
_(
- "For product '%(product)s', the unit of measure is "
- "%(uom_product)s on the existing line, but it is "
- "%(uom_imported)s on the imported line."
+ "For product '%(p)s', the unit of measure is %(el)s on the"
+ " existing line, but it is %(name)s on the imported line. "
"We don't support this scenario for the moment, so "
- "the lines haven't been updated.",
- product=product.display_name,
- uom_product=existing_lines_dict[product]["uom"].name,
- uom_imported=uom.name,
+ "the lines haven't been updated."
)
+ % {
+ "p": product.display_name,
+ "el": existing_lines_dict[product]["uom"].name,
+ "name": uom.name,
+ }
)
return False
# used for to_remove
@@ -1136,9 +1041,7 @@ def _prepare_order_line_update_values(
):
values = {}
if float_compare(
- iline["qty"],
- existing_line["qty"],
- precision_digits=qty_precision,
+ iline["qty"], existing_line["qty"], precision_digits=qty_precision
):
values["qty"] = [existing_line["qty"], iline["qty"]]
if "price_unit" in iline and float_compare(
@@ -1146,10 +1049,7 @@ def _prepare_order_line_update_values(
existing_line["price_unit"],
precision_digits=price_precision,
):
- values["price_unit"] = [
- existing_line["price_unit"],
- iline["price_unit"],
- ]
+ values["price_unit"] = [existing_line["price_unit"], iline["price_unit"]]
return values
def _prepare_account_speed_dict(self):
@@ -1198,11 +1098,10 @@ def _match_account(self, account_dict, chatter_msg, speed_dict=None):
if code.startswith(acc_code):
chatter_msg.append(
_(
- "Approximate match: account %(account)s has been matched "
- "with account %(matched_account)s",
- account=account_dict["code"],
- matched_account=code,
+ "Approximate match: account %(account_dict)s has been matched "
+ "with account %(code)s"
)
+ % {"account_dict": account_dict["code"], "code": code}
)
return aao.browse(account_id)
raise self.user_error_wrap(
@@ -1211,9 +1110,9 @@ def _match_account(self, account_dict, chatter_msg, speed_dict=None):
_(
"Odoo couldn't find any account corresponding to the "
"following information extracted from the business document:\n"
- "Account code: %s"
+ "Account code: %(code)s"
)
- % (account_dict.get("code") or ""),
+ % {"code": (account_dict.get("code") or "")},
)
def _prepare_analytic_account_speed_dict(self):
@@ -1255,9 +1154,9 @@ def _match_analytic_account(self, aaccount_dict, chatter_msg, speed_dict=None):
_(
"Odoo couldn't find any analytic account corresponding to the "
"following information extracted from the business document:\n"
- "Analytic account code: %s"
+ "Analytic account code: %(aaccount)s"
)
- % (aaccount_dict.get("code") or ""),
+ % {"aaccount": (aaccount_dict.get("code") or "")},
)
def _prepare_journal_speed_dict(self):
@@ -1299,9 +1198,9 @@ def _match_journal(self, journal_dict, chatter_msg, speed_dict=None):
_(
"Odoo couldn't find any journal corresponding to the "
"following information extracted from the business document:\n"
- "Journal code: %s"
+ "Journal code: %(journal)s"
)
- % (journal_dict.get("code") or ""),
+ % {"journal": (journal_dict.get("code") or "")},
)
# Code moved from base_business_document_import_stock
@@ -1331,8 +1230,11 @@ def _match_incoterm(self, incoterm_dict, chatter_msg):
self.user_error_wrap(
"_match_incoterm",
incoterm_dict,
- _("Could not find any Incoterm in Odoo corresponding " "to '%s'")
- % incoterm_dict["code"],
+ _(
+ "Could not find any Incoterm in Odoo corresponding "
+ "to '%(incoterm)s'"
+ )
+ % {"incoterm": incoterm_dict["code"]},
)
return False
@@ -1354,17 +1256,20 @@ def _check_company(self, company_dict, chatter_msg):
company_dict,
_(
"The VAT number of the customer written in the "
- "business document (%(parsed_vat)s) doesn't match "
- "the VAT number of the company '%(company)s' (%(vat)s) "
- "in which you are trying to import this document.",
- parsed_vat=parsed_company_vat,
- company=company.display_name,
- vat=company.partner_id.vat,
- ),
+ "business document (%(vat)s) doesn't match the VAT number "
+ "of the company '%(display_name)s' (%(partner_vat)s) in "
+ " which you are trying to import this document."
+ )
+ % {
+ "vat": parsed_company_vat,
+ "display_name": company.display_name,
+ "partner_vat": company.partner_id.vat,
+ },
)
else:
chatter_msg.append(
- _("Missing VAT number on company '%s'") % company.display_name
+ _("Missing VAT number on company '%(company_name)s'")
+ % {"company_name": company.display_name}
)
def get_xml_files_from_pdf(self, pdf_file):
@@ -1390,7 +1295,9 @@ def post_create_or_update(self, parsed_dict, record, doc_filename=None):
record.message_post(body=msg)
if parsed_dict.get("note"):
if doc_filename:
- msg = _("Notes in file %s:") % doc_filename
+ msg = _("Notes in file %(filename)s:") % {
+ "filename": doc_filename
+ }
else:
msg = _("Notes in imported document:")
record.message_post( # pylint: disable=translation-required