From 901edc5fd8b22cbc73a4a204639ee911f1dca4f0 Mon Sep 17 00:00:00 2001 From: duongtq Date: Mon, 25 Sep 2023 15:40:59 +0700 Subject: [PATCH] [MIG] sale_order_import_edifact: Migration to 16.0 --- sale_order_import_edifact/README.rst | 64 +++------- sale_order_import_edifact/__manifest__.py | 4 +- .../models/business_document_import.py | 9 +- .../readme/CONFIGURE.rst | 24 ---- .../readme/CONTRIBUTORS.rst | 1 + sale_order_import_edifact/readme/CREDITS.rst | 1 + sale_order_import_edifact/readme/HISTORY.rst | 2 +- sale_order_import_edifact/readme/ROADMAP.rst | 5 - .../static/description/index.html | 74 ++++-------- .../tests/test_edifact_order_import.py | 6 + .../wizard/sale_order_import.py | 114 ++++++++++-------- .../wizard/sale_order_import_view.xml | 12 +- 12 files changed, 133 insertions(+), 183 deletions(-) create mode 100644 sale_order_import_edifact/readme/CREDITS.rst delete mode 100644 sale_order_import_edifact/readme/ROADMAP.rst diff --git a/sale_order_import_edifact/README.rst b/sale_order_import_edifact/README.rst index 9d447023430..532f9fbd2e0 100644 --- a/sale_order_import_edifact/README.rst +++ b/sale_order_import_edifact/README.rst @@ -2,10 +2,13 @@ Import Business Document EDIFACT/D96A Order =========================================== -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:5593f695246c5fb666e0e01b5f8eb8256fab93e4b11a1dcdf64602ee3be92818 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png :target: https://odoo-community.org/page/development-status @@ -14,16 +17,16 @@ Import Business Document EDIFACT/D96A Order :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github - :target: https://github.com/OCA/edi/tree/14.0/sale_order_import_edifact + :target: https://github.com/OCA/edi/tree/16.0/sale_order_import_edifact :alt: OCA/edi .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/edi-14-0/edi-14-0-sale_order_import_edifact + :target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-sale_order_import_edifact :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/226/14.0 - :alt: Try me on Runbot +.. |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| +|badge1| |badge2| |badge3| |badge4| |badge5| UN/EDIFACT United Nations rules for Elec­tronic Data Interchange for Administration, Commerce and Transport @@ -46,45 +49,12 @@ Configuration ============= -EDI Exchange Type "Advanced Settings" - -.. code-block:: yaml - - components: - process: - usage: input.process.sale.order - - sale_order_import: - price_source: order - confirm_order: false - wiz_ctx: - file_ext: 'edi' - release: 'd96a' - doc_type: 'rfq' - - -- price_source. Can be 'order' or 'pricelist' -- confirm_order. False by default -- wiz_ctx. Wizard's context - - file_ext. File extensions supported. By default: 'txt,d96a' - - release. EDIFACT format release. - - doc_type. ('rfq', "Request for Quotation") | ('order', "Order"). Default 'order' - This module struggles with EDIFACT format, if you need X12 format you will need something like sale_order_import_x12 module. Regardless format, a concret document should need a concret specification nammed release. For example Amazon uses "D96A" specification. See -Known issues / Roadmap -====================== - -.. Enumerate known caveats and future potential improvements. - It is mostly intended for end-users, and can also help - potential new contributors discovering new features to implement. - -* Refactor import by release - Changelog ========= @@ -101,7 +71,7 @@ Changelog 14.0.1.0.0 (2023-06-07) ~~~~~~~~~~~~~~~~~~~~~~~ -* [14.0][MIG] sale_order_import_edifact & base_edifact. +* [14.0][ADD] sale_order_import_edifact & base_edifact. (`#779 `_) Bug Tracker @@ -109,8 +79,8 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +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. @@ -127,6 +97,12 @@ Contributors * Rafa Morant (https://www.albasoft.com) * Marc Poch +* Duong (Tran Quoc) + +Other credits +~~~~~~~~~~~~~ + +The migration of this module from 14.0 to 16.0 was financially supported by Camptocamp Maintainers ~~~~~~~~~~~ @@ -149,6 +125,6 @@ Current `maintainer `__: |maintainer-rmorant| -This module is part of the `OCA/edi `_ project on GitHub. +This module is part of the `OCA/edi `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_order_import_edifact/__manifest__.py b/sale_order_import_edifact/__manifest__.py index eeea97e1894..69356fea84a 100644 --- a/sale_order_import_edifact/__manifest__.py +++ b/sale_order_import_edifact/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Import Business Document EDIFACT/D96A Order", "summary": "EDIFACT/D96A Order", - "version": "14.0.1.0.0", + "version": "16.0.1.0.0", "development_status": "Alpha", "category": "Sales Management", "website": "https://github.com/OCA/edi", @@ -22,7 +22,7 @@ "partner_identification", "partner_identification_gln", "base_edifact", - "edi_sale_order_import", + "sale_order_import", ], "data": [ "wizard/sale_order_import_view.xml", diff --git a/sale_order_import_edifact/models/business_document_import.py b/sale_order_import_edifact/models/business_document_import.py index f495f4f3f04..d79ad3c4f62 100644 --- a/sale_order_import_edifact/models/business_document_import.py +++ b/sale_order_import_edifact/models/business_document_import.py @@ -7,6 +7,7 @@ class BusinessDocumentImport(models.AbstractModel): _inherit = "business.document.import" + # TODO: refactor code in partner_identification_import and drop this one @api.model def _hook_match_partner(self, partner_dict, chatter_msg, domain, order): """ @@ -40,10 +41,12 @@ def _hook_match_partner(self, partner_dict, chatter_msg, domain, order): ) raise exceptions.UserError( _( - "Partner GLN Code: %s not found in order file: '%s' " - "from VAT registration number '%s'." + "Partner GLN Code: %(party)s not found in order file: '%(file)s' " + "from VAT registration number '%(vat)s'.", + party=party_id, + file=ctx.get("order_filename"), + vat=ctx.get("rff_va"), ) - % (party_id, ctx.get("order_filename"), ctx.get("rff_va")) ) return id_number.partner_id diff --git a/sale_order_import_edifact/readme/CONFIGURE.rst b/sale_order_import_edifact/readme/CONFIGURE.rst index dfd1b95a6ae..89cd9f6bded 100644 --- a/sale_order_import_edifact/readme/CONFIGURE.rst +++ b/sale_order_import_edifact/readme/CONFIGURE.rst @@ -1,28 +1,4 @@ -EDI Exchange Type "Advanced Settings" - -.. code-block:: yaml - - components: - process: - usage: input.process.sale.order - - sale_order_import: - price_source: order - confirm_order: false - wiz_ctx: - file_ext: 'edi' - release: 'd96a' - doc_type: 'rfq' - - -- price_source. Can be 'order' or 'pricelist' -- confirm_order. False by default -- wiz_ctx. Wizard's context - - file_ext. File extensions supported. By default: 'txt,d96a' - - release. EDIFACT format release. - - doc_type. ('rfq', "Request for Quotation") | ('order', "Order"). Default 'order' - This module struggles with EDIFACT format, if you need X12 format you will need something like sale_order_import_x12 module. Regardless format, a concret document should need a concret specification nammed release. For example Amazon uses "D96A" specification. diff --git a/sale_order_import_edifact/readme/CONTRIBUTORS.rst b/sale_order_import_edifact/readme/CONTRIBUTORS.rst index a153b2ddd1f..91ffeada11d 100644 --- a/sale_order_import_edifact/readme/CONTRIBUTORS.rst +++ b/sale_order_import_edifact/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Rafa Morant (https://www.albasoft.com) * Marc Poch +* Duong (Tran Quoc) diff --git a/sale_order_import_edifact/readme/CREDITS.rst b/sale_order_import_edifact/readme/CREDITS.rst new file mode 100644 index 00000000000..a5c8f66b93c --- /dev/null +++ b/sale_order_import_edifact/readme/CREDITS.rst @@ -0,0 +1 @@ +The migration of this module from 14.0 to 16.0 was financially supported by Camptocamp diff --git a/sale_order_import_edifact/readme/HISTORY.rst b/sale_order_import_edifact/readme/HISTORY.rst index c57a493aa1a..6d08184cf02 100644 --- a/sale_order_import_edifact/readme/HISTORY.rst +++ b/sale_order_import_edifact/readme/HISTORY.rst @@ -11,5 +11,5 @@ 14.0.1.0.0 (2023-06-07) ~~~~~~~~~~~~~~~~~~~~~~~ -* [14.0][MIG] sale_order_import_edifact & base_edifact. +* [14.0][ADD] sale_order_import_edifact & base_edifact. (`#779 `_) diff --git a/sale_order_import_edifact/readme/ROADMAP.rst b/sale_order_import_edifact/readme/ROADMAP.rst deleted file mode 100644 index e5c8273d153..00000000000 --- a/sale_order_import_edifact/readme/ROADMAP.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. Enumerate known caveats and future potential improvements. - It is mostly intended for end-users, and can also help - potential new contributors discovering new features to implement. - -* Refactor import by release diff --git a/sale_order_import_edifact/static/description/index.html b/sale_order_import_edifact/static/description/index.html index 007ccd6242c..6d76c7b5838 100644 --- a/sale_order_import_edifact/static/description/index.html +++ b/sale_order_import_edifact/static/description/index.html @@ -366,8 +366,10 @@

Import Business Document EDIFACT/D96A Order

-

Alpha License: AGPL-3 OCA/edi Translate me on Weblate Try me on Runbot

+

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

UN/EDIFACT
United Nations rules for Elec­tronic Data Interchange for Administration, Commerce and Transport
@@ -384,15 +386,15 @@

Import Business Document EDIFACT/D96A Order

Configuration

-

EDI Exchange Type “Advanced Settings”

-
-components:
-   process:
-      usage: input.process.sale.order
-
-sale_order_import:
-   price_source: order
-   confirm_order: false
-   wiz_ctx:
-      file_ext: 'edi'
-      release: 'd96a'
-      doc_type: 'rfq'
-
-
    -
  • price_source. Can be ‘order’ or ‘pricelist’
  • -
  • confirm_order. False by default
  • -
  • wiz_ctx. Wizard’s context -- file_ext. File extensions supported. By default: ‘txt,d96a’ -- release. EDIFACT format release. -- doc_type. (‘rfq’, “Request for Quotation”) | (‘order’, “Order”). Default ‘order’
  • -

This module struggles with EDIFACT format, if you need X12 format you will need something like sale_order_import_x12 module.

Regardless format, a concret document should need a concret specification nammed release. For example Amazon uses “D96A” specification.

See <https://www.stedi.com/edi/edifact>

-
-

Known issues / Roadmap

- -
    -
  • Refactor import by release
  • -
-
-

Changelog

+

Changelog

-

14.0.1.0.0 (2023-06-07)

+

14.0.1.0.0 (2023-06-07)

    -
  • [14.0][MIG] sale_order_import_edifact & base_edifact. +
  • [14.0][ADD] sale_order_import_edifact & base_edifact. (#779)
-

Bug Tracker

+

Bug Tracker

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

+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

+

Credits

-

Authors

+

Authors

  • ALBA Software
+
+

Other credits

+

The migration of this module from 14.0 to 16.0 was financially supported by Camptocamp

+

Maintainers

This module is maintained by the OCA.

@@ -486,7 +462,7 @@

Maintainers

promote its widespread use.

Current maintainer:

rmorant

-

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

+

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

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

diff --git a/sale_order_import_edifact/tests/test_edifact_order_import.py b/sale_order_import_edifact/tests/test_edifact_order_import.py index 5bf0f570162..ed3bad58325 100644 --- a/sale_order_import_edifact/tests/test_edifact_order_import.py +++ b/sale_order_import_edifact/tests/test_edifact_order_import.py @@ -10,6 +10,11 @@ class TestEdifactOrderImport(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + @mute_logger("odoo.addons.sale_order_import.wizard.sale_order_import") def test_edifact_order_import(self): tests = get_test_data(self.env) @@ -17,6 +22,7 @@ def test_edifact_order_import(self): edifact_file = expected._get_content() wiz = self.env["sale.order.import"].create( { + "import_type": "edifact", "order_file": base64.b64encode(edifact_file), "order_filename": filename, } diff --git a/sale_order_import_edifact/wizard/sale_order_import.py b/sale_order_import_edifact/wizard/sale_order_import.py index 3b597525a72..f797af0ae85 100644 --- a/sale_order_import_edifact/wizard/sale_order_import.py +++ b/sale_order_import_edifact/wizard/sale_order_import.py @@ -10,44 +10,46 @@ logger = logging.getLogger(__name__) -class SaleOrderImportEdifact(models.TransientModel): - _name = "sale.order.import" - _inherit = ["sale.order.import", "base.edifact"] +class SaleOrderImport(models.TransientModel): + _inherit = "sale.order.import" - state = fields.Selection( - selection_add=[("tech", "Technical")], ondelete={"tech": "set default"} + import_type = fields.Selection( + selection_add=[("edifact", "EDIFACT")], ondelete={"edifact": "cascade"} ) + # Make doc_type field support for EDIFACT type + doc_type = fields.Selection(readonly=False) parsed_json = fields.Text() - - @property - def edifact_ok(self): - conf_ext = self.env.context.get("file_ext", "txt,d96a") - extensions = conf_ext.split(",") - ok = False - if self.order_filename: + edifact_ok = fields.Boolean(compute="_compute_edifact_ok", store=True) + # Techincal fields used to get the extension part of files + file_ext = fields.Char(default="txt,d96a") + # EDIFACT format release + release = fields.Char(default="d96a") + + @api.depends("order_file", "order_filename") + def _compute_edifact_ok(self): + for rec in self: + if not (rec.order_file and rec.order_filename): + rec.edifact_ok = False + continue + extensions = rec.file_ext.split(",") path, ext = os.path.splitext(self.order_filename) ok = ext and ext[1:] in extensions - if not ok and self.order_file: + if not ok: ok = b64decode(self.order_file[:4]) == b"UNB" - return ok + rec.edifact_ok = ok - @api.onchange("order_file") - def order_file_change(self): - if self.edifact_ok: - self.csv_import = False - self.doc_type = self.env.context.get("doc_type", "rfq") - self.price_source = "order" - else: - res = super(SaleOrderImportEdifact, self).order_file_change() - if isinstance(res, dict): - return res - - def parse_order_button(self): + def button_parse_order_preview(self): + """ + This method is called by the button to take a quick look at the pydifact + structure ('edifact' type) and the parsed object ('order') from + the original document before importing the document. + """ self.ensure_one() + edifact_model = self.env["base.edifact"] order_file_decoded = b64decode(self.order_file) parsed_obj = dict(edifact=None, order=None) if self.edifact_ok: - parsed_obj["edifact"] = self.pydifact_obj(order_file_decoded) + parsed_obj["edifact"] = edifact_model.pydifact_obj(order_file_decoded) parsed_order = self.parse_order( order_file_decoded, self.order_filename, self.partner_id @@ -57,7 +59,6 @@ def parse_order_button(self): self.write( { "parsed_json": json.dumps(parsed_obj, indent=4, default=str), - "state": "tech", } ) action = self.env["ir.actions.act_window"]._for_xml_id( @@ -66,26 +67,27 @@ def parse_order_button(self): action["res_id"] = self.id return action - # Parser hook - def _parse_file(self, filename, filecontent, detect_doc_type=False): - "Called from parse_order()" - parsed_order = super(SaleOrderImportEdifact, self)._parse_file( - filename, filecontent, detect_doc_type - ) - if not parsed_order and self.edifact_ok: - self.env.context.get("release", "d96a") - interchange = self._loads_edifact(filecontent) - parsed_order = self.parse_edifact_sale_order(interchange) - return parsed_order + def _get_supported_types(self): + # Add more types for EDIFACT + res = super()._get_supported_types() + res.update({"edifact": ("text/plain")}) + return res @api.model - def parse_edifact_sale_order(self, interchange): + def parse_edifact_order(self, filecontent, detect_doc_type=False): # https://github.com/nerdocs/pydifact/blob/master/pydifact/segmentcollection.py + if detect_doc_type: + if not self.edifact_ok: + return None + return self.env.context.get("doc_type", "rfq") + + edifact_model = self.env["base.edifact"] + interchange = edifact_model._loads_edifact(filecontent) header = interchange.get_header_segment() # > UNB segment: [['UNOA', '2'], ['5450534000000', '14'], # ['8435337000003', '14'], ['230306', '0435'], '5506'] - msg_type, msg_type_release = self._get_msg_type(interchange) + msg_type, msg_type_release = edifact_model._get_msg_type(interchange) supported = ["ORDERS"] if msg_type not in supported: raise UserError(_("%s document is not a Sale Order document")) @@ -143,17 +145,22 @@ def _prepare_edifact_parties(self, interchange): @api.model def _prepare_edifact_dates(self, interchange): dates = defaultdict(dict) + edifact_model = self.env["base.edifact"] for seg in interchange.get_segments("DTM"): date_meaning_code = seg[0][0] if date_meaning_code == "137": - dates["date"] = self.map2odoo_date(seg[0]) + dates["date"] = edifact_model.map2odoo_date(seg[0]) elif date_meaning_code == "63": # latest delivery date # dates.setdefault("delivery_detail",{}) - dates["delivery_detail"]["validity_date"] = self.map2odoo_date(seg[0]) + dates["delivery_detail"]["validity_date"] = edifact_model.map2odoo_date( + seg[0] + ) elif date_meaning_code == "64": # earliest delivery date - dates["delivery_detail"]["commitment_date"] = self.map2odoo_date(seg[0]) + dates["delivery_detail"][ + "commitment_date" + ] = edifact_model.map2odoo_date(seg[0]) return dates @@ -186,36 +193,39 @@ def _prepare_edifact_references(self, interchange): @api.model def _prepare_edifact_name_and_address(self, interchange): nads = {} + edifact_model = self.env["base.edifact"] for seg in interchange.get_segments("NAD"): reference_code = seg[0] if reference_code == "BY": # NAD segment: ['BY', ['5450534001649', '', '9']] # Customer (Buyer's GLN) - nads["partner"] = self.map2odoo_partner(seg) + nads["partner"] = edifact_model.map2odoo_partner(seg) elif reference_code == "SU": # Our number of Supplier's GLN # Can be used to check that we are not importing the order # in the wrong company by mistake - nads["company"] = self.map2odoo_partner(seg) + nads["company"] = edifact_model.map2odoo_partner(seg) elif reference_code == "DP": # Delivery Party - nads["ship_to"] = self.map2odoo_address(seg) + nads["ship_to"] = edifact_model.map2odoo_address(seg) elif reference_code == "IV": # Invoice Party - nads["invoice_to"] = self.map2odoo_address(seg) + nads["invoice_to"] = edifact_model.map2odoo_address(seg) return nads @api.model def _prepare_edifact_currencies(self, interchange): currencies = {} + edifact_model = self.env["base.edifact"] for seg in interchange.get_segments("CUX"): usage_code = seg[0] if usage_code == "2": - currencies["currency"] = self.map2odoo_currency(seg) + currencies["currency"] = edifact_model.map2odoo_currency(seg) return currencies @api.model def _prepare_edifact_lines(self, interchange): + edifact_model = self.env["base.edifact"] lines = [] zipsegments = zip( interchange.get_segments("LIN"), @@ -227,10 +237,10 @@ def _prepare_edifact_lines(self, interchange): lines.append( { "sequence": int(linseg[0]), - "product": self.map2odoo_product(linseg), - "qty": self.map2odoo_qty(qtyseg), + "product": edifact_model.map2odoo_product(linseg), + "qty": edifact_model.map2odoo_qty(qtyseg), # price without taxes - "price_unit": self.map2odoo_unit_price(priseg), + "price_unit": edifact_model.map2odoo_unit_price(priseg), } ) diff --git a/sale_order_import_edifact/wizard/sale_order_import_view.xml b/sale_order_import_edifact/wizard/sale_order_import_view.xml index 967599d65a5..5ecd70574fd 100644 --- a/sale_order_import_edifact/wizard/sale_order_import_view.xml +++ b/sale_order_import_edifact/wizard/sale_order_import_view.xml @@ -5,17 +5,23 @@ sale.order.import + + + {'readonly': [('import_type','!=','edifact')]} +
- +