From 875a52bfd5d89c9245063124ff97fbd44cb68448 Mon Sep 17 00:00:00 2001 From: V3st1g3 Date: Thu, 5 Dec 2024 13:53:17 +0100 Subject: [PATCH] [MIG] account_invoice_import_invoice2data: Migration to 16.0 --- .../README.rst | 10 +-- .../__manifest__.py | 2 +- .../demo/demo_data.xml | 2 +- .../static/description/index.html | 6 +- .../tests/test_invoice_import.py | 85 ++++++++++--------- .../wizard/account_invoice_import.py | 16 +++- .../wizard/account_invoice_import_view.xml | 2 +- .../account_invoice_import_invoice2data | 1 + .../setup.py | 6 ++ 9 files changed, 77 insertions(+), 53 deletions(-) create mode 120000 setup/account_invoice_import_invoice2data/odoo/addons/account_invoice_import_invoice2data create mode 100644 setup/account_invoice_import_invoice2data/setup.py diff --git a/account_invoice_import_invoice2data/README.rst b/account_invoice_import_invoice2data/README.rst index 3328fa3729..800f0603fd 100644 --- a/account_invoice_import_invoice2data/README.rst +++ b/account_invoice_import_invoice2data/README.rst @@ -17,13 +17,13 @@ Account Invoice Import Invoice2data :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/14.0/account_invoice_import_invoice2data + :target: https://github.com/OCA/edi/tree/16.0/account_invoice_import_invoice2data :alt: OCA/edi .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/edi-14-0/edi-14-0-account_invoice_import_invoice2data + :target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-account_invoice_import_invoice2data :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=14.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=16.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -245,7 +245,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -286,6 +286,6 @@ Current `maintainers `__: |maintainer-alexis-via| |maintainer-bosd| -This module is part of the `OCA/edi `_ project on GitHub. +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/account_invoice_import_invoice2data/__manifest__.py b/account_invoice_import_invoice2data/__manifest__.py index 45c204ffd8..862ba77a66 100644 --- a/account_invoice_import_invoice2data/__manifest__.py +++ b/account_invoice_import_invoice2data/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Account Invoice Import Invoice2data", - "version": "14.0.2.4.0", + "version": "16.0.1.0.0", "category": "Accounting/Accounting", "license": "AGPL-3", "summary": "Import supplier invoices using the invoice2data lib", diff --git a/account_invoice_import_invoice2data/demo/demo_data.xml b/account_invoice_import_invoice2data/demo/demo_data.xml index 770b126dd5..e8e0723bfb 100644 --- a/account_invoice_import_invoice2data/demo/demo_data.xml +++ b/account_invoice_import_invoice2data/demo/demo_data.xml @@ -18,7 +18,7 @@ 75008 Paris - http://www.free.fr + https://www.free.fr FR60421938861 diff --git a/account_invoice_import_invoice2data/static/description/index.html b/account_invoice_import_invoice2data/static/description/index.html index a3f302efe2..cd973608db 100644 --- a/account_invoice_import_invoice2data/static/description/index.html +++ b/account_invoice_import_invoice2data/static/description/index.html @@ -369,7 +369,7 @@

Account Invoice Import Invoice2data

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:c7d1d2a38227a9bf81bc6132091b5285a4afe0b1280bea7541ebab212f57f16a !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/edi Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/edi Translate me on Weblate Try me on Runboat

This module is an extension of the module account_invoice_import: it adds support for regular PDF invoices i.e. PDF invoice that don’t have an embedded XML file. It uses the invoice2data library which takes care of extracting the text of the PDF invoice, find an existing invoice template and execute the invoice template to extract the useful information from the invoice.

To know the full story behind the development of this module, read this blog post.

More information for creating the templates can be found in tutorial of the invoice2data library. The templates have to be created manually. An graphical template creator for odoo is a work in progress.

@@ -570,7 +570,7 @@

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

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

@@ -598,7 +598,7 @@

Maintainers

promote its widespread use.

Current maintainers:

alexis-via bosd

-

This module is part of the OCA/edi project on GitHub.

+

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/account_invoice_import_invoice2data/tests/test_invoice_import.py b/account_invoice_import_invoice2data/tests/test_invoice_import.py index 09ce1d90f5..771643e174 100644 --- a/account_invoice_import_invoice2data/tests/test_invoice_import.py +++ b/account_invoice_import_invoice2data/tests/test_invoice_import.py @@ -2,12 +2,12 @@ # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import base64 -import logging +from base64 import b64encode +from logging import getLogger from unittest import mock from odoo import fields -from odoo.tests.common import SavepointCase +from odoo.tests.common import TransactionCase from odoo.tools import file_open, float_compare # TODO v16: use @@ -21,19 +21,21 @@ } -class TestInvoiceImport(SavepointCase): +class TestInvoiceImport(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT)) frtax = cls.env["account.tax"].create( - { - "name": "French VAT purchase 20.0%", - "description": "FR-VAT-buy-20.0", - "amount": 20, - "amount_type": "percent", - "type_tax_use": "purchase", - } + [ + { + "name": "French VAT purchase 20.0%", + "description": "FR-VAT-buy-20.0", + "amount": 20, + "amount_type": "percent", + "type_tax_use": "purchase", + } + ] ) # Set this tax on Internet access product internet_product = cls.env.ref( @@ -44,25 +46,27 @@ def setUpClass(cls): def test_have_invoice2data_unavailable(self): with mock.patch.dict("sys.modules", {"invoice2data": None}): with self.assertLogs("", level="DEBUG") as cm: - logging.getLogger("").debug("Cannot import invoice2data") + getLogger("").debug("Cannot import invoice2data") self.assertEqual(cm.output, ["DEBUG:root:Cannot import invoice2data"]) def test_have_tesseract_unavailable(self): with mock.patch.dict("sys.modules", {"tesseract": None}): with self.assertLogs("", level="DEBUG") as cm: - logging.getLogger("").debug("Cannot import tesseract") + getLogger("").debug("Cannot import tesseract") self.assertEqual(cm.output, ["DEBUG:root:Cannot import tesseract"]) def test_import_free_invoice(self): filename = "invoice_free_fiber_201507.pdf" f = file_open("account_invoice_import_invoice2data/tests/pdf/" + filename, "rb") pdf_file = f.read() - pdf_file_b64 = base64.b64encode(pdf_file) + pdf_file_b64 = b64encode(pdf_file) wiz = self.env["account.invoice.import"].create( - { - "invoice_file": pdf_file_b64, - "invoice_filename": filename, - } + [ + { + "invoice_file": pdf_file_b64, + "invoice_filename": filename, + } + ] ) f.close() wiz.import_invoice() @@ -107,10 +111,12 @@ def test_import_free_invoice(self): # New import with update of an existing draft invoice wiz2 = self.env["account.invoice.import"].create( - { - "invoice_file": pdf_file_b64, - "invoice_filename": "invoice_free_fiber_201507.pdf", - } + [ + { + "invoice_file": pdf_file_b64, + "invoice_filename": "invoice_free_fiber_201507.pdf", + } + ] ) action = wiz2.import_invoice() self.assertEqual(action["res_model"], "account.invoice.import") @@ -130,21 +136,24 @@ def test_import_free_invoice(self): def test_import_azure_interior_invoice(self): """Function for testing almost all supported fields""" filename = "AzureInterior.pdf" - invoice_file = file_open( + + with file_open( "account_invoice_import_invoice2data/tests/pdf/" + filename, "rb" - ) - pdf_file = invoice_file.read() - pdf_file_b64 = base64.b64encode(pdf_file) - wiz = self.env["account.invoice.import"].create( - { - "invoice_file": pdf_file_b64, - "invoice_filename": filename, - } - ) - invoice_file.close() + ) as invoice_file: + pdf_file = invoice_file.read() + pdf_file_b64 = b64encode(pdf_file) + wiz = self.env["account.invoice.import"].create( + [ + { + "invoice_file": pdf_file_b64, + "invoice_filename": filename, + } + ] + ) + wiz.import_invoice() # create_invoice_action_button - wiz.create_invoice_action(origin="BOSD Import Vendor Bill wizard") + # wiz.create_invoice_action(origin="BOSD Import Vendor Bill wizard") # Check result of invoice creation invoices = self.env["account.move"].search( [ @@ -167,7 +176,7 @@ def test_import_azure_interior_invoice(self): self.assertEqual( inv.narration, - "Due to global inflation our payment term has changed to 15 days.", + "

Due to global inflation our payment term has changed to 15 days.

", ) # Following tests are disabled. Not yet implemented in account_invoice_import @@ -179,7 +188,7 @@ def test_import_azure_interior_invoice(self): self.assertEqual(iline.name, "--- Non Food ---") self.assertEqual(iline.display_type, "line_section") iline = inv.invoice_line_ids[1] - self.assertEqual(iline.name, "Beeswax XL\nAcme beeswax") + self.assertEqual(iline.name, "[17589684] Beeswax XL") self.assertEqual( iline.product_id, self.env.ref("account_invoice_import_invoice2data.product_beeswax_xl"), @@ -188,7 +197,7 @@ def test_import_azure_interior_invoice(self): self.assertEqual(float_compare(iline.price_unit, 42.00, precision_digits=2), 0) iline = inv.invoice_line_ids[2] - self.assertEqual(iline.name, "Office Chair") + self.assertEqual(iline.name, "[FURN_7777] Office Chair") self.assertEqual( iline.product_id, self.env.ref("product.product_delivery_01"), @@ -214,7 +223,7 @@ def test_import_azure_interior_invoice(self): ) self.assertEqual(iline.display_type, "line_note") iline = inv.invoice_line_ids[6] - self.assertEqual(iline.name, "Luxury Truffles") + self.assertEqual(iline.name, "[LUX_TRF] Luxury Truffles") self.assertEqual( iline.product_id, self.env.ref("account_invoice_import_invoice2data.luxury_truffles"), diff --git a/account_invoice_import_invoice2data/wizard/account_invoice_import.py b/account_invoice_import_invoice2data/wizard/account_invoice_import.py index 1ab14d6e35..2527d05fb7 100644 --- a/account_invoice_import_invoice2data/wizard/account_invoice_import.py +++ b/account_invoice_import_invoice2data/wizard/account_invoice_import.py @@ -40,6 +40,8 @@ def fallback_parse_pdf_invoice(self, file_data): @api.model def parse_invoice2data_taxes(self, line): + amount = 0.0 + amount_type = False taxes = [] type_code = "VAT" price_include = False @@ -69,10 +71,12 @@ def parse_invoice2data_taxes(self, line): ) return taxes - def _clean_string(self, string): + @staticmethod + def _clean_string(string): return re.sub(r"\W+", "", string) - def _clean_digits(self, string): + @staticmethod + def _clean_digits(string): return re.sub(r"\D+", "", string) @api.model @@ -98,7 +102,9 @@ def invoice2data_parse_invoice(self, file_data): invoice2data_res = extract_data(fileobj.name, templates=templates) except Exception as e: fileobj.close() - raise UserError(_("PDF Invoice parsing failed. Error message: %s") % e) + raise UserError( + _("PDF Invoice parsing failed. Error message: %s") % e + ) from None if not invoice2data_res: if not shutil.which("tesseract"): logger.warning( @@ -116,7 +122,9 @@ def invoice2data_parse_invoice(self, file_data): ) except Exception as e: fileobj.close() - raise UserError(_("PDF Invoice parsing failed. Error message: %s") % e) + raise UserError( + _("PDF Invoice parsing failed. Error message: %s") % e + ) from None if not invoice2data_res: fileobj.close() return False diff --git a/account_invoice_import_invoice2data/wizard/account_invoice_import_view.xml b/account_invoice_import_invoice2data/wizard/account_invoice_import_view.xml index 6c11356c93..fc67a2af89 100644 --- a/account_invoice_import_invoice2data/wizard/account_invoice_import_view.xml +++ b/account_invoice_import_invoice2data/wizard/account_invoice_import_view.xml @@ -16,7 +16,7 @@
  • regular PDF file without any embedded XML file via the invoice2data library (reads the text of the PDF and get the information). It will work only if the invoice2data library has a template for the invoices of that supplier.
  • + >invoice2data library (reads the text of the PDF and get the information). It will work only if the invoice2data library has a template for the invoices for that supplier.
    diff --git a/setup/account_invoice_import_invoice2data/odoo/addons/account_invoice_import_invoice2data b/setup/account_invoice_import_invoice2data/odoo/addons/account_invoice_import_invoice2data new file mode 120000 index 0000000000..630cb905fe --- /dev/null +++ b/setup/account_invoice_import_invoice2data/odoo/addons/account_invoice_import_invoice2data @@ -0,0 +1 @@ +../../../../account_invoice_import_invoice2data \ No newline at end of file diff --git a/setup/account_invoice_import_invoice2data/setup.py b/setup/account_invoice_import_invoice2data/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/account_invoice_import_invoice2data/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)