diff --git a/l10n_es_account_import_facturae/README.rst b/l10n_es_account_import_facturae/README.rst new file mode 100644 index 00000000000..32e532e76c1 --- /dev/null +++ b/l10n_es_account_import_facturae/README.rst @@ -0,0 +1,75 @@ +==================== +Importación Facturae +==================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-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%2Fl10n--spain-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-spain/tree/14.0/l10n_es_account_import_facturae + :alt: OCA/l10n-spain +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-spain-14-0/l10n-spain-14-0-l10n_es_account_import_facturae + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/189/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Este módulo permite la importación de facturas desde el formato Facturae. + +Se importa usando los mecanismos estándar de importación de facturas de odoo. + +**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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* CreuBlanca + +Contributors +~~~~~~~~~~~~ + +* Enric Tobella + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/l10n-spain `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/l10n_es_account_import_facturae/__init__.py b/l10n_es_account_import_facturae/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/l10n_es_account_import_facturae/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/l10n_es_account_import_facturae/__manifest__.py b/l10n_es_account_import_facturae/__manifest__.py new file mode 100644 index 00000000000..d25855493df --- /dev/null +++ b/l10n_es_account_import_facturae/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2023 CreuBlanca +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Importación Facturae", + "summary": """ + Importación de facturas en formato Facturae""", + "version": "14.0.1.0.0", + "license": "AGPL-3", + "author": "CreuBlanca,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/l10n-spain", + "depends": ["l10n_es_facturae"], + "data": [], + "demo": [], +} diff --git a/l10n_es_account_import_facturae/models/__init__.py b/l10n_es_account_import_facturae/models/__init__.py new file mode 100644 index 00000000000..9c0a4213854 --- /dev/null +++ b/l10n_es_account_import_facturae/models/__init__.py @@ -0,0 +1 @@ +from . import account_move diff --git a/l10n_es_account_import_facturae/models/account_move.py b/l10n_es_account_import_facturae/models/account_move.py new file mode 100644 index 00000000000..8feb0eb0d12 --- /dev/null +++ b/l10n_es_account_import_facturae/models/account_move.py @@ -0,0 +1,325 @@ +# Copyright 2023 CreuBlanca +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import base64 +import mimetypes + +from lxml import etree + +from odoo import _, api, fields, models +from odoo.tools import float_compare +from odoo.tools.misc import format_amount + +mimetypes.add_type("application/xml", ".xsig") + + +class AccountMove(models.Model): + + _inherit = "account.move" + + facturae_received = fields.Boolean() + + @api.depends("facturae_received") + def _compute_facturae(self): + super()._compute_facturae() + for record in self.filtered(lambda r: r.facturae_received): + record.facturae = True + + def _get_create_invoice_from_attachment_decoders(self): + res = super()._get_create_invoice_from_attachment_decoders() + res.append( + ( + 9, + self._create_invoice_from_attachment_facturae, + ) + ) + return res + + def _get_update_invoice_from_attachment_decoders(self, invoice): + res = super()._get_update_invoice_from_attachment_decoders(invoice) + res.append( + ( + 9, + self._update_invoice_from_attachment_facturae, + ) + ) + return res + + def _process_facturae(self, attachment): + content = base64.b64decode(attachment.with_context(bin_size=False).datas) + is_text_plain_xml = attachment.mimetype == "application/xml" or ( + ("text/plain" in attachment.mimetype) and content.startswith(b"".join(messages)) + return move + + def _update_invoice_facturae_vals(self, vals, data): + new_vals = { + "ref": vals.get("ref"), + "payment_reference": vals.get("payment_reference"), + "invoice_date": vals.get("invoice_date"), + "invoice_date_due": vals.get("invoice_date_due"), + "facturae_received": vals.get("facturae_received"), + } + if not self.partner_id: + new_vals["partner_id"] = vals.get("partner_id") + if not self.invoice_line_ids: + new_vals["invoice_line_ids"] = vals.get("invoice_line_ids", []) + return new_vals + + def _update_invoice_facturae(self, vals, data): + self.write(self._update_invoice_facturae_vals(vals, data)) + messages = self._check_invoice_facturae(data) + if messages: + self.message_post(body="
".join(messages)) + return self + + def _check_invoice_facturae(self, data): + messages = [] + for field in ["amount_total", "amount_untaxed"]: + if ( + float_compare( + data[field], + self[field], + precision_rounding=self.currency_id.rounding, + ) + != 0 + ): + messages.append( + _("%s is not coincident (%s - %s)") + % ( + self._fields[field].string, + format_amount(self.env, data[field], self.currency_id), + format_amount(self.env, self[field], self.currency_id), + ) + ) + return messages + + def _update_invoice_from_attachment_facturae(self, attachment, invoice): + facturae_data = self._process_facturae(attachment) + if facturae_data is None: + return self.env["account.move"] + ( + invoice_vals, + company_id, + ) = self._prepare_vals_invoice_from_attachment_facturae(facturae_data) + if len(invoice_vals) != 1: + return self.env["account.move"] + vals, context, data = invoice_vals[0] + return ( + invoice.with_company(company_id or self.env.company.id) + .with_context(**context) + ._update_invoice_facturae(vals, data) + ) diff --git a/l10n_es_account_import_facturae/readme/CONTRIBUTORS.rst b/l10n_es_account_import_facturae/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..85004765bc5 --- /dev/null +++ b/l10n_es_account_import_facturae/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Enric Tobella diff --git a/l10n_es_account_import_facturae/readme/DESCRIPTION.rst b/l10n_es_account_import_facturae/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..8e741b73e85 --- /dev/null +++ b/l10n_es_account_import_facturae/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +Este módulo permite la importación de facturas desde el formato Facturae. + +Se importa usando los mecanismos estándar de importación de facturas de odoo. diff --git a/l10n_es_account_import_facturae/static/description/icon.png b/l10n_es_account_import_facturae/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/l10n_es_account_import_facturae/static/description/icon.png differ diff --git a/l10n_es_account_import_facturae/static/description/index.html b/l10n_es_account_import_facturae/static/description/index.html new file mode 100644 index 00000000000..22fa3d5fde3 --- /dev/null +++ b/l10n_es_account_import_facturae/static/description/index.html @@ -0,0 +1,420 @@ + + + + + + +Importación Facturae + + + +
+

Importación Facturae

+ + +

Beta License: AGPL-3 OCA/l10n-spain Translate me on Weblate Try me on Runbot

+

Este módulo permite la importación de facturas desde el formato Facturae.

+

Se importa usando los mecanismos estándar de importación de facturas de odoo.

+

Table of contents

+ +
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • CreuBlanca
  • +
+
+
+

Contributors

+
    +
  • Enric Tobella
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

This module is part of the OCA/l10n-spain project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/l10n_es_account_import_facturae/tests/__init__.py b/l10n_es_account_import_facturae/tests/__init__.py new file mode 100644 index 00000000000..9fb5d4b1775 --- /dev/null +++ b/l10n_es_account_import_facturae/tests/__init__.py @@ -0,0 +1 @@ +from . import test_import_facturae diff --git a/l10n_es_account_import_facturae/tests/invoice.xsig b/l10n_es_account_import_facturae/tests/invoice.xsig new file mode 100644 index 00000000000..a5362929e5a --- /dev/null +++ b/l10n_es_account_import_facturae/tests/invoice.xsig @@ -0,0 +1,194 @@ + + + 3.2 + I + EM + + INV/2023/04/0002ES59962470K + 1 + + 177.87 + 177.87 + + + 177.87 + 177.87 + + + 177.87 + 177.87 + + EUR + + + + + + F + R + ES59962470K + + + ES Company + + + +
A
+ 00000 + Candasnos + Zaragoza + ESP +
+ + +34 612 34 56 7 + http://www.esexample.com + info@company.esexample.com + ES Company + +
+
+ + + J + R + ESA12345674 + + + + 1 + 01 + +
4557 De Silva St
+ 94538 + Fremont + Albacete + ESP +
+ + (870)-931-0505 + http://www.azure-interior.com + azure.Interior24@example.com + Azure Interior + + Azure Interior +
+ + 1 + 02 + +
4557 De Silva St
+ 94538 + Fremont + Albacete + ESP +
+ + (870)-931-0505 + http://www.azure-interior.com + azure.Interior24@example.com + Azure Interior + + Azure Interior +
+ + 1 + 03 + +
4557 De Silva St
+ 94538 + Fremont + Albacete + ESP +
+ + (870)-931-0505 + http://www.azure-interior.com + azure.Interior24@example.com + Azure Interior + + Azure Interior +
+
+ + Azure Interior + Azure Interior + +
4557 De Silva St
+ 94538 + Fremont + Albacete + ESP +
+ + (870)-931-0505 + http://www.azure-interior.com + azure.Interior24@example.com + Azure Interior + +
+
+
+ + + + INV/2023/04/0002 + + FC + OO + + + 2023-04-12 + EUR + EUR + en + + + + 01 + 21.00 + + 147.00 + 147.00 + + + 30.87 + 30.87 + + + + + 147.00 + 147.00 + 30.87 + -0.00 + 177.87 + 177.87 + 177.87 + + + + [E-COM06] Corner Desk Right Sit + 1.0 + 147.000000 + 147.000000 + 147.000000 + + + 01 + 21.00 + + 147.00 + 147.00 + + + 30.87 + 30.87 + + + + E-COM06 + + + + +
diff --git a/l10n_es_account_import_facturae/tests/test_import_facturae.py b/l10n_es_account_import_facturae/tests/test_import_facturae.py new file mode 100644 index 00000000000..fa7b3d69cdf --- /dev/null +++ b/l10n_es_account_import_facturae/tests/test_import_facturae.py @@ -0,0 +1,52 @@ +# Copyright 2023 CreuBlanca +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +import base64 + +from odoo.modules.module import get_module_resource + +from odoo.addons.l10n_es_aeat.tests.test_l10n_es_aeat_mod_base import ( + TestL10nEsAeatModBase, +) + + +class TestL10nEsAeatMod115Base(TestL10nEsAeatModBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company.vat = "ESA12345674" + cls.seller = cls.env["res.partner"].create( + {"vat": "ES59962470K", "name": "Seller"} + ) + cls.invoice_data = open( + get_module_resource( + "l10n_es_account_import_facturae", "tests", "invoice.xsig" + ), + "rb", + ).read() + + def test_update_invoice(self): + move = ( + self.env["account.move"] + .with_context(default_move_type="in_invoice") + .create({}) + ) + self.assertEqual(move.amount_untaxed, 0.0) + self.assertEqual(move.amount_total, 0.0) + move.message_post( + body="Import invoice", attachments=[("invoice.xsig", self.invoice_data)] + ) + self.assertEqual(move.amount_untaxed, 147.0) + self.assertEqual(move.amount_total, 177.87) + + def test_create_invoice(self): + attachment = self.env["ir.attachment"].create( + {"name": "invoice.xsig", "datas": base64.b64encode(self.invoice_data)} + ) + move_action = self.env["account.journal"].create_invoice_from_attachment( + attachment.ids + ) + move = self.env[move_action["res_model"]].search(move_action["domain"]) + self.assertEqual(move.amount_untaxed, 147.0) + self.assertEqual(move.amount_total, 177.87) diff --git a/setup/l10n_es_account_import_facturae/odoo/addons/l10n_es_account_import_facturae b/setup/l10n_es_account_import_facturae/odoo/addons/l10n_es_account_import_facturae new file mode 120000 index 00000000000..c54924035b1 --- /dev/null +++ b/setup/l10n_es_account_import_facturae/odoo/addons/l10n_es_account_import_facturae @@ -0,0 +1 @@ +../../../../l10n_es_account_import_facturae \ No newline at end of file diff --git a/setup/l10n_es_account_import_facturae/setup.py b/setup/l10n_es_account_import_facturae/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/l10n_es_account_import_facturae/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)