From c8e623287db875b1e338c3d81224eeb2a988f2ef Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 2 Aug 2022 14:56:58 +0200 Subject: [PATCH 01/62] Add edi_sale_oca --- edi_sale_oca/README.rst | 88 +++++++++++++++++ edi_sale_oca/__init__.py | 1 + edi_sale_oca/__manifest__.py | 21 ++++ edi_sale_oca/data/job_function.xml | 7 ++ edi_sale_oca/models/__init__.py | 1 + edi_sale_oca/models/sale_order.py | 34 +++++++ edi_sale_oca/readme/CONTRIBUTORS.rst | 1 + edi_sale_oca/readme/DESCRIPTION.rst | 1 + edi_sale_oca/tests/__init__.py | 1 + edi_sale_oca/tests/test_edi.py | 107 +++++++++++++++++++++ edi_sale_oca/views/edi_exchange_record.xml | 30 ++++++ edi_sale_oca/views/res_partner.xml | 22 +++++ edi_sale_oca/views/sale_order.xml | 35 +++++++ 13 files changed, 349 insertions(+) create mode 100644 edi_sale_oca/README.rst create mode 100644 edi_sale_oca/__init__.py create mode 100644 edi_sale_oca/__manifest__.py create mode 100644 edi_sale_oca/data/job_function.xml create mode 100644 edi_sale_oca/models/__init__.py create mode 100644 edi_sale_oca/models/sale_order.py create mode 100644 edi_sale_oca/readme/CONTRIBUTORS.rst create mode 100644 edi_sale_oca/readme/DESCRIPTION.rst create mode 100644 edi_sale_oca/tests/__init__.py create mode 100644 edi_sale_oca/tests/test_edi.py create mode 100644 edi_sale_oca/views/edi_exchange_record.xml create mode 100644 edi_sale_oca/views/res_partner.xml create mode 100644 edi_sale_oca/views/sale_order.xml diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst new file mode 100644 index 000000000..7cffd6134 --- /dev/null +++ b/edi_sale_oca/README.rst @@ -0,0 +1,88 @@ +=========== +Edi Account +=========== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github + :target: https://github.com/OCA/edi/tree/14.0/edi_account_oca + :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-edi_account_oca + :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 + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module intends to create a base to be extended by local edi rules +for accounting. + +In order to add a new integration for an account, you need to create a listener: + +.. code-block:: python + + class MyEventListener(Component): + _name = "sale.order.event.listener.demo" + _inherit = "base.event.listener" + _apply_on = ["sale.order"] + + def on_post_sale_order(self, move): + """Add your code here about creation of record""" + +A skip if decorator can be added in order to make some checks on the state of the move + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp SA + +Contributors +~~~~~~~~~~~~ + +* Enric Tobella + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/edi `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/edi_sale_oca/__init__.py b/edi_sale_oca/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/edi_sale_oca/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py new file mode 100644 index 000000000..80411ee1e --- /dev/null +++ b/edi_sale_oca/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "EDI Sales", + "summary": """ + Configuration and special behaviors for EDI on sales. + """, + "version": "14.0.1.0.0", + "development_status": "Alpha", + "license": "AGPL-3", + "author": "Camptocamp,Odoo Community Association (OCA)", + "maintainers": ["simahawk"], + "website": "https://github.com/OCA/edi", + "depends": ["sale", "edi_oca", "component_event"], + "data": [ + "views/res_partner.xml", + "views/sale_order.xml", + "views/edi_exchange_record.xml", + ], +} diff --git a/edi_sale_oca/data/job_function.xml b/edi_sale_oca/data/job_function.xml new file mode 100644 index 000000000..94d62e089 --- /dev/null +++ b/edi_sale_oca/data/job_function.xml @@ -0,0 +1,7 @@ + + + + _edi_auto_handle_generate + + + diff --git a/edi_sale_oca/models/__init__.py b/edi_sale_oca/models/__init__.py new file mode 100644 index 000000000..6aacb7531 --- /dev/null +++ b/edi_sale_oca/models/__init__.py @@ -0,0 +1 @@ +from . import sale_order diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py new file mode 100644 index 000000000..b5bdb1b4e --- /dev/null +++ b/edi_sale_oca/models/sale_order.py @@ -0,0 +1,34 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class SaleOrder(models.Model): + _name = "sale.order" + _inherit = ["sale.order", "edi.auto.exchange.consumer.mixin", "edi.id.mixin"] + + # TODO: this field should be moved to the consumer mixin + # Each extending module should then override `states` as needed. + disable_edi_auto = fields.Boolean( + help="When marked, EDI automatic processing will be avoided", + readonly=True, + states={"draft": [("readonly", False)]}, + ) + # Receiver may send or not the response on create + # then for each update IF required. + # https://docs.oasis-open.org/ubl/os-UBL-2.3/UBL-2.3.html#S-ORDERING-POST-AWARD + # https://docs.peppol.eu/poacc/upgrade-3/profiles/28-ordering + # /#_response_code_on_header_level + + # TBD: implementing OrdResp for all modifications + # can be complex to manage (also for the 3rd party). + # Hence, we could block further modifications w/ sale exceptions + # and ask the sender to issue a new order request. + # This approach seems suitable only for orders that do not get processed immediately. + + +class SaleOrderLine(models.Model): + _name = "sale.order.line" + _inherit = ["sale.order.line", "edi.auto.exchange.consumer.mixin", "edi.id.mixin"] diff --git a/edi_sale_oca/readme/CONTRIBUTORS.rst b/edi_sale_oca/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..f1c71bce1 --- /dev/null +++ b/edi_sale_oca/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Simone Orsi diff --git a/edi_sale_oca/readme/DESCRIPTION.rst b/edi_sale_oca/readme/DESCRIPTION.rst new file mode 100644 index 000000000..1333ed77b --- /dev/null +++ b/edi_sale_oca/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +TODO diff --git a/edi_sale_oca/tests/__init__.py b/edi_sale_oca/tests/__init__.py new file mode 100644 index 000000000..25aeb70b8 --- /dev/null +++ b/edi_sale_oca/tests/__init__.py @@ -0,0 +1 @@ +from . import test_edi diff --git a/edi_sale_oca/tests/test_edi.py b/edi_sale_oca/tests/test_edi.py new file mode 100644 index 000000000..8ea209252 --- /dev/null +++ b/edi_sale_oca/tests/test_edi.py @@ -0,0 +1,107 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging + +from odoo import fields +from odoo.tests.common import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.addons.component.core import Component +from odoo.addons.component.tests.common import SavepointComponentRegistryCase + +_logger = logging.getLogger(__name__) + + +@tagged("-at_install", "post_install") +class EDIBackendTestCase(AccountTestInvoicingCommon, SavepointComponentRegistryCase): + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + + class SaleOrderEventListenerDemo(Component): + _name = "sale.order.event.listener.demo" + _inherit = "base.event.listener" + + def on_post_sale_order(self, move): + move.name = "new_name" + + def on_paid_sale_order(self, move): + move.name = "paid" + + def on_cancel_sale_order(self, move): + move.name = "cancelled" + + SaleOrderEventListenerDemo._build_component(cls.comp_registry) + cls.comp_registry._cache.clear() + cls.test_move = ( + cls.env["sale.order"] + .with_context(components_registry=cls.comp_registry) + .create( + { + "move_type": "out_invoice", + "partner_id": cls.partner_a.id, + "date": fields.Date.from_string("2016-01-01"), + "invoice_line_ids": [ + ( + 0, + None, + { + "name": "revenue line 1", + "account_id": cls.company_data[ + "default_account_revenue" + ].id, + "quantity": 1.0, + "price_unit": 100.0, + }, + ), + ( + 0, + None, + { + "name": "revenue line 2", + "account_id": cls.company_data[ + "default_account_revenue" + ].id, + "quantity": 1.0, + "price_unit": 100.0, + "tax_ids": [ + (6, 0, cls.company_data["default_tax_sale"].ids) + ], + }, + ), + ], + } + ) + ) + cls.test_move.refresh() + + def test_paid_move(self): + self.test_move.action_post() + self.assertEqual(self.test_move.name, "new_name") + + payment_action = self.test_move.action_register_payment() + payment = ( + self.env[payment_action["res_model"]] + .with_context(**payment_action["context"]) + .create( + { + "payment_method_id": self.env.ref( + "account.account_payment_method_manual_in" + ).id, + "journal_id": self.company_data["default_journal_bank"].id, + } + ) + ) + payment.with_context( + components_registry=self.comp_registry + ).action_create_payments() + self.assertEqual(self.test_move.name, "paid") + + def test_cancel_move(self): + self.test_move.action_post() + self.assertEqual(self.test_move.name, "new_name") + self.test_move.button_cancel() + self.assertEqual(self.test_move.name, "cancelled") diff --git a/edi_sale_oca/views/edi_exchange_record.xml b/edi_sale_oca/views/edi_exchange_record.xml new file mode 100644 index 000000000..45f6475be --- /dev/null +++ b/edi_sale_oca/views/edi_exchange_record.xml @@ -0,0 +1,30 @@ + + + + + + Sale Order Exchange Records + ir.actions.act_window + edi.exchange.record + tree,form + [('model', '=', 'sale.order')] + {} + + + + diff --git a/edi_sale_oca/views/res_partner.xml b/edi_sale_oca/views/res_partner.xml new file mode 100644 index 000000000..c0afc4a76 --- /dev/null +++ b/edi_sale_oca/views/res_partner.xml @@ -0,0 +1,22 @@ + + + + + res.partner.view.form + res.partner + + + + + + + + + + + diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml new file mode 100644 index 000000000..addb9e272 --- /dev/null +++ b/edi_sale_oca/views/sale_order.xml @@ -0,0 +1,35 @@ + + + + + sale.order.form (in edi_account) + sale.order + + + + + + + + + + + + + + + From 3b83d358824f20fcec42dcadd0cdbb58c0ce41ed Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Sun, 14 Aug 2022 09:48:06 +0200 Subject: [PATCH 02/62] edi_sale: take over edi_sale_order_import --- edi_sale_oca/README.rst | 89 +------------ edi_sale_oca/__init__.py | 1 + edi_sale_oca/__manifest__.py | 8 +- edi_sale_oca/components/__init__.py | 1 + edi_sale_oca/components/process.py | 92 +++++++++++++ edi_sale_oca/readme/DESCRIPTION.rst | 22 ++++ .../templates/exchange_chatter_msg.xml | 37 ++++++ edi_sale_oca/tests/__init__.py | 2 +- edi_sale_oca/tests/test_edi.py | 107 ---------------- edi_sale_oca/tests/test_process.py | 121 ++++++++++++++++++ edi_sale_oca/views/sale_order.xml | 1 + 11 files changed, 284 insertions(+), 197 deletions(-) create mode 100644 edi_sale_oca/components/__init__.py create mode 100644 edi_sale_oca/components/process.py create mode 100644 edi_sale_oca/templates/exchange_chatter_msg.xml delete mode 100644 edi_sale_oca/tests/test_edi.py create mode 100644 edi_sale_oca/tests/test_process.py diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index 7cffd6134..09c967b07 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -1,88 +1 @@ -=========== -Edi Account -=========== - -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! This file is generated by oca-gen-addon-readme !! - !! changes will be overwritten. !! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png - :target: https://odoo-community.org/page/development-status - :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png - :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html - :alt: License: LGPL-3 -.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github - :target: https://github.com/OCA/edi/tree/14.0/edi_account_oca - :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-edi_account_oca - :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 - -|badge1| |badge2| |badge3| |badge4| |badge5| - -This module intends to create a base to be extended by local edi rules -for accounting. - -In order to add a new integration for an account, you need to create a listener: - -.. code-block:: python - - class MyEventListener(Component): - _name = "sale.order.event.listener.demo" - _inherit = "base.event.listener" - _apply_on = ["sale.order"] - - def on_post_sale_order(self, move): - """Add your code here about creation of record""" - -A skip if decorator can be added in order to make some checks on the state of the move - -**Table of contents** - -.. contents:: - :local: - -Bug Tracker -=========== - -Bugs are tracked on `GitHub Issues `_. -In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. - -Do not contact contributors directly about support or help with technical issues. - -Credits -======= - -Authors -~~~~~~~ - -* Camptocamp SA - -Contributors -~~~~~~~~~~~~ - -* Enric Tobella - -Maintainers -~~~~~~~~~~~ - -This module is maintained by the OCA. - -.. image:: https://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: https://odoo-community.org - -OCA, or the Odoo Community Association, is a nonprofit organization whose -mission is to support the collaborative development of Odoo features and -promote its widespread use. - -This module is part of the `OCA/edi `_ project on GitHub. - -You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. +bot yet to come \ No newline at end of file diff --git a/edi_sale_oca/__init__.py b/edi_sale_oca/__init__.py index 0650744f6..f24d3e242 100644 --- a/edi_sale_oca/__init__.py +++ b/edi_sale_oca/__init__.py @@ -1 +1,2 @@ +from . import components from . import models diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index 80411ee1e..df245036b 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -12,10 +12,16 @@ "author": "Camptocamp,Odoo Community Association (OCA)", "maintainers": ["simahawk"], "website": "https://github.com/OCA/edi", - "depends": ["sale", "edi_oca", "component_event"], + "depends": [ + "edi_oca", + "edi_exchange_type_auto", + "sale_order_import", + ], "data": [ + "data/job_function.xml", "views/res_partner.xml", "views/sale_order.xml", "views/edi_exchange_record.xml", + "templates/exchange_chatter_msg.xml", ], } diff --git a/edi_sale_oca/components/__init__.py b/edi_sale_oca/components/__init__.py new file mode 100644 index 000000000..bfb4ceb84 --- /dev/null +++ b/edi_sale_oca/components/__init__.py @@ -0,0 +1 @@ +from . import process diff --git a/edi_sale_oca/components/process.py b/edi_sale_oca/components/process.py new file mode 100644 index 000000000..33f38ea47 --- /dev/null +++ b/edi_sale_oca/components/process.py @@ -0,0 +1,92 @@ +# Copyright 2021 Camptocamp SA +# @author: Simone Orsi +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import _, api +from odoo.exceptions import UserError + +from odoo.addons.component.core import Component + + +class EDIExchangeSOInput(Component): + """Process sale orders.""" + + _name = "edi.input.sale.order.process" + _inherit = "edi.component.input.mixin" + _usage = "input.process.sale.order" + + def __init__(self, work_context): + super().__init__(work_context) + self.settings = {} + # Suppor legacy key `self.type_settings` + for key in ("sale_order", "sale_order_import"): + if key in self.type_settings: + self.settings = self.type_settings.get(key, {}) + break + + def process(self): + wiz = self._setup_wizard() + res = wiz.import_order_button() + # TODO: log debug + if wiz.state == "update" and wiz.sale_id: + order = wiz.sale_id + msg = self.msg_order_existing_error + self._handle_existing_order(order, msg) + raise UserError(msg) + else: + order_id = res["res_id"] + order = self.env["sale.order"].browse(order_id) + if self._order_should_be_confirmed(): + order.action_confirm() + self.exchange_record.sudo()._set_related_record(order) + order._edi_set_origin(self.exchange_record) + return self.msg_order_created % order.name + raise UserError(self.msg_generic_error) + + @property + def msg_order_existing_error(self): + return _("Sales order has already been imported before") + + @property + def msg_order_created(self): + return _("Sales order %s created") + + @property + def msg_generic_error(self): + return _("Something went wrong with the importing wizard.") + + def _setup_wizard(self): + """Init a `sale.order.import` instance for current record.""" + ctx = self.settings.get("wiz_ctx", {}) + wiz = self.env["sale.order.import"].with_context(**ctx).sudo().create({}) + wiz.order_file = self.exchange_record._get_file_content(binary=False) + wiz.order_filename = self.exchange_record.exchange_filename + wiz.order_file_change() + wiz.price_source = self._get_default_price_source() + return wiz + + @api.model + def _get_default_price_source(self): + return self.settings.get("price_source", "pricelist") + + def _order_should_be_confirmed(self): + return self.settings.get("confirm_order", False) + + def _handle_existing_order(self, order, message): + prev_record = self._get_previous_record(order) + self.exchange_record.message_post_with_view( + "edi_sale_order_import.message_already_imported", + values={ + "order": order, + "prev_record": prev_record, + "message": message, + "level": "info", + }, + subtype_id=self.env.ref("mail.mt_note").id, + ) + + def _get_previous_record(self, order): + return self.env["edi.exchange.record"].search( + [("model", "=", "sale.order"), ("res_id", "=", order.id)], limit=1 + ) diff --git a/edi_sale_oca/readme/DESCRIPTION.rst b/edi_sale_oca/readme/DESCRIPTION.rst index 1333ed77b..c66a89709 100644 --- a/edi_sale_oca/readme/DESCRIPTION.rst +++ b/edi_sale_oca/readme/DESCRIPTION.rst @@ -1 +1,23 @@ TODO + +Inbound +~~~~~~~ +Receive sale orders from EDI channels. + +Control sale order confirmation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can decide if the order should be confirmed by exchange type. + +On your exchange type, go to advanced settings and add the following:: + + [...] + components: + process: + usage: input.process.sale.order + [...] + sale_order: + confirm_order: true + + +TODO: shall we add an exchange type example as demo? diff --git a/edi_sale_oca/templates/exchange_chatter_msg.xml b/edi_sale_oca/templates/exchange_chatter_msg.xml new file mode 100644 index 000000000..b57444cc5 --- /dev/null +++ b/edi_sale_oca/templates/exchange_chatter_msg.xml @@ -0,0 +1,37 @@ + + + + diff --git a/edi_sale_oca/tests/__init__.py b/edi_sale_oca/tests/__init__.py index 25aeb70b8..c2bb451dd 100644 --- a/edi_sale_oca/tests/__init__.py +++ b/edi_sale_oca/tests/__init__.py @@ -1 +1 @@ -from . import test_edi +from . import test_process diff --git a/edi_sale_oca/tests/test_edi.py b/edi_sale_oca/tests/test_edi.py deleted file mode 100644 index 8ea209252..000000000 --- a/edi_sale_oca/tests/test_edi.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2022 Camptocamp SA -# @author: Simone Orsi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). - -import logging - -from odoo import fields -from odoo.tests.common import tagged - -from odoo.addons.account.tests.common import AccountTestInvoicingCommon -from odoo.addons.component.core import Component -from odoo.addons.component.tests.common import SavepointComponentRegistryCase - -_logger = logging.getLogger(__name__) - - -@tagged("-at_install", "post_install") -class EDIBackendTestCase(AccountTestInvoicingCommon, SavepointComponentRegistryCase): - @classmethod - def setUpClass(cls, chart_template_ref=None): - super().setUpClass(chart_template_ref=chart_template_ref) - cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - - class SaleOrderEventListenerDemo(Component): - _name = "sale.order.event.listener.demo" - _inherit = "base.event.listener" - - def on_post_sale_order(self, move): - move.name = "new_name" - - def on_paid_sale_order(self, move): - move.name = "paid" - - def on_cancel_sale_order(self, move): - move.name = "cancelled" - - SaleOrderEventListenerDemo._build_component(cls.comp_registry) - cls.comp_registry._cache.clear() - cls.test_move = ( - cls.env["sale.order"] - .with_context(components_registry=cls.comp_registry) - .create( - { - "move_type": "out_invoice", - "partner_id": cls.partner_a.id, - "date": fields.Date.from_string("2016-01-01"), - "invoice_line_ids": [ - ( - 0, - None, - { - "name": "revenue line 1", - "account_id": cls.company_data[ - "default_account_revenue" - ].id, - "quantity": 1.0, - "price_unit": 100.0, - }, - ), - ( - 0, - None, - { - "name": "revenue line 2", - "account_id": cls.company_data[ - "default_account_revenue" - ].id, - "quantity": 1.0, - "price_unit": 100.0, - "tax_ids": [ - (6, 0, cls.company_data["default_tax_sale"].ids) - ], - }, - ), - ], - } - ) - ) - cls.test_move.refresh() - - def test_paid_move(self): - self.test_move.action_post() - self.assertEqual(self.test_move.name, "new_name") - - payment_action = self.test_move.action_register_payment() - payment = ( - self.env[payment_action["res_model"]] - .with_context(**payment_action["context"]) - .create( - { - "payment_method_id": self.env.ref( - "account.account_payment_method_manual_in" - ).id, - "journal_id": self.company_data["default_journal_bank"].id, - } - ) - ) - payment.with_context( - components_registry=self.comp_registry - ).action_create_payments() - self.assertEqual(self.test_move.name, "paid") - - def test_cancel_move(self): - self.test_move.action_post() - self.assertEqual(self.test_move.name, "new_name") - self.test_move.button_cancel() - self.assertEqual(self.test_move.name, "cancelled") diff --git a/edi_sale_oca/tests/test_process.py b/edi_sale_oca/tests/test_process.py new file mode 100644 index 000000000..d9e3f8958 --- /dev/null +++ b/edi_sale_oca/tests/test_process.py @@ -0,0 +1,121 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import base64 +import textwrap + +import mock + +from odoo import exceptions + +from odoo.addons.component.tests.common import SavepointComponentCase +from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin + + +class TestProcessComponent(SavepointComponentCase, EDIBackendTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.backend = cls._get_backend() + cls.exc_type = cls._create_exchange_type( + name="Test SO import", + code="test_so_import", + direction="input", + exchange_file_ext="xml", + exchange_filename_pattern="{record.identifier}-{type.code}-{dt}", + backend_id=cls.backend.id, + advanced_settings_edit=textwrap.dedent( + """ + components: + process: + usage: input.process.sale.order + sale_order_import: + wiz_ctx: + random_key: custom + """ + ), + ) + cls.record = cls.backend.create_record("test_so_import", {}) + cls.record._set_file_content(b"") + cls.wiz_model = cls.env["sale.order.import"] + + def test_lookup(self): + comp = self.backend._get_component(self.record, "process") + self.assertEqual(comp._name, "edi.input.sale.order.process") + + def test_wizard_setup(self): + comp = self.backend._get_component(self.record, "process") + with mock.patch.object( + type(self.wiz_model), "order_file_change" + ) as md_onchange: + wiz = comp._setup_wizard() + self.assertEqual(wiz._name, self.wiz_model._name) + self.assertEqual(wiz.env.context["random_key"], "custom") + self.assertEqual( + base64.b64decode(wiz.order_file), b"" + ) + self.assertEqual(wiz.order_filename, self.record.exchange_filename) + self.assertEqual(wiz.price_source, "pricelist") + md_onchange.assert_called() + + def test_settings(self): + self.exc_type.advanced_settings_edit = textwrap.dedent( + """ + components: + process: + usage: input.process.sale.order + sale_order_import: + price_source: order + confirm_order: true + """ + ) + comp = self.backend._get_component(self.record, "process") + self.assertEqual(comp._get_default_price_source(), "order") + self.assertTrue(comp._order_should_be_confirmed()) + + def test_existing_order(self): + order = self.env["sale.order"].create( + {"partner_id": self.env["res.partner"].search([], limit=1).id} + ) + comp = self.backend._get_component(self.record, "process") + m1 = mock.patch.object(type(self.wiz_model), "order_file_change") + m2 = mock.patch.object(type(self.wiz_model), "import_order_button") + m3 = mock.patch.object( + type(self.wiz_model), + "sale_id", + new_callable=mock.PropertyMock, + ) + m4 = mock.patch.object( + type(self.wiz_model), + "state", + new_callable=mock.PropertyMock, + ) + # Simulate the wizard detected an existing order state + err_msg = "Sales order has already been imported before" + with m1 as md_onchange, m2 as md_btn, m3 as md_sale_id, m4 as md_state: + md_sale_id.return_value = order + md_state.return_value = "update" + with self.assertRaisesRegex(exceptions.UserError, err_msg): + comp.process() + md_onchange.assert_called() + md_btn.assert_called() + self.assertEqual(self.exc_record_in.exchange_error, err_msg) + + def test_new_order(self): + order = self.env["sale.order"].create( + {"partner_id": self.env["res.partner"].search([], limit=1).id} + ) + comp = self.backend._get_component(self.record, "process") + mock1 = mock.patch.object(type(self.wiz_model), "order_file_change") + mock2 = mock.patch.object(type(self.wiz_model), "import_order_button") + self.assertFalse(self.record.record) + # Simulate the wizard detected an existing order state + with mock1 as md_onchange, mock2 as md_btn: + md_btn.return_value = {"res_id": order.id} + res = comp.process() + md_onchange.assert_called() + md_btn.assert_called() + self.assertEqual(res, f"Sales order {order.name} created") + + self.assertEqual(self.record.record, order) diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml index addb9e272..cebb3125e 100644 --- a/edi_sale_oca/views/sale_order.xml +++ b/edi_sale_oca/views/sale_order.xml @@ -11,6 +11,7 @@ + From 048a3d835c69077f717ea878fc04048c8fcfec5c Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 2 Sep 2022 14:45:50 +0200 Subject: [PATCH 03/62] edi_sale: filter/group by origin --- edi_sale_oca/views/sale_order.xml | 48 +++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml index cebb3125e..f4d584ad8 100644 --- a/edi_sale_oca/views/sale_order.xml +++ b/edi_sale_oca/views/sale_order.xml @@ -2,8 +2,8 @@ - - sale.order.form (in edi_account) + + sale.order.form (in edi_sale) sale.order @@ -12,6 +12,7 @@ + @@ -33,4 +34,47 @@ + + + sale.order.tree (in edi_sale) + sale.order + + + + + + + + + + + sale.order.search (in edi_sale) + sale.order + + + + + + + + + + + + + + + From 27e177c495d8f63246a651dace87f3c32706effb Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 14 Sep 2022 17:22:03 +0200 Subject: [PATCH 04/62] edi_sale: handle ext ref for sol --- edi_sale_oca/README.rst | 2 +- edi_sale_oca/__init__.py | 1 + edi_sale_oca/models/sale_order.py | 2 +- edi_sale_oca/wizard/__init__.py | 1 + edi_sale_oca/wizard/sale_order_import.py | 22 ++++++++++++++++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 edi_sale_oca/wizard/__init__.py create mode 100644 edi_sale_oca/wizard/sale_order_import.py diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index 09c967b07..40734932d 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -1 +1 @@ -bot yet to come \ No newline at end of file +bot yet to come diff --git a/edi_sale_oca/__init__.py b/edi_sale_oca/__init__.py index f24d3e242..d2243add2 100644 --- a/edi_sale_oca/__init__.py +++ b/edi_sale_oca/__init__.py @@ -1,2 +1,3 @@ from . import components from . import models +from . import wizard diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index b5bdb1b4e..005a09cf8 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -7,7 +7,7 @@ class SaleOrder(models.Model): _name = "sale.order" - _inherit = ["sale.order", "edi.auto.exchange.consumer.mixin", "edi.id.mixin"] + _inherit = ["sale.order", "edi.auto.exchange.consumer.mixin"] # TODO: this field should be moved to the consumer mixin # Each extending module should then override `states` as needed. diff --git a/edi_sale_oca/wizard/__init__.py b/edi_sale_oca/wizard/__init__.py new file mode 100644 index 000000000..e0ddf6156 --- /dev/null +++ b/edi_sale_oca/wizard/__init__.py @@ -0,0 +1 @@ +from . import sale_order_import diff --git a/edi_sale_oca/wizard/sale_order_import.py b/edi_sale_oca/wizard/sale_order_import.py new file mode 100644 index 000000000..cdb25a596 --- /dev/null +++ b/edi_sale_oca/wizard/sale_order_import.py @@ -0,0 +1,22 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import api, models + + +class SaleOrderImport(models.TransientModel): + _inherit = "sale.order.import" + + @api.model + def _prepare_create_order_line( + self, product, uom, order, import_line, price_source + ): + vals = super()._prepare_create_order_line( + product, uom, order, import_line, price_source + ) + # TODO: we should probably add an ext reference field to s.o.l. in sale_order_import + # and get rid of this override. + vals["edi_id"] = import_line.get("order_line_ref") + return vals From 83f1a7201cbb884d065e2b2de712f2cb1e8ae2ac Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 15 May 2023 16:10:39 +0200 Subject: [PATCH 05/62] edi_sale: show edi_id --- edi_sale_oca/views/sale_order.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml index f4d584ad8..61635df46 100644 --- a/edi_sale_oca/views/sale_order.xml +++ b/edi_sale_oca/views/sale_order.xml @@ -32,6 +32,18 @@ + + + + + + From ac2049c9375cbf1868480f6b90414fc4cfa6618a Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 18 May 2023 12:58:06 +0200 Subject: [PATCH 06/62] edi_sale: store metadata --- edi_sale_oca/__manifest__.py | 1 + edi_sale_oca/models/sale_order.py | 13 ++++++ edi_sale_oca/tests/test_process.py | 65 ++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index df245036b..40618b600 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -15,6 +15,7 @@ "depends": [ "edi_oca", "edi_exchange_type_auto", + "edi_record_metadata_oca", "sale_order_import", ], "data": [ diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 005a09cf8..fa431cab1 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -28,6 +28,19 @@ class SaleOrder(models.Model): # and ask the sender to issue a new order request. # This approach seems suitable only for orders that do not get processed immediately. + # edi_record_metadata api + def _edi_get_metadata_to_store(self, orig_vals): + data = super()._edi_get_metadata_to_store(orig_vals) + # collect line values + line_vals_by_edi_id = {} + for line_vals in orig_vals.get("order_line", []): + # line_vals in the form `(0, 0, vals)` + vals = line_vals[-1] + line_vals_by_edi_id[vals["edi_id"]] = vals + + data.update({"orig_values": {"lines": line_vals_by_edi_id}}) + return data + class SaleOrderLine(models.Model): _name = "sale.order.line" diff --git a/edi_sale_oca/tests/test_process.py b/edi_sale_oca/tests/test_process.py index d9e3f8958..629a0dc67 100644 --- a/edi_sale_oca/tests/test_process.py +++ b/edi_sale_oca/tests/test_process.py @@ -7,8 +7,6 @@ import mock -from odoo import exceptions - from odoo.addons.component.tests.common import SavepointComponentCase from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin @@ -17,6 +15,7 @@ class TestProcessComponent(SavepointComponentCase, EDIBackendTestMixin): @classmethod def setUpClass(cls): super().setUpClass() + cls._setup_env() cls.backend = cls._get_backend() cls.exc_type = cls._create_exchange_type( name="Test SO import", @@ -36,7 +35,9 @@ def setUpClass(cls): """ ), ) - cls.record = cls.backend.create_record("test_so_import", {}) + cls.record = cls.backend.create_record( + "test_so_import", {"edi_exchange_state": "input_received"} + ) cls.record._set_file_content(b"") cls.wiz_model = cls.env["sale.order.import"] @@ -74,11 +75,12 @@ def test_settings(self): self.assertEqual(comp._get_default_price_source(), "order") self.assertTrue(comp._order_should_be_confirmed()) + # In both tests here we don"t care about the specific format of the import. + # We only care that the wizard plugged with the component works as expected. def test_existing_order(self): order = self.env["sale.order"].create( {"partner_id": self.env["res.partner"].search([], limit=1).id} ) - comp = self.backend._get_component(self.record, "process") m1 = mock.patch.object(type(self.wiz_model), "order_file_change") m2 = mock.patch.object(type(self.wiz_model), "import_order_button") m3 = mock.patch.object( @@ -96,26 +98,65 @@ def test_existing_order(self): with m1 as md_onchange, m2 as md_btn, m3 as md_sale_id, m4 as md_state: md_sale_id.return_value = order md_state.return_value = "update" - with self.assertRaisesRegex(exceptions.UserError, err_msg): - comp.process() - md_onchange.assert_called() - md_btn.assert_called() - self.assertEqual(self.exc_record_in.exchange_error, err_msg) + self.record.action_exchange_process() + md_onchange.assert_called() + md_btn.assert_called() + self.assertEqual(self.record.exchange_error, err_msg) def test_new_order(self): + # Create the order manully and use it via the mock on md_btn order = self.env["sale.order"].create( {"partner_id": self.env["res.partner"].search([], limit=1).id} ) - comp = self.backend._get_component(self.record, "process") mock1 = mock.patch.object(type(self.wiz_model), "order_file_change") mock2 = mock.patch.object(type(self.wiz_model), "import_order_button") self.assertFalse(self.record.record) # Simulate the wizard detected an existing order state with mock1 as md_onchange, mock2 as md_btn: md_btn.return_value = {"res_id": order.id} - res = comp.process() + self.record.action_exchange_process() md_onchange.assert_called() md_btn.assert_called() - self.assertEqual(res, f"Sales order {order.name} created") + self.assertEqual(self.record.edi_exchange_state, "input_processed") self.assertEqual(self.record.record, order) + self.assertIn( + "Exchange processed successfully", + "|".join(order.message_ids.mapped("body")), + ) + + def test_metadata(self): + parsed_order = { + "partner": {"email": "john.doe@example.com"}, + "date": "2023-05-18", + "order_ref": "EDISALE", + "lines": [ + { + "product": {"code": "FURN_8888"}, + "qty": 1, + "uom": {"unece_code": "C62"}, + "price_unit": 100, + "order_line_ref": "1111", + } + ], + "chatter_msg": [], + "doc_type": "rfq", + } + self.wiz_model.with_context( + edi_framework_action="process", + sale_order_import__default_vals=dict( + origin_exchange_record_id=self.record.id + ), + ).create_order(parsed_order, "pricelist") + metadata = self.record.get_metadata() + # Lines are mapped via `edi_id` (coming from `order_line_ref` by default) + line_metadata = metadata["orig_values"]["lines"]["1111"] + for k in ( + "product_id", + "product_uom_qty", + "product_uom", + "name", + "price_unit", + "edi_id", + ): + self.assertIn(k, line_metadata) From e59340b6cb820ed89bbd68b4a0ec36081e4b50d6 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 19 May 2023 08:49:17 +0200 Subject: [PATCH 07/62] edi_sale: clean file and drop *type_auto dependency --- edi_sale_oca/__manifest__.py | 1 - edi_sale_oca/models/sale_order.py | 27 +++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index 40618b600..b469cdc1f 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -14,7 +14,6 @@ "website": "https://github.com/OCA/edi", "depends": [ "edi_oca", - "edi_exchange_type_auto", "edi_record_metadata_oca", "sale_order_import", ], diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index fa431cab1..870a9775c 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -7,15 +7,10 @@ class SaleOrder(models.Model): _name = "sale.order" - _inherit = ["sale.order", "edi.auto.exchange.consumer.mixin"] - - # TODO: this field should be moved to the consumer mixin - # Each extending module should then override `states` as needed. - disable_edi_auto = fields.Boolean( - help="When marked, EDI automatic processing will be avoided", - readonly=True, - states={"draft": [("readonly", False)]}, - ) + _inherit = [ + "sale.order", + "edi.exchange.consumer.mixin", + ] # Receiver may send or not the response on create # then for each update IF required. # https://docs.oasis-open.org/ubl/os-UBL-2.3/UBL-2.3.html#S-ORDERING-POST-AWARD @@ -28,6 +23,14 @@ class SaleOrder(models.Model): # and ask the sender to issue a new order request. # This approach seems suitable only for orders that do not get processed immediately. + # TODO: this field should be moved to the consumer mixin + # Each extending module should then override `states` as needed. + disable_edi_auto = fields.Boolean( + help="When marked, EDI automatic processing will be avoided", + readonly=True, + states={"draft": [("readonly", False)]}, + ) + # edi_record_metadata api def _edi_get_metadata_to_store(self, orig_vals): data = super()._edi_get_metadata_to_store(orig_vals) @@ -44,4 +47,8 @@ def _edi_get_metadata_to_store(self, orig_vals): class SaleOrderLine(models.Model): _name = "sale.order.line" - _inherit = ["sale.order.line", "edi.auto.exchange.consumer.mixin", "edi.id.mixin"] + _inherit = [ + "sale.order.line", + "edi.exchange.consumer.mixin", + "edi.id.mixin", + ] From 6ec588afc2300a56198c3187b082aa1f80e7a2c7 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 19 May 2023 09:37:57 +0200 Subject: [PATCH 08/62] edi_sale: add process hook for order create --- edi_sale_oca/components/process.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/edi_sale_oca/components/process.py b/edi_sale_oca/components/process.py index 33f38ea47..92eda3fd7 100644 --- a/edi_sale_oca/components/process.py +++ b/edi_sale_oca/components/process.py @@ -35,12 +35,7 @@ def process(self): self._handle_existing_order(order, msg) raise UserError(msg) else: - order_id = res["res_id"] - order = self.env["sale.order"].browse(order_id) - if self._order_should_be_confirmed(): - order.action_confirm() - self.exchange_record.sudo()._set_related_record(order) - order._edi_set_origin(self.exchange_record) + order = self._handle_create_order(res["res_id"]) return self.msg_order_created % order.name raise UserError(self.msg_generic_error) @@ -73,6 +68,14 @@ def _get_default_price_source(self): def _order_should_be_confirmed(self): return self.settings.get("confirm_order", False) + def _handle_create_order(self, order_id): + order = self.env["sale.order"].browse(order_id) + self.exchange_record._set_related_record(order) + order._edi_set_origin(self.exchange_record) + if self._order_should_be_confirmed(): + order.action_confirm() + return order + def _handle_existing_order(self, order, message): prev_record = self._get_previous_record(order) self.exchange_record.message_post_with_view( From ab8b349f449b05fbcccba1949e0a41b157b113a3 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 19 May 2023 15:25:24 +0200 Subject: [PATCH 09/62] edi_sale: process propagate edi origin --- edi_sale_oca/components/process.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/edi_sale_oca/components/process.py b/edi_sale_oca/components/process.py index 92eda3fd7..4b31fd892 100644 --- a/edi_sale_oca/components/process.py +++ b/edi_sale_oca/components/process.py @@ -54,6 +54,11 @@ def msg_generic_error(self): def _setup_wizard(self): """Init a `sale.order.import` instance for current record.""" ctx = self.settings.get("wiz_ctx", {}) + # Set the right EDI origin on both order and lines + edi_defaults = {"origin_exchange_record_id": self.exchange_record.id} + ctx["sale_order_import__default_vals"] = dict( + order=edi_defaults, lines=edi_defaults + ) wiz = self.env["sale.order.import"].with_context(**ctx).sudo().create({}) wiz.order_file = self.exchange_record._get_file_content(binary=False) wiz.order_filename = self.exchange_record.exchange_filename @@ -71,7 +76,6 @@ def _order_should_be_confirmed(self): def _handle_create_order(self, order_id): order = self.env["sale.order"].browse(order_id) self.exchange_record._set_related_record(order) - order._edi_set_origin(self.exchange_record) if self._order_should_be_confirmed(): order.action_confirm() return order From b1054f90e2e1d534bed2aa15532aef5cb2ea2ffc Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 23 May 2023 08:36:49 +0200 Subject: [PATCH 10/62] edi_sale: add edi_exchange_ready --- edi_sale_oca/models/sale_order.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 870a9775c..bb1350af8 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -2,7 +2,7 @@ # @author: Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import api, fields, models class SaleOrder(models.Model): @@ -52,3 +52,22 @@ class SaleOrderLine(models.Model): "edi.exchange.consumer.mixin", "edi.id.mixin", ] + + # TODO: add test + edi_exchange_ready = fields.Boolean(compute="_compute_edi_exchange_ready") + + @api.depends() + def _compute_edi_exchange_ready(self): + for rec in self: + rec.edi_exchange_ready = rec._edi_exchange_ready() + + def _edi_exchange_ready(self): + # TODO: not sure we want to exclude lines w/o qty. + # We could have lines that are replaced and kept w/ no qty. + # ATM we don't give full info on replacements on such lines. + # Lines are simply marked as changed. + return ( + not self._is_delivery() + and not self.display_type + and bool(self.product_uom_qty) + ) From 073271ae53f7b555275fd46fb563437f7ac672d3 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 26 May 2023 18:15:47 +0200 Subject: [PATCH 11/62] edi_sale: fix edi disable flag --- edi_sale_oca/models/sale_order.py | 6 ++---- edi_sale_oca/views/sale_order.xml | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index bb1350af8..1257d25ab 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -23,11 +23,7 @@ class SaleOrder(models.Model): # and ask the sender to issue a new order request. # This approach seems suitable only for orders that do not get processed immediately. - # TODO: this field should be moved to the consumer mixin - # Each extending module should then override `states` as needed. disable_edi_auto = fields.Boolean( - help="When marked, EDI automatic processing will be avoided", - readonly=True, states={"draft": [("readonly", False)]}, ) @@ -53,6 +49,8 @@ class SaleOrderLine(models.Model): "edi.id.mixin", ] + disable_edi_auto = fields.Boolean(related="order_id.disable_edi_auto") + # TODO: add test edi_exchange_ready = fields.Boolean(compute="_compute_edi_exchange_ready") diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml index 61635df46..a95bd268f 100644 --- a/edi_sale_oca/views/sale_order.xml +++ b/edi_sale_oca/views/sale_order.xml @@ -10,7 +10,10 @@ - + From e8d472a23ed9f674b653da9ab277e26509f57017 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 6 Jul 2023 13:26:38 +0200 Subject: [PATCH 12/62] edi_sale: fix _edi_exchange_ready for qty=0 Lines w/ no qty must not be excluded a priori --- edi_sale_oca/models/sale_order.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 1257d25ab..891ec196b 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -60,12 +60,4 @@ def _compute_edi_exchange_ready(self): rec.edi_exchange_ready = rec._edi_exchange_ready() def _edi_exchange_ready(self): - # TODO: not sure we want to exclude lines w/o qty. - # We could have lines that are replaced and kept w/ no qty. - # ATM we don't give full info on replacements on such lines. - # Lines are simply marked as changed. - return ( - not self._is_delivery() - and not self.display_type - and bool(self.product_uom_qty) - ) + return not self._is_delivery() and not self.display_type From ec256a244d2ee7b8929b91d0eb4e415c5ba2b489 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 7 Aug 2023 16:04:46 +0200 Subject: [PATCH 13/62] edi_sale: move OrderMixin from edi_sale_ubl --- edi_sale_oca/tests/common.py | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 edi_sale_oca/tests/common.py diff --git a/edi_sale_oca/tests/common.py b/edi_sale_oca/tests/common.py new file mode 100644 index 000000000..2fc1f1540 --- /dev/null +++ b/edi_sale_oca/tests/common.py @@ -0,0 +1,50 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields + + +class OrderMixin(object): + @classmethod + def _create_sale_order(cls, **kw): + """Create a sale order + + :return: sale order + """ + model = cls.env["sale.order"] + vals = dict(commitment_date=fields.Date.today()) + vals.update(kw) + so_vals = model.play_onchanges(vals, []) + if "order_line" in so_vals: + so_vals["order_line"] = [(0, 0, x) for x in vals["order_line"]] + return model.create(so_vals) + + @classmethod + def _setup_order(cls, **kw): + cls.product_a = cls.env.ref("product.product_product_4") + cls.product_a.barcode = "1" * 14 + cls.product_b = cls.env.ref("product.product_product_4b") + cls.product_b.barcode = "2" * 14 + cls.product_c = cls.env.ref("product.product_product_4c") + cls.product_c.barcode = "3" * 14 + cls.product_d = cls.env.ref("product.product_product_5") + cls.product_d.barcode = "4" * 14 + line_defaults = kw.pop("line_defaults", {}) + vals = { + "partner_id": cls.env.ref("base.res_partner_10").id, + "commitment_date": "2022-07-29", + } + vals.update(kw) + if "client_order_ref" not in vals: + vals["client_order_ref"] = "ABC123" + vals["order_line"] = [ + {"product_id": cls.product_a.id, "product_uom_qty": 300, "edi_id": 1000}, + {"product_id": cls.product_b.id, "product_uom_qty": 200, "edi_id": 2000}, + {"product_id": cls.product_c.id, "product_uom_qty": 100, "edi_id": 3000}, + ] + if line_defaults: + for line in vals["order_line"]: + line.update(line_defaults) + cls.sale = cls._create_sale_order(**vals) + cls.sale.action_confirm() From f27b5cd891d16912d0a9e0685fa11bfbfc4f599e Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 7 Aug 2023 16:07:01 +0200 Subject: [PATCH 14/62] edi_sale: fix test_process --- edi_sale_oca/tests/test_process.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edi_sale_oca/tests/test_process.py b/edi_sale_oca/tests/test_process.py index 629a0dc67..633ef24ed 100644 --- a/edi_sale_oca/tests/test_process.py +++ b/edi_sale_oca/tests/test_process.py @@ -145,7 +145,7 @@ def test_metadata(self): self.wiz_model.with_context( edi_framework_action="process", sale_order_import__default_vals=dict( - origin_exchange_record_id=self.record.id + order=dict(origin_exchange_record_id=self.record.id) ), ).create_order(parsed_order, "pricelist") metadata = self.record.get_metadata() From 1b25ef476c88094a93fe2683905189233ea2160a Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 7 Aug 2023 16:12:53 +0200 Subject: [PATCH 15/62] edi_sale: propagate origin on lines --- edi_sale_oca/models/sale_order.py | 10 +++++++ edi_sale_oca/tests/__init__.py | 1 + edi_sale_oca/tests/test_order.py | 50 +++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 edi_sale_oca/tests/test_order.py diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 891ec196b..7e3f23e29 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -61,3 +61,13 @@ def _compute_edi_exchange_ready(self): def _edi_exchange_ready(self): return not self._is_delivery() and not self.display_type + + @api.model_create_multi + def create(self, vals_list): + # Set default origin if not passed + for vals in vals_list: + orig_id = vals.get("origin_exchange_record_id") + if not orig_id and "order_id" in vals: + order = self.env["sale.order"].browse(vals["order_id"]) + vals["origin_exchange_record_id"] = order.origin_exchange_record_id.id + return super().create(vals_list) diff --git a/edi_sale_oca/tests/__init__.py b/edi_sale_oca/tests/__init__.py index c2bb451dd..80e522578 100644 --- a/edi_sale_oca/tests/__init__.py +++ b/edi_sale_oca/tests/__init__.py @@ -1 +1,2 @@ +from . import test_order from . import test_process diff --git a/edi_sale_oca/tests/test_order.py b/edi_sale_oca/tests/test_order.py new file mode 100644 index 000000000..3f231c380 --- /dev/null +++ b/edi_sale_oca/tests/test_order.py @@ -0,0 +1,50 @@ +# Copyright 2022 Camptocamp SA +# @author: Simone Orsi +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import SavepointCase + +from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin + +from .common import OrderMixin + + +class TestOrder(SavepointCase, EDIBackendTestMixin, OrderMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + # force metadata storage w/ proper key + cls.env = cls.env(context=dict(cls.env.context, edi_framework_action=True)) + cls._setup_records() + cls.exchange_type_in.exchange_filename_pattern = "{record.id}-{type.code}-{dt}" + cls.exc_record_in = cls.backend.create_record( + cls.exchange_type_in.code, {"edi_exchange_state": "input_received"} + ) + cls._setup_order( + origin_exchange_record_id=cls.exc_record_in.id, + ) + + def test_line_origin(self): + order = self.sale + self.assertEqual(order.origin_exchange_record_id, self.exc_record_in) + lines = order.order_line + self.env["sale.order.line"].create( + [ + { + "order_id": order.id, + "product_id": self.product_d.id, + "product_uom_qty": 300, + "edi_id": 4000, + }, + { + "order_id": order.id, + "product_id": self.product_d.id, + "product_uom_qty": 400, + "edi_id": 5000, + }, + ] + ) + order.invalidate_cache() + new_line1, new_line2 = order.order_line - lines + self.assertEqual(new_line1.origin_exchange_record_id, self.exc_record_in) + self.assertEqual(new_line2.origin_exchange_record_id, self.exc_record_in) From b6e5140c5bbc7d9347883d4edc33df08bb4c99a5 Mon Sep 17 00:00:00 2001 From: duongtq Date: Wed, 18 Oct 2023 10:55:58 +0700 Subject: [PATCH 16/62] [MIG] edi_sale_oca: Migration to 16.0 --- edi_sale_oca/README.rst | 116 +++++- edi_sale_oca/__manifest__.py | 4 +- edi_sale_oca/components/process.py | 14 +- edi_sale_oca/models/sale_order.py | 4 +- edi_sale_oca/readme/CONTRIBUTORS.rst | 1 + edi_sale_oca/readme/CREDITS.rst | 1 + edi_sale_oca/readme/DESCRIPTION.rst | 4 +- edi_sale_oca/static/description/index.html | 447 +++++++++++++++++++++ edi_sale_oca/tests/test_order.py | 6 +- edi_sale_oca/tests/test_process.py | 26 +- edi_sale_oca/views/sale_order.xml | 4 +- 11 files changed, 582 insertions(+), 45 deletions(-) create mode 100644 edi_sale_oca/readme/CREDITS.rst create mode 100644 edi_sale_oca/static/description/index.html diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index 40734932d..2897e4ddd 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -1 +1,115 @@ -bot yet to come +========= +EDI Sales +========= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a15a65af9b9ffa6808d4901942982eb8467aa13f7c1ac65c07f8751ccbceeff7 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |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--framework-lightgray.png?logo=github + :target: https://github.com/OCA/edi-framework/tree/16.0/edi_sale_oca + :alt: OCA/edi-framework +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/edi-framework-16-0/edi-framework-16-0-edi_sale_oca + :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-framework&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Inbound +~~~~~~~ +Receive sale orders from EDI channels. + +Control sale order confirmation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can decide if the order should be confirmed by exchange type. + +On your exchange type, go to advanced settings and add the following:: + + [...] + components: + process: + usage: input.process.sale.order + [...] + sale_order: + default_confirm_order: true + + +TODO: shall we add an exchange type example as demo? + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**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 +~~~~~~~~~~~~ + +* Simone Orsi +* Duong (Tran Quoc) + +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. + +.. 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. + +.. |maintainer-simahawk| image:: https://github.com/simahawk.png?size=40px + :target: https://github.com/simahawk + :alt: simahawk + +Current `maintainer `__: + +|maintainer-simahawk| + +This module is part of the `OCA/edi-framework `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index b469cdc1f..901509357 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -6,12 +6,12 @@ "summary": """ Configuration and special behaviors for EDI on sales. """, - "version": "14.0.1.0.0", + "version": "16.0.1.0.0", "development_status": "Alpha", "license": "AGPL-3", "author": "Camptocamp,Odoo Community Association (OCA)", "maintainers": ["simahawk"], - "website": "https://github.com/OCA/edi", + "website": "https://github.com/OCA/edi-framework", "depends": [ "edi_oca", "edi_record_metadata_oca", diff --git a/edi_sale_oca/components/process.py b/edi_sale_oca/components/process.py index 4b31fd892..61dbf53f7 100644 --- a/edi_sale_oca/components/process.py +++ b/edi_sale_oca/components/process.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import _, api +from odoo import _ from odoo.exceptions import UserError from odoo.addons.component.core import Component @@ -63,27 +63,17 @@ def _setup_wizard(self): wiz.order_file = self.exchange_record._get_file_content(binary=False) wiz.order_filename = self.exchange_record.exchange_filename wiz.order_file_change() - wiz.price_source = self._get_default_price_source() return wiz - @api.model - def _get_default_price_source(self): - return self.settings.get("price_source", "pricelist") - - def _order_should_be_confirmed(self): - return self.settings.get("confirm_order", False) - def _handle_create_order(self, order_id): order = self.env["sale.order"].browse(order_id) self.exchange_record._set_related_record(order) - if self._order_should_be_confirmed(): - order.action_confirm() return order def _handle_existing_order(self, order, message): prev_record = self._get_previous_record(order) self.exchange_record.message_post_with_view( - "edi_sale_order_import.message_already_imported", + "edi_sale_oca.message_already_imported", values={ "order": order, "prev_record": prev_record, diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 7e3f23e29..bd025230f 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -23,7 +23,7 @@ class SaleOrder(models.Model): # and ask the sender to issue a new order request. # This approach seems suitable only for orders that do not get processed immediately. - disable_edi_auto = fields.Boolean( + edi_disable_auto = fields.Boolean( states={"draft": [("readonly", False)]}, ) @@ -49,7 +49,7 @@ class SaleOrderLine(models.Model): "edi.id.mixin", ] - disable_edi_auto = fields.Boolean(related="order_id.disable_edi_auto") + edi_disable_auto = fields.Boolean(related="order_id.edi_disable_auto") # TODO: add test edi_exchange_ready = fields.Boolean(compute="_compute_edi_exchange_ready") diff --git a/edi_sale_oca/readme/CONTRIBUTORS.rst b/edi_sale_oca/readme/CONTRIBUTORS.rst index f1c71bce1..20b0da936 100644 --- a/edi_sale_oca/readme/CONTRIBUTORS.rst +++ b/edi_sale_oca/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Simone Orsi +* Duong (Tran Quoc) diff --git a/edi_sale_oca/readme/CREDITS.rst b/edi_sale_oca/readme/CREDITS.rst new file mode 100644 index 000000000..4c5b2fca2 --- /dev/null +++ b/edi_sale_oca/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/edi_sale_oca/readme/DESCRIPTION.rst b/edi_sale_oca/readme/DESCRIPTION.rst index c66a89709..b11290099 100644 --- a/edi_sale_oca/readme/DESCRIPTION.rst +++ b/edi_sale_oca/readme/DESCRIPTION.rst @@ -1,5 +1,3 @@ -TODO - Inbound ~~~~~~~ Receive sale orders from EDI channels. @@ -17,7 +15,7 @@ On your exchange type, go to advanced settings and add the following:: usage: input.process.sale.order [...] sale_order: - confirm_order: true + default_confirm_order: true TODO: shall we add an exchange type example as demo? diff --git a/edi_sale_oca/static/description/index.html b/edi_sale_oca/static/description/index.html new file mode 100644 index 000000000..eada31a83 --- /dev/null +++ b/edi_sale_oca/static/description/index.html @@ -0,0 +1,447 @@ + + + + + + +EDI Sales + + + +
+

EDI Sales

+ + +

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

+
+

Inbound

+

Receive sale orders from EDI channels.

+
+
+

Control sale order confirmation

+

You can decide if the order should be confirmed by exchange type.

+

On your exchange type, go to advanced settings and add the following:

+
+[...]
+components:
+    process:
+        usage: input.process.sale.order
+[...]
+sale_order:
+    default_confirm_order: true
+
+

TODO: shall we add an exchange type example as demo?

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

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.

+
+ +
+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

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.

+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.

+

Current maintainer:

+

simahawk

+

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

+

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

+
+
+ + diff --git a/edi_sale_oca/tests/test_order.py b/edi_sale_oca/tests/test_order.py index 3f231c380..ad91d79c2 100644 --- a/edi_sale_oca/tests/test_order.py +++ b/edi_sale_oca/tests/test_order.py @@ -2,14 +2,14 @@ # @author: Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.tests.common import SavepointCase +from odoo.tests.common import TransactionCase from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin from .common import OrderMixin -class TestOrder(SavepointCase, EDIBackendTestMixin, OrderMixin): +class TestOrder(TransactionCase, EDIBackendTestMixin, OrderMixin): @classmethod def setUpClass(cls): super().setUpClass() @@ -44,7 +44,7 @@ def test_line_origin(self): }, ] ) - order.invalidate_cache() + order.env.invalidate_all() new_line1, new_line2 = order.order_line - lines self.assertEqual(new_line1.origin_exchange_record_id, self.exc_record_in) self.assertEqual(new_line2.origin_exchange_record_id, self.exc_record_in) diff --git a/edi_sale_oca/tests/test_process.py b/edi_sale_oca/tests/test_process.py index 633ef24ed..1ec85332c 100644 --- a/edi_sale_oca/tests/test_process.py +++ b/edi_sale_oca/tests/test_process.py @@ -4,14 +4,13 @@ import base64 import textwrap +from unittest import mock -import mock - -from odoo.addons.component.tests.common import SavepointComponentCase +from odoo.addons.component.tests.common import TransactionComponentCase from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin -class TestProcessComponent(SavepointComponentCase, EDIBackendTestMixin): +class TestProcessComponent(TransactionComponentCase, EDIBackendTestMixin): @classmethod def setUpClass(cls): super().setUpClass() @@ -24,6 +23,7 @@ def setUpClass(cls): exchange_file_ext="xml", exchange_filename_pattern="{record.identifier}-{type.code}-{dt}", backend_id=cls.backend.id, + # Bypass required fields with default_import_type = 'xml' in sale_order_import advanced_settings_edit=textwrap.dedent( """ components: @@ -32,6 +32,8 @@ def setUpClass(cls): sale_order_import: wiz_ctx: random_key: custom + default_price_source: 'pricelist' + default_import_type: 'xml' """ ), ) @@ -60,21 +62,6 @@ def test_wizard_setup(self): self.assertEqual(wiz.price_source, "pricelist") md_onchange.assert_called() - def test_settings(self): - self.exc_type.advanced_settings_edit = textwrap.dedent( - """ - components: - process: - usage: input.process.sale.order - sale_order_import: - price_source: order - confirm_order: true - """ - ) - comp = self.backend._get_component(self.record, "process") - self.assertEqual(comp._get_default_price_source(), "order") - self.assertTrue(comp._order_should_be_confirmed()) - # In both tests here we don"t care about the specific format of the import. # We only care that the wizard plugged with the component works as expected. def test_existing_order(self): @@ -155,7 +142,6 @@ def test_metadata(self): "product_id", "product_uom_qty", "product_uom", - "name", "price_unit", "edi_id", ): diff --git a/edi_sale_oca/views/sale_order.xml b/edi_sale_oca/views/sale_order.xml index a95bd268f..857129b38 100644 --- a/edi_sale_oca/views/sale_order.xml +++ b/edi_sale_oca/views/sale_order.xml @@ -11,7 +11,7 @@ @@ -42,7 +42,7 @@
From c00ec381336b64732c31f7debe8c10eb385e5b7b Mon Sep 17 00:00:00 2001 From: duongtq Date: Wed, 18 Oct 2023 10:59:36 +0700 Subject: [PATCH 17/62] [IMP] edi_sale_oca: Support edi_id for edi_sale_edifact_oca --- edi_sale_oca/wizard/sale_order_import.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/edi_sale_oca/wizard/sale_order_import.py b/edi_sale_oca/wizard/sale_order_import.py index cdb25a596..81a30e8f9 100644 --- a/edi_sale_oca/wizard/sale_order_import.py +++ b/edi_sale_oca/wizard/sale_order_import.py @@ -18,5 +18,7 @@ def _prepare_create_order_line( ) # TODO: we should probably add an ext reference field to s.o.l. in sale_order_import # and get rid of this override. - vals["edi_id"] = import_line.get("order_line_ref") + vals["edi_id"] = import_line.get("order_line_ref") or import_line.get( + "sequence" + ) return vals From 5694aa34cc92c14d78fb452a29f872ce658f422e Mon Sep 17 00:00:00 2001 From: duongtq Date: Thu, 26 Oct 2023 10:04:46 +0700 Subject: [PATCH 18/62] [IMP] edi_sale_oca: Refactor code for passing all configurations via env_ctx The configurations here are values for the wizard and whatever we need --- edi_sale_oca/README.rst | 16 +++++++++++----- edi_sale_oca/components/process.py | 21 ++++++++------------- edi_sale_oca/readme/DESCRIPTION.rst | 12 +++++++++--- edi_sale_oca/static/description/index.html | 14 ++++++++++---- edi_sale_oca/tests/test_process.py | 9 ++++----- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index 2897e4ddd..b0124caf2 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -7,7 +7,7 @@ EDI Sales !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:a15a65af9b9ffa6808d4901942982eb8467aa13f7c1ac65c07f8751ccbceeff7 + !! source digest: sha256:fb52928e31a51155acf8913e3bded99f8f488dc78beadcf8d6e35bb1f29b1bae !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png @@ -43,10 +43,16 @@ On your exchange type, go to advanced settings and add the following:: components: process: usage: input.process.sale.order - [...] - sale_order: - default_confirm_order: true - + env_ctx: + # Values for the wizard + default_confirm_order: true + default_price_source: order + # Custom keys, whatever you need + random_one: true + +Note that `env_ctx` will propagate all keys to the whole env so you can use it +for any kind of context related configuration. In the case of the sale order import wizard +here we are just passing defaults as we could do in odoo standard. TODO: shall we add an exchange type example as demo? diff --git a/edi_sale_oca/components/process.py b/edi_sale_oca/components/process.py index 61dbf53f7..13bce23e5 100644 --- a/edi_sale_oca/components/process.py +++ b/edi_sale_oca/components/process.py @@ -16,15 +16,6 @@ class EDIExchangeSOInput(Component): _inherit = "edi.component.input.mixin" _usage = "input.process.sale.order" - def __init__(self, work_context): - super().__init__(work_context) - self.settings = {} - # Suppor legacy key `self.type_settings` - for key in ("sale_order", "sale_order_import"): - if key in self.type_settings: - self.settings = self.type_settings.get(key, {}) - break - def process(self): wiz = self._setup_wizard() res = wiz.import_order_button() @@ -53,13 +44,17 @@ def msg_generic_error(self): def _setup_wizard(self): """Init a `sale.order.import` instance for current record.""" - ctx = self.settings.get("wiz_ctx", {}) # Set the right EDI origin on both order and lines edi_defaults = {"origin_exchange_record_id": self.exchange_record.id} - ctx["sale_order_import__default_vals"] = dict( - order=edi_defaults, lines=edi_defaults + addtional_ctx = dict( + sale_order_import__default_vals=dict(order=edi_defaults, lines=edi_defaults) + ) + wiz = ( + self.env["sale.order.import"] + .with_context(**addtional_ctx) + .sudo() + .create({}) ) - wiz = self.env["sale.order.import"].with_context(**ctx).sudo().create({}) wiz.order_file = self.exchange_record._get_file_content(binary=False) wiz.order_filename = self.exchange_record.exchange_filename wiz.order_file_change() diff --git a/edi_sale_oca/readme/DESCRIPTION.rst b/edi_sale_oca/readme/DESCRIPTION.rst index b11290099..55cdc88ed 100644 --- a/edi_sale_oca/readme/DESCRIPTION.rst +++ b/edi_sale_oca/readme/DESCRIPTION.rst @@ -13,9 +13,15 @@ On your exchange type, go to advanced settings and add the following:: components: process: usage: input.process.sale.order - [...] - sale_order: - default_confirm_order: true + env_ctx: + # Values for the wizard + default_confirm_order: true + default_price_source: order + # Custom keys, whatever you need + random_one: true +Note that `env_ctx` will propagate all keys to the whole env so you can use it +for any kind of context related configuration. In the case of the sale order import wizard +here we are just passing defaults as we could do in odoo standard. TODO: shall we add an exchange type example as demo? diff --git a/edi_sale_oca/static/description/index.html b/edi_sale_oca/static/description/index.html index eada31a83..5afcfd7b5 100644 --- a/edi_sale_oca/static/description/index.html +++ b/edi_sale_oca/static/description/index.html @@ -367,7 +367,7 @@

EDI Sales

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:a15a65af9b9ffa6808d4901942982eb8467aa13f7c1ac65c07f8751ccbceeff7 +!! source digest: sha256:fb52928e31a51155acf8913e3bded99f8f488dc78beadcf8d6e35bb1f29b1bae !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

@@ -383,10 +383,16 @@

Control sale order confirmation

components: process: usage: input.process.sale.order -[...] -sale_order: - default_confirm_order: true + env_ctx: + # Values for the wizard + default_confirm_order: true + default_price_source: order + # Custom keys, whatever you need + random_one: true +

Note that env_ctx will propagate all keys to the whole env so you can use it +for any kind of context related configuration. In the case of the sale order import wizard +here we are just passing defaults as we could do in odoo standard.

TODO: shall we add an exchange type example as demo?

Important

diff --git a/edi_sale_oca/tests/test_process.py b/edi_sale_oca/tests/test_process.py index 1ec85332c..dbf05bbe3 100644 --- a/edi_sale_oca/tests/test_process.py +++ b/edi_sale_oca/tests/test_process.py @@ -29,11 +29,10 @@ def setUpClass(cls): components: process: usage: input.process.sale.order - sale_order_import: - wiz_ctx: - random_key: custom - default_price_source: 'pricelist' - default_import_type: 'xml' + env_ctx: + default_price_source: 'pricelist' + default_import_type: 'xml' + random_key: custom """ ), ) From c9a5ad78503c29edfd0463f75c56d25f8e32314f Mon Sep 17 00:00:00 2001 From: oca-ci Date: Tue, 21 Nov 2023 09:00:04 +0000 Subject: [PATCH 19/62] [UPD] Update edi_sale_oca.pot --- edi_sale_oca/i18n/edi_sale_oca.pot | 176 +++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 edi_sale_oca/i18n/edi_sale_oca.pot diff --git a/edi_sale_oca/i18n/edi_sale_oca.pot b/edi_sale_oca/i18n/edi_sale_oca.pot new file mode 100644 index 000000000..55c4deef7 --- /dev/null +++ b/edi_sale_oca/i18n/edi_sale_oca.pot @@ -0,0 +1,176 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * edi_sale_oca +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form +msgid "EDI" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.message_already_imported +msgid "Message:" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.message_already_imported +msgid "Order:" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.message_already_imported +msgid "Previous record:" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_disable_auto +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_disable_auto +msgid "Disable auto" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form +msgid "Disable automated actions" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_root +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_partner_form +msgid "EDI" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter +msgid "EDI exchange" +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter +msgid "EDI exchange type" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__origin_exchange_type_id +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__origin_exchange_type_id +msgid "EDI origin exchange type" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__origin_exchange_record_id +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__origin_exchange_record_id +msgid "EDI origin record" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order__origin_exchange_record_id +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__origin_exchange_record_id +msgid "EDI record that originated this document." +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_id +msgid "Edi" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_config +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_config +msgid "Edi Config" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_exchange_ready +msgid "Edi Exchange Ready" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_has_form_config +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_has_form_config +msgid "Edi Has Form Config" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_record_ids +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_record_ids +msgid "Exchange Record" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_record_count +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_record_count +msgid "Exchange Record Count" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_records +msgid "Exchanges" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__edi_id +msgid "Internal or external identifier for records." +msgstr "" + +#. module: edi_sale_oca +#: model:ir.actions.act_window,name:edi_sale_oca.act_open_edi_exchange_record_sale_order_view +msgid "Sale Order Exchange Records" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model,name:edi_sale_oca.model_sale_order_import +msgid "Sale Order Import from Files" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model,name:edi_sale_oca.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model,name:edi_sale_oca.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: edi_sale_oca +#. odoo-python +#: code:addons/edi_sale_oca/components/process.py:0 +#, python-format +msgid "Sales order %s created" +msgstr "" + +#. module: edi_sale_oca +#. odoo-python +#: code:addons/edi_sale_oca/components/process.py:0 +#, python-format +msgid "Sales order has already been imported before" +msgstr "" + +#. module: edi_sale_oca +#. odoo-python +#: code:addons/edi_sale_oca/components/process.py:0 +#, python-format +msgid "Something went wrong with the importing wizard." +msgstr "" + +#. module: edi_sale_oca +#: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter +msgid "Source: EDI" +msgstr "" + +#. module: edi_sale_oca +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order__edi_disable_auto +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__edi_disable_auto +msgid "When marked, EDI automatic processing will be avoided" +msgstr "" From 3ae07c09253e7c2c93c63e39ce7880e97d5bcfbc Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 21 Nov 2023 09:02:26 +0000 Subject: [PATCH 20/62] [BOT] post-merge updates --- edi_sale_oca/README.rst | 2 +- edi_sale_oca/static/description/icon.png | Bin 0 -> 9455 bytes edi_sale_oca/static/description/index.html | 22 ++++++++++----------- 3 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 edi_sale_oca/static/description/icon.png diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index b0124caf2..8e35d6304 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -7,7 +7,7 @@ EDI Sales !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:fb52928e31a51155acf8913e3bded99f8f488dc78beadcf8d6e35bb1f29b1bae + !! source digest: sha256:5fcc2020f8975d9b8c3b277ca820d949c0e52fa907f0c00959ad9ec751105d5d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png diff --git a/edi_sale_oca/static/description/icon.png b/edi_sale_oca/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/edi_sale_oca/static/description/index.html b/edi_sale_oca/static/description/index.html index 5afcfd7b5..fbc668202 100644 --- a/edi_sale_oca/static/description/index.html +++ b/edi_sale_oca/static/description/index.html @@ -1,20 +1,20 @@ - + - + EDI Sales -
-

EDI Sales

+
+ + +Odoo Community Association + +
+

EDI Sales

-

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

+

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

Handle sale orders via EDI.

This is a base module to plug sales processes with the EDI framework.

To handle inbound/outbound sale orders, you need to use @@ -395,7 +400,7 @@

EDI Sales

-

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 to smash it by providing a detailed and welcomed @@ -403,15 +408,15 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
-

Contributors

+

Contributors

-

Other credits

+

Other credits

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

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -439,5 +444,6 @@

Maintainers

+
From f02e25416bc7403143d331c1ddd612205ca3b057 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 19 Jun 2025 12:44:13 +0000 Subject: [PATCH 55/62] Translated using Weblate (Italian) Currently translated at 100.0% (30 of 30 strings) Translation: edi-framework-18.0/edi-framework-18.0-edi_sale_oca Translate-URL: https://translation.odoo-community.org/projects/edi-framework-18-0/edi-framework-18-0-edi_sale_oca/it/ --- edi_sale_oca/i18n/it.po | 64 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/edi_sale_oca/i18n/it.po b/edi_sale_oca/i18n/it.po index 0c9ee8cce..59c47d3a7 100644 --- a/edi_sale_oca/i18n/it.po +++ b/edi_sale_oca/i18n/it.po @@ -6,179 +6,181 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2025-06-19 15:25+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form msgid "EDI" -msgstr "" +msgstr "EDI" #. module: edi_sale_oca #: model:ir.model,name:edi_sale_oca.model_res_partner msgid "Contact" -msgstr "" +msgstr "Contatto" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__disable_edi_auto #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__disable_edi_auto msgid "Disable auto" -msgstr "" +msgstr "Disabilita automatico" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form msgid "Disable automated actions" -msgstr "" +msgstr "Disabilita azioni automatiche" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner__display_name #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__display_name #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__display_name msgid "Display Name" -msgstr "" +msgstr "Nome visualizzato" #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_root #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form msgid "EDI" -msgstr "" +msgstr "EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_id msgid "EDI ID" -msgstr "" +msgstr "ID EDI" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter msgid "EDI exchange" -msgstr "" +msgstr "Scambio EDI" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter msgid "EDI exchange type" -msgstr "" +msgstr "Tipo scambio EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__origin_edi_endpoint_id #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__origin_edi_endpoint_id msgid "EDI origin endpoint" -msgstr "" +msgstr "Endpoint origine EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__origin_exchange_type_id #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__origin_exchange_type_id msgid "EDI origin exchange type" -msgstr "" +msgstr "Tipo scambio origine EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__origin_exchange_record_id #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__origin_exchange_record_id msgid "EDI origin record" -msgstr "" +msgstr "Record origine EDI" #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order__origin_exchange_record_id #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__origin_exchange_record_id msgid "EDI record that originated this document." -msgstr "" +msgstr "Record EDI che ha generato questo documento." #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner__edi_sale_conf_ids #: model:ir.model.fields,field_description:edi_sale_oca.field_res_users__edi_sale_conf_ids msgid "EDI sale configuration" -msgstr "" +msgstr "Configurazione vendite EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_config #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_config msgid "Edi Config" -msgstr "" +msgstr "Configurazione EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_exchange_ready msgid "Edi Exchange Ready" -msgstr "" +msgstr "Pronto allo scambio EDI" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_has_form_config #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_has_form_config msgid "Edi Has Form Config" -msgstr "" +msgstr "EDI ha una maschera di configurazione" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_record_ids #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_record_ids msgid "Exchange Record" -msgstr "" +msgstr "Record di scambio" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_record_count #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_record_count msgid "Exchange Record Count" -msgstr "" +msgstr "Conteggio record di scambio" #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_records msgid "Exchanges" -msgstr "" +msgstr "Scambi" #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner__id #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__id #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__id msgid "ID" -msgstr "" +msgstr "ID" #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__edi_id msgid "Internal or external identifier for records." -msgstr "" +msgstr "Identificatore interno o esterno per i record." #. module: edi_sale_oca #: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner____last_update #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order____last_update #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line____last_update msgid "Last Modified on" -msgstr "" +msgstr "Ultima modifica il" #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order__origin_edi_endpoint_id #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__origin_edi_endpoint_id msgid "Record generated via this endpoint" -msgstr "" +msgstr "Record generato attraverso questo endpoint" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_partner_form msgid "Sale" -msgstr "" +msgstr "Vendita" #. module: edi_sale_oca #: model:ir.actions.act_window,name:edi_sale_oca.act_open_edi_exchange_record_sale_order_view msgid "Sale Order Exchange Records" -msgstr "" +msgstr "Record scambio ordine di vendita" #. module: edi_sale_oca #: model:ir.model,name:edi_sale_oca.model_sale_order msgid "Sales Order" -msgstr "" +msgstr "Ordine di vendita" #. module: edi_sale_oca #: model:ir.model,name:edi_sale_oca.model_sale_order_line msgid "Sales Order Line" -msgstr "" +msgstr "Riga ordine di vendita" #. module: edi_sale_oca #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_sales_order_filter msgid "Source: EDI" -msgstr "" +msgstr "Origine: EDI" #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order__disable_edi_auto #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__disable_edi_auto msgid "When marked, EDI automatic processing will be avoided" -msgstr "" +msgstr "Quando selezionata, l'elaborazione EDI automatica verrĂ  evitata" From 73dc11c4bf16386ac4e604361f9ecc4724a85e61 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 11 Sep 2025 11:57:46 +0000 Subject: [PATCH 56/62] [UPD] Update edi_sale_oca.pot --- edi_sale_oca/i18n/edi_sale_oca.pot | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/edi_sale_oca/i18n/edi_sale_oca.pot b/edi_sale_oca/i18n/edi_sale_oca.pot index 87a295983..a63014d51 100644 --- a/edi_sale_oca/i18n/edi_sale_oca.pot +++ b/edi_sale_oca/i18n/edi_sale_oca.pot @@ -114,6 +114,12 @@ msgstr "" msgid "Exchange Record Count" msgstr "" +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_related_record_ids +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_related_record_ids +msgid "Exchange Related Record" +msgstr "" + #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_records msgid "Exchanges" From 2eaa194965b80a9e0f4d0cdaa53bcb6285b4c7b5 Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 11 Sep 2025 12:01:14 +0000 Subject: [PATCH 57/62] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: edi-framework-18.0/edi-framework-18.0-edi_sale_oca Translate-URL: https://translation.odoo-community.org/projects/edi-framework-18-0/edi-framework-18-0-edi_sale_oca/ --- edi_sale_oca/i18n/it.po | 44 ++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/edi_sale_oca/i18n/it.po b/edi_sale_oca/i18n/it.po index 59c47d3a7..5c37d977a 100644 --- a/edi_sale_oca/i18n/it.po +++ b/edi_sale_oca/i18n/it.po @@ -27,8 +27,8 @@ msgid "Contact" msgstr "Contatto" #. module: edi_sale_oca -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__disable_edi_auto -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__disable_edi_auto +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__edi_disable_auto +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__edi_disable_auto msgid "Disable auto" msgstr "Disabilita automatico" @@ -37,13 +37,6 @@ msgstr "Disabilita automatico" msgid "Disable automated actions" msgstr "Disabilita azioni automatiche" -#. module: edi_sale_oca -#: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner__display_name -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__display_name -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__display_name -msgid "Display Name" -msgstr "Nome visualizzato" - #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_root #: model_terms:ir.ui.view,arch_db:edi_sale_oca.view_order_form @@ -124,30 +117,22 @@ msgstr "Record di scambio" msgid "Exchange Record Count" msgstr "Conteggio record di scambio" +#. module: edi_sale_oca +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_related_record_ids +#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_related_record_ids +msgid "Exchange Related Record" +msgstr "" + #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_records msgid "Exchanges" msgstr "Scambi" -#. module: edi_sale_oca -#: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner__id -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__id -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__id -msgid "ID" -msgstr "ID" - #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__edi_id msgid "Internal or external identifier for records." msgstr "Identificatore interno o esterno per i record." -#. module: edi_sale_oca -#: model:ir.model.fields,field_description:edi_sale_oca.field_res_partner____last_update -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order____last_update -#: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line____last_update -msgid "Last Modified on" -msgstr "Ultima modifica il" - #. module: edi_sale_oca #: model:ir.model.fields,help:edi_sale_oca.field_sale_order__origin_edi_endpoint_id #: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__origin_edi_endpoint_id @@ -180,7 +165,16 @@ msgid "Source: EDI" msgstr "Origine: EDI" #. module: edi_sale_oca -#: model:ir.model.fields,help:edi_sale_oca.field_sale_order__disable_edi_auto -#: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__disable_edi_auto +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order__edi_disable_auto +#: model:ir.model.fields,help:edi_sale_oca.field_sale_order_line__edi_disable_auto msgid "When marked, EDI automatic processing will be avoided" msgstr "Quando selezionata, l'elaborazione EDI automatica verrĂ  evitata" + +#~ msgid "Display Name" +#~ msgstr "Nome visualizzato" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" From e0048bb03fba74a4db100a595ca71963b934e162 Mon Sep 17 00:00:00 2001 From: mymage Date: Mon, 15 Sep 2025 06:36:35 +0000 Subject: [PATCH 58/62] Translated using Weblate (Italian) Currently translated at 100.0% (28 of 28 strings) Translation: edi-framework-18.0/edi-framework-18.0-edi_sale_oca Translate-URL: https://translation.odoo-community.org/projects/edi-framework-18-0/edi-framework-18-0-edi_sale_oca/it/ --- edi_sale_oca/i18n/it.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/edi_sale_oca/i18n/it.po b/edi_sale_oca/i18n/it.po index 5c37d977a..5e9c2f875 100644 --- a/edi_sale_oca/i18n/it.po +++ b/edi_sale_oca/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-19 15:25+0000\n" +"PO-Revision-Date: 2025-09-15 08:42+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -121,7 +121,7 @@ msgstr "Conteggio record di scambio" #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order__exchange_related_record_ids #: model:ir.model.fields,field_description:edi_sale_oca.field_sale_order_line__exchange_related_record_ids msgid "Exchange Related Record" -msgstr "" +msgstr "Record relativo allo scambio" #. module: edi_sale_oca #: model:ir.ui.menu,name:edi_sale_oca.menu_sale_edi_records From 5405714770446553fc42bbccc4776cc4da26f90b Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Fri, 29 Aug 2025 19:27:34 +0200 Subject: [PATCH 59/62] [IMP] edi_sale_oca: Adapt to new edi_core_oca logic Remove components and use new system for configuration --- edi_sale_oca/__init__.py | 1 - edi_sale_oca/__manifest__.py | 2 +- edi_sale_oca/components/__init__.py | 1 - edi_sale_oca/components/listeners.py | 27 --------------------------- edi_sale_oca/models/sale_order.py | 3 +++ edi_sale_oca/tests/test_generate.py | 6 +++--- edi_sale_oca/tests/test_order.py | 2 +- edi_sale_oca/views/res_partner.xml | 2 +- 8 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 edi_sale_oca/components/__init__.py delete mode 100644 edi_sale_oca/components/listeners.py diff --git a/edi_sale_oca/__init__.py b/edi_sale_oca/__init__.py index f24d3e242..0650744f6 100644 --- a/edi_sale_oca/__init__.py +++ b/edi_sale_oca/__init__.py @@ -1,2 +1 @@ -from . import components from . import models diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index f3ec13722..71c9cac83 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -13,7 +13,7 @@ "maintainers": ["simahawk"], "website": "https://github.com/OCA/edi-framework", "depends": [ - "edi_oca", + "edi_core_oca", "edi_record_metadata_oca", "sale", ], diff --git a/edi_sale_oca/components/__init__.py b/edi_sale_oca/components/__init__.py deleted file mode 100644 index a441d8bd1..000000000 --- a/edi_sale_oca/components/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import listeners diff --git a/edi_sale_oca/components/listeners.py b/edi_sale_oca/components/listeners.py deleted file mode 100644 index c213d646a..000000000 --- a/edi_sale_oca/components/listeners.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2024 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo.addons.component.core import Component - - -class EDIConfigSOListener(Component): - _name = "edi.listener.config.sale.order" - _inherit = "base.event.listener" - _apply_on = ["sale.order"] - - def on_record_create(self, record, fields=None): - trigger = "on_record_create" - return self._exec_conf(record, trigger) - - def on_record_write(self, record, fields=None): - trigger = "on_record_write" - return self._exec_conf(record, trigger) - - def on_edi_sale_order_state_change(self, record, state=None): - trigger = "on_edi_sale_order_state_change" - return self._exec_conf(record, trigger) - - def _exec_conf(self, record, trigger, conf_field="edi_sale_conf_ids"): - confs = record.partner_id[conf_field].edi_get_conf(trigger) - for conf in confs: - conf.edi_exec_snippet_do(record) diff --git a/edi_sale_oca/models/sale_order.py b/edi_sale_oca/models/sale_order.py index 73dd90157..e74e72913 100644 --- a/edi_sale_oca/models/sale_order.py +++ b/edi_sale_oca/models/sale_order.py @@ -12,6 +12,9 @@ class SaleOrder(models.Model): "edi.exchange.consumer.mixin", ] + def _edi_config_field_relation(self): + return self.partner_id.edi_sale_conf_ids + # edi_record_metadata api def _edi_get_metadata_to_store(self, orig_vals): data = super()._edi_get_metadata_to_store(orig_vals) diff --git a/edi_sale_oca/tests/test_generate.py b/edi_sale_oca/tests/test_generate.py index 06c5e1f5d..a56f88919 100644 --- a/edi_sale_oca/tests/test_generate.py +++ b/edi_sale_oca/tests/test_generate.py @@ -4,8 +4,8 @@ from odoo.addons.component.tests.common import TransactionComponentRegistryCase -from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin -from odoo.addons.edi_oca.tests.fake_components import ( +from odoo.addons.edi_component_oca.tests.common import EDIBackendTestMixin +from odoo.addons.edi_component_oca.tests.fake_components import ( FakeOutputGenerator, FakeOutputSender, ) @@ -34,7 +34,7 @@ def setUpClass(cls): ) cls.edi_conf_done = cls.env.ref("edi_sale_oca.demo_edi_configuration_done") cls.partner = cls.env.ref("base.res_partner_2").copy({"name": "John Doe"}) - cls._load_module_components(cls, "edi_oca") + cls._load_module_components(cls, "edi_core_oca") cls._load_module_components(cls, "edi_sale_oca") cls._build_components( cls, diff --git a/edi_sale_oca/tests/test_order.py b/edi_sale_oca/tests/test_order.py index 9bec9bd84..d94508210 100644 --- a/edi_sale_oca/tests/test_order.py +++ b/edi_sale_oca/tests/test_order.py @@ -4,7 +4,7 @@ from odoo.tests.common import TransactionCase -from odoo.addons.edi_oca.tests.common import EDIBackendTestMixin +from odoo.addons.edi_core_oca.tests.common import EDIBackendTestMixin from .common import OrderMixin diff --git a/edi_sale_oca/views/res_partner.xml b/edi_sale_oca/views/res_partner.xml index d9d083ed8..8075fae39 100644 --- a/edi_sale_oca/views/res_partner.xml +++ b/edi_sale_oca/views/res_partner.xml @@ -5,7 +5,7 @@ res.partner.view.form res.partner - + From 3a4ec5cab3832f1792099e95d880e0f4a39cbf86 Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Wed, 24 Sep 2025 07:55:12 +0200 Subject: [PATCH 60/62] [IMP] edi_sale_oca: Adapt to new component handler --- edi_sale_oca/tests/test_generate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/edi_sale_oca/tests/test_generate.py b/edi_sale_oca/tests/test_generate.py index a56f88919..c8b19e4b6 100644 --- a/edi_sale_oca/tests/test_generate.py +++ b/edi_sale_oca/tests/test_generate.py @@ -29,6 +29,11 @@ def setUpClass(cls): cls._setup_env() cls.backend = cls._get_backend() cls.exc_type = cls.env.ref("edi_sale_oca.demo_edi_exc_type_order_out") + model = cls.env.ref("edi_component_oca.model_edi_oca_component_handler") + cls.exc_type.generate_model_id = model + cls.exc_type.send_model_id = model + cls.exc_type.process_model_id = model + cls.exc_type.receive_model_id = model cls.edi_conf_confirmed = cls.env.ref( "edi_sale_oca.demo_edi_configuration_confirmed" ) From 07f546bc01a13f65bea94d067ac0f1eee6136eaf Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 29 Sep 2025 15:30:38 +0000 Subject: [PATCH 61/62] [BOT] post-merge updates --- edi_sale_oca/README.rst | 2 +- edi_sale_oca/__manifest__.py | 2 +- edi_sale_oca/static/description/index.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index e76a2ae7d..43a6e5820 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -11,7 +11,7 @@ EDI Sales !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:841b083486b8082e03fc9ed15655125fffde9e99e8fdf89ee1efc1be3a7f8b4b + !! source digest: sha256:9a5bcb3a36371db790dd492551d19d7210d51802c8bd92e3c5dc0ea6a5710920 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index 71c9cac83..0e7887282 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -6,7 +6,7 @@ "summary": """ Configuration and special behaviors for EDI on sales. """, - "version": "18.0.1.0.0", + "version": "18.0.1.0.1", "development_status": "Alpha", "license": "AGPL-3", "author": "Camptocamp,Odoo Community Association (OCA)", diff --git a/edi_sale_oca/static/description/index.html b/edi_sale_oca/static/description/index.html index 52f021138..ed59bdef8 100644 --- a/edi_sale_oca/static/description/index.html +++ b/edi_sale_oca/static/description/index.html @@ -372,7 +372,7 @@

EDI Sales

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:841b083486b8082e03fc9ed15655125fffde9e99e8fdf89ee1efc1be3a7f8b4b +!! source digest: sha256:9a5bcb3a36371db790dd492551d19d7210d51802c8bd92e3c5dc0ea6a5710920 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

Handle sale orders via EDI.

From 708aef513f49bad888f6f52322465c0f672bc666 Mon Sep 17 00:00:00 2001 From: ilo Date: Thu, 25 Jun 2026 18:02:01 -0300 Subject: [PATCH 62/62] [MIG] edi_sale_oca: Migration to 19.0 --- edi_sale_oca/README.rst | 17 ++-- edi_sale_oca/__manifest__.py | 2 +- edi_sale_oca/readme/CONTRIBUTORS.md | 1 + edi_sale_oca/tests/common.py | 71 ++++++++++--- edi_sale_oca/tests/test_generate.py | 150 ++++++++++++---------------- edi_sale_oca/tests/test_order.py | 11 +- 6 files changed, 135 insertions(+), 117 deletions(-) diff --git a/edi_sale_oca/README.rst b/edi_sale_oca/README.rst index 43a6e5820..6516d3ef5 100644 --- a/edi_sale_oca/README.rst +++ b/edi_sale_oca/README.rst @@ -21,13 +21,13 @@ EDI Sales :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--framework-lightgray.png?logo=github - :target: https://github.com/OCA/edi-framework/tree/18.0/edi_sale_oca + :target: https://github.com/OCA/edi-framework/tree/19.0/edi_sale_oca :alt: OCA/edi-framework .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/edi-framework-18-0/edi-framework-18-0-edi_sale_oca + :target: https://translation.odoo-community.org/projects/edi-framework-19-0/edi-framework-19-0-edi_sale_oca :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-framework&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi-framework&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -56,7 +56,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -71,9 +71,10 @@ Authors Contributors ------------ -- Simone Orsi -- Duong (Tran Quoc) -- Thien (Vo Hong) +- Simone Orsi +- Duong (Tran Quoc) +- Thien (Vo Hong) +- Italo Lopes Other credits ------------- @@ -102,6 +103,6 @@ Current `maintainer `__: |maintainer-simahawk| -This module is part of the `OCA/edi-framework `_ project on GitHub. +This module is part of the `OCA/edi-framework `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/edi_sale_oca/__manifest__.py b/edi_sale_oca/__manifest__.py index 0e7887282..68af8fefe 100644 --- a/edi_sale_oca/__manifest__.py +++ b/edi_sale_oca/__manifest__.py @@ -6,7 +6,7 @@ "summary": """ Configuration and special behaviors for EDI on sales. """, - "version": "18.0.1.0.1", + "version": "19.0.1.0.0", "development_status": "Alpha", "license": "AGPL-3", "author": "Camptocamp,Odoo Community Association (OCA)", diff --git a/edi_sale_oca/readme/CONTRIBUTORS.md b/edi_sale_oca/readme/CONTRIBUTORS.md index d44409ed6..da1e3c10d 100644 --- a/edi_sale_oca/readme/CONTRIBUTORS.md +++ b/edi_sale_oca/readme/CONTRIBUTORS.md @@ -1,3 +1,4 @@ - Simone Orsi \<\> - Duong (Tran Quoc) \<\> - Thien (Vo Hong) \<\> +- Italo Lopes \<\> diff --git a/edi_sale_oca/tests/common.py b/edi_sale_oca/tests/common.py index 2558e97be..3d89aa630 100644 --- a/edi_sale_oca/tests/common.py +++ b/edi_sale_oca/tests/common.py @@ -3,15 +3,68 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields +from odoo.fields import Domain + +from odoo.addons.edi_core_oca.tests.common import EDIBackendTestMixin + + +class SaleEDIBackendTestMixin(EDIBackendTestMixin): + @classmethod + def _get_backend_type(cls): + backend_type = cls.env["edi.backend.type"].search( + Domain([("code", "=", "sale_demo")]), limit=1 + ) + if backend_type: + return backend_type + return cls.env["edi.backend.type"].create( + {"name": "Sale DEMO", "code": "sale_demo"} + ) + + @classmethod + def _get_backend(cls): + backend_type = cls._get_backend_type() + backend = cls.env["edi.backend"].search( + Domain([("backend_type_id", "=", backend_type.id)]), limit=1 + ) + if backend: + return backend + return cls.env["edi.backend"].create( + {"name": "Sale DEMO", "backend_type_id": backend_type.id} + ) + + @classmethod + def _create_exchange_type(cls, **kw): + model = cls.env["edi.exchange.type"] + code = kw.get("code") + if code: + exchange_type = model.search( + Domain([("code", "=", code), ("backend_id", "=", cls.backend.id)]), + limit=1, + ) + if exchange_type: + return exchange_type + return super()._create_exchange_type(**kw) class OrderMixin: @classmethod - def _create_sale_order(cls, **kw): - """Create a sale order + def _setup_order_records(cls): + cls.sale_partner = cls.env["res.partner"].create({"name": "Test Sale Customer"}) + cls.product_a = cls.env["product.product"].create( + {"name": "Product A", "sale_ok": True, "barcode": "1" * 14} + ) + cls.product_b = cls.env["product.product"].create( + {"name": "Product B", "sale_ok": True, "barcode": "2" * 14} + ) + cls.product_c = cls.env["product.product"].create( + {"name": "Product C", "sale_ok": True, "barcode": "3" * 14} + ) + cls.product_d = cls.env["product.product"].create( + {"name": "Product D", "sale_ok": True, "barcode": "4" * 14} + ) - :return: sale order - """ + @classmethod + def _create_sale_order(cls, **kw): model = cls.env["sale.order"] vals = dict(commitment_date=fields.Date.today()) vals.update(kw) @@ -26,17 +79,9 @@ def _create_sale_order(cls, **kw): @classmethod def _setup_order(cls, **kw): - cls.product_a = cls.env.ref("product.product_product_4") - cls.product_a.barcode = "1" * 14 - cls.product_b = cls.env.ref("product.product_product_4b") - cls.product_b.barcode = "2" * 14 - cls.product_c = cls.env.ref("product.product_product_4c") - cls.product_c.barcode = "3" * 14 - cls.product_d = cls.env.ref("product.product_product_5") - cls.product_d.barcode = "4" * 14 line_defaults = kw.pop("line_defaults", {}) vals = { - "partner_id": cls.env.ref("base.res_partner_10").id, + "partner_id": cls.sale_partner.id, "commitment_date": "2022-07-29", } vals.update(kw) diff --git a/edi_sale_oca/tests/test_generate.py b/edi_sale_oca/tests/test_generate.py index c8b19e4b6..b91e5c425 100644 --- a/edi_sale_oca/tests/test_generate.py +++ b/edi_sale_oca/tests/test_generate.py @@ -1,113 +1,89 @@ # Copyright 2024 Camptocamp SA # @author: Simone Orsi -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.tests.common import TransactionCase -from odoo.addons.component.tests.common import TransactionComponentRegistryCase -from odoo.addons.edi_component_oca.tests.common import EDIBackendTestMixin -from odoo.addons.edi_component_oca.tests.fake_components import ( - FakeOutputGenerator, - FakeOutputSender, -) +from .common import SaleEDIBackendTestMixin -class Generator(FakeOutputGenerator): - _backend_type = "sale_demo" - _exchange_type = "demo_SaleOrder_out" +class TestGenerateViaConf(TransactionCase, SaleEDIBackendTestMixin): + """Verify that sale EDI generation is driven by ``edi.configuration``. + No component / no fake handler: we simply assert that the snippets bound + to the partner via ``partner_id.edi_sale_conf_ids`` are executed by + the state-change event dispatched by ``edi.exchange.consumer.mixin``. -class Sender(FakeOutputSender): - _backend_type = "sale_demo" - _exchange_type = "demo_SaleOrder_out" + Each snippet writes a marker on ``conf.description`` so we can verify + which configurations actually ran. + """ + _snippet_tpl = ( + "if record.state == '{state}':\n" + " conf.write({{'description': " + "(conf.description or '') + '|' + record.state}})" + ) -class TestProcessComponent(TransactionComponentRegistryCase, EDIBackendTestMixin): @classmethod def setUpClass(cls): super().setUpClass() - cls._setup_registry(cls) + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls._setup_env() - cls.backend = cls._get_backend() - cls.exc_type = cls.env.ref("edi_sale_oca.demo_edi_exc_type_order_out") - model = cls.env.ref("edi_component_oca.model_edi_oca_component_handler") - cls.exc_type.generate_model_id = model - cls.exc_type.send_model_id = model - cls.exc_type.process_model_id = model - cls.exc_type.receive_model_id = model - cls.edi_conf_confirmed = cls.env.ref( - "edi_sale_oca.demo_edi_configuration_confirmed" + cls._setup_records() + + cls.exc_type = cls._create_exchange_type( + name="Demo Sale Order out", + code="demo_SaleOrder_out", + direction="output", + exchange_filename_pattern="{record_name}-{type.code}-{dt}", + exchange_file_ext="xml", ) - cls.edi_conf_done = cls.env.ref("edi_sale_oca.demo_edi_configuration_done") - cls.partner = cls.env.ref("base.res_partner_2").copy({"name": "John Doe"}) - cls._load_module_components(cls, "edi_core_oca") - cls._load_module_components(cls, "edi_sale_oca") - cls._build_components( - cls, - Generator, - Sender, + cls.state_change_trigger = cls.env.ref( + "edi_sale_oca.edi_conf_trigger_sale_order_state_change" ) - - def setUp(self): - super().setUp() - Generator.reset_faked() - Sender.reset_faked() - - @classmethod - def _get_backend(cls): - return cls.env.ref("edi_sale_oca.demo_edi_backend") - - def test_lookup(self): - # Just ensuring test setup is done properly - record = self.backend.create_record(self.exc_type.code, {}) - comp = self.backend._get_component(record, "generate") - self.assertEqual(comp._name, Generator._name) - comp = self.backend._get_component(record, "send") - self.assertEqual(comp._name, Sender._name) - - def test_new_order_no_conf_no_output(self): - order = self.env["sale.order"].create( + sale_model_id = cls.env["ir.model"]._get_id("sale.order") + cls.edi_conf_confirmed = cls.env["edi.configuration"].create( + { + "name": "Demo Sale Order - order confirmed", + "type_id": cls.exc_type.id, + "backend_id": cls.backend.id, + "model_id": sale_model_id, + "trigger_id": cls.state_change_trigger.id, + "snippet_do": cls._snippet_tpl.format(state="sale"), + } + ) + cls.edi_conf_done = cls.env["edi.configuration"].create( { - "partner_id": self.partner.id, + "name": "Demo Sale Order - order cancelled", + "type_id": cls.exc_type.id, + "backend_id": cls.backend.id, + "model_id": sale_model_id, + "trigger_id": cls.state_change_trigger.id, + "snippet_do": cls._snippet_tpl.format(state="cancel"), } ) + cls.partner = cls.env["res.partner"].create({"name": "John Doe"}) + + def test_new_order_no_conf_no_output(self): + order = self.env["sale.order"].create({"partner_id": self.partner.id}) order.action_confirm() - self.assertFalse(order.exchange_record_ids) + self.assertFalse(self.edi_conf_confirmed.description) + self.assertFalse(self.edi_conf_done.description) def test_new_order_1conf_output(self): self.partner.edi_sale_conf_ids = self.edi_conf_confirmed - order = self.env["sale.order"].create( - { - "partner_id": self.partner.id, - } - ) - self.assertFalse(order.exchange_record_ids) - order.with_context(fake_output="ORDER CONFIRM").action_confirm() - self.assertEqual(len(order.exchange_record_ids), 1) - record = order.exchange_record_ids[0] - self.assertEqual(record._get_file_content(), "ORDER CONFIRM") - self.assertEqual(record.type_id, self.exc_type) - # When locked, nothing changes - order.action_lock() - self.assertEqual(len(order.exchange_record_ids), 1) - record = order.exchange_record_ids[0] - self.assertEqual(record.type_id, self.exc_type) + order = self.env["sale.order"].create({"partner_id": self.partner.id}) + self.assertFalse(self.edi_conf_confirmed.description) + order.action_confirm() + self.assertEqual(self.edi_conf_confirmed.description, "|sale") + self.assertFalse(self.edi_conf_done.description) def test_new_order_2conf_output(self): self.partner.edi_sale_conf_ids = self.edi_conf_confirmed | self.edi_conf_done - order = self.env["sale.order"].create( - { - "partner_id": self.partner.id, - } - ) - self.assertFalse(order.exchange_record_ids) - order.with_context(fake_output="ORDER CONFIRM").action_confirm() - self.assertEqual(len(order.exchange_record_ids), 1) - record = order.exchange_record_ids[0] - self.assertEqual(record._get_file_content(), "ORDER CONFIRM") - self.assertEqual(record.type_id, self.exc_type) - order.with_context(fake_output="ORDER CANCEL")._action_cancel() - record1, record2 = order.exchange_record_ids - self.assertEqual(record1.type_id, self.exc_type) - self.assertEqual(record1._get_file_content(), "ORDER CONFIRM") - self.assertEqual(record2.type_id, self.exc_type) - self.assertEqual(record2._get_file_content(), "ORDER CANCEL") + order = self.env["sale.order"].create({"partner_id": self.partner.id}) + order.action_confirm() + self.assertEqual(self.edi_conf_confirmed.description, "|sale") + self.assertFalse(self.edi_conf_done.description) + order._action_cancel() + self.assertEqual(self.edi_conf_confirmed.description, "|sale") + self.assertEqual(self.edi_conf_done.description, "|cancel") diff --git a/edi_sale_oca/tests/test_order.py b/edi_sale_oca/tests/test_order.py index d94508210..b9597c5f3 100644 --- a/edi_sale_oca/tests/test_order.py +++ b/edi_sale_oca/tests/test_order.py @@ -4,12 +4,10 @@ from odoo.tests.common import TransactionCase -from odoo.addons.edi_core_oca.tests.common import EDIBackendTestMixin +from .common import OrderMixin, SaleEDIBackendTestMixin -from .common import OrderMixin - -class TestOrder(TransactionCase, EDIBackendTestMixin, OrderMixin): +class TestOrder(TransactionCase, SaleEDIBackendTestMixin, OrderMixin): @classmethod def setUpClass(cls): super().setUpClass() @@ -20,14 +18,11 @@ def setUpClass(cls): cls.exc_record_in = cls.backend.create_record( cls.exchange_type_in.code, {"edi_exchange_state": "input_received"} ) + cls._setup_order_records() cls.order = cls._setup_order( origin_exchange_record_id=cls.exc_record_in.id, ) - @classmethod - def _get_backend(cls): - return cls.env.ref("edi_sale_oca.demo_edi_backend") - def test_line_origin(self): order = self.order self.assertEqual(order.origin_exchange_record_id, self.exc_record_in)