From f3f0a13da4dc37a520ac3f6191e7248d71645825 Mon Sep 17 00:00:00 2001 From: szalatyzuzanna Date: Mon, 30 Sep 2024 14:26:11 +0200 Subject: [PATCH] [ADD] bc3_importer --- bc3_importer/README.rst | 80 ++ bc3_importer/__init__.py | 2 + bc3_importer/__manifest__.py | 22 + bc3_importer/data/bc3_version_data.xml | 259 ++++ bc3_importer/data/product_data.xml | 99 ++ bc3_importer/data/uom_data.xml | 9 + bc3_importer/i18n/bc3_importer.pot | 577 +++++++++ bc3_importer/i18n/es.po | 580 +++++++++ bc3_importer/models/__init__.py | 2 + bc3_importer/models/bc3_version.py | 166 +++ bc3_importer/models/sale_order.py | 23 + bc3_importer/readme/CONTRIBUTORS.rst | 4 + bc3_importer/readme/DESCRIPTION.rst | 2 + bc3_importer/security/bc3_file_security.xml | 27 + bc3_importer/security/ir.model.access.csv | 9 + bc3_importer/static/description/icon.png | Bin 0 -> 8776 bytes bc3_importer/static/description/index.html | 430 +++++++ bc3_importer/tests/__init__.py | 2 + bc3_importer/tests/bc3_file_test.bc3 | 4 + bc3_importer/tests/test_bc3_import_wizard.py | 32 + bc3_importer/tests/test_bc3_version.py | 60 + bc3_importer/views/bc3_version_views.xml | 161 +++ bc3_importer/views/sale_order_views.xml | 91 ++ bc3_importer/wizard/__init__.py | 1 + bc3_importer/wizard/bc3_import_wizard.py | 1041 +++++++++++++++++ .../wizard/bc3_import_wizard_views.xml | 62 + requirements.txt | 3 + setup/bc3_importer/odoo/addons/bc3_importer | 1 + setup/bc3_importer/setup.py | 6 + 29 files changed, 3755 insertions(+) create mode 100644 bc3_importer/README.rst create mode 100644 bc3_importer/__init__.py create mode 100644 bc3_importer/__manifest__.py create mode 100644 bc3_importer/data/bc3_version_data.xml create mode 100644 bc3_importer/data/product_data.xml create mode 100644 bc3_importer/data/uom_data.xml create mode 100644 bc3_importer/i18n/bc3_importer.pot create mode 100644 bc3_importer/i18n/es.po create mode 100644 bc3_importer/models/__init__.py create mode 100644 bc3_importer/models/bc3_version.py create mode 100644 bc3_importer/models/sale_order.py create mode 100755 bc3_importer/readme/CONTRIBUTORS.rst create mode 100755 bc3_importer/readme/DESCRIPTION.rst create mode 100644 bc3_importer/security/bc3_file_security.xml create mode 100644 bc3_importer/security/ir.model.access.csv create mode 100644 bc3_importer/static/description/icon.png create mode 100755 bc3_importer/static/description/index.html create mode 100644 bc3_importer/tests/__init__.py create mode 100644 bc3_importer/tests/bc3_file_test.bc3 create mode 100644 bc3_importer/tests/test_bc3_import_wizard.py create mode 100644 bc3_importer/tests/test_bc3_version.py create mode 100644 bc3_importer/views/bc3_version_views.xml create mode 100644 bc3_importer/views/sale_order_views.xml create mode 100644 bc3_importer/wizard/__init__.py create mode 100644 bc3_importer/wizard/bc3_import_wizard.py create mode 100644 bc3_importer/wizard/bc3_import_wizard_views.xml create mode 100644 requirements.txt create mode 120000 setup/bc3_importer/odoo/addons/bc3_importer create mode 100755 setup/bc3_importer/setup.py diff --git a/bc3_importer/README.rst b/bc3_importer/README.rst new file mode 100644 index 0000000..12b92f7 --- /dev/null +++ b/bc3_importer/README.rst @@ -0,0 +1,80 @@ +================== +BC3 files importer +================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:7daee495c7ca99f6178a9535d2bee76b39dd8ee4d83d4515714c7614a99abaf9 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fvertical--construction-lightgray.png?logo=github + :target: https://github.com/OCA/vertical-construction/tree/14.0/bc3_importer + :alt: OCA/vertical-construction +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/vertical-construction-14-0/vertical-construction-14-0-bc3_importer + :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/vertical-construction&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Importer of quotations in bc3 format. + + +**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 +~~~~~~~ + +* Binhex + +Contributors +~~~~~~~~~~~~ + +* `Binhex `_: + + * Zuzanna Elzbieta Szalaty Szalaty + + +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/vertical-construction `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/bc3_importer/__init__.py b/bc3_importer/__init__.py new file mode 100644 index 0000000..9b42961 --- /dev/null +++ b/bc3_importer/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/bc3_importer/__manifest__.py b/bc3_importer/__manifest__.py new file mode 100644 index 0000000..f5aeddd --- /dev/null +++ b/bc3_importer/__manifest__.py @@ -0,0 +1,22 @@ +{ + "name": "BC3 files importer", + "author": "Binhex, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/vertical-construction", + "category": "BC3", + "version": "14.0.1.0.0", + "license": "AGPL-3", + "depends": ["project", "sale_management"], + "data": [ + "security/bc3_file_security.xml", + "security/ir.model.access.csv", + "wizard/bc3_import_wizard_views.xml", + "views/bc3_version_views.xml", + "data/bc3_version_data.xml", + "views/sale_order_views.xml", + "data/uom_data.xml", + "data/product_data.xml", + ], + "external_dependencies": { + "python": ["iteration_utilities", "chardet"], + }, +} diff --git a/bc3_importer/data/bc3_version_data.xml b/bc3_importer/data/bc3_version_data.xml new file mode 100644 index 0000000..347da23 --- /dev/null +++ b/bc3_importer/data/bc3_version_data.xml @@ -0,0 +1,259 @@ + + + + FIEBDC-3-2020v2 + + + + 1 + + False + + + + 2 + + False + + + + 3 + + True + + + + 4 + + False + + + + 5 + + False + + + + 6 + + True + + + + 7 + + False + + + + 8 + + False + + + + 9 + + False + + + + 10 + + False + + + + 11 + + False + + + + 12 + + False + + + + v + ~V | [ PROPIEDAD_ARCHIVO ] | VERSION_FORMATO [ \ DDMMAAAA ] | [ +PROGRAMA_EMISION ] | [ CABECERA ] \ { ROTULO_IDENTIFICACION \ } | [ +JUEGO_CARACTERES ] | [ COMENTARIO ] | [ TIPO INFORMACIÓN ] | [ NÚMERO +CERTIFICACIÓN ] | [ FECHA CERTIFICACIÓN ] | [ URL_BASE ] | + + + + + + + 1 + + False + + + + 2 + + True + + + + 3 + + False + + + + 4 + + False + + + + 5 + + False + + + + 6 + False + + + 7 + + False + + + + c + ~C | CODIGO { \ CODIGO } | [ UNIDAD ] | [ RESUMEN ] | { PRECIO \ } | { FECHA \ } | [ TIPO ] | + + + + + + + 1 + + False + + + 2 + + False + + True + + + + 3 + True + + + + + 4 + + True + + + + + 5 + False + + + 6 + True + + + 7 + True + + + 8 + + True + + + + d + ~D | CODIGO_PADRE | < CODIGO_HIJO \ [ FACTOR ] \ [ RENDIMIENTO ] \ > | < CODIGO_HIJO \ [ FACTOR ] \ [ RENDIMIENTO ] \ {CODIGO_PORCENTAJE ; } \ > | + + + True + + + + + 1 + + True + + + + 2 + + + + + t + ~T | CODIGO_CONCEPTO | TEXTO_DESCRIPTIVO | + + + True + + + + + + + + + + + + + + + + diff --git a/bc3_importer/data/product_data.xml b/bc3_importer/data/product_data.xml new file mode 100644 index 0000000..3cdac78 --- /dev/null +++ b/bc3_importer/data/product_data.xml @@ -0,0 +1,99 @@ + + + + BC3 Template Product (Units) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Template Product (Meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Template Product (Square meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Template Product (Cubic meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Template Product (g) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Template Product (L) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (Units) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (Meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (Square meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (Cubic meter) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (g) + + + BC3 product that will be used if imported product does not exist. + + + BC3 Product (L) + + + BC3 product that will be used if imported product does not exist. + + diff --git a/bc3_importer/data/uom_data.xml b/bc3_importer/data/uom_data.xml new file mode 100644 index 0000000..fe22881 --- /dev/null +++ b/bc3_importer/data/uom_data.xml @@ -0,0 +1,9 @@ + + + + + m2 + + bigger + + diff --git a/bc3_importer/i18n/bc3_importer.pot b/bc3_importer/i18n/bc3_importer.pot new file mode 100644 index 0000000..1e9b539 --- /dev/null +++ b/bc3_importer/i18n/bc3_importer.pot @@ -0,0 +1,577 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * bc3_importer +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0-20231106\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-09-30 10:09+0000\n" +"PO-Revision-Date: 2024-09-30 10:09+0000\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: bc3_importer +#: model:res.groups,name:bc3_importer.group_bc3_manager +msgid "Administrator" +msgstr "" + +#. module: bc3_importer +#: model:ir.module.category,name:bc3_importer.module_bc3_importer +#: model:ir.module.category,name:bc3_importer.module_bc3_importer_bc3 +#: model:ir.ui.menu,name:bc3_importer.bc3_files +#: model:ir.ui.menu,name:bc3_importer.bc3_menuitem +msgid "BC3" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.view_sales_order_bc3 +msgid "BC3 Info" +msgstr "" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_orders_show +msgid "BC3 Orders" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_cubic_meter +#: model:product.template,name:bc3_importer.product_product_product_cubic_meter_product_template +msgid "BC3 Product (Cubic meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_l +#: model:product.template,name:bc3_importer.product_product_product_l_product_template +msgid "BC3 Product (L)" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_meter +#: model:product.template,name:bc3_importer.product_product_product_meter_product_template +msgid "BC3 Product (Meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_square_meter +#: model:product.template,name:bc3_importer.product_product_product_square_meter_product_template +msgid "BC3 Product (Square meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_units +#: model:product.template,name:bc3_importer.product_product_product_units_product_template +msgid "BC3 Product (Units)" +msgstr "" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_g +#: model:product.template,name:bc3_importer.product_product_product_g_product_template +msgid "BC3 Product (g)" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.action_quotations_bc3 +#: model:ir.ui.menu,name:bc3_importer.bc3_quotations_show +msgid "BC3 Quotations" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_cubic_meter +msgid "BC3 Template Product (Cubic meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_l +msgid "BC3 Template Product (L)" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_meter +msgid "BC3 Template Product (Meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_square_meter +msgid "BC3 Template Product (Square meter)" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_units +msgid "BC3 Template Product (Units)" +msgstr "" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_g +msgid "BC3 Template Product (g)" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_action +#: model:ir.model,name:bc3_importer.model_bc3_version +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "BC3 Version" +msgstr "" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_version_register +msgid "BC3 Version Register" +msgstr "" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_version_register_rule +msgid "BC3 Version Register Rule" +msgstr "" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_version_show +msgid "BC3 Versions" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__bc3_file +msgid "BC3 file" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__bc3_file_name +msgid "BC3 file name" +msgstr "" + +#. module: bc3_importer +#: model:product.product,description_sale:bc3_importer.product_product_product_cubic_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_g +#: model:product.product,description_sale:bc3_importer.product_product_product_l +#: model:product.product,description_sale:bc3_importer.product_product_product_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_square_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_units +#: model:product.template,description_sale:bc3_importer.product_product_product_cubic_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_g_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_l_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_square_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_template_cubic_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_g +#: model:product.template,description_sale:bc3_importer.product_product_product_template_l +#: model:product.template,description_sale:bc3_importer.product_product_product_template_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_square_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_units +#: model:product.template,description_sale:bc3_importer.product_product_product_units_product_template +msgid "BC3 product that will be used if imported product does not exist." +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3 +msgid "BC3 sale order" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_base_url +msgid "Base url" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_import_wizard_form +msgid "Cancel" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_certification_date +msgid "Certification date" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_certification_number +msgid "Certification number" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_character_set +msgid "Character set" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__is_child +msgid "Child" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__code +msgid "Code" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_comment +msgid "Comment" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.action_quotations_bc3 +msgid "Create a new quotation, the first step of a new sale!" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_products +msgid "Create non-existent products" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__create_uid +msgid "Created by" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__create_date +msgid "Created on" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__partner_id +msgid "Customer/Vendor" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__date +msgid "Date" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__product_id +msgid "Default product" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Description" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__display_name +msgid "Display Name" +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Dynamic Product " +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/models/bc3_version.py:0 +#, python-format +msgid "Error in register description or not enough rules" +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Error parsing the file" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__field_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__field_ids +msgid "Field" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_file_property +msgid "File property" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_header +msgid "Header" +msgstr "" + +#. module: bc3_importer +#: model:ir.module.category,description:bc3_importer.module_bc3_importer +msgid "Helps you handle your bc3 files, versions and registers." +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__id +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__id +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__id +msgid "ID" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_identifying_label +msgid "Identifying label" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_import_wizard_form +msgid "Import" +msgstr "" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_files_import +msgid "Import BC3" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_import_wizard_action +msgid "Import BC3 File" +msgstr "" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_import_wizard +msgid "Import BC3 file" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_information_type +msgid "Information Type" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__write_date +msgid "Last Updated on" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__model_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__model_id +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Model" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__name +msgid "Name" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_action +msgid "No bc3 version found. Let's create one!" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_register_action +msgid "No register found. Let's create one!" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_register_rule_action +msgid "No register rule found. Let's create one!" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.action_quotations_bc3 +msgid "" +"Once the quotation is confirmed by the customer, it becomes a sales " +"order.
You will be able to create an invoice and collect the payment." +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Parsing error, missing data" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__primary_key +msgid "Primary key" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_program +msgid "Program" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__project_id +msgid "Project" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__register_id +msgid "Register" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_register_rule_action +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_rule_form_view +msgid "Register Rule" +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/models/bc3_version.py:0 +#, python-format +msgid "Register name should unique" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__register_ids +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "Registers" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__regular_expression +msgid "Regular expression" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__description +msgid "Rule Description" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__rule_ids +msgid "Rule Lines" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Rules" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__sale_id +msgid "Sale Order" +msgstr "" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.action_orders_bc3 +msgid "Sales Orders" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,help:bc3_importer.field_bc3_import_wizard__product_id +msgid "Select a product which will be used in the BC3 file." +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__sequence +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__sequence +msgid "Sequence" +msgstr "" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Show Sale Order" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__edit_existent +msgid "The register may edit existent records" +msgstr "" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_units +#: model:product.template,uom_name:bc3_importer.product_product_product_template_units +#: model:product.template,uom_name:bc3_importer.product_product_product_units_product_template +msgid "Units" +msgstr "" + +#. module: bc3_importer +#: model:res.groups,name:bc3_importer.group_bc3_user +msgid "User" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__version_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__version_id +msgid "Version" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_version_format +msgid "Version / Format" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.view_sales_order_bc3 +msgid "Version Information" +msgstr "" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_register_action +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Version Register" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_version_date +msgid "Version date" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "e.g. FIEBDC-3-2020v2" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "e.g. ~K" +msgstr "" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_square_meter +#: model:product.template,uom_name:bc3_importer.product_product_product_square_meter_product_template +#: model:product.template,uom_name:bc3_importer.product_product_product_template_square_meter +#: model:uom.uom,name:bc3_importer.product_uom_square_meter +msgid "m2" +msgstr "" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_cubic_meter +#: model:product.template,uom_name:bc3_importer.product_product_product_cubic_meter_product_template +#: model:product.template,uom_name:bc3_importer.product_product_product_template_cubic_meter +msgid "m³" +msgstr "" diff --git a/bc3_importer/i18n/es.po b/bc3_importer/i18n/es.po new file mode 100644 index 0000000..4d3f4b6 --- /dev/null +++ b/bc3_importer/i18n/es.po @@ -0,0 +1,580 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * bc3_importer +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0-20231106\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-09-30 10:14+0000\n" +"PO-Revision-Date: 2024-09-30 12:33+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.5\n" + +#. module: bc3_importer +#: model:res.groups,name:bc3_importer.group_bc3_manager +msgid "Administrator" +msgstr "" + +#. module: bc3_importer +#: model:ir.module.category,name:bc3_importer.module_bc3_importer +#: model:ir.module.category,name:bc3_importer.module_bc3_importer_bc3 +#: model:ir.ui.menu,name:bc3_importer.bc3_files +#: model:ir.ui.menu,name:bc3_importer.bc3_menuitem +msgid "BC3" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.view_sales_order_bc3 +msgid "BC3 Info" +msgstr "" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_orders_show +msgid "BC3 Orders" +msgstr "Pedidos BC3" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_cubic_meter +#: model:product.template,name:bc3_importer.product_product_product_cubic_meter_product_template +msgid "BC3 Product (Cubic meter)" +msgstr "Producto BC3 (metro cúbico)" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_l +#: model:product.template,name:bc3_importer.product_product_product_l_product_template +msgid "BC3 Product (L)" +msgstr "Producto BC3 (L)" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_meter +#: model:product.template,name:bc3_importer.product_product_product_meter_product_template +msgid "BC3 Product (Meter)" +msgstr "Producto BC3 (Metro)" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_square_meter +#: model:product.template,name:bc3_importer.product_product_product_square_meter_product_template +msgid "BC3 Product (Square meter)" +msgstr "BC3 Producto (metro cuadrado)" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_units +#: model:product.template,name:bc3_importer.product_product_product_units_product_template +msgid "BC3 Product (Units)" +msgstr "BC3 Producto (Unidades)" + +#. module: bc3_importer +#: model:product.product,name:bc3_importer.product_product_product_g +#: model:product.template,name:bc3_importer.product_product_product_g_product_template +msgid "BC3 Product (g)" +msgstr "BC3 Producto (g)" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.action_quotations_bc3 +#: model:ir.ui.menu,name:bc3_importer.bc3_quotations_show +msgid "BC3 Quotations" +msgstr "Presupuestos BC3" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_cubic_meter +msgid "BC3 Template Product (Cubic meter)" +msgstr "Plantilla BC3 Producto (metro cúbico)" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_l +msgid "BC3 Template Product (L)" +msgstr "Plantilla BC3 Producto (L)" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_meter +msgid "BC3 Template Product (Meter)" +msgstr "Plantilla BC3 Producto (Metro)" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_square_meter +msgid "BC3 Template Product (Square meter)" +msgstr "Plantilla BC3 Producto (metro cuadrado)" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_units +msgid "BC3 Template Product (Units)" +msgstr "Cuenta de gastos en plantilla producto" + +#. module: bc3_importer +#: model:product.template,name:bc3_importer.product_product_product_template_g +msgid "BC3 Template Product (g)" +msgstr "Plantilla BC3 Producto (g)" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_action +#: model:ir.model,name:bc3_importer.model_bc3_version +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "BC3 Version" +msgstr "Versión BC3" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_version_register +msgid "BC3 Version Register" +msgstr "Registro de versión BC3" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_version_register_rule +msgid "BC3 Version Register Rule" +msgstr "Regla de registro de la versión BC3" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_version_show +msgid "BC3 Versions" +msgstr "Versiones BC3" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__bc3_file +msgid "BC3 file" +msgstr "Archivo BC3" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__bc3_file_name +msgid "BC3 file name" +msgstr "Nombre del archivo BC3" + +#. module: bc3_importer +#: model:product.product,description_sale:bc3_importer.product_product_product_cubic_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_g +#: model:product.product,description_sale:bc3_importer.product_product_product_l +#: model:product.product,description_sale:bc3_importer.product_product_product_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_square_meter +#: model:product.product,description_sale:bc3_importer.product_product_product_units +#: model:product.template,description_sale:bc3_importer.product_product_product_cubic_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_g_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_l_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_square_meter_product_template +#: model:product.template,description_sale:bc3_importer.product_product_product_template_cubic_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_g +#: model:product.template,description_sale:bc3_importer.product_product_product_template_l +#: model:product.template,description_sale:bc3_importer.product_product_product_template_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_square_meter +#: model:product.template,description_sale:bc3_importer.product_product_product_template_units +#: model:product.template,description_sale:bc3_importer.product_product_product_units_product_template +msgid "BC3 product that will be used if imported product does not exist." +msgstr "Producto BC3 que se utilizará si no existe el producto importado." + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3 +msgid "BC3 sale order" +msgstr "Pedido de venta BC3" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_base_url +msgid "Base url" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_import_wizard_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_certification_date +msgid "Certification date" +msgstr "Fecha de certificación" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_certification_number +msgid "Certification number" +msgstr "Número de certificación" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_character_set +msgid "Character set" +msgstr "Conjunto de caracteres" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__is_child +msgid "Child" +msgstr "Hijo" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__code +msgid "Code" +msgstr "Código" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_comment +msgid "Comment" +msgstr "Comentario" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.action_quotations_bc3 +msgid "Create a new quotation, the first step of a new sale!" +msgstr "Crear un nuevo presupuesto, ¡el primer paso de una nueva venta!" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_products +msgid "Create non-existent products" +msgstr "Crear productos no existentes" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__create_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__create_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__partner_id +msgid "Customer/Vendor" +msgstr "Cliente/Proveedor" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__date +msgid "Date" +msgstr "Fecha" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__product_id +msgid "Default product" +msgstr "Producto por defecto" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Description" +msgstr "Descripción" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__display_name +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Dynamic Product " +msgstr "Producto dinámico " + +#. module: bc3_importer +#: code:addons/bc3_importer/models/bc3_version.py:0 +#, python-format +msgid "Error in register description or not enough rules" +msgstr "Error en la descripción del registro o reglas insuficientes" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Error parsing the file" +msgstr "Error al analizar el archivo" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__field_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__field_ids +msgid "Field" +msgstr "Campo" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_file_property +msgid "File property" +msgstr "Propiedad del archivo" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_header +msgid "Header" +msgstr "Encabezado" + +#. module: bc3_importer +#: model:ir.module.category,description:bc3_importer.module_bc3_importer +msgid "Helps you handle your bc3 files, versions and registers." +msgstr "Le ayuda a manejar sus archivos bc3, versiones y registros." + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__id +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__id +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line__id +msgid "ID" +msgstr "" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_identifying_label +msgid "Identifying label" +msgstr "Etiqueta identificativa" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_import_wizard_form +msgid "Import" +msgstr "Importar" + +#. module: bc3_importer +#: model:ir.ui.menu,name:bc3_importer.bc3_files_import +msgid "Import BC3" +msgstr "Importar BC3" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_import_wizard_action +msgid "Import BC3 File" +msgstr "Importar archivo BC3" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_bc3_import_wizard +msgid "Import BC3 file" +msgstr "Importar archivo BC3" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_information_type +msgid "Information Type" +msgstr "Tipo de información" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order____last_update +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order_line____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__write_uid +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__write_date +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__model_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__model_id +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Model" +msgstr "Modelo" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__name +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__name +msgid "Name" +msgstr "Nombre" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_action +msgid "No bc3 version found. Let's create one!" +msgstr "No se ha encontrado ninguna versión de bc3. ¡Vamos a crear una!" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_register_action +msgid "No register found. Let's create one!" +msgstr "No se ha encontrado ningún registro. ¡Vamos a crear uno!" + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.bc3_version_register_rule_action +msgid "No register rule found. Let's create one!" +msgstr "No se ha encontrado ninguna regla de registro. Creemos una." + +#. module: bc3_importer +#: model_terms:ir.actions.act_window,help:bc3_importer.action_quotations_bc3 +msgid "" +"Once the quotation is confirmed by the customer, it becomes a sales order." +"
You will be able to create an invoice and collect the payment." +msgstr "" +"Una vez que el presupuesto es confirmado por el cliente, se convierte en un " +"pedido de venta.
Podrás crear una factura y cobrar el pago." + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Parsing error, missing data" +msgstr "Error de análisis sintáctico, faltan datos" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__primary_key +msgid "Primary key" +msgstr "Clave principal" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_program +msgid "Program" +msgstr "Programa" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__project_id +msgid "Project" +msgstr "Proyecto" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__register_id +msgid "Register" +msgstr "Registro" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_register_rule_action +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_rule_form_view +msgid "Register Rule" +msgstr "Regla de registro" + +#. module: bc3_importer +#: code:addons/bc3_importer/models/bc3_version.py:0 +#, python-format +msgid "Register name should unique" +msgstr "El nombre de registro debe ser único" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version__register_ids +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "Registers" +msgstr "Registros" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__regular_expression +msgid "Regular expression" +msgstr "Expresión regular" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__description +msgid "Rule Description" +msgstr "Descripción de la regla" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__rule_ids +msgid "Rule Lines" +msgstr "Líneas de la regla" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Rules" +msgstr "Reglas" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__sale_id +msgid "Sale Order" +msgstr "Pedido de venta" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_sale_order +msgid "Sales Order" +msgstr "Pedido de venta" + +#. module: bc3_importer +#: model:ir.model,name:bc3_importer.model_sale_order_line +msgid "Sales Order Line" +msgstr "Línea de pedido de venta" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.action_orders_bc3 +msgid "Sales Orders" +msgstr "Pedidos de ventas" + +#. module: bc3_importer +#: model:ir.model.fields,help:bc3_importer.field_bc3_import_wizard__product_id +msgid "Select a product which will be used in the BC3 file." +msgstr "Seleccione el producto que se utilizará en el archivo BC3." + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__sequence +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register_rule__sequence +msgid "Sequence" +msgstr "Secuencia" + +#. module: bc3_importer +#: code:addons/bc3_importer/wizard/bc3_import_wizard.py:0 +#, python-format +msgid "Show Sale Order" +msgstr "Mostrar pedido de venta" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__edit_existent +msgid "The register may edit existent records" +msgstr "El registro puede editar registros existentes" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_units +#: model:product.template,uom_name:bc3_importer.product_product_product_template_units +#: model:product.template,uom_name:bc3_importer.product_product_product_units_product_template +msgid "Units" +msgstr "Unidades" + +#. module: bc3_importer +#: model:res.groups,name:bc3_importer.group_bc3_user +msgid "User" +msgstr "Usuario" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_import_wizard__version_id +#: model:ir.model.fields,field_description:bc3_importer.field_bc3_version_register__version_id +msgid "Version" +msgstr "Versión BC3" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_version_format +msgid "Version / Format" +msgstr "Versión / Formato" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.view_sales_order_bc3 +msgid "Version Information" +msgstr "Información sobre la versión" + +#. module: bc3_importer +#: model:ir.actions.act_window,name:bc3_importer.bc3_version_register_action +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "Version Register" +msgstr "Registro de versiones" + +#. module: bc3_importer +#: model:ir.model.fields,field_description:bc3_importer.field_sale_order__bc3_version_date +msgid "Version date" +msgstr "Fecha de la versión" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_form_view +msgid "e.g. FIEBDC-3-2020v2" +msgstr "" + +#. module: bc3_importer +#: model_terms:ir.ui.view,arch_db:bc3_importer.bc3_version_register_form_view +msgid "e.g. ~K" +msgstr "" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_square_meter +#: model:product.template,uom_name:bc3_importer.product_product_product_square_meter_product_template +#: model:product.template,uom_name:bc3_importer.product_product_product_template_square_meter +#: model:uom.uom,name:bc3_importer.product_uom_square_meter +msgid "m2" +msgstr "" + +#. module: bc3_importer +#: model:product.product,uom_name:bc3_importer.product_product_product_cubic_meter +#: model:product.template,uom_name:bc3_importer.product_product_product_cubic_meter_product_template +#: model:product.template,uom_name:bc3_importer.product_product_product_template_cubic_meter +msgid "m³" +msgstr "" diff --git a/bc3_importer/models/__init__.py b/bc3_importer/models/__init__.py new file mode 100644 index 0000000..51d3907 --- /dev/null +++ b/bc3_importer/models/__init__.py @@ -0,0 +1,2 @@ +from . import bc3_version +from . import sale_order diff --git a/bc3_importer/models/bc3_version.py b/bc3_importer/models/bc3_version.py new file mode 100644 index 0000000..1dabe96 --- /dev/null +++ b/bc3_importer/models/bc3_version.py @@ -0,0 +1,166 @@ +import logging +import re + +from iteration_utilities import duplicates + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class Bc3Version(models.Model): + _name = "bc3.version" + _description = "BC3 Version" + _order = "name" + name = fields.Char("Name", required=True) + register_ids = fields.One2many( + "bc3.version.register", "version_id", string="Registers" + ) + + @api.constrains("register_ids") + def _check_registers(self): + for record in self: + if record.register_ids: + register_name = record.register_ids.mapped("name") + if len(list(duplicates(register_name))) > 0: + raise ValidationError(_("Register name should unique")) + + +class Bc3VersionRegister(models.Model): + _name = "bc3.version.register" + _description = "BC3 Version Register" + _order = "name" + name = fields.Selection( + selection=[ + ("v", "~V"), + ("k", "~K"), + ("c", "~C"), + ("d", "~D"), + ("t", "~T"), + ("g", "~G"), + ("f", "~F"), + ], + string="Name", + required=True, + ) + description = fields.Text("Rule Description") + rule_ids = fields.One2many( + "bc3.version.register.rule", "register_id", string="Rule Lines" + ) + version_id = fields.Many2one("bc3.version", string="Version", ondelete="cascade") + model_id = fields.Many2one( + "ir.model", + "Model", + required=True, + ondelete="cascade", + domain=[ + "|", + "|", + ("model", "=", "sale.order"), + ("model", "=", "sale.order.line"), + ("model", "=", "product.product"), + ], + ) + edit_existent = fields.Boolean("The register may edit existent records") + + @api.onchange("description", "rule_ids") + def get_regular_expression(self): + if self.description and self.rule_ids: + self.description[0].lower() + register_line = self.description[1:].rstrip().strip().split("|") + register_line.pop(0) + len_rule_child = len(self.rule_ids.filtered(lambda x: not x.is_child)) + if len(register_line) > len_rule_child: + del register_line[-1] + if not len(register_line) == len( + self.rule_ids.filtered(lambda x: not x.is_child) + ): + raise ValidationError( + _("Error in register description or not enough rules") + ) + i = 0 + for rule in self.rule_ids.filtered(lambda x: not x.is_child): + rule.generate_regular_expression(register_line[i]) + i += 1 + + +class Bc3VersionRegisterRule(models.Model): + _name = "bc3.version.register.rule" + _description = "BC3 Version Register Rule" + _order = "sequence" + + sequence = fields.Integer(string="Sequence") + model_id = fields.Many2one("ir.model", string="Model", ondelete="cascade") + field_id = fields.Many2one( + "ir.model.fields", + "Field", + domain=[ + ("model_id", "=", model_id), + ( + "ttype", + "not in", + [ + "many2one_reference", + "reference", + "serialized", + "job_serialized", + "selection", + ], + ), + ], + ondelete="cascade", + ) + register_id = fields.Many2one( + "bc3.version.register", string="Register", ondelete="cascade" + ) + is_child = fields.Boolean("Child") + regular_expression = fields.Char("Regular expression") + primary_key = fields.Boolean("Primary key") + field_ids = fields.Many2many( + "ir.model.fields", + string="Field", + domain=[ + ( + "ttype", + "not in", + [ + "many2one_reference", + "reference", + "serialized", + "job_serialized", + "selection", + ], + ), + ], + ondelete="cascade", + ) + + def generate_regular_expression(self, line): + code = line + code = code.replace(" ", "").replace("\\", "\\\\?") + pattern3 = r"[^<>\\\[\]{}?]+" + replacement2 = r'([à-ü-À-Üa-zA-Z0-9_.+#;,":/\ \-\%\²\³\=\€\ª\º]+)' + html = re.sub(pattern3, replacement2, code) + pattern6 = r"\{" + replacement6 = "(" + pattern7 = r"\}" + replacement7 = ")*" + html = re.sub(pattern6, replacement6, html) + html = re.sub(pattern7, replacement7, html) + pattern8 = r"\(\\.*\)\*" + replacement8 = '(\\?[à-ü-À-Üa-zA-Z0-9_+.#;,":/\\ \\-\\%\\²\\³\\=\\€\\ª\\º]+)*' + html = re.sub(pattern8, replacement8, html) + html = html.replace("(\\?", "(\\\\?") + pattern9 = r"\[\([^?]*\)\]" + replacement9 = '([à-ü-À-Üa-zA-Z0-9_+.#,:";/\\ \\-\\%\\²\\³\\=\\€\\ª\\º]+)*' + html = re.sub(pattern9, replacement9, html) + pattern10 = r"\[\\.*\+\)\]" + replacement10 = '(\\?[à-ü-À-Üa-zA-Z0-9_+.#,:";/\\ \\-\\%\\²\\³\\=\\€\\ª\\º]+)*' + html = re.sub(pattern10, replacement10, html) + html = html.replace("(\\?", "(\\\\?") + pattern11 = r"\(\(.*\+\)\\\\\?\)\*" + replacement11 = r'([à-ü-À-Üa-zA-Z0-9_+.#,:";/\ \-\%\²\³\=\€\ª\º]+\\\\?)*' + html = re.sub(pattern11, replacement11, html) + html = html.replace("<", "").replace(">", "") + self.regular_expression = html diff --git a/bc3_importer/models/sale_order.py b/bc3_importer/models/sale_order.py new file mode 100644 index 0000000..8ead1d8 --- /dev/null +++ b/bc3_importer/models/sale_order.py @@ -0,0 +1,23 @@ +from odoo import fields, models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + bc3 = fields.Boolean("BC3 sale order") + bc3_file_property = fields.Char("File property") + bc3_version_format = fields.Char("Version / Format") + bc3_version_date = fields.Date("Version date") + bc3_program = fields.Char("Program") + bc3_header = fields.Char("Header") + bc3_identifying_label = fields.Char("Identifying label") + bc3_character_set = fields.Char("Character set") + bc3_comment = fields.Text("Comment") + bc3_information_type = fields.Char("Information Type") + bc3_certification_number = fields.Char("Certification number") + bc3_certification_date = fields.Date("Certification date") + bc3_base_url = fields.Char("Base url") + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + bc3_code = fields.Char("Code") diff --git a/bc3_importer/readme/CONTRIBUTORS.rst b/bc3_importer/readme/CONTRIBUTORS.rst new file mode 100755 index 0000000..97be4f5 --- /dev/null +++ b/bc3_importer/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Binhex `_: + + * Zuzanna Elzbieta Szalaty Szalaty + diff --git a/bc3_importer/readme/DESCRIPTION.rst b/bc3_importer/readme/DESCRIPTION.rst new file mode 100755 index 0000000..bf862cf --- /dev/null +++ b/bc3_importer/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +Importer of quotations in bc3 format. + diff --git a/bc3_importer/security/bc3_file_security.xml b/bc3_importer/security/bc3_file_security.xml new file mode 100644 index 0000000..820b271 --- /dev/null +++ b/bc3_importer/security/bc3_file_security.xml @@ -0,0 +1,27 @@ + + + + BC3 + + Helps you handle your bc3 files, versions and registers. + 10 + + + + User + + + + + + Administrator + + + + + diff --git a/bc3_importer/security/ir.model.access.csv b/bc3_importer/security/ir.model.access.csv new file mode 100644 index 0000000..313adac --- /dev/null +++ b/bc3_importer/security/ir.model.access.csv @@ -0,0 +1,9 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_bc3_import_wizard,bc3.import.wizard,model_bc3_import_wizard,bc3_importer.group_bc3_user,1,0,0,0 +access_bc3_version,bc3.version,model_bc3_version,bc3_importer.group_bc3_user,1,0,0,0 +access_bc3_version_register,bc3.version.register,model_bc3_version_register,bc3_importer.group_bc3_user,1,0,0,0 +access_bc3_version_register_rule,bc3.version.register.rule,model_bc3_version_register_rule,bc3_importer.group_bc3_user,1,0,0,0 +access_bc3_import_wizard_manager,bc3.import.wizard.manager,model_bc3_import_wizard,bc3_importer.group_bc3_manager,1,1,1,1 +access_bc3_version_manager,bc3.version-manager,model_bc3_version,bc3_importer.group_bc3_manager,1,1,1,1 +access_bc3_version_register_manager,bc3.version.register.manager,model_bc3_version_register,bc3_importer.group_bc3_manager,1,1,1,1 +access_bc3_version_register_rule_manager,bc3.version.register.rule.manager,model_bc3_version_register_rule,bc3_importer.group_bc3_manager,1,1,1,1 diff --git a/bc3_importer/static/description/icon.png b/bc3_importer/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..45b34226c46bb5170193e322cd8642623d7ae4fe GIT binary patch literal 8776 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 H75YB_vXmfr literal 0 HcmV?d00001 diff --git a/bc3_importer/static/description/index.html b/bc3_importer/static/description/index.html new file mode 100755 index 0000000..b56f16b --- /dev/null +++ b/bc3_importer/static/description/index.html @@ -0,0 +1,430 @@ + + + + + + +BC3 files importer + + + +
+

BC3 files importer

+ + +

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

+

Importer of quotations in bc3 format.

+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Binhex
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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

+

This module is part of the OCA/vertical-construction project on GitHub.

+

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

+
+
+
+ + diff --git a/bc3_importer/tests/__init__.py b/bc3_importer/tests/__init__.py new file mode 100644 index 0000000..ce1d18d --- /dev/null +++ b/bc3_importer/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_bc3_import_wizard +from . import test_bc3_version diff --git a/bc3_importer/tests/bc3_file_test.bc3 b/bc3_importer/tests/bc3_file_test.bc3 new file mode 100644 index 0000000..fb06cb6 --- /dev/null +++ b/bc3_importer/tests/bc3_file_test.bc3 @@ -0,0 +1,4 @@ +~V|SOFT S.A.|FIEBDC-3/2002|Presto 8.8||ANSI|\n' +'~K|\2\2\3\2\2\2\2\EUR\|0|\n' +'~C|%0.03||Medios Auxiliares|10|030223|0|\n' +'~C|A03B0010|m³|Hormigón aligerado de cemento y picón.|38.34|011222|3| diff --git a/bc3_importer/tests/test_bc3_import_wizard.py b/bc3_importer/tests/test_bc3_import_wizard.py new file mode 100644 index 0000000..153e16d --- /dev/null +++ b/bc3_importer/tests/test_bc3_import_wizard.py @@ -0,0 +1,32 @@ +import base64 +import os + +from odoo.tests.common import TransactionCase + +__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) + + +class TestBC3ImportWizard(TransactionCase): + def setUp(self): + super(TestBC3ImportWizard, self).setUp() + with open(os.path.join(__location__, "bc3_file_test.bc3"), "rb") as file: + bc3_content = file.read() + self.bc3_import_wizard = self.env["bc3.import.wizard"].create( + { + "bc3_file": base64.b64encode(bc3_content), + "bc3_file_name": "test.bc3", + "project_id": self.env.ref("project.project_project_1").id, + "version_id": self.env.ref("bc3_importer.bc3_version_2020_v2").id, + "partner_id": self.env.ref("base.res_partner_1").id, + "create_products": False, + "sale_id": self.env.ref("sale.sale_order_1").id, + } + ) + + def test_do_action(self): + result = self.bc3_import_wizard.do_action() + self.assertEqual(result["res_model"], "sale.order", "Wrong model") + self.assertEqual(result["res_id"], self.bc3_import_wizard.sale_id.id) + self.assertEqual(result["view_mode"], "form") + self.assertEqual(result["target"], "current") + self.assertEqual(result["type"], "ir.actions.act_window") diff --git a/bc3_importer/tests/test_bc3_version.py b/bc3_importer/tests/test_bc3_version.py new file mode 100644 index 0000000..e72394c --- /dev/null +++ b/bc3_importer/tests/test_bc3_version.py @@ -0,0 +1,60 @@ +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase + + +class TestBC3Version(TransactionCase): + def setUp(self): + super(TestBC3Version, self).setUp() + self.bc3_version = self.env["bc3.version"].create({"name": "Test Version"}) + self.bc3_version_register = self.env["bc3.version.register"].create( + { + "name": "v", + "description": "v|rule1|rule2|rule3", + "version_id": self.bc3_version.id, + "model_id": self.env.ref("base.model_res_partner").id, + } + ) + self.bc3_version_register_rule_1 = self.env["bc3.version.register.rule"].create( + { + "sequence": 1, + "model_id": self.env.ref("base.model_res_partner").id, + "field_id": self.env.ref("base.field_res_partner__name").id, + "register_id": self.bc3_version_register.id, + "is_child": False, + } + ) + self.bc3_version_register_rule_2 = self.env["bc3.version.register.rule"].create( + { + "sequence": 2, + "model_id": self.env.ref("base.model_res_partner").id, + "field_id": self.env.ref("base.field_res_partner__email").id, + "register_id": self.bc3_version_register.id, + "is_child": False, + } + ) + self.bc3_version_register_rule_3 = self.env["bc3.version.register.rule"].create( + { + "sequence": 3, + "model_id": self.env.ref("base.model_res_partner").id, + "field_id": self.env.ref("base.field_res_partner__phone").id, + "register_id": self.bc3_version_register.id, + "is_child": False, + } + ) + + def test_get_regular_expression_success(self): + self.bc3_version_register.get_regular_expression() + self.assertTrue(self.bc3_version_register_rule_1.regular_expression) + self.assertTrue(self.bc3_version_register_rule_2.regular_expression) + self.assertTrue(self.bc3_version_register_rule_3.regular_expression) + + def test_get_regular_expression_error_in_description(self): + self.bc3_version_register.description = "v|rule1" + with self.assertRaises(ValidationError): + self.bc3_version_register.get_regular_expression() + + def test_get_regular_expression_not_enough_rules(self): + self.bc3_version_register_rule_2.unlink() + self.bc3_version_register_rule_3.unlink() + with self.assertRaises(ValidationError): + self.bc3_version_register.get_regular_expression() diff --git a/bc3_importer/views/bc3_version_views.xml b/bc3_importer/views/bc3_version_views.xml new file mode 100644 index 0000000..032cbba --- /dev/null +++ b/bc3_importer/views/bc3_version_views.xml @@ -0,0 +1,161 @@ + + + + + BC3 Version + bc3.version + tree,form + +

+ No bc3 version found. Let's create one! +

+
+
+ + bc3.version.form + bc3.version + +
+ +
+

+ +

+
+ + + +
+
+
+
+ + bc3.version.tree + bc3.version + + + + + + + + + + + + Version Register + bc3.version.register + tree,form + +

+ No register found. Let's create one! +

+
+
+ + bc3.version.form.register + bc3.version.register + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + bc3.version.register.tree + bc3.version.register + + + + + + + + + Register Rule + bc3.version.register.rule + tree,form + +

+ No register rule found. Let's create one! +

+
+
+ + + bc3.version.register.rule.form + bc3.version.register.rule + +
+ + + + + + + + + + + +
+
+
+ + bc3.version.register.rule.tree + bc3.version.register.rule + + + + + + + +
diff --git a/bc3_importer/views/sale_order_views.xml b/bc3_importer/views/sale_order_views.xml new file mode 100644 index 0000000..9a81461 --- /dev/null +++ b/bc3_importer/views/sale_order_views.xml @@ -0,0 +1,91 @@ + + + + BC3 Quotations + ir.actions.act_window + sale.order + + tree,kanban,form,calendar,pivot,graph,activity + + [('bc3', '=', True)] + {'default_bc3': 1} + +

+ Create a new quotation, the first step of a new sale! +

+ Once the quotation is confirmed by the customer, it becomes a sales order.
You will be able to create an invoice and collect the payment. +

+
+
+ + Sales Orders + ir.actions.act_window + sale.order + tree,form,calendar,graph,kanban,pivot + + [('state', 'not in', ('draft', 'sent', 'cancel'))] + {'default_bc3': 1} + + + sale.order.form + sale.order + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/bc3_importer/wizard/__init__.py b/bc3_importer/wizard/__init__.py new file mode 100644 index 0000000..2d79918 --- /dev/null +++ b/bc3_importer/wizard/__init__.py @@ -0,0 +1 @@ +from . import bc3_import_wizard diff --git a/bc3_importer/wizard/bc3_import_wizard.py b/bc3_importer/wizard/bc3_import_wizard.py new file mode 100644 index 0000000..0ee8266 --- /dev/null +++ b/bc3_importer/wizard/bc3_import_wizard.py @@ -0,0 +1,1041 @@ +import base64 +import io +import os +import re +import tempfile +from datetime import datetime + +import chardet + +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError + +BC3_PRODUCTS = {} +created_product = False +parse_later = [] +lines = {} +erase_lines = [] + + +class BC3ImportWizard(models.TransientModel): + _name = "bc3.import.wizard" + _description = "Import BC3 file" + + @api.model + def _default_version(self): + return self.env.ref("bc3_importer.bc3_version_2020_v2") or self.env[ + "bc3.version" + ].search([], limit=1) + + bc3_file = fields.Binary(string="BC3 file", required=True) + bc3_file_name = fields.Char(string="BC3 file name") + project_id = fields.Many2one("project.project", string="Project") + version_id = fields.Many2one( + "bc3.version", string="Version", ondelete="cascade", default=_default_version + ) + partner_id = fields.Many2one( + comodel_name="res.partner", + string="Customer/Vendor", + store=True, + readonly=False, + ondelete="restrict", + domain="['|', ('parent_id','=', False), ('is_company','=', True)]", + check_company=True, + ) + create_products = fields.Boolean("Create non-existent products") + product_id = fields.Many2one( + "product.product", + string="Default product", + ondelete="cascade", + help="Select a product which will be used in the BC3 file.", + ) + sale_id = fields.Many2one("sale.order", "Sale Order") + sequence = fields.Integer() + + def do_action(self): + self.ensure_one() + self.get_uom_products() + self.sequence = 0 + self.sale_id = ( + self.env["sale.order"] + .create({"partner_id": self.partner_id.id, "bc3": True}) + .id + ) + # decode the base64 encoded data + data = base64.decodebytes(self.bc3_file) + # create a temporary file, and save the bc3 + fobj = tempfile.NamedTemporaryFile(delete=False) + fname = fobj.name + fobj.write(data) + fobj.close() + try: + rawdata = open(fname, "rb").read() + encoding = chardet.detect(rawdata)["encoding"] + file_content = list( + filter( + None, + io.open(fname, "rt", encoding=encoding, errors="replace") + .read() + .split("~"), + ) + ) + for f in file_content: + self._parse_register(f) + # do stuff here + finally: + # delete the file when done + os.unlink(fname) + seq = 0 + line_ids = [] + sorted_chapters = dict(sorted(lines.items())) + for key in sorted_chapters: + s = ( + self.env["sale.order.line"] + .sudo() + .search( + [("bc3_code", "=", key), ("order_id", "=", self.sale_id.id)], + limit=1, + ) + ) + if s and ( + (s.price_unit == 1 and s.product_uom_qty == 1) + or (s.price_unit == 0 and s.product_uom_qty == 1) + or ("%" in s.bc3_code) + or (s.price_unit == 1) + ): + s.sudo().unlink() + self.env["sale.order.line"].sudo().search( + [("id", "in", sorted_chapters[key])] + ).unlink() + elif s: + if s.id not in line_ids: + line_ids.append(s.id) + s.write({"sequence": seq}) + seq += 1 + for line in ( + self.env["sale.order.line"] + .sudo() + .search( + [ + ("order_id", "=", self.sale_id.id), + ("id", "in", sorted_chapters[key]), + ] + ) + .sorted("name") + ): + if line: + if ( + (line.price_unit == 1 and line.product_uom_qty == 1) + or (line.price_unit == 0 and line.product_uom_qty == 1) + or ("%" in line.bc3_code) + or (line.price_unit == 1) + or not line.price_subtotal + ): + line.sudo().unlink() + elif line.id not in line_ids: + line_ids.append(line.id) + line.sudo().write({"sequence": seq}) + seq += 1 + elif not s and key == "0": + for line in ( + self.env["sale.order.line"] + .sudo() + .search( + [ + ("order_id", "=", self.sale_id.id), + ("id", "in", sorted_chapters[key]), + ] + ) + .sorted("name") + ): + if line: + if ( + (line.price_unit == 1 and line.product_uom_qty == 1) + or (line.price_unit == 0 and line.product_uom_qty == 1) + or ("%" in line.bc3_code) + or (line.price_unit == 1) + ): + line.sudo().unlink() + else: + line_ids.append(line.id) + line.sudo().write({"sequence": seq}) + seq += 1 + for s in self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id)], order="sequence asc" + ): + if ( + (s.price_unit == 1 and s.product_uom_qty == 1) + or (s.price_unit == 0 and s.product_uom_qty == 1) + or (s.bc3_code and "%" in s.bc3_code) + or (s.price_unit == 1) + ) and not s.display_type: + s.sudo().unlink() + elif s.id not in line_ids and not s.display_type == "line_note": + s.sudo().unlink() + elif s.bc3_code not in lines and s.display_type == "line_section": + s.sudo().unlink() + elif s.display_type == "line_section": + next_sequence = ( + self.env["sale.order.line"] + .sudo() + .search( + [ + ("order_id", "=", self.sale_id.id), + ("display_type", "=", "line_section"), + ("sequence", ">", s.sequence), + ], + limit=1, + ) + ) + if next_sequence and next_sequence.sequence == s.sequence + 1: + s.sudo().unlink() + for c in erase_lines: + line = ( + self.env["sale.order.line"] + .sudo() + .search([("bc3_code", "=", c), ("order_id", "=", self.sale_id.id)]) + ) + if line and not (c in lines): + line.sudo().unlink() + return { + "name": _("Show Sale Order"), + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_model": "sale.order", + "views": [(self.env.ref("sale.view_order_form").id, "form")], + "view_id": self.env.ref("sale.view_order_form").id, + "target": "current", + "res_id": self.sale_id.id, + } + + def parse_line(self, line): + split_line = line.rstrip().strip().split("|") + return split_line + + @api.model + def _parse_register_sale_order( + self, parsed_line, rules, current_register, red=False + ): + if len(parsed_line) == len(rules): + i = 0 + for rule in rules: + if len(parsed_line[i]) == 1: + self.sale_id[rule.field_id.name] = self._parse_data( + parsed_line[i][0], rule.field_id.ttype + ) + elif len(parsed_line[i]) > 1: + if self.sale_id[rule.field_id.name]: + self.sale_id[rule.field_id.name] += self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + else: + self.sale_id[rule.field_id.name] = self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + i += 1 + return True + + # and "\\" not in line[i] + @api.model + def _parse_register_product_product(self, line, rules, current_register, red=False): + return True + + @api.model + def _search_create_product(self, code): + product = self.env["product.template"].search( + [("default_code", "ilike", code[0])], limit=1 + ) + if product: + return product + else: + if self.create_products: + code_temp = "" + if len(code) > 1: + for c in code: + code_temp += c + "-" + else: + code_temp = code + product = self.env["product.template"].create( + { + "name": _("Dynamic Product ") + code_temp, + "default_code": code_temp, + } + ) + else: + # Por defecto se ponen unidades + product = self.env.ref("bc3_importer.product_product_product_units") + return product + + @api.model + def _search_create_uom(self, name): + uom = False + if name == "m3" or name == "M3" or name == "m³": + uom = self.env.ref("uom.product_uom_cubic_meter").id or False + elif name == "m²" or name == "M2" or name == "m2": + uom = self.env.ref("bc3_importer.product_uom_square_meter").id or False + elif name == "ud": + uom = self.env.ref("uom.product_uom_unit").id or False + else: + uom = ( + self.env["uom.uom"] + .search( + [ + "|", + "|", + ("name", "in", name), + ("name", "in", name.upper()), + ("name", "in", name.lower()), + ], + limit=1, + ) + .id + or False + ) + return uom + + def _parse_repeats_line(self, existent_line, temp_line, sale_order_line): + create_line = False + if ( + existent_line + and not existent_line.id == sale_order_line.id + and not existent_line.display_type + and not sale_order_line.display_type + ): + if not self.line_in_any_dict(sale_order_line.id): + erase_lines.append(temp_line["bc3_code"]) + return + if existent_line and not existent_line.id == sale_order_line.id and lines: + if not self.line_in_dict( + existent_line.bc3_code, sale_order_line.id + ) and not (sale_order_line.id in self.sale_id.order_line.ids): + create_line = True + elif self.line_in_any_dict(sale_order_line.id): + create_line = True + if create_line: + sale_order_line = sale_order_line.copy( + { + "order_id": self.sale_id.id, + "price_unit": sale_order_line.price_unit, + } + ) + if ( + sale_order_line + and "price_unit" in temp_line + and float(temp_line["price_unit"]) == 1.0 + ): + temp_line["price_unit"] = sale_order_line.price_unit + sale_order_line.sudo().write(temp_line) + else: + if ( + "product_uom_qty" in temp_line + and float(temp_line["product_uom_qty"]) == 1.0 + and sale_order_line.product_uom_qty + and not sale_order_line.display_type + ): + temp_line["product_uom_qty"] = sale_order_line.product_uom_qty + elif not sale_order_line.product_uom_qty == 1: + temp_line["product_uom_qty"] = ( + float(temp_line["product_uom_qty"]) + + sale_order_line.product_uom_qty + ) + if ( + "price_unit" in temp_line + and float(temp_line["price_unit"]) == 1.0 + and not sale_order_line.display_type + ): + temp_line["price_unit"] = sale_order_line.price_unit + if "name" in temp_line and sale_order_line.name: + temp_line["name"] = sale_order_line.name + "-" + temp_line["name"] + if sale_order_line.display_type: + temp_line["product_uom_qty"] = 0 + temp_line["price_unit"] = 0 + sale_order_line.sudo().write(temp_line) + if ( + existent_line + and not existent_line.id == sale_order_line.id + and existent_line.display_type + and existent_line.display_type == "line_section" + ): + if existent_line.bc3_code in lines: + lines[existent_line.bc3_code].append(sale_order_line.id) + else: + lines[existent_line.bc3_code] = [sale_order_line.id] + + def _parse_repeats_line_product(self, temp_line, seq, existent_line): + product = self.env.ref("bc3_importer.product_product_product_units") + if "bc3_code" in temp_line: + temp_line["name"] = temp_line["bc3_code"] or product.default_code or "Line" + else: + temp_line["name"] = product.default_code or "Line" + temp_line["product_id"] = product.id + temp_line["product_uom"] = product.uom_id.id + temp_line["order_id"] = self.sale_id.id + temp_line["sequence"] = seq + if "price_unit" in temp_line and float(temp_line["price_unit"]) == 1.0: + s = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("bc3_code", "=", temp_line["bc3_code"]), + ("price_unit", ">", 1), + ], + limit=1, + ) + if s: + temp_line["price_unit"] = s.price_unit + sale_order_line = self.env["sale.order.line"].create(temp_line) + if ( + existent_line + and not existent_line.id == sale_order_line.id + and existent_line.display_type + and existent_line.display_type == "line_section" + ): + if existent_line.bc3_code in lines: + lines[existent_line.bc3_code].append(sale_order_line.id) + else: + lines[existent_line.bc3_code] = [sale_order_line.id] + + def _parse_repeats( + self, rules, i, dependent_rules, parsed_line, line, parent_seq, existent_line + ): + if rules[i] in dependent_rules: + z = 0 + while z < len(parsed_line[i]): + j = i + counter = 0 + temp_line = {} + if parent_seq: + seq = parent_seq + 1 + # self.lines_reorder(seq) + else: + seq = self.sequence + self.sequence += 1 + while counter < len(dependent_rules[rules[i]]): + if len(parsed_line[j]) == 0: + temp_line[ + dependent_rules[rules[i]][counter]["field_id"]["name"] + ] = False + else: + temp_line[ + dependent_rules[rules[i]][counter]["field_id"]["name"] + ] = parsed_line[j][z] + j += 1 + counter += 1 + z += 1 + temp_line["sequence"] = seq + sale_order_line = False + if "bc3_code" in temp_line: + sale_order_line = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("bc3_code", "=", temp_line["bc3_code"]), + ] + ) + if len(sale_order_line) > 1: + if existent_line: + chapter = existent_line.bc3_code + for s in sale_order_line: + if chapter in lines and s.id in lines[chapter]: + sale_order_line = s + else: + sale_order_line = False + if sale_order_line: + self._parse_repeats_line(existent_line, temp_line, sale_order_line) + else: + self._parse_repeats_line_product(temp_line, seq, existent_line) + + if line: + line = {} + + def _update_line(self, line, seq): + s = False + if "bc3_code" in line: + line["bc3_code"] = line["bc3_code"].replace("#", "") + s = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("bc3_code", "=", line["bc3_code"].replace("#", "")), + ] + ) + if s: + for sale_order_line in s: + if sale_order_line.bc3_code in erase_lines: + erase_lines.remove(sale_order_line.bc3_code) + if ( + "product_uom_qty" in line + and sale_order_line.product_uom_qty + and not sale_order_line.display_type + ): + line["product_uom_qty"] = float(line["product_uom_qty"]) + float( + sale_order_line.product_uom_qty + ) + if ( + "price_unit" in line + and sale_order_line.price_unit + and sale_order_line.price_unit > 1 + and line["price_unit"] == 1 + and not sale_order_line.display_type + ): + line["price_unit"] = sale_order_line.price_unit + if "name" in line and sale_order_line.name: + if sale_order_line.name not in line["name"]: + line["name"] = sale_order_line.name + "- " + line["name"] + if sale_order_line.display_type: + line["product_uom_qty"] = 0 + line["price_unit"] = 0 + sale_order_line.sudo().write(line) + + else: + product = self.env.ref("bc3_importer.product_product_product_units") + + if "bc3_code" in line: + if "name" in line: + line["name"] = ( + line["bc3_code"] or product.default_code or "Line" + ) + line["name"] + else: + line["name"] = line["bc3_code"] or product.default_code or "Line" + else: + if "name" in line: + line["name"] = (product.default_code or "Line") + line["name"] + else: + line["name"] = product.default_code or "Line" + line["product_id"] = product.id + line["product_uom"] = product.uom_id.id + line["order_id"] = self.sale_id.id + line["sequence"] = seq + sale_order_line = self.env["sale.order.line"].create(line) + + def _parse_register_edit_sale_order_line( + self, parsed_line, rules, dependent_rules, rule_ids, current_register, red=False + ): + if len(parsed_line) == len(rules): + primary_key_id = parsed_line[0][0] + existent_line = self.search_line(primary_key_id.replace("#", "")) + parent_seq = False + # Está dentro de un capítulo + if existent_line: + parent_seq = existent_line.sequence + + elif "#" in primary_key_id and not existent_line: + existent_line = ( + self.env["sale.order.line"] + .sudo() + .create( + { + "name": primary_key_id.replace("#", ""), + "display_type": "line_section", + "bc3_code": primary_key_id.replace("#", ""), + "order_id": self.sale_id.id, + } + ) + ) + + i = 0 + seq = False + line = {} + while i < len(rules): + # Repetidos + if rules[i]["id"] in rule_ids: + self._parse_repeats( + rules, + i, + dependent_rules, + parsed_line, + line, + parent_seq, + existent_line, + ) + # Únicos + else: + if rules[i]["field_id"]["name"]: + if len(parsed_line[i]) > 0: + line[rules[i]["field_id"]["name"]] = parsed_line[i][0] + if parent_seq: + seq = parent_seq + 1 + # self.lines_reorder(seq) + else: + seq = self.sequence + self.sequence += 1 + line["sequence"] = seq + i += 1 + # Solo cuando actualiza un dato -> lo hago para todos + + if line: + self._update_line(line, seq) + + return + + @api.model + def search_seq_line(self, seq): + sale_order_line = self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("bc3_code", "=", seq)], limit=1 + ) + return sale_order_line.sequence or False + + @api.model + def search_line(self, code): + code = code.replace("#", "") + a = self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("bc3_code", "=", code)], limit=1 + ) + if not a: + a = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("bc3_code", "=", code.split(".")[0]), + ], + limit=1, + ) + return a + + @api.model + def search_lines(self, code): + code = code.replace("#", "") + a = self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("bc3_code", "=", code)] + ) + return a + + @api.model + def lines_reorder(self, seq): + sale_order_line = self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("sequence", "=", seq)], limit=1 + ) + if sale_order_line: + for s in self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("sequence", ">=", seq)] + ): + s.write({"sequence": s.sequence + 1}) + return + + def _parse_register_sale_order_line_sl( + self, rule, parsed_line, line, i, product_name, product + ): + if (not rule.field_id.relation) or ( + rule.field_id.relation and rule.field_id.relation == "product.template" + ): + if ( + not rule.field_id.name == "product_template_id" + and not rule.field_id.name == "categ_id" + ): + if len(parsed_line[i]) == 1 and parsed_line[i]: + line[rule.field_id.name] = self._parse_data( + parsed_line[i][0], rule.field_id.ttype + ) + elif len(parsed_line[i]) > 1: + if rule.field_id.name in line: + line[rule.field_id.name] += self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + else: + line[rule.field_id.name] = self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + elif rule.field_id.name == "product_template_id": + if len(parsed_line[i]) == 1 and parsed_line[i]: + product_name = self._parse_data( + parsed_line[i][0], rule.field_id.ttype + ) + elif rule.field_id.relation and rule.field_id.relation == "uom.uom": + if len(parsed_line[i]) == 1 and parsed_line[i]: + uom_id = int(self._search_create_uom(parsed_line[i][0])) + line[rule.field_id.name] = uom_id + if product and product.uom_id and not product.uom_id.id == uom_id: + if created_product: + product.uom_id = uom_id + else: + if uom_id in BC3_PRODUCTS: + product = BC3_PRODUCTS[uom_id] + else: + product = self.env.ref( + "bc3_importer.product_product_product_units" + ) + line["product_id"] = product.id + line["product_uom"] = product.uom_id.id + return product_name + + def _parse_line_t(self, line_t, line): + for t in line_t: + if t.display_type: + line["price_unit"] = 0.0 + line["product_id"] = False + line["product_uom_qty"] = 0.0 + + if "display_type" in line and not t.display_type: + if not t.product_uom_qty > 1: + a = t.read(["sequence", "bc3_code"])[0] + a["order_id"] = self.sale_id.id + a.update(line) + t.unlink() + sale_order_line = self.env["sale.order.line"].create(a) + if ( + sale_order_line.display_type + and sale_order_line.display_type == "line_note" + ): + if "0" in lines: + lines["0"].append(sale_order_line.id) + else: + lines["0"] = [sale_order_line.id] + else: + line["display_type"] = False + t.write(line) + + else: + t.write(line) + if t.display_type and line_t.display_type == "line_note": + if "0" in lines: + lines["0"].append(line_t.id) + else: + lines["0"] = [line_t.id] + + @api.model + def _parse_register_sale_order_line( + self, parsed_line, rules, current_register, red=False + ): + product_name = "" + if len(parsed_line) == len(rules): + # Se busca el codigo del producto + if not len(parsed_line[0]) > 0: + return + if len(parsed_line[0]) > 0 and "%" in parsed_line[0][0]: + return + line_t = self.search_lines(parsed_line[0][0]) + product = self._search_create_product(parsed_line[0]) + if not line_t: + line = { + "name": product.default_code or parsed_line[0], + "product_id": product.id, + "product_uom_qty": 1, + "qty_delivered": 1, + "product_uom": product.uom_id.id, + "order_id": self.sale_id.id, + "sequence": self.sequence, + } + self.sequence += 1 + else: + line = {} + i = len(rules) - 1 + for rule in rules.sorted(key="sequence", reverse=True): + # Sale order line + if rule.model_id.model == "sale.order.line": + product_name = self._parse_register_sale_order_line_sl( + rule, parsed_line, line, i, product_name, product + ) + + elif rule.model_id.model == "product.template": + if len(parsed_line[i]) == 1: + line_type = int(self._parse_data(parsed_line[i][0], "char")) + if line_type == 0 and "##" in parsed_line[0][0]: + line["display_type"] = "line_note" + elif line_type == 0 and "#" in parsed_line[0][0]: + line["display_type"] = "line_section" + i -= 1 + line["name"] = "[" + line["bc3_code"] + "] " + product_name + if self.create_products: + product.name = product_name + if not line_t: + if "display_type" in line: + line["price_unit"] = 0.0 + line["product_id"] = False + line["product_uom_qty"] = 0.0 + sale_order_line = self.env["sale.order.line"].create(line) + if ( + sale_order_line.display_type + and sale_order_line.display_type == "line_note" + ): + if "0" in lines: + lines["0"].append(sale_order_line.id) + else: + lines["0"] = [sale_order_line.id] + else: + self._parse_line_t(line_t, line) + return True + + @api.model + def _parse_data(self, data, field_type): + data = data.replace("\\", "").replace("#", "") + if field_type in ["char", "text"]: + return data + if field_type == "date": + # if odd -> 0 + if not len(data) % 2 == 0: + data += "0" + # AA + if len(data) == 2: + return datetime.strptime(data, "%y").date() + # MMAA + elif len(data) == 4: + return datetime.strptime(data, "%m%y").date() + # DDMMAA + elif len(data) == 6: + return datetime.strptime(data, "%d%m%y").date() + # DDMMAAAA + elif len(data) == 8: + return datetime.strptime(data, "%d%m%Y").date() + return data + return data + + @api.model + def _parse_child_data(self, data, field_type): + if field_type == "char" or field_type == "text": + result = "" + for d in data: + d = d.replace("\\", "").replace("\\\\", "") + result += d + ";" + return result + elif field_type == "float": + if len(data) > 0: + return float(data[-1].replace("\\", "")) + else: + return float(data.replace("\\", "")) + return data + + def _parse_register_data( + self, register_rules, register_line, current_register, model, render_func + ): + i = 0 + regular_expression = [] + parser_result = [] + for r in register_rules.filtered(lambda x: not x.is_child): + regular_expression.append(r.regular_expression) + if len(regular_expression) == len(register_line): + i = 0 + while i < len(regular_expression): + parser_result.append( + self._get_results( + regular_expression[i], register_line[i].replace("\n", "") + ) + ) + i += 1 + else: + raise ValidationError(_("Parsing error, missing data")) + if len(parser_result) > 0: + final_result = [] + for i in parser_result: + if len(i) > 1: + for j in i: + final_result.append(j) + elif not len(i) == 0: + final_result.append(i[0]) + else: + final_result.append([]) + if register_rules[0].register_id.edit_existent: + repeat_value_rule = {} + rule_ids = [] + temp_r = [] + for r in register_rules: + if r.field_ids: + for a in register_rules.filtered( + lambda rule: rule.field_id in r.field_ids + ): + temp_r.append(a) + temp_r.insert(0, r) + repeat_value_rule[r] = temp_r + rule_ids.append(r.id) + rule_ids += register_rules.filtered( + lambda rule: rule.field_id in r.field_ids + ).ids + + render_func = getattr(self, "_parse_register_edit_" + model, None) + if not render_func: + raise UserError(_("Error parsing the file")) + render_func( + final_result, + register_rules, + repeat_value_rule, + rule_ids, + current_register, + ) + return + else: + render_func(final_result, register_rules, current_register) + + def _parse_register(self, line): + register_type = line[0].lower() + current_register = register_type + register_line = ( + line[1:] + .rstrip() + .replace("�", "") + .replace("(", ",") + .replace(")", ",") + .replace("[", ",") + .replace("]", ",") + .strip() + .split("|") + ) + register_rules = ( + self.env["bc3.version.register"] + .search( + [ + ("name", "ilike", register_type), + ("version_id", "=", self.version_id.id), + ], + limit=1, + ) + .rule_ids + ) + + if ( + register_rules + and register_rules[0] + and register_rules[0].register_id.model_id + ): + model = register_rules[0].register_id.model_id.model.replace(".", "_") + register_line.pop(0) + if len(register_line) < len( + register_rules.filtered(lambda x: not x.is_child) + ): + for _i in range( + abs( + len(register_rules.filtered(lambda x: not x.is_child)) + - len(register_line) + ) + ): + register_line.append("") + elif len(register_line) > len( + register_rules.filtered(lambda x: not x.is_child) + ): + for _i in range( + abs( + len(register_rules.filtered(lambda x: not x.is_child)) + - len(register_line) + ) + ): + register_line.pop() + render_func = getattr(self, "_parse_register_" + model, None) + if not render_func: + raise UserError(_("Error parsing the file")) + + self._parse_register_data( + register_rules, register_line, current_register, model, render_func + ) + + # Parseo + def get_groups_matches(self, group_id, check_list, text, group_pattern): + # Hay que revisar las substring: + for a in check_list: + t = text[a[0] : a[1]] + matches = re.finditer(group_pattern[group_id]["expression"], t) + last_index = (0, 0) + for match in matches: + if match.lastindex: + for index in range(1, match.lastindex + 1): + group_pattern[str(group_id)]["groups"].insert( + 0, match.group(index) + ) + if not last_index[0] == match.span(index)[0]: + group_pattern[str(group_id)]["check"].append( + (last_index[0], match.span(index)[0]) + ) + group_pattern[str(group_id)]["check"].remove(a) + if len(group_pattern[group_id]["check"]) > 0: + self.get_groups_matches( + group_id, group_pattern[group_id]["check"], t, group_pattern + ) + else: + return True + + def _parse_matches(self, matches, group_pattern): + for match in matches: + # Recorro los grupos + # Empiezo en 1 porque el primer grupo es todo el match, no me interesa + last_index = (0, 0) + if match.lastindex: + if match.lastindex > 1: + for index in range(1, match.lastindex + 1): + if str(index) in group_pattern and match.group(index): + group_pattern[str(index)]["groups"].append( + match.group(index) + ) + # Es el primer grupo + if index == 1: + last_index = match.span(index) + else: + if not last_index[1] == match.span(index)[0]: + group_pattern[str(index)]["check"].append( + (last_index[1], match.span(index)[0]) + ) + last_index = match.span(index) + else: + for index in range(1, match.lastindex + 1): + if str(index) in group_pattern and match.group(index): + group_pattern[str(index)]["groups"].append( + match.group(index) + ) + if not last_index[1] == match.span(index)[0]: + group_pattern[str(index)]["check"].append( + (last_index[1], match.span(index)[0]) + ) + last_index = match.span(index) + return group_pattern + + def _get_results(self, pattern, text): + text = text.rstrip() + result = [] + if pattern: + pattern_2 = pattern.split("(") + group_pattern = {} + counter = 1 + for p in pattern_2: + if p: + group_pattern[str(counter)] = { + "expression": "(" + p, + "groups": [], + "check": [], + } + counter += 1 + matches = re.finditer(pattern, text) + group_pattern = self._parse_matches(matches, group_pattern) + + # Reviso los checks + for i in group_pattern: + if len(group_pattern[i]["check"]) > 0: + self.get_groups_matches( + i, group_pattern[i]["check"], text, group_pattern + ) + for i in group_pattern: + result.append(group_pattern[i]["groups"]) + return result + + @api.model + def get_uom_products(self): + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_units").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_units") + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_meter").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_meter") + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_square_meter").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_square_meter") + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_cubic_meter").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_cubic_meter") + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_g").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_g") + BC3_PRODUCTS[ + self.env.ref("bc3_importer.product_product_product_l").uom_id.id + ] = self.env.ref("bc3_importer.product_product_product_l") + + @api.model + def line_in_dict(self, code, line_id): + if code in lines and line_id in lines[code]: + return True + return False + + @api.model + def line_in_any_dict(self, line_id): + a = self.env["sale.order.line"].search( + [("order_id", "=", self.sale_id.id), ("id", "=", int(line_id))] + ) + if a: + if a in lines: + return True + else: + for d in lines: + if line_id in lines[d]: + return True + return False diff --git a/bc3_importer/wizard/bc3_import_wizard_views.xml b/bc3_importer/wizard/bc3_import_wizard_views.xml new file mode 100644 index 0000000..a24243c --- /dev/null +++ b/bc3_importer/wizard/bc3_import_wizard_views.xml @@ -0,0 +1,62 @@ + + + + bc3.import.wizard.wizard.form + bc3.import.wizard + +
+ + + + + + + + + + + +
+
+
+
+
+ + Import BC3 File + bc3.import.wizard + form + new + + + + + +
diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..39acb10 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +# generated from manifests external_dependencies +chardet +iteration_utilities diff --git a/setup/bc3_importer/odoo/addons/bc3_importer b/setup/bc3_importer/odoo/addons/bc3_importer new file mode 120000 index 0000000..98e58ed --- /dev/null +++ b/setup/bc3_importer/odoo/addons/bc3_importer @@ -0,0 +1 @@ +../../../../bc3_importer \ No newline at end of file diff --git a/setup/bc3_importer/setup.py b/setup/bc3_importer/setup.py new file mode 100755 index 0000000..28c57bb --- /dev/null +++ b/setup/bc3_importer/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)