From 4787b0c9825fbea03e9b296e8f8e850ca905bf63 Mon Sep 17 00:00:00 2001 From: Tran Anh Tuan Date: Tue, 31 Oct 2023 09:43:24 +0000 Subject: [PATCH] [ADD] base_wamas, base_wamas_ubl: Add new modules to handle the WAMAS document --- .pre-commit-config.yaml | 2 + base_wamas/README.rst | 89 ++ base_wamas/__init__.py | 1 + base_wamas/__manifest__.py | 30 + base_wamas/data/ir_config_parameter_data.xml | 29 + .../wamas_document_default_field_data.xml | 55 + ...s_document_default_field_template_data.xml | 36 + ...ument_default_field_template_line_data.xml | 204 +++ .../data/wamas_document_element_data.xml | 146 ++ base_wamas/data/wamas_document_field_data.xml | 799 ++++++++++ .../data/wamas_document_template_data.xml | 28 + base_wamas/models/__init__.py | 7 + .../models/wamas_document_default_field.py | 11 + .../wamas_document_default_field_template.py | 18 + ...as_document_default_field_template_line.py | 17 + base_wamas/models/wamas_document_element.py | 129 ++ base_wamas/models/wamas_document_field.py | 279 ++++ base_wamas/models/wamas_document_template.py | 84 + .../models/wamas_document_template_line.py | 14 + base_wamas/readme/CONTRIBUTORS.rst | 2 + base_wamas/readme/CREDITS.rst | 1 + base_wamas/readme/DESCRIPTION.rst | 7 + base_wamas/security/ir_model_access.xml | 96 ++ base_wamas/static/description/index.html | 435 ++++++ base_wamas/tests/__init__.py | 1 + base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt | 6 + base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt | 6 + base_wamas/tests/test_base_wamas.py | 68 + ..._document_default_field_template_views.xml | 73 + .../wamas_document_default_field_views.xml | 71 + .../views/wamas_document_element_views.xml | 67 + .../views/wamas_document_field_views.xml | 86 ++ .../views/wamas_document_template_views.xml | 60 + base_wamas/views/wamas_menus.xml | 79 + base_wamas_ubl/README.rst | 85 ++ base_wamas_ubl/__init__.py | 1 + base_wamas_ubl/__manifest__.py | 30 + .../data/ir_actions_server_data.xml | 196 +++ .../data/ir_config_parameter_data.xml | 9 + ...s_document_default_field_template_data.xml | 76 + .../data/wamas_document_element_data.xml | 8 + .../data/wamas_document_field_data.xml | 292 ++++ ...mas_document_xml_conversion_field_data.xml | 1348 +++++++++++++++++ ..._document_xml_conversion_template_data.xml | 35 + base_wamas_ubl/models/__init__.py | 5 + ...as_document_default_field_template_line.py | 14 + .../models/wamas_document_element.py | 76 + base_wamas_ubl/models/wamas_document_field.py | 18 + .../wamas_document_xml_conversion_field.py | 219 +++ .../wamas_document_xml_conversion_template.py | 342 +++++ base_wamas_ubl/readme/CONTRIBUTORS.rst | 2 + base_wamas_ubl/readme/CREDITS.rst | 1 + base_wamas_ubl/readme/DESCRIPTION.rst | 4 + base_wamas_ubl/security/ir_model_access.xml | 40 + base_wamas_ubl/static/description/index.html | 431 ++++++ base_wamas_ubl/tests/__init__.py | 1 + .../WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml | 129 ++ .../files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt | 6 + .../XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml | 145 ++ .../files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt | 6 + base_wamas_ubl/tests/test_base_wamas_ubl.py | 60 + ..._document_default_field_template_views.xml | 30 + .../views/wamas_document_element_views.xml | 21 + .../views/wamas_document_field_views.xml | 21 + ...as_document_xml_conversion_field_views.xml | 79 + ...document_xml_conversion_template_views.xml | 113 ++ base_wamas_ubl/views/wamas_menus.xml | 13 + setup/base_wamas/odoo/addons/base_wamas | 1 + setup/base_wamas/setup.py | 6 + .../base_wamas_ubl/odoo/addons/base_wamas_ubl | 1 + setup/base_wamas_ubl/setup.py | 6 + 71 files changed, 6906 insertions(+) create mode 100644 base_wamas/README.rst create mode 100644 base_wamas/__init__.py create mode 100644 base_wamas/__manifest__.py create mode 100644 base_wamas/data/ir_config_parameter_data.xml create mode 100644 base_wamas/data/wamas_document_default_field_data.xml create mode 100644 base_wamas/data/wamas_document_default_field_template_data.xml create mode 100644 base_wamas/data/wamas_document_default_field_template_line_data.xml create mode 100644 base_wamas/data/wamas_document_element_data.xml create mode 100644 base_wamas/data/wamas_document_field_data.xml create mode 100644 base_wamas/data/wamas_document_template_data.xml create mode 100644 base_wamas/models/__init__.py create mode 100644 base_wamas/models/wamas_document_default_field.py create mode 100644 base_wamas/models/wamas_document_default_field_template.py create mode 100644 base_wamas/models/wamas_document_default_field_template_line.py create mode 100644 base_wamas/models/wamas_document_element.py create mode 100644 base_wamas/models/wamas_document_field.py create mode 100644 base_wamas/models/wamas_document_template.py create mode 100644 base_wamas/models/wamas_document_template_line.py create mode 100644 base_wamas/readme/CONTRIBUTORS.rst create mode 100644 base_wamas/readme/CREDITS.rst create mode 100644 base_wamas/readme/DESCRIPTION.rst create mode 100644 base_wamas/security/ir_model_access.xml create mode 100644 base_wamas/static/description/index.html create mode 100644 base_wamas/tests/__init__.py create mode 100644 base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt create mode 100644 base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt create mode 100644 base_wamas/tests/test_base_wamas.py create mode 100644 base_wamas/views/wamas_document_default_field_template_views.xml create mode 100644 base_wamas/views/wamas_document_default_field_views.xml create mode 100644 base_wamas/views/wamas_document_element_views.xml create mode 100644 base_wamas/views/wamas_document_field_views.xml create mode 100644 base_wamas/views/wamas_document_template_views.xml create mode 100644 base_wamas/views/wamas_menus.xml create mode 100644 base_wamas_ubl/README.rst create mode 100644 base_wamas_ubl/__init__.py create mode 100644 base_wamas_ubl/__manifest__.py create mode 100644 base_wamas_ubl/data/ir_actions_server_data.xml create mode 100644 base_wamas_ubl/data/ir_config_parameter_data.xml create mode 100644 base_wamas_ubl/data/wamas_document_default_field_template_data.xml create mode 100644 base_wamas_ubl/data/wamas_document_element_data.xml create mode 100644 base_wamas_ubl/data/wamas_document_field_data.xml create mode 100644 base_wamas_ubl/data/wamas_document_xml_conversion_field_data.xml create mode 100644 base_wamas_ubl/data/wamas_document_xml_conversion_template_data.xml create mode 100644 base_wamas_ubl/models/__init__.py create mode 100644 base_wamas_ubl/models/wamas_document_default_field_template_line.py create mode 100644 base_wamas_ubl/models/wamas_document_element.py create mode 100644 base_wamas_ubl/models/wamas_document_field.py create mode 100644 base_wamas_ubl/models/wamas_document_xml_conversion_field.py create mode 100644 base_wamas_ubl/models/wamas_document_xml_conversion_template.py create mode 100644 base_wamas_ubl/readme/CONTRIBUTORS.rst create mode 100644 base_wamas_ubl/readme/CREDITS.rst create mode 100644 base_wamas_ubl/readme/DESCRIPTION.rst create mode 100644 base_wamas_ubl/security/ir_model_access.xml create mode 100644 base_wamas_ubl/static/description/index.html create mode 100644 base_wamas_ubl/tests/__init__.py create mode 100644 base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml create mode 100644 base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt create mode 100644 base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml create mode 100644 base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt create mode 100644 base_wamas_ubl/tests/test_base_wamas_ubl.py create mode 100644 base_wamas_ubl/views/wamas_document_default_field_template_views.xml create mode 100644 base_wamas_ubl/views/wamas_document_element_views.xml create mode 100644 base_wamas_ubl/views/wamas_document_field_views.xml create mode 100644 base_wamas_ubl/views/wamas_document_xml_conversion_field_views.xml create mode 100644 base_wamas_ubl/views/wamas_document_xml_conversion_template_views.xml create mode 100644 base_wamas_ubl/views/wamas_menus.xml create mode 120000 setup/base_wamas/odoo/addons/base_wamas create mode 100644 setup/base_wamas/setup.py create mode 120000 setup/base_wamas_ubl/odoo/addons/base_wamas_ubl create mode 100644 setup/base_wamas_ubl/setup.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73cac03550..41a06aa928 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,8 @@ exclude: | .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| # Maybe reactivate this when all README files include prettier ignore tags? ^README\.md$| + # Ignore the text files + /tests/.*\.(txt|xml)| # Library files can have extraneous formatting (even minimized) /static/(src/)?lib/| # Repos using Sphinx to generate docs don't need prettying diff --git a/base_wamas/README.rst b/base_wamas/README.rst new file mode 100644 index 0000000000..aefab5ee7c --- /dev/null +++ b/base_wamas/README.rst @@ -0,0 +1,89 @@ +========== +Base WAMAS +========== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:35bce522f6b089d82e4cfb4203e72324a0f14cb96e19cea30a55d8d3040c316e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github + :target: https://github.com/OCA/edi/tree/16.0/base_wamas + :alt: OCA/edi +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-base_wamas + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Provides following models: + +* WAMAS Document Template, to define WAMAS document, it includes WAMAS document elements. +* WAMAS Document Element, to define elements in WAMAS document, such as: WEAK, WEAP... +* WAMAS Document Field, to define fields that WAMAS elment has, there are a lot of fields in a WAMAS element. +* WAMAS Document Default Field, to define default fields of WAMAS document has. +* WAMAS Document Default Field Template, to define the template of default fields of the elements. + +**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 +~~~~~~~ + +* BCIM +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Jacques-Etienne Baudoux +* Tuan Tran + +Other credits +~~~~~~~~~~~~~ + +The creation of this module was financially supported by Camptocamp. + +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/edi `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_wamas/__init__.py b/base_wamas/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/base_wamas/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/base_wamas/__manifest__.py b/base_wamas/__manifest__.py new file mode 100644 index 0000000000..def07c7e70 --- /dev/null +++ b/base_wamas/__manifest__.py @@ -0,0 +1,30 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Base WAMAS", + "summary": """Base module to aggregate WAMAS features.""", + "version": "16.0.1.0.0", + "development_status": "Beta", + "website": "https://github.com/OCA/edi", + "license": "AGPL-3", + "author": "BCIM,Camptocamp,Odoo Community Association (OCA)", + "depends": ["base_edi"], + "data": [ + "security/ir_model_access.xml", + "data/ir_config_parameter_data.xml", + "data/wamas_document_field_data.xml", + "data/wamas_document_default_field_data.xml", + "data/wamas_document_default_field_template_data.xml", + "data/wamas_document_default_field_template_line_data.xml", + "data/wamas_document_element_data.xml", + "data/wamas_document_template_data.xml", + "views/wamas_document_template_views.xml", + "views/wamas_document_element_views.xml", + "views/wamas_document_field_views.xml", + "views/wamas_document_default_field_views.xml", + "views/wamas_document_default_field_template_views.xml", + "views/wamas_menus.xml", + ], +} diff --git a/base_wamas/data/ir_config_parameter_data.xml b/base_wamas/data/ir_config_parameter_data.xml new file mode 100644 index 0000000000..9a7f03598f --- /dev/null +++ b/base_wamas/data/ir_config_parameter_data.xml @@ -0,0 +1,29 @@ + + + + + wamas_document_default_field_type + Sentence Type + + + + wamas_document_list_false_value + ["n", "nein", "non", "no", "none", "f", "false"] + + + + wamas_document_list_true_value + ["j", "ja", "o", "oui", "t", "true", "y", "yes"] + + + + wamas_document_default_false_value + "N" + + + + wamas_document_default_true_value + "J" + + + diff --git a/base_wamas/data/wamas_document_default_field_data.xml b/base_wamas/data/wamas_document_default_field_data.xml new file mode 100644 index 0000000000..e6a194cfba --- /dev/null +++ b/base_wamas/data/wamas_document_default_field_data.xml @@ -0,0 +1,55 @@ + + + + + Source + Source + str + 10 + + + + Destination + Destination + str + 10 + + + + Telegram Sequence + Telegram Sequence + int + 6 + 30 + + + + Creation Time + Creation Time + datetime + 14 + + + + Sentence Type + Sentence Type + str + 9 + + + diff --git a/base_wamas/data/wamas_document_default_field_template_data.xml b/base_wamas/data/wamas_document_default_field_template_data.xml new file mode 100644 index 0000000000..48bec71473 --- /dev/null +++ b/base_wamas/data/wamas_document_default_field_template_data.xml @@ -0,0 +1,36 @@ + + + + + Default Field Template - WEAK + Default Field Template - WEAK + + + + Default Field Template - WEAP + Default Field Template - WEAP + + + + Default Field Template - WEAKQ + Default Field Template - WEAKQ + + + + Default Field Template - WEAPQ + Default Field Template - WEAPQ + + + diff --git a/base_wamas/data/wamas_document_default_field_template_line_data.xml b/base_wamas/data/wamas_document_default_field_template_line_data.xml new file mode 100644 index 0000000000..84c6406348 --- /dev/null +++ b/base_wamas/data/wamas_document_default_field_template_line_data.xml @@ -0,0 +1,204 @@ + + + + + + + 10 + + + + + + 20 + + + + + + 30 + + + + + + 40 + + + + + + 50 + + + + + + + + 10 + + + + + + 20 + + + + + + 30 + + + + + + 40 + + + + + + 50 + + + + + + + + 10 + + + + + + 20 + + + + + + 30 + + + + + + 40 + + + + + + 50 + + + + + + + + 10 + + + + + + 20 + + + + + + 30 + + + + + + 40 + + + + + + 50 + + + + + diff --git a/base_wamas/data/wamas_document_element_data.xml b/base_wamas/data/wamas_document_element_data.xml new file mode 100644 index 0000000000..0c0528926b --- /dev/null +++ b/base_wamas/data/wamas_document_element_data.xml @@ -0,0 +1,146 @@ + + + + + WEAK + WEAK + + + + + + WEAP + WEAP + + + + + + WEAKQ + WEAKQ + + + + + + WEAPQ + WEAPQ + + + + + diff --git a/base_wamas/data/wamas_document_field_data.xml b/base_wamas/data/wamas_document_field_data.xml new file mode 100644 index 0000000000..141d0a18eb --- /dev/null +++ b/base_wamas/data/wamas_document_field_data.xml @@ -0,0 +1,799 @@ + + + + + + + Client + Client + str + 3 + 60 + + + + EM Notice Number + EM Notice Number + str + 20 + 70 + + + + EM Host Review Code + EM Host Review Code + str + 5 + 80 + + + + External Reference + External Reference + str + 20 + 90 + + + + EM Notice Type + EM Notice Type + str + 6 + 100 + + + + Mand. Supplier + Mand. Supplier + str + 3 + 110 + + + + Supplier Number + Supplier Number + str + 13 + 120 + + + + Name + Name + str + 40 + 130 + + + + Name 2 + Name 2 + str + 40 + 140 + + + + Name 3 + Name 3 + str + 40 + 150 + + + + Name 4 + Name 4 + str + 40 + 160 + + + + Call Form + Call Form + str + 15 + 170 + + + + Address + Address + str + 40 + 180 + + + + Address 2 + Address 2 + str + 40 + 190 + + + + Postal Code + Postal Code + str + 10 + 200 + + + + Location + Location + str + 40 + 210 + + + + District + District + str + 40 + 220 + + + + Country + Country + str + 4 + 230 + + + + Phone Number + Phone Number + str + 35 + 240 + + + + Fax Number + Fax Number + str + 35 + 250 + + + + Email + Email + str + 40 + 260 + + + + Home Page + Home Page + str + 35 + 270 + + + + ILN/GLN + ILN/GLN + str + 13 + 280 + + + + Order Date + Order Date + datetime + 14 + 290 + + + + Information for WAMAS + Information for WAMAS + str + 77 + 300 + + + + + + Client + Client + str + 3 + 60 + + + + EM Notice Number + EM Notice Number + str + 20 + 70 + + + + EM Host Review Code + EM Host Review Code + str + 5 + 80 + + + + External Reference + External Reference + str + 20 + 90 + + + + HOST-PosNr + HOST-PosNr + str + 6 + 100 + + + + Client 2 + Client 2 + str + 3 + 110 + + + + Item Number + Item Number + str + 20 + 120 + + + + Variant + Variant + str + 5 + 130 + + + + Batch + Batch + str + 20 + 140 + + + + DLC + DLC + date + 8 + 150 + + + + Booking Number + Booking Number + str + 20 + 160 + + + + KZ Transport Assistance + KZ Transport Assistance + bool + 1 + 170 + + + + Material Qualifier 1 + Material Qualifier 1 + str + 20 + 180 + + + + Material Qualifier 2 + Material Qualifier 2 + str + 20 + 190 + + + + Material Qualifier 3 + Material Qualifier 3 + str + 20 + 200 + + + + Ordered Quantity + Ordered Quantity + float + 12 + 3 + 210 + + + + Order Unit + Order Unit + str + 5 + 220 + + + + TypePos-EM + TypePos-EM + str + 7 + 230 + + + + Notified Delivery Date + Notified Delivery Date + datetime + 14 + 240 + + + + Notified Delivery Note Number + Notified Delivery Note Number + str + 20 + 250 + + + + Notified Delivery Note Date + Notified Delivery Note Date + datetime + 14 + 260 + + + + Supplier Item Number + Supplier Item Number + str + 20 + 270 + + + + Sentence ID + Sentence ID + str + 1 + 280 + + + + Position Finished + Position Finished + bool + 1 + 290 + + + + Feedback + Feedback + str + 3 + 300 + + + + Serial Number + Serial Number + str + 20 + 310 + + + + Information for WAMAS + Information for WAMAS + str + 77 + 320 + + + + + + Client + Client + str + 3 + 60 + + + + EM Transaction Number + EM Transaction Number + str + 20 + 70 + + + + EM Notice ID for Host + EM Notice ID for Host + str + 5 + 80 + + + + Delivery Date + Delivery Date + datetime + 14 + 90 + + + + Truck Driver + Truck Driver + str + 40 + 100 + + + + Truck License Plate + Truck License Plate + str + 10 + 110 + + + + Truck Entry Time + Truck Entry Time + datetime + 14 + 120 + + + + Start Time + Start Time + datetime + 14 + 130 + + + + Finish Time + Finish Time + datetime + 14 + 140 + + + + Registration Time + Registration Time + datetime + 14 + 150 + + + + Host Information + Host Information + str + 77 + 160 + + + + Mand. Supplier + Mand. Supplier + str + 3 + 170 + + + + Vendor Code + Vendor Code + str + 13 + 180 + + + + + + Client + Client + str + 3 + 60 + + + + EM Transaction Number + EM Transaction Number + str + 20 + 70 + + + + Client 2 + Client 2 + str + 3 + 80 + + + + EM Notice Number + EM Notice Number + str + 20 + 90 + + + + EM Notice ID for Host + EM Notice ID for Host + str + 5 + 100 + + + + External Reference + External Reference + str + 20 + 110 + + + + HOST-PosNr + HOST-PosNr + str + 6 + 120 + + + + Delivery Note Number + Delivery Note Number + str + 20 + 130 + + + + Client 3 + Client 3 + str + 3 + 140 + + + + Item Number + Item Number + str + 20 + 150 + + + + Variant + Variant + str + 5 + 160 + + + + Host Material Qualification ID + Host Material Qualification ID + str + 20 + 170 + + + + Quantity + Quantity + float + 12 + 3 + 180 + + + + Weight + Weight + float + 12 + 3 + 190 + + + + HOST Weight Unit + HOST Weight Unit + str + 5 + 200 + + + + Stock Unit + Stock Unit + str + 5 + 210 + + + + Batch + Batch + str + 20 + 220 + + + + DLC + DLC + date + 8 + 230 + + + + Booking Number + Booking Number + str + 20 + 240 + + + + EM Number + EM Number + str + 20 + 250 + + + + KZ Transport Assistance + KZ Transport Assistance + bool + 1 + 260 + + + diff --git a/base_wamas/data/wamas_document_template_data.xml b/base_wamas/data/wamas_document_template_data.xml new file mode 100644 index 0000000000..30a779e627 --- /dev/null +++ b/base_wamas/data/wamas_document_template_data.xml @@ -0,0 +1,28 @@ + + + + + WEAK - WEAP + WEAK - WEAP + + + + + WEAKQ - WEAPQ + WEAKQ - WEAPQ + + + + diff --git a/base_wamas/models/__init__.py b/base_wamas/models/__init__.py new file mode 100644 index 0000000000..b2bb5f862f --- /dev/null +++ b/base_wamas/models/__init__.py @@ -0,0 +1,7 @@ +from . import wamas_document_field +from . import wamas_document_default_field +from . import wamas_document_default_field_template +from . import wamas_document_default_field_template_line +from . import wamas_document_element +from . import wamas_document_template +from . import wamas_document_template_line diff --git a/base_wamas/models/wamas_document_default_field.py b/base_wamas/models/wamas_document_default_field.py new file mode 100644 index 0000000000..5dcae2749c --- /dev/null +++ b/base_wamas/models/wamas_document_default_field.py @@ -0,0 +1,11 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class WamasDocumentDefaultField(models.Model): + _name = "wamas.document.default.field" + _inherit = "wamas.document.field" + _description = "WAMAS Document Default Field" diff --git a/base_wamas/models/wamas_document_default_field_template.py b/base_wamas/models/wamas_document_default_field_template.py new file mode 100644 index 0000000000..af9199b160 --- /dev/null +++ b/base_wamas/models/wamas_document_default_field_template.py @@ -0,0 +1,18 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class WamasDocumentDefaultField(models.Model): + _name = "wamas.document.default.field.template" + _description = "WAMAS Document Default Field Template" + + name = fields.Char(required=True) + code = fields.Char(required=True) + line_ids = fields.One2many( + "wamas.document.default.field.template.line", + "template_id", + "Lines of Default Fields", + ) diff --git a/base_wamas/models/wamas_document_default_field_template_line.py b/base_wamas/models/wamas_document_default_field_template_line.py new file mode 100644 index 0000000000..1a6fb5b016 --- /dev/null +++ b/base_wamas/models/wamas_document_default_field_template_line.py @@ -0,0 +1,17 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class WamasDocumentDefaultFieldLine(models.Model): + _name = "wamas.document.default.field.template.line" + _description = "WAMAS Document Default Field Template Line" + _rec_name = "df_field_id" + + df_field_id = fields.Many2one( + "wamas.document.default.field", "Default Field", required=True + ) + sequence = fields.Integer(required=True, default=10) + template_id = fields.Many2one("wamas.document.default.field.template", "Template") diff --git a/base_wamas/models/wamas_document_element.py b/base_wamas/models/wamas_document_element.py new file mode 100644 index 0000000000..c184271b52 --- /dev/null +++ b/base_wamas/models/wamas_document_element.py @@ -0,0 +1,129 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from collections import OrderedDict + +from odoo import _, fields, models +from odoo.exceptions import UserError + +from ..models.wamas_document_template import check_type_of_item + + +def get_item(recordset_field, row, idx_start, res, convert_type): + for field in recordset_field: + if field._name == "wamas.document.default.field.template.line": + field = field.df_field_id + + idx_end = idx_start + field.len_field + + val = row[idx_start:idx_end] + if convert_type: + val = field.get_value_from_string(val) + + if isinstance(res, OrderedDict): + res[field.code] = val + elif isinstance(res, list): + res.append((field.code, val)) + + idx_start = idx_end + + return res, idx_start + + +class WamasDocumentElement(models.Model): + _name = "wamas.document.element" + _description = "WAMAS Document Element" + + name = fields.Char(required=True) + code = fields.Char(required=True) + df_field_template_id = fields.Many2one( + "wamas.document.default.field.template", "Default Field Template", required=True + ) + field_ids = fields.One2many("wamas.document.field", "element_id", "Fields") + + def get_values_from_element( + self, row, convert_type=False, result_type="ordered_dict" + ): + self.ensure_one() + + res = False + + if result_type == "list_tuple": + res = [] + elif result_type == "ordered_dict": + res = OrderedDict() + idx = 0 + + # Get value from `row` for `default fields` + sorted_fields = self.df_field_template_id.line_ids.sorted( + key=lambda r: r.sequence + ) + res, idx = get_item(sorted_fields, row, idx, res, convert_type) + + # Get value from `row` for `fields` + sorted_fields = self.field_ids.sorted(key=lambda r: r.sequence) + res, idx = get_item(sorted_fields, row, idx, res, convert_type) + + return res + + def set_values_to_element(self, items): + self.ensure_one() + + res = "" + + item_type = check_type_of_item(items) + if not item_type: + raise UserError( + _( + "The input must be the list of tuples OR " + "the the list of ordered dictionary!" + ) + ) + + for item in items: + if item_type == "list_tuple": + _key = item[0] + _value = item[1] + elif item_type == "ordered_dict": + _key = item + _value = items[_key] + + for line in self.df_field_template_id.line_ids: + df_field = line.df_field_id + + if _key == df_field.code: + res += df_field.set_value_to_string(_value) + + for field in self.field_ids: + if _key == field.code: + a1 = field.set_value_to_string(_value) + res += a1 + + return res + + def get_index_of_field_type(self): + self.ensure_one() + + idx_start = False + idx_end = False + + default_field_type = self.env["ir.config_parameter"].get_param( + "wamas_document_default_field_type", "Sentence Type" + ) + line_of_field_type = self.df_field_template_id.line_ids.filtered( + lambda r: r.df_field_id.code == default_field_type + ) + + if line_of_field_type: + field_type = line_of_field_type.df_field_id + + filtered_lines = self.df_field_template_id.line_ids.filtered( + lambda r: r.sequence < line_of_field_type.sequence + ) + + if filtered_lines: + idx_start = sum([line.df_field_id.len_field for line in filtered_lines]) + idx_end = idx_start + field_type.len_field + + return idx_start, idx_end diff --git a/base_wamas/models/wamas_document_field.py b/base_wamas/models/wamas_document_field.py new file mode 100644 index 0000000000..9f226c0055 --- /dev/null +++ b/base_wamas/models/wamas_document_field.py @@ -0,0 +1,279 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import date, datetime + +from dateutil.parser import parse + +from odoo import _, fields, models +from odoo.exceptions import UserError +from odoo.tools.safe_eval import safe_eval + +FIELD_TYPES = [ + ("str", "String"), + ("int", "Integer"), + ("float", "Float"), + ("date", "Date"), + ("datetime", "Datetime"), + ("bool", "Boolean"), +] + + +def is_date(string, fuzzy=False): + """ + Return whether the string can be interpreted as a date. + + :param string: str, string to check for date + :param fuzzy: bool, ignore unknown tokens in string if True + """ + try: + parse(string, fuzzy=fuzzy) + return True + + except ValueError: + return False + + +class WamasDocumentField(models.Model): + _name = "wamas.document.field" + _description = "WAMAS Document Field" + + name = fields.Char(required=True) + code = fields.Char(required=True) + ttype = fields.Selection(FIELD_TYPES, "Type", required=True) + len_field = fields.Integer("Length", required=True) + decimal_place = fields.Integer() + sequence = fields.Integer(required=True, default=10) + element_id = fields.Many2one("wamas.document.element", "Element") + + def get_value_from_string(self, value): + self.ensure_one() + + res = value + + if self.ttype == "str": + res = self._get_string(value) + elif self.ttype == "int": + res = self._get_int(value) + elif self.ttype == "float": + res = self._get_float(value) + elif self.ttype == "date": + res = self._get_date(value) + elif self.ttype == "datetime": + res = self._get_datetime(value) + elif self.ttype == "bool": + res = self._get_bool(value) + + return res + + def set_value_to_string(self, value): + self.ensure_one() + + res = value + + if self.ttype == "str": + res = self._set_from_string(value) + elif self.ttype == "int": + res = self._set_from_int(value) + elif self.ttype == "float": + res = self._set_from_float(value) + elif self.ttype == "date": + res = self._set_from_date(value) + elif self.ttype == "datetime": + res = self._set_from_datetime(value) + elif self.ttype == "bool": + res = self._set_from_bool(value) + + return res + + def _get_string(self, value): + self.ensure_one() + + res = value.strip() + + return res + + def _get_int(self, value): + self.ensure_one() + + res = value.strip() + + try: + res = int(res) + except TypeError: # pylint: disable=except-pass + pass + + return res + + def _get_float(self, value): + self.ensure_one() + + res = value.strip() + + try: + if len(res) >= self.len_field: + str_whole_number = res[: self.len_field - self.decimal_place] + str_decimal_portion = res[self.decimal_place * -1 :] + + res = str_whole_number + "." + str_decimal_portion + + res = float(res.strip()) + except TypeError: # pylint: disable=except-pass + pass + + return res + + def _get_date(self, value): + self.ensure_one() + + res = value.strip() + + try: + if res: + res = parse(res).date() + except TypeError: # pylint: disable=except-pass + pass + + return res + + def _get_datetime(self, value): + self.ensure_one() + + res = value.strip() + + try: + if res: + res = parse(res) + except TypeError: # pylint: disable=except-pass + pass + + return res + + def _get_bool(self, value): + self.ensure_one() + + res = value.strip() + + ICP = self.env["ir.config_parameter"] + lst_false = safe_eval(ICP.get_param("wamas_document_list_false_value", ["f"])) + lst_true = safe_eval(ICP.get_param("wamas_document_list_true_value", ["t"])) + + try: + if value.lower() in lst_false: + res = False + elif value.lower() in lst_true: + res = True + except TypeError: # pylint: disable=except-pass + pass + + return res + + def _set_from_string(self, value): + self.ensure_one() + + res = str(value).ljust(self.len_field)[: self.len_field] + + return res + + def _set_from_int(self, value): + self.ensure_one() + + res = str(value).rjust(self.len_field, "0")[: self.len_field] + + return res + + def _set_from_float(self, value): + self.ensure_one() + + res = str(float(value)) + + # Check if it is int / float or not + if not res.replace(".", "", 1).isdigit(): + raise UserError( + _( + "The value '%s' is not the float type. " + "Please check it again!" % res + ) + ) + + str_whole_number, str_decimal_portion = res.split(".") + + str_whole_number = str_whole_number.rjust( + self.len_field - self.decimal_place, "0" + ) + str_decimal_portion = str_decimal_portion.ljust(self.decimal_place, "0") + + res = (str_whole_number + str_decimal_portion)[: self.len_field] + + return res + + def _set_from_date(self, value): + self.ensure_one() + + res = value + + if isinstance(res, date): + res = res.strftime("%Y%m%d") + elif isinstance(res, datetime): + res = res.date().strftime("%Y%m%d") + elif isinstance(res, str): + if res == "": + res = res.ljust(self.len_field) + elif not is_date(res): + raise UserError( + _( + "The value '%s' is not the date type. " + "Please check it again!" % value + ) + ) + else: + res = str(value).ljust(self.len_field) + + res = res[: self.len_field] + + return res + + def _set_from_datetime(self, value): + self.ensure_one() + + res = value + + if isinstance(res, (date, datetime)): + res = res.strftime("%Y%m%d%H%M%S") + elif isinstance(res, str): + if res == "": + res = res.ljust(self.len_field) + elif not is_date(res): + raise UserError( + _( + "The value '%s' is not the datetime type. " + "Please check it again!" % value + ) + ) + else: + res = str(value).ljust(self.len_field) + + res = res[: self.len_field] + + return res + + def _set_from_bool(self, value): + self.ensure_one() + + ICP = self.env["ir.config_parameter"] + default_false_value = safe_eval( + ICP.get_param("wamas_document_default_false_value", "F") + ) + default_true_value = safe_eval( + ICP.get_param("wamas_document_default_true_value", "T") + ) + + res = default_false_value + + if value: + res = default_true_value + + res = res[: self.len_field] + + return res diff --git a/base_wamas/models/wamas_document_template.py b/base_wamas/models/wamas_document_template.py new file mode 100644 index 0000000000..087e2bcdd5 --- /dev/null +++ b/base_wamas/models/wamas_document_template.py @@ -0,0 +1,84 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from collections import OrderedDict + +from odoo import _, fields, models +from odoo.exceptions import UserError + + +def check_type_of_item(items): + res = False + + if isinstance(items, list): + res = "list_tuple" + elif isinstance(items, OrderedDict): + res = "ordered_dict" + + return res + + +class WamasDocumentTemplate(models.Model): + _name = "wamas.document.template" + _description = "WAMAS Document Template" + + name = fields.Char(required=True) + code = fields.Char(required=True) + line_ids = fields.One2many( + "wamas.document.template.line", "template_id", "Lines of Elements" + ) + + def get_proper_element_from_row(self, row): + self.ensure_one() + res = False + + for line in self.line_ids: + element = line.element_id + + idx_start, idx_end = element.get_index_of_field_type() + + if idx_start and idx_end: + str_row_type = row[idx_start:idx_end] + + if str_row_type and element.code in str_row_type: + res = element + break + + return res + + def get_proper_element_from_items(self, items): + self.ensure_one() + + res = False + + item_type = check_type_of_item(items) + if not item_type: + raise UserError( + _( + "The input must be the list of tuples OR " + "the the list of ordered dictionary!" + ) + ) + + default_field_type = self.env["ir.config_parameter"].get_param( + "wamas_document_default_field_type", "Sentence Type" + ) + + for item in items: + if item_type == "list_tuple": + _key = item[0] + _value = item[1] + elif item_type == "ordered_dict": + _key = item + _value = items[_key] + + if _key == default_field_type: + found_line = self.line_ids.filtered( + lambda r: r.element_id.code in _value + ) + + if found_line: + res = found_line.element_id + + return res diff --git a/base_wamas/models/wamas_document_template_line.py b/base_wamas/models/wamas_document_template_line.py new file mode 100644 index 0000000000..b06d019ae6 --- /dev/null +++ b/base_wamas/models/wamas_document_template_line.py @@ -0,0 +1,14 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class WamasDocumentTemplateLine(models.Model): + _name = "wamas.document.template.line" + _description = "WAMAS Document Template Line" + + element_id = fields.Many2one("wamas.document.element", required=True) + sequence = fields.Integer(required=True, default=10) + template_id = fields.Many2one("wamas.document.template", "Template") diff --git a/base_wamas/readme/CONTRIBUTORS.rst b/base_wamas/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..0ab51a38a2 --- /dev/null +++ b/base_wamas/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Jacques-Etienne Baudoux +* Tuan Tran diff --git a/base_wamas/readme/CREDITS.rst b/base_wamas/readme/CREDITS.rst new file mode 100644 index 0000000000..ac19123b04 --- /dev/null +++ b/base_wamas/readme/CREDITS.rst @@ -0,0 +1 @@ +The creation of this module was financially supported by Camptocamp. diff --git a/base_wamas/readme/DESCRIPTION.rst b/base_wamas/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..f34d7d0ae2 --- /dev/null +++ b/base_wamas/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +Provides following models: + +* WAMAS Document Template, to define WAMAS document, it includes WAMAS document elements. +* WAMAS Document Element, to define elements in WAMAS document, such as: WEAK, WEAP... +* WAMAS Document Field, to define fields that WAMAS elment has, there are a lot of fields in a WAMAS element. +* WAMAS Document Default Field, to define default fields of WAMAS document has. +* WAMAS Document Default Field Template, to define the template of default fields of the elements. diff --git a/base_wamas/security/ir_model_access.xml b/base_wamas/security/ir_model_access.xml new file mode 100644 index 0000000000..9396473102 --- /dev/null +++ b/base_wamas/security/ir_model_access.xml @@ -0,0 +1,96 @@ + + + + + Access WAMAS Document Template - EDI Manager + + + + + + + + + + Access WAMAS Document Template Line - EDI Manager + + + + + + + + + + Access WAMAS Document Element - EDI Manager + + + + + + + + + + Access WAMAS Document Field - EDI Manager + + + + + + + + + + Access WAMAS Document Default Field - EDI Manager + + + + + + + + + + Access WAMAS Document Default Field Template Line - EDI Manager + + + + + + + + + + Access WAMAS Document Default Field Template - EDI Manager + + + + + + + + + diff --git a/base_wamas/static/description/index.html b/base_wamas/static/description/index.html new file mode 100644 index 0000000000..f6ee9e19f7 --- /dev/null +++ b/base_wamas/static/description/index.html @@ -0,0 +1,435 @@ + + + + + + +Base WAMAS + + + +
+

Base WAMAS

+ + +

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

+

Provides following models:

+
    +
  • WAMAS Document Template, to define WAMAS document, it includes WAMAS document elements.
  • +
  • WAMAS Document Element, to define elements in WAMAS document, such as: WEAK, WEAP…
  • +
  • WAMAS Document Field, to define fields that WAMAS elment has, there are a lot of fields in a WAMAS element.
  • +
  • WAMAS Document Default Field, to define default fields of WAMAS document has.
  • +
  • WAMAS Document Default Field Template, to define the template of default fields of the elements.
  • +
+

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

+
    +
  • BCIM
  • +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The creation of this module was financially supported by Camptocamp.

+
+
+

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/edi project on GitHub.

+

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

+
+
+
+ + diff --git a/base_wamas/tests/__init__.py b/base_wamas/tests/__init__.py new file mode 100644 index 0000000000..97ff99b302 --- /dev/null +++ b/base_wamas/tests/__init__.py @@ -0,0 +1 @@ +from . import test_base_wamas diff --git a/base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt b/base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt new file mode 100644 index 0000000000..943e40db56 --- /dev/null +++ b/base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt @@ -0,0 +1,6 @@ +WAMAS SYSTEM1 00000120230501065723WEAKQ0051000196241 HOST 20230501060217 19700101010000202305010609112023050106433920230501060221 0001040 +WAMAS SYSTEM1 00000220230501065723WEAPQ0050000196241 000123477 HOST 00002045415 0001111 00000DISPONIBLE 000001536000000000000000 BOUT 19700101 12 eCAM 018090 N +WAMAS SYSTEM1 00000320230501065723WEAPQ0050000196241 000123477 HOST 00003045415 0001112 00000DISPONIBLE 000005184000000000000000 PET 19700101 12 eCAM 018090 N +WAMAS SYSTEM1 00000420230501065723WEAPQ0050000196241 000123477 HOST 00004045415 0001113 00000DISPONIBLE 000003840000000000000000 BOUT 19700101 12 eCAM 018090 N +WAMAS SYSTEM1 00000520230501065723WEAPQ0050000196241 000123477 HOST 00005045415 0001114 00000DISPONIBLE 000003072000000000000000 PET 19700101 12 eCAM 018090 N +WAMAS SYSTEM1 00000620230501065723WEAPQ0050000196241 000123477 HOST 00006045415 0001115 00000DISPONIBLE 000003024000000000000000 PET 19700101 12 eCAM 018090 N diff --git a/base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt b/base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt new file mode 100644 index 0000000000..bcffe47aa6 --- /dev/null +++ b/base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt @@ -0,0 +1,6 @@ +SYSTEM1 WAMAS 00000120231031100930WEAK00050000123477 HOST STDMAN0001040 New Company 1 1th Ave S 55406 Minneapolis Minnesota Unit+41 111 222 333 +41 11 222 33 44 customerservice@new.company.com 20231028000000 +SYSTEM1 WAMAS 00002020231031100930WEAP00045000123477 HOST 0000200001111 00000 20231031 NDISPONIBLE 000001536000BOUT NORMAL 20231031000000 202310310000007910063 NNLG +SYSTEM1 WAMAS 00003020231031100930WEAP00045000123477 HOST 0000300001112 00000 20231031 NDISPONIBLE 000005184000PET NORMAL 20231031000000 202310310000007910105 NNLG +SYSTEM1 WAMAS 00004020231031100930WEAP00045000123477 HOST 0000400001113 00000 20231031 NDISPONIBLE 000003840000BOUT NORMAL 20231031000000 202310310000007910004 NNLG +SYSTEM1 WAMAS 00005020231031100930WEAP00045000123477 HOST 0000500001114 00000 20231031 NDISPONIBLE 000003072000PET NORMAL 20231031000000 2023103100000012156876 NNLG +SYSTEM1 WAMAS 00006020231031100930WEAP00045000123477 HOST 0000600001115 00000 20231031 NDISPONIBLE 000003024000PET NORMAL 20231031000000 202310310000007910044 NNLG diff --git a/base_wamas/tests/test_base_wamas.py b/base_wamas/tests/test_base_wamas.py new file mode 100644 index 0000000000..bfaabb4712 --- /dev/null +++ b/base_wamas/tests/test_base_wamas.py @@ -0,0 +1,68 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import filecmp +import os +import tempfile + +from odoo.tests.common import TransactionCase +from odoo.tools import file_open, file_path + + +class TestBaseWamas(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.weak_weap = cls.env.ref("base_wamas.wamas_document_template_weak_weap") + cls.weakq_weapq = cls.env.ref("base_wamas.wamas_document_template_weakq_weapq") + cls.tmpfile_path = tempfile.mkstemp(suffix=".txt")[1] + + @classmethod + def tearDownClass(cls): + if os.path.exists(cls.tmpfile_path): + os.remove(cls.tmpfile_path) + return super().tearDownClass() + + def test_weak_weap(self): + path = "base_wamas/tests/files/SAMPLE_WEAK_WEAP.txt" + self._run_full_workflow(path, self.weak_weap) + + def test_weakq_weapq(self): + path = "base_wamas/tests/files/SAMPLE_WEAKQ_WEAPQ.txt" + self._run_full_workflow(path, self.weakq_weapq) + + def _run_full_workflow(self, path, template_rec): + # Get the data from WAMAS document file + result = [] + + with file_open(path) as f: + for row in f: + found_element = template_rec.get_proper_element_from_row(row) + + if not found_element: + continue + + values = found_element.get_values_from_element( + row, convert_type=True, result_type="list_tuple" + ) + result.append(values) + + # Generate WAMAS document file from the `result` above + lst_lines = [] + + for items in result: + found_element = template_rec.get_proper_element_from_items(items) + if not found_element: + continue + + str_line = found_element.set_values_to_element(items) + if str_line: + lst_lines.append(str_line + "\n") + + if lst_lines: + with open(self.tmpfile_path, "w") as f: + f.writelines(lst_lines) + + # Compare 2 files + self.assertTrue(filecmp.cmp(file_path(path), self.tmpfile_path)) diff --git a/base_wamas/views/wamas_document_default_field_template_views.xml b/base_wamas/views/wamas_document_default_field_template_views.xml new file mode 100644 index 0000000000..e44852dcaf --- /dev/null +++ b/base_wamas/views/wamas_document_default_field_template_views.xml @@ -0,0 +1,73 @@ + + + + + wamas.document.default.field.template.view.tree + wamas.document.default.field.template + + + + + + + + + + wamas.document.default.field.template.view.form + wamas.document.default.field.template + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + wamas.document.default.field.template.view.search + wamas.document.default.field.template + + + + + + + + + + WAMAS Document Default Field Template + ir.actions.act_window + wamas.document.default.field.template + tree,form + + {} + + +
diff --git a/base_wamas/views/wamas_document_default_field_views.xml b/base_wamas/views/wamas_document_default_field_views.xml new file mode 100644 index 0000000000..9df41888c1 --- /dev/null +++ b/base_wamas/views/wamas_document_default_field_views.xml @@ -0,0 +1,71 @@ + + + + + wamas.document.default.field.view.tree + wamas.document.default.field + + + + + + + + + + + + + wamas.document.default.field.view.form + wamas.document.default.field + +
+ + + + + + + + + + + + + +
+
+
+ + + wamas.document.default.field.view.search + wamas.document.default.field + + + + + + + + + + + + + + + + + WAMAS Document Default Field + ir.actions.act_window + wamas.document.default.field + tree,form + + {} + + +
diff --git a/base_wamas/views/wamas_document_element_views.xml b/base_wamas/views/wamas_document_element_views.xml new file mode 100644 index 0000000000..a3a9ae2ca6 --- /dev/null +++ b/base_wamas/views/wamas_document_element_views.xml @@ -0,0 +1,67 @@ + + + + + wamas.document.element.view.tree + wamas.document.element + + + + + + + + + + + wamas.document.element.view.form + wamas.document.element + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + wamas.document.element.view.search + wamas.document.element + + + + + + + + + + + WAMAS Document Element + ir.actions.act_window + wamas.document.element + tree,form + + {} + + +
diff --git a/base_wamas/views/wamas_document_field_views.xml b/base_wamas/views/wamas_document_field_views.xml new file mode 100644 index 0000000000..b2da58910d --- /dev/null +++ b/base_wamas/views/wamas_document_field_views.xml @@ -0,0 +1,86 @@ + + + + + wamas.document.field.view.tree + wamas.document.field + + + + + + + + + + + + + + wamas.document.field.view.form + wamas.document.field + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + wamas.document.field.view.search + wamas.document.field + + + + + + + + + + + + + + + + + + + WAMAS Document Field + ir.actions.act_window + wamas.document.field + tree,form + + {'search_default_gb_element_id': 1} + + +
diff --git a/base_wamas/views/wamas_document_template_views.xml b/base_wamas/views/wamas_document_template_views.xml new file mode 100644 index 0000000000..6cfda7ca07 --- /dev/null +++ b/base_wamas/views/wamas_document_template_views.xml @@ -0,0 +1,60 @@ + + + + + wamas.document.template.view.tree + wamas.document.template + + + + + + + + + + wamas.document.template.view.form + wamas.document.template + +
+ + + + + + + + + + + + + + + + +
+
+
+ + + wamas.document.template.view.search + wamas.document.template + + + + + + + + + + WAMAS Document Template + ir.actions.act_window + wamas.document.template + tree,form + + {} + + +
diff --git a/base_wamas/views/wamas_menus.xml b/base_wamas/views/wamas_menus.xml new file mode 100644 index 0000000000..fc8dc9903e --- /dev/null +++ b/base_wamas/views/wamas_menus.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_wamas_ubl/README.rst b/base_wamas_ubl/README.rst new file mode 100644 index 0000000000..bb32699ec0 --- /dev/null +++ b/base_wamas_ubl/README.rst @@ -0,0 +1,85 @@ +================ +Base WAMAS - UBL +================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:987f4c4d5bb9d02f6c7acc1b3d049780f73641c9db70effd548a9398a00c251a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github + :target: https://github.com/OCA/edi/tree/16.0/base_wamas_ubl + :alt: OCA/edi +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-base_wamas_ubl + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Provides following models: + +* WAMAS Document XML Conversion Template, to define the conversion between WAMAS document and UBL XML file +* WAMAS Document XML Conversion Field, to define the mapping between UBL XML field and WAMAS field when converting from WAMAS document to UBL XML file + +**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 +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Jacques-Etienne Baudoux +* Tuan Tran + +Other credits +~~~~~~~~~~~~~ + +The creation of this module was financially supported by Camptocamp. + +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/edi `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_wamas_ubl/__init__.py b/base_wamas_ubl/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/base_wamas_ubl/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/base_wamas_ubl/__manifest__.py b/base_wamas_ubl/__manifest__.py new file mode 100644 index 0000000000..f502074682 --- /dev/null +++ b/base_wamas_ubl/__manifest__.py @@ -0,0 +1,30 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Base WAMAS - UBL", + "summary": """Base module to aggregate WAMAS - UBL features.""", + "version": "16.0.1.0.0", + "development_status": "Beta", + "website": "https://github.com/OCA/edi", + "license": "AGPL-3", + "author": "Camptocamp,Odoo Community Association (OCA)", + "depends": ["base_ubl", "base_wamas"], + "data": [ + "security/ir_model_access.xml", + "data/ir_config_parameter_data.xml", + "data/ir_actions_server_data.xml", + "data/wamas_document_field_data.xml", + "data/wamas_document_default_field_template_data.xml", + "data/wamas_document_element_data.xml", + "data/wamas_document_xml_conversion_template_data.xml", + "data/wamas_document_xml_conversion_field_data.xml", + "views/wamas_document_field_views.xml", + "views/wamas_document_default_field_template_views.xml", + "views/wamas_document_element_views.xml", + "views/wamas_document_xml_conversion_field_views.xml", + "views/wamas_document_xml_conversion_template_views.xml", + "views/wamas_menus.xml", + ], +} diff --git a/base_wamas_ubl/data/ir_actions_server_data.xml b/base_wamas_ubl/data/ir_actions_server_data.xml new file mode 100644 index 0000000000..a9c448f489 --- /dev/null +++ b/base_wamas_ubl/data/ir_actions_server_data.xml @@ -0,0 +1,196 @@ + + + + + get_ubl_version + + code + +action = record.ubl_version or "2.2" + + + + + get_ubl_Party_PartyName_Name + + code + +company = record._get_default_company() +action = company.partner_id.name or "" + + + + + get_ubl_Party_PostalAddress_StreetName + + code + +company = record._get_default_company() +action = company.partner_id.street or "" + + + + + get_ubl_Party_PostalAddress_CityName + + code + +company = record._get_default_company() +action = company.partner_id.city or "" + + + + + get_ubl_Party_PostalAddress_PostalZone + + code + +company = record._get_default_company() +action = company.partner_id.zip or "" + + + + + get_ubl_Party_PostalAddress_CountrySubentity + + code + +company = record._get_default_company() +action = company.partner_id.state_id and company.partner_id.state_id.name or "" + + + + + get_ubl_Party_PostalAddress_Country_IdentificationCode + + code + +company = record._get_default_company() +action = company.partner_id.country_id and company.partner_id.country_id.code or "" + + + + + get_ubl_Party_PartyTaxScheme_CompanyID + + code + +company = record._get_default_company() +action = company.partner_id.vat or "" + + + + + get_ubl_Party_PartyTaxScheme_TaxScheme_ID + + code + +action = "" + + + + + get_ubl_Party_PartyTaxScheme_TaxScheme_TaxTypeCode + + code + +action = "" + + + + + get_ubl_Party_Contact_Name + + code + +company = record._get_default_company() +action = company.partner_id.child_ids and company.partner_id.child_ids[0].name or "" + + + + + get_ubl_Party_Contact_Telephone + + code + +company = record._get_default_company() +action = company.partner_id.child_ids and company.partner_id.child_ids[0].phone or "" + + + + + get_ubl_Party_Contact_Telefax + + code + +action = "" + + + + + get_ubl_Party_Contact_ElectronicMail + + code + +company = record._get_default_company() +action = company.partner_id.child_ids and company.partner_id.child_ids[0].email or "" + + + + diff --git a/base_wamas_ubl/data/ir_config_parameter_data.xml b/base_wamas_ubl/data/ir_config_parameter_data.xml new file mode 100644 index 0000000000..2d7990f8ba --- /dev/null +++ b/base_wamas_ubl/data/ir_config_parameter_data.xml @@ -0,0 +1,9 @@ + + + + + wamas_to_xml_default_company_id + 1 + + + diff --git a/base_wamas_ubl/data/wamas_document_default_field_template_data.xml b/base_wamas_ubl/data/wamas_document_default_field_template_data.xml new file mode 100644 index 0000000000..70cbe40c3c --- /dev/null +++ b/base_wamas_ubl/data/wamas_document_default_field_template_data.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + diff --git a/base_wamas_ubl/data/wamas_document_element_data.xml b/base_wamas_ubl/data/wamas_document_element_data.xml new file mode 100644 index 0000000000..5f5b4cf116 --- /dev/null +++ b/base_wamas_ubl/data/wamas_document_element_data.xml @@ -0,0 +1,8 @@ + + + + + ./cac:DespatchLine + + + diff --git a/base_wamas_ubl/data/wamas_document_field_data.xml b/base_wamas_ubl/data/wamas_document_field_data.xml new file mode 100644 index 0000000000..8c72a1ed6a --- /dev/null +++ b/base_wamas_ubl/data/wamas_document_field_data.xml @@ -0,0 +1,292 @@ + + + + + + + 000 + + + + /main:DespatchAdvice/cbc:ID/text() + + + + HOST + + + + + + + + substring(/main:DespatchAdvice/cac:OrderReference/cbc:ID/text(), 1, 6) + + + + substring(/main:DespatchAdvice/cac:OrderReference/cbc:ID/text(), 7, 3) + + + + substring(/main:DespatchAdvice/cac:OrderReference/cbc:ID/text(), 10, 13) + + + + /main:DespatchAdvice/cac:OrderReference/cbc:IssueDate/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PartyName/cbc:Name/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PostalAddress/cbc:CountrySubentity/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PostalAddress/cbc:CityName/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PostalAddress/cbc:PostalZone/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:PostalAddress/cac:Country/cbc:IdentificationCode/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:Contact/cbc:Telephone/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:Contact/cbc:Telefax/text() + + + + /main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party/cac:Contact/cbc:ElectronicMail/text() + + + + + + 000 + + + + /main:DespatchAdvice/cbc:ID/text() + + + + HOST + + + + DISPONIBLE + + + + NORMAL + + + + N + + + + N + + + + LG + + + + 00000 + + + + + + + + substring(/main:DespatchAdvice/cac:DespatchLine[%s]/cbc:ID/text(), 1, 6) + + + + substring(/main:DespatchAdvice/cac:DespatchLine[%s]/cbc:ID/text(), 7, 3) + + + + substring(/main:DespatchAdvice/cac:DespatchLine[%s]/cbc:ID/text(), 10, 20) + + + + /main:DespatchAdvice/cac:DespatchLine[%s]/cbc:DeliveredQuantity/text() + + + + /main:DespatchAdvice/cac:DespatchLine[%s]/cbc:DeliveredQuantity/@unitCode + + + + /main:DespatchAdvice/cac:DespatchLine[%s]/cac:Item/cac:SellersItemIdentification/cbc:ID/text() + + + + normalize-space(/main:DespatchAdvice/cac:Shipment/cac:Delivery/cac:EstimatedDeliveryPeriod) + + + + normalize-space(/main:DespatchAdvice/cac:Shipment/cac:Delivery/cac:EstimatedDeliveryPeriod) + + + diff --git a/base_wamas_ubl/data/wamas_document_xml_conversion_field_data.xml b/base_wamas_ubl/data/wamas_document_xml_conversion_field_data.xml new file mode 100644 index 0000000000..e841b0490c --- /dev/null +++ b/base_wamas_ubl/data/wamas_document_xml_conversion_field_data.xml @@ -0,0 +1,1348 @@ + + + + + + + 10 + cbc + UBLVersionID + + + + + + + + + + + + + 20 + cbc + ID + + + + + + + + + + + + 30 + cbc + IssueDate + date + + + + + + + + + + + + 40 + cac + OrderReference + + + + + + + + + + + + 50 + cbc + ID + + + + + + + + + + + + 60 + cbc + IssueDate + date + + + + + + + + + + + + 70 + cac + DespatchSupplierParty + + + + + + + + + + + + 80 + cbc + CustomerAssignedAccountID + + + + + + + + + + + + 90 + cac + Party + + + + + + + + + + + + 100 + cac + PartyName + + + + + + + + + + + + 110 + cbc + Name + + + + + + + + + + + + 120 + cac + PostalAddress + + + + + + + + + + + + 130 + cbc + StreetName + + + + + + + + + + + + 140 + cbc + CityName + + + + + + + + + + + + 150 + cbc + PostalZone + + + + + + + + + + + + 160 + cac + Country + + + + + + + + + + + + 170 + cbc + IdentificationCode + + + + + + + + + + + + 180 + cac + Contact + + + + + + + + + + + + 190 + cbc + Telephone + + + + + + + + + + + + 200 + cbc + Telefax + + + + + + + + + + + + 210 + cbc + ElectronicMail + + + + + + + + + + + + 220 + cac + DeliveryCustomerParty + + + + + + + + + + + + 230 + cac + Party + + + + + + + + + + + + 240 + cac + PartyName + + + + + + + + + + + + 250 + cbc + Name + + + + + + + + + + + + + 260 + cac + PostalAddress + + + + + + + + + + + + 270 + cbc + StreetName + + + + + + + + + + + + + 280 + cbc + CityName + + + + + + + + + + + + + 290 + cbc + PostalZone + + + + + + + + + + + + + 300 + cbc + CountrySubentity + + + + + + + + + + + + + 310 + cac + Country + + + + + + + + + + + + 320 + cbc + IdentificationCode + + + + + + + + + + + + + 330 + cac + PartyTaxScheme + + + + + + + + + + + + 340 + cbc + CompanyID + + + + + + + + + + + + + 350 + cac + TaxScheme + + + + + + + + + + + + 360 + cbc + ID + + + + + + + + + + + + + 370 + cbc + TaxTypeCode + + + + + + + + + + + + + 380 + cac + Contact + + + + + + + + + + + + 390 + cbc + Name + + + + + + + + + + + + + 400 + cbc + Telephone + + + + + + + + + + + + + 410 + cbc + Telefax + + + + + + + + + + + + 420 + cbc + ElectronicMail + + + + + + + + + + + + + 430 + cac + Shipment + + + + + + + + + + + + 440 + cbc + ID + + + + + + + + + + + + 450 + cac + Delivery + + + + + + + + + + + + 460 + cac + EstimatedDeliveryPeriod + + + + + + + + + + + + 470 + cbc + EndDate + date + + + + + + + + + + + + 480 + cbc + EndTime + time + + + + + + + + + + + + 490 + cac + DespatchLine + + + + + + + + + + + + + 500 + cbc + ID + + + + + + + + + + + + 510 + cbc + DeliveredQuantity + int + + + + + + + + + + + + + 511 + cbc + DeliveredQuantity[unitCode] + + + + + + + + + + + + 520 + cac + OrderLineReference + + + + + + + + + + + + 530 + cbc + LineID + int + 4 + + + + + + + + + + + + 540 + cac + Item + + + + + + + + + + + + 550 + cac + BuyersItemIdentification + + + + + + + + + + + + 560 + cbc + ID + + + + + + + + + + + diff --git a/base_wamas_ubl/data/wamas_document_xml_conversion_template_data.xml b/base_wamas_ubl/data/wamas_document_xml_conversion_template_data.xml new file mode 100644 index 0000000000..de2a5af45b --- /dev/null +++ b/base_wamas_ubl/data/wamas_document_xml_conversion_template_data.xml @@ -0,0 +1,35 @@ + + + + + XML to WEAK - WEAP + XML to WEAK - WEAP + from_xml + + DespatchAdvice + + + + WEAKQ - WEAPQ to XML + WEAKQ - WEAPQ to XML + to_xml + + DespatchAdvice-2 + DespatchAdvice + 2.2 + en_US + + + diff --git a/base_wamas_ubl/models/__init__.py b/base_wamas_ubl/models/__init__.py new file mode 100644 index 0000000000..7d9e0f00d3 --- /dev/null +++ b/base_wamas_ubl/models/__init__.py @@ -0,0 +1,5 @@ +from . import wamas_document_field +from . import wamas_document_default_field_template_line +from . import wamas_document_element +from . import wamas_document_xml_conversion_template +from . import wamas_document_xml_conversion_field diff --git a/base_wamas_ubl/models/wamas_document_default_field_template_line.py b/base_wamas_ubl/models/wamas_document_default_field_template_line.py new file mode 100644 index 0000000000..653a4a0b70 --- /dev/null +++ b/base_wamas_ubl/models/wamas_document_default_field_template_line.py @@ -0,0 +1,14 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class WamasDocumentDefaultFieldTemplateLine(models.Model): + _inherit = "wamas.document.default.field.template.line" + + # From XML to WAMAS Document + xml_path = fields.Text("XML Path") + xml_default_value = fields.Text("XML Default Value") + xml_default_func = fields.Text("XML Default Function") diff --git a/base_wamas_ubl/models/wamas_document_element.py b/base_wamas_ubl/models/wamas_document_element.py new file mode 100644 index 0000000000..47681abe8a --- /dev/null +++ b/base_wamas_ubl/models/wamas_document_element.py @@ -0,0 +1,76 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from collections import OrderedDict + +from odoo import fields, models + + +def get_item_from_xml( + recordset_field, xml_root, ns, res, convert_type=False, freq=False +): + for field in recordset_field: + xml_path = field.xml_path + xml_default_value = field.xml_default_value + xml_default_func = field.xml_default_func + + if field._name == "wamas.document.default.field.template.line": + field = field.df_field_id + + if xml_path: + if freq and "%s" in xml_path: + xml_path = xml_path % str(freq) + val = xml_root.xpath(xml_path, namespaces=ns) + if isinstance(val, list): + val = len(val) > 0 and val[0] or "" + elif xml_default_value: + val = xml_default_value + elif xml_default_func: + val = str(getattr(field, xml_default_func)()) + else: + val = "" + + if convert_type and val: + val = field.get_value_from_string(val) + + if isinstance(res, OrderedDict): + res[field.code] = val + elif isinstance(res, list): + res.append((field.code, val)) + + return res + + +class WamasDocumentElement(models.Model): + _inherit = "wamas.document.element" + + freq_xml_path = fields.Text("Frequency XML Path", help="It is the relative path") + + def get_values_from_xml( + self, xml_root, ns, convert_type=False, result_type="ordered_dict", freq=False + ): + self.ensure_one() + + res = False + + if result_type == "list_tuple": + res = [] + elif result_type == "ordered_dict": + res = OrderedDict() + + # Get value from `row` for `default fields` + sorted_fields = self.df_field_template_id.line_ids.sorted( + key=lambda r: r.sequence + ) + res = get_item_from_xml( + sorted_fields, xml_root, ns, res, convert_type=convert_type, freq=freq + ) + + # Get value from `row` for `fields` + sorted_fields = self.field_ids.sorted(key=lambda r: r.sequence) + res = get_item_from_xml( + sorted_fields, xml_root, ns, res, convert_type=convert_type, freq=freq + ) + + return res diff --git a/base_wamas_ubl/models/wamas_document_field.py b/base_wamas_ubl/models/wamas_document_field.py new file mode 100644 index 0000000000..e64a1e23c8 --- /dev/null +++ b/base_wamas_ubl/models/wamas_document_field.py @@ -0,0 +1,18 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class WamasDocumentField(models.Model): + _inherit = "wamas.document.field" + + # From XML to WAMAS Document + xml_path = fields.Text("XML Path") + xml_default_value = fields.Text("XML Default Value") + xml_default_func = fields.Text("XML Default Function") + + @api.model + def get_default_telegram_sequence(self, seq_value=0): + return seq_value + 1 diff --git a/base_wamas_ubl/models/wamas_document_xml_conversion_field.py b/base_wamas_ubl/models/wamas_document_xml_conversion_field.py new file mode 100644 index 0000000000..78dcdb1117 --- /dev/null +++ b/base_wamas_ubl/models/wamas_document_xml_conversion_field.py @@ -0,0 +1,219 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import re +from datetime import date, datetime + +from dateutil.parser import parse +from lxml import etree + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + +from odoo.addons.base_wamas.models.wamas_document_field import is_date + +# NOTE: At the moment, only supports these following types +FIELD_TYPES = [ + ("str", "String"), + ("int", "Integer"), + ("date", "Date"), + ("time", "Time"), +] + + +class WamasDocumentXmlConversionTemplateMappingField(models.Model): + _name = "wamas.document.xml.conversion.field" + _description = "WAMAS Document XML Conversion Field" + + name = fields.Char(required=True) + namespace = fields.Char(equired=True) + sequence = fields.Integer(required=True, default=10) + ttype = fields.Selection(FIELD_TYPES, "Type", default="str") + len_field = fields.Integer("Length") + template_id = fields.Many2one("wamas.document.xml.conversion.template") + parent_id = fields.Many2one("wamas.document.xml.conversion.field", "Parent Node") + element_id = fields.Many2one("wamas.document.element", "Element") + field_id = fields.Many2one("wamas.document.field", "Field") + df_field_template_id = fields.Many2one( + "wamas.document.default.field.template", + compute="_compute_df_field_template_id", + store=True, + ) + df_field_line_id = fields.Many2one( + "wamas.document.default.field.template.line", "Default Field of Element" + ) + default_value = fields.Text() + default_func = fields.Text("Default Function") + default_server_action_id = fields.Many2one( + "ir.actions.server", "Default Server Action" + ) + is_freq_element = fields.Boolean("Is Freq. Element", default=False) + freq_element_id = fields.Many2one("wamas.document.element", "Freq. Element") + has_attribute = fields.Boolean(default=False) + + @api.depends("element_id") + def _compute_df_field_template_id(self): + for rec in self: + rec.df_field_template_id = ( + rec.element_id and rec.element_id.df_field_template_id or False + ) + + @api.onchange("element_id") + def _onchange_element_id(self): + self.field_id = False + self.df_field_line_id = False + + def name_get(self): + result = [] + for rec in self.sudo(): + name = "%s:%s" % (rec.namespace, rec.name) + result.append((rec.id, name)) + return result + + def convert_value(self, value): + res = value + + res = value + + if self.ttype == "str": + res = self._set_from_string(value) + elif self.ttype == "int": + res = self._set_from_int(value) + elif self.ttype == "date": + res = self._set_from_date(value) + elif self.ttype == "time": + res = self._set_from_time(value) + + return res + + def _set_from_string(self, value): + self.ensure_one() + + res = str(value) + + if self.len_field: + res = res.ljust(self.len_field)[: self.len_field] + + return res + + def _set_from_int(self, value): + self.ensure_one() + + try: + res = str(int(float(value))) + except TypeError: # pylint: disable=except-pass + pass + + if self.len_field: + res = res.rjust(self.len_field, "0")[: self.len_field] + + return res + + def _set_from_date(self, value): + self.ensure_one() + + res = value + + if isinstance(res, date): + res = res.strftime("%Y-%m-%d") + elif isinstance(res, datetime): + res = res.date().strftime("%Y-%m-%d") + elif isinstance(res, str): + if is_date(res): + res = parse(res).date().strftime("%Y-%m-%d") + else: + raise UserError( + _( + "The value '%s' is not the datetime / date type. " + "Please check it again!" % value + ) + ) + else: + res = str(value) + + if self.len_field: + res = res[: self.len_field] + + return res + + def _set_from_time(self, value): + self.ensure_one() + + res = value + + if isinstance(res, date): + res = res.strftime("%H:%M:%S") + elif isinstance(res, datetime): + res = res.strftime("%H:%M:%S") + elif isinstance(res, str): + if is_date(res): + res = parse(res).strftime("%H:%M:%S") + else: + raise UserError( + _( + "The value '%s' is not the datetime / date type. " + "Please check it again!" % value + ) + ) + else: + res = str(value) + + if self.len_field: + res = res[: self.len_field] + + return res + + def ubl_add_item(self, items, parent_node, ns, idx=0): + self.ensure_one() + + # Check if the element is a node or an attribute + is_node = True + if bool(re.search(r"\[.*?\]", self.name)): + is_node = False + + if is_node: + # If element is a node -> Create that node + str_element = ns[self.namespace] + self.name + node = etree.SubElement(parent_node, str_element) + else: + # If element is an attribute -> Get the parent node instead + node = parent_node + + # Get value from `items` + val = "" + if self.element_id: + if self.field_id: + val = str(items[self.element_id.code][idx][self.field_id.code]) + elif self.df_field_line_id: + val = str( + items[self.element_id.code][idx][ + self.df_field_line_id.df_field_id.code + ] + ) + elif self.default_value: + val = str(self.default_value) + elif self.default_func: + val = str(getattr(self.template_id, self.default_func)()) + elif self.default_server_action_id: + ctx = { + "active_model": "wamas.document.xml.conversion.template", + "active_id": self.template_id.id, + "active_ids": [self.template_id.id], + } + val = self.default_server_action_id.with_context(**ctx).run() + + if val is False: + val = "" + + val = self.convert_value(val) + + if is_node: + # If element is a node -> Set value to that node + node.text = val + else: + # If element is an attribute -> Set attribute to the parent node instead + xml_attr = re.findall(r"\[.*?\]", self.name)[0][1:-1] + node.set(xml_attr, val) + + return node diff --git a/base_wamas_ubl/models/wamas_document_xml_conversion_template.py b/base_wamas_ubl/models/wamas_document_xml_conversion_template.py new file mode 100644 index 0000000000..fedf2e327b --- /dev/null +++ b/base_wamas_ubl/models/wamas_document_xml_conversion_template.py @@ -0,0 +1,342 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +from collections import OrderedDict +from io import BytesIO, TextIOWrapper + +from lxml import etree + +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools.safe_eval import safe_eval + +from odoo.addons.base.models.res_partner import _lang_get + +logger = logging.getLogger(__name__) + + +UBL_VERSION = [ + ("2.0", "2.0"), + ("2.1", "2.1"), + ("2.2", "2.2"), +] + + +class WamasDocumentXmlConversionTemplate(models.Model): + _name = "wamas.document.xml.conversion.template" + _inherit = "base.ubl" + _description = "WAMAS Document XML Conversion Template" + + name = fields.Char(required=True) + code = fields.Char(required=True) + ttype = fields.Selection( + [ + ("from_xml", "From XML"), + ("to_xml", "To XML"), + ], + "Type", + required=True, + ) + from_wamas_document_template_id = fields.Many2one( + "wamas.document.template", + "From WAMAS Document Template", + ) + to_wamas_document_template_id = fields.Many2one( + "wamas.document.template", + "To WAMAS Document Template", + ) + ubl_document_name = fields.Char("UBL Document Name") + ubl_xml_root_name = fields.Char("UBL XML Root Name") + ubl_version = fields.Selection(UBL_VERSION, "UBL Version") + ubl_lang = fields.Selection(_lang_get, string="Language") + mapping_field_ids = fields.One2many( + "wamas.document.xml.conversion.field", "template_id", "Mapping Fields" + ) + from_wamas_element_ids = fields.Many2many( + "wamas.document.element", + "wamas_document_element_xml_conversion_rel", + "convesion_template_id", + "element_id", + compute="_compute_from_wamas_element_ids", + store=True, + ) + + @api.depends("ttype", "from_wamas_document_template_id") + def _compute_from_wamas_element_ids(self): + for rec in self: + from_wamas_element_ids = [(5, 0, 0)] + + if rec.ttype == "to_xml": + for line in rec.from_wamas_document_template_id.line_ids: + from_wamas_element_ids.append((4, line.element_id.id)) + + rec.from_wamas_element_ids = from_wamas_element_ids + + @api.onchange("ttype") + def _onchange_ttype(self): + self.from_wamas_document_template_id = False + self.to_wamas_document_template_id = False + + def convert_from_xml_to_wamas_document(self, xml_file): + self.ensure_one() + + # Get XML info + xml_root = etree.fromstring(xml_file) + + ns = xml_root.nsmap + main_xmlns = ns.pop(None) + ns["main"] = main_xmlns + root_name = False + + if self.ubl_xml_root_name in main_xmlns: + document = self.ubl_xml_root_name + root_name = "main:" + self.ubl_xml_root_name + + if not root_name: + raise UserError( + _("Cannot find '%s' in the UBL file." % self.ubl_xml_root_name) + ) + + # Check XML file + xml_string = etree.tostring( + xml_root, pretty_print=True, encoding="UTF-8", xml_declaration=True + ) + version = self._ubl_get_version(xml_root, root_name, ns) + self._ubl_check_xml_schema(xml_string, document, version=version) + + # Get data from XML + wamas_tmpl = self.to_wamas_document_template_id + + res = [] + + for element_line in wamas_tmpl.line_ids: + element = element_line.element_id + + if element.freq_xml_path: + lines = xml_root.iterfind(element.freq_xml_path, namespaces=ns) + + idx = 0 + for _dummy in lines: + idx += 1 + + res_element = element.get_values_from_xml( + xml_root, + ns, + convert_type=True, + result_type="list_tuple", + freq=idx, + ) + + if res_element: + res.append(res_element) + else: + res_element = element.get_values_from_xml( + xml_root, ns, convert_type=True, result_type="list_tuple" + ) + + if res_element: + res.append(res_element) + + # Generate XML file from the `res` above + lst_lines = [] + + for items in res: + found_element = wamas_tmpl.get_proper_element_from_items(items) + if not found_element: + continue + + str_line = found_element.set_values_to_element(items) + if str_line: + lst_lines.append(str_line + "\n") + + return lst_lines + + def convert_from_wamas_document_to_xml(self, file_wamas): + self.ensure_one() + + if isinstance(file_wamas, bytes): + file_wamas = TextIOWrapper(BytesIO(file_wamas), "utf-8") + + res_wamas = OrderedDict() + + # Get data from WAMAS Document + for row in file_wamas: + found_element = ( + self.from_wamas_document_template_id.get_proper_element_from_row(row) + ) + + if not found_element: + continue + + values = found_element.get_values_from_element( + row, convert_type=True, result_type="ordered_dict" + ) + + if found_element.code in res_wamas: + next_key = next(reversed(res_wamas[found_element.code])) + 1 + res_wamas[found_element.code][next_key] = values + else: + res_wamas[found_element.code] = OrderedDict() + res_wamas[found_element.code][0] = values + + res = self.generate_ubl_xml_string(res_wamas) + + return res + + def generate_ubl_xml_string(self, items, version="2.2"): + self.ensure_one() + + self.check_input_before_generating_ubl_xml_string() + + lang = self.get_ubl_lang() + version = self.ubl_version or version + + # Generate XML etree + xml_root = self.with_context( + lang=lang + ).generate_wamas_document_element_xml_etree(items, version=version) + + etree.indent(xml_root, space=" ") + + xml_string = etree.tostring( + xml_root, pretty_print=True, encoding="UTF-8", xml_declaration=True + ) + + # Check generated XML string + self._ubl_check_xml_schema(xml_string, self.ubl_xml_root_name, version=version) + + logger.debug( + "The UBL XML file of WAMAS Document Element '%s' generated", + self.name, + ) + logger.debug(xml_string.decode("utf-8")) + + return xml_string + + def check_input_before_generating_ubl_xml_string(self): + self.ensure_one() + + if not self.ubl_document_name: + raise ValidationError( + _( + "Please input 'UBL Document Name' of the conversion " + "'%s' to generate UBL file." + ) + % self.name + ) + + if not self.ubl_document_name: + raise ValidationError( + _( + "Please input 'UBL XML Root Name' of the conversion " + "'%s' to generate UBL file." + ) + % self.name + ) + + logger.debug( + "Starting to generate the UBL XML file of WAMAS Document Element '%s'", + self.name, + ) + + def _add_item_to_xml_etree( + self, + items, + xml_root, + ns, + mapping_field_ids, + dict_parent_node, + lst_freq_mapping_field=False, + idx=0, + ): + self.ensure_one() + + for line in mapping_field_ids.sorted(key=lambda r: r.sequence): + _key = (line.namespace, line.name, idx + 1) + + parent_node = xml_root + + if line.parent_id: + _key_parent = (line.parent_id.namespace, line.parent_id.name, idx + 1) + parent_node = dict_parent_node[_key_parent] + + node = line.ubl_add_item(items, parent_node, ns, idx=idx) + + if line.namespace == "cac" or line.has_attribute: + dict_parent_node[_key] = node + + if line.is_freq_element and line.freq_element_id: + if lst_freq_mapping_field is False: + lst_freq_mapping_field = [] + + lst_freq_mapping_field.append(line) + + return True + + def generate_wamas_document_element_xml_etree(self, items, version="2.2"): + self.ensure_one() + + wdxcf_obj = self.env["wamas.document.xml.conversion.field"] + + nsmap, ns = self._ubl_get_nsmap_namespace( + self.ubl_document_name, version=version + ) + xml_root = etree.Element(self.ubl_xml_root_name, nsmap=nsmap) + + dict_parent_node = {} + lst_freq_mapping_field = [] + + mapping_field_ids = self.mapping_field_ids.sorted(key=lambda r: r.sequence) + self._add_item_to_xml_etree( + items, + xml_root, + ns, + mapping_field_ids, + dict_parent_node, + lst_freq_mapping_field, + ) + + dict_parent_node_2 = {} + + for mapping_line in lst_freq_mapping_field: + lines = wdxcf_obj.search( + [("template_id", "=", self.id), ("id", "child_of", mapping_line.id)], + order="sequence", + ) + + for idx in range(1, len(items[mapping_line.freq_element_id.code])): + self._add_item_to_xml_etree( + items, xml_root, ns, lines, dict_parent_node_2, [], idx + ) + + return xml_root + + def get_ubl_version(self): + self.ensure_one() + return self.ubl_version or "2.2" + + def get_ubl_lang(self): + self.ensure_one() + return self.ubl_lang or "en_US" + + def _get_default_company(self, company_id=False): + rc_obj = self.env["res.company"] + + res = False + + if company_id: + res = rc_obj.browse(company_id) + else: + res = self.env.ref("base.main_company") + + ICP = self.env["ir.config_parameter"] + default_company_id = safe_eval( + ICP.get_param("wamas_to_xml_default_company_id", 0) + ) + + if default_company_id: + res = rc_obj.browse(default_company_id) + + return res diff --git a/base_wamas_ubl/readme/CONTRIBUTORS.rst b/base_wamas_ubl/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..0ab51a38a2 --- /dev/null +++ b/base_wamas_ubl/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Jacques-Etienne Baudoux +* Tuan Tran diff --git a/base_wamas_ubl/readme/CREDITS.rst b/base_wamas_ubl/readme/CREDITS.rst new file mode 100644 index 0000000000..ac19123b04 --- /dev/null +++ b/base_wamas_ubl/readme/CREDITS.rst @@ -0,0 +1 @@ +The creation of this module was financially supported by Camptocamp. diff --git a/base_wamas_ubl/readme/DESCRIPTION.rst b/base_wamas_ubl/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..ce80bdafba --- /dev/null +++ b/base_wamas_ubl/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +Provides following models: + +* WAMAS Document XML Conversion Template, to define the conversion between WAMAS document and UBL XML file +* WAMAS Document XML Conversion Field, to define the mapping between UBL XML field and WAMAS field when converting from WAMAS document to UBL XML file diff --git a/base_wamas_ubl/security/ir_model_access.xml b/base_wamas_ubl/security/ir_model_access.xml new file mode 100644 index 0000000000..8ad8f7fc7c --- /dev/null +++ b/base_wamas_ubl/security/ir_model_access.xml @@ -0,0 +1,40 @@ + + + + + Access WAMAS Document XML Conversion Template - EDI Manager + + + + + + + + + + Access WAMAS Document XML Conversion Field - EDI Manager + + + + + + + + + diff --git a/base_wamas_ubl/static/description/index.html b/base_wamas_ubl/static/description/index.html new file mode 100644 index 0000000000..ceab2b5a4f --- /dev/null +++ b/base_wamas_ubl/static/description/index.html @@ -0,0 +1,431 @@ + + + + + + +Base WAMAS - UBL + + + +
+

Base WAMAS - UBL

+ + +

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

+

Provides following models:

+
    +
  • WAMAS Document XML Conversion Template, to define the conversion between WAMAS document and UBL XML file
  • +
  • WAMAS Document XML Conversion Field, to define the mapping between UBL XML field and WAMAS field when converting from WAMAS document to UBL XML file
  • +
+

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

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The creation of this module was financially supported by Camptocamp.

+
+
+

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/edi project on GitHub.

+

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

+
+
+
+ + diff --git a/base_wamas_ubl/tests/__init__.py b/base_wamas_ubl/tests/__init__.py new file mode 100644 index 0000000000..4503eb691c --- /dev/null +++ b/base_wamas_ubl/tests/__init__.py @@ -0,0 +1 @@ +from . import test_base_wamas_ubl diff --git a/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml b/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml new file mode 100644 index 0000000000..0bf5430e81 --- /dev/null +++ b/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml @@ -0,0 +1,129 @@ + + + 2.2 + 1 + 2023-05-01 + + 130377 + 2023-05-01 + + + 1040 + + + + + + + + + + + + + + + + + + + + + + + YourCompany + + + 250 Executive Park Blvd, Suite 3400 + San Francisco + 94134 + California + + US + + + + + + + + + + + Chester Reed + (979)-904-8902 + + chester.reed79@example.com + + + + + + + + 2023-05-01 + 06:43:39 + + + + + + 1536 + + 0002 + + + + 1151 + + + + + + 5184 + + 0003 + + + + 1156 + + + + + + 3840 + + 0004 + + + + 1160 + + + + + + 3072 + + 0005 + + + + 1162 + + + + + + 3024 + + 0006 + + + + 1176 + + + + diff --git a/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt b/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt new file mode 100644 index 0000000000..1ecf19a6cf --- /dev/null +++ b/base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt @@ -0,0 +1,6 @@ +WAMAS SYSLOG 00000120230501065723WEAKQ0051000196241 HOST 20230501060217 19700101010000202305010609112023050106433920230501060221 0001040 +WAMAS SYSLOG 00000220230501065723WEAPQ0050000196241 000130377 HOST 00002045415 0001151 00000DISPONIBLE 000001536000000000000000 BOUT 19700101 12 eCAM 018090 N +WAMAS SYSLOG 00000320230501065723WEAPQ0050000196241 000130377 HOST 00003045415 0001156 00000DISPONIBLE 000005184000000000000000 PET 19700101 12 eCAM 018090 N +WAMAS SYSLOG 00000420230501065723WEAPQ0050000196241 000130377 HOST 00004045415 0001160 00000DISPONIBLE 000003840000000000000000 BOUT 19700101 12 eCAM 018090 N +WAMAS SYSLOG 00000520230501065723WEAPQ0050000196241 000130377 HOST 00005045415 0001162 00000DISPONIBLE 000003072000000000000000 PET 19700101 12 eCAM 018090 N +WAMAS SYSLOG 00000620230501065723WEAPQ0050000196241 000130377 HOST 00006045415 0001176 00000DISPONIBLE 000003024000000000000000 PET 19700101 12 eCAM 018090 N diff --git a/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml b/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml new file mode 100644 index 0000000000..79ac90f135 --- /dev/null +++ b/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml @@ -0,0 +1,145 @@ + + + 2.2 + 130377 + 2023-05-01 + + STDMAN0001040 + 2023-04-27 + + + 1040 + + + MyCompany + + + 1839 Arbor Way + Turlock + 95380 + California + + US + + + + (623)-853-7197 + + wood.corner26@example.com + + + + + + + YourCompany + + + 250 Executive Park Blvd, Suite 3400 + San Francisco + 94134 + California + + US + + + + + + + + + + + Chester Reed + (979)-904-8902 + + chester.reed79@example.com + + + + + 130377 + + + 2023-05-01 + 00:00:00.0Z + + + + + 0000200001151 + 1536 + + 0001 + + + + 1151 + + + 7910063 + + + + + 0000300001156 + 5184 + + 0002 + + + + 1156 + + + 7910105 + + + + + 0000400001160 + 3840 + + 0003 + + + + 1160 + + + 7910004 + + + + + 0000500001162 + 3072 + + 0004 + + + + 1162 + + + 12156876 + + + + + 0000600001176 + 3024 + + 0005 + + + + 1176 + + + 7910044 + + + + diff --git a/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt b/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt new file mode 100644 index 0000000000..f1d083cf9f --- /dev/null +++ b/base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt @@ -0,0 +1,6 @@ +SYSLOG WAMAS 00000120230501000000WEAK00050000130377 HOST STDMAN0001040 MyCompany 1839 Arbor Way California 95380 Turlock US (623)-853-7197 wood.corner26@example.com 20230427000000 +SYSLOG WAMAS 00002020230501000000WEAP00045000130377 HOST 0000200001151 00000 NDISPONIBLE 000001536000BOUT NORMAL 20230501000000 202305010000007910063 NNLG +SYSLOG WAMAS 00003020230501000000WEAP00045000130377 HOST 0000300001156 00000 NDISPONIBLE 000005184000PET NORMAL 20230501000000 202305010000007910105 NNLG +SYSLOG WAMAS 00004020230501000000WEAP00045000130377 HOST 0000400001160 00000 NDISPONIBLE 000003840000BOUT NORMAL 20230501000000 202305010000007910004 NNLG +SYSLOG WAMAS 00005020230501000000WEAP00045000130377 HOST 0000500001162 00000 NDISPONIBLE 000003072000PET NORMAL 20230501000000 2023050100000012156876 NNLG +SYSLOG WAMAS 00006020230501000000WEAP00045000130377 HOST 0000600001176 00000 NDISPONIBLE 000003024000PET NORMAL 20230501000000 202305010000007910044 NNLG diff --git a/base_wamas_ubl/tests/test_base_wamas_ubl.py b/base_wamas_ubl/tests/test_base_wamas_ubl.py new file mode 100644 index 0000000000..86be03b6c2 --- /dev/null +++ b/base_wamas_ubl/tests/test_base_wamas_ubl.py @@ -0,0 +1,60 @@ +# Copyright 2023 Jacques-Etienne Baudoux (BCIM) +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import filecmp +import os +import tempfile + +from odoo.tests.common import TransactionCase +from odoo.tools import file_open, file_path + + +class TestBaseWamas(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.xml_to_weakweap = cls.env.ref( + "base_wamas_ubl.wamas_document_xml_conversion_template_from_xml_to_weak_weap" + ) + cls.weakqweapq_to_xml = cls.env.ref( + "base_wamas_ubl.wamas_document_xml_conversion_template_from_weakq_weapq_to_xml" + ) + cls.tmpfile_path_txt = tempfile.mkstemp(suffix=".txt")[1] + cls.tmpfile_path_xml = tempfile.mkstemp(suffix=".xml")[1] + + @classmethod + def tearDownClass(cls): + if os.path.exists(cls.tmpfile_path_txt): + os.remove(cls.tmpfile_path_txt) + if os.path.exists(cls.tmpfile_path_xml): + os.remove(cls.tmpfile_path_xml) + return super().tearDownClass() + + def test_convert_from_xml_to_weak_weap(self): + path = "base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_DESPATCH_ADVICE.xml" + path_wamas_doc = "base_wamas_ubl/tests/files/XML2WAMAS-SAMPLE_WEAK_WEAP.txt" + xml_file = file_open(path, "rb").read() + + res = self.xml_to_weakweap.convert_from_xml_to_wamas_document(xml_file) + + if res: + with open(self.tmpfile_path_txt, "w") as f: + f.writelines(res) + + # Compare 2 files + self.assertTrue(filecmp.cmp(file_path(path_wamas_doc), self.tmpfile_path_txt)) + + def test_convert_from_weakq_weapq_to_xml(self): + path = "base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_WEAKQ_WEAPQ.txt" + path_xml_doc = "base_wamas_ubl/tests/files/WAMAS2XML-SAMPLE_DESPATCH_ADVICE.xml" + + with file_open(path) as f: + res = self.weakqweapq_to_xml.convert_from_wamas_document_to_xml(f) + + if res: + with open(self.tmpfile_path_xml, "wb") as f2: + f2.write(res) + + # Compare 2 files + self.assertTrue(filecmp.cmp(file_path(path_xml_doc), self.tmpfile_path_xml)) diff --git a/base_wamas_ubl/views/wamas_document_default_field_template_views.xml b/base_wamas_ubl/views/wamas_document_default_field_template_views.xml new file mode 100644 index 0000000000..001eb6c868 --- /dev/null +++ b/base_wamas_ubl/views/wamas_document_default_field_template_views.xml @@ -0,0 +1,30 @@ + + + + + wamas.document.default.field.template.view.form + wamas.document.default.field.template + + + + + + + + + + + + + + + diff --git a/base_wamas_ubl/views/wamas_document_element_views.xml b/base_wamas_ubl/views/wamas_document_element_views.xml new file mode 100644 index 0000000000..02849c3b14 --- /dev/null +++ b/base_wamas_ubl/views/wamas_document_element_views.xml @@ -0,0 +1,21 @@ + + + + + wamas.document.element.view.form + wamas.document.element + + + + + + + + + + + + + + + diff --git a/base_wamas_ubl/views/wamas_document_field_views.xml b/base_wamas_ubl/views/wamas_document_field_views.xml new file mode 100644 index 0000000000..10e4c145dc --- /dev/null +++ b/base_wamas_ubl/views/wamas_document_field_views.xml @@ -0,0 +1,21 @@ + + + + + wamas.document.field.view.form + wamas.document.field + + + + + + + + + + + + + + + diff --git a/base_wamas_ubl/views/wamas_document_xml_conversion_field_views.xml b/base_wamas_ubl/views/wamas_document_xml_conversion_field_views.xml new file mode 100644 index 0000000000..e2dd69aace --- /dev/null +++ b/base_wamas_ubl/views/wamas_document_xml_conversion_field_views.xml @@ -0,0 +1,79 @@ + + + + + wamas.document.xml.conversion.field.view.tree + wamas.document.xml.conversion.field + + + + + + + + + + + + + + + + + + + + + wamas.document.xml.conversion.field.view.form + wamas.document.xml.conversion.field + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
diff --git a/base_wamas_ubl/views/wamas_document_xml_conversion_template_views.xml b/base_wamas_ubl/views/wamas_document_xml_conversion_template_views.xml new file mode 100644 index 0000000000..1d77c83f4b --- /dev/null +++ b/base_wamas_ubl/views/wamas_document_xml_conversion_template_views.xml @@ -0,0 +1,113 @@ + + + + + wamas.document.xml.conversion.template.view.tree + wamas.document.xml.conversion.template + + + + + + + + + + + + + wamas.document.xml.conversion.template.view.form + wamas.document.xml.conversion.template + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + wamas.document.xml.conversion.template.view.search + wamas.document.xml.conversion.template + + + + + + + + + + + + + + + + + WAMAS Document XML Conversion Template + ir.actions.act_window + wamas.document.xml.conversion.template + tree,form + + {} + + +
diff --git a/base_wamas_ubl/views/wamas_menus.xml b/base_wamas_ubl/views/wamas_menus.xml new file mode 100644 index 0000000000..6909f937ec --- /dev/null +++ b/base_wamas_ubl/views/wamas_menus.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/setup/base_wamas/odoo/addons/base_wamas b/setup/base_wamas/odoo/addons/base_wamas new file mode 120000 index 0000000000..67481d5507 --- /dev/null +++ b/setup/base_wamas/odoo/addons/base_wamas @@ -0,0 +1 @@ +../../../../base_wamas \ No newline at end of file diff --git a/setup/base_wamas/setup.py b/setup/base_wamas/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/base_wamas/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/base_wamas_ubl/odoo/addons/base_wamas_ubl b/setup/base_wamas_ubl/odoo/addons/base_wamas_ubl new file mode 120000 index 0000000000..ed321a51e7 --- /dev/null +++ b/setup/base_wamas_ubl/odoo/addons/base_wamas_ubl @@ -0,0 +1 @@ +../../../../base_wamas_ubl \ No newline at end of file diff --git a/setup/base_wamas_ubl/setup.py b/setup/base_wamas_ubl/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/base_wamas_ubl/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)