From 199f24f9984e75162a95a61b7fe9a1b06f5c2234 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Mon, 14 Feb 2022 16:41:16 +0100 Subject: [PATCH 01/26] [ADD] edi_purchase_oca [UPD] Update edi_purchase_oca.pot [UPD] README.rst --- edi_purchase_oca/README.rst | 86 ++++ edi_purchase_oca/__init__.py | 1 + edi_purchase_oca/__manifest__.py | 15 + edi_purchase_oca/i18n/edi_purchase_oca.pot | 39 ++ edi_purchase_oca/models/__init__.py | 1 + edi_purchase_oca/models/purchase_order.py | 21 + edi_purchase_oca/readme/CONTRIBUTORS.rst | 1 + edi_purchase_oca/readme/DESCRIPTION.rst | 14 + edi_purchase_oca/static/description/icon.png | Bin 0 -> 5055 bytes .../static/description/index.html | 430 ++++++++++++++++++ .../views/edi_exchange_record_views.xml | 30 ++ .../views/purchase_order_views.xml | 28 ++ 12 files changed, 666 insertions(+) create mode 100644 edi_purchase_oca/README.rst create mode 100644 edi_purchase_oca/__init__.py create mode 100644 edi_purchase_oca/__manifest__.py create mode 100644 edi_purchase_oca/i18n/edi_purchase_oca.pot create mode 100644 edi_purchase_oca/models/__init__.py create mode 100644 edi_purchase_oca/models/purchase_order.py create mode 100644 edi_purchase_oca/readme/CONTRIBUTORS.rst create mode 100644 edi_purchase_oca/readme/DESCRIPTION.rst create mode 100644 edi_purchase_oca/static/description/icon.png create mode 100644 edi_purchase_oca/static/description/index.html create mode 100644 edi_purchase_oca/views/edi_exchange_record_views.xml create mode 100644 edi_purchase_oca/views/purchase_order_views.xml diff --git a/edi_purchase_oca/README.rst b/edi_purchase_oca/README.rst new file mode 100644 index 000000000..d54839902 --- /dev/null +++ b/edi_purchase_oca/README.rst @@ -0,0 +1,86 @@ +============ +EDI Purchase +============ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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/13.0/edi_purchase_oca + :alt: OCA/edi +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/edi-13-0/edi-13-0-edi_purchase_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/13.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 purchase. + +In order to add a new integration, you need to create a listener: + +.. code-block:: python + + class MyEventListener(Component): + _name = "purchase.order.event.listener.demo" + _inherit = "base.event.listener" + _apply_on = ["purchase.order"] + + def on_button_confirm_purchase_order(self, move): + """Add your code here""" + +**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 +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + +* Lois Rilo + +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_purchase_oca/__init__.py b/edi_purchase_oca/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/edi_purchase_oca/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/edi_purchase_oca/__manifest__.py b/edi_purchase_oca/__manifest__.py new file mode 100644 index 000000000..c9ff3c686 --- /dev/null +++ b/edi_purchase_oca/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "EDI Purchase", + "summary": """ + Define EDI Configuration for Purchase Orders""", + "version": "13.0.1.0.0", + "license": "LGPL-3", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/edi", + "depends": ["purchase", "edi", "component_event"], + "data": ["views/purchase_order_views.xml", "views/edi_exchange_record_views.xml"], + "demo": [], +} diff --git a/edi_purchase_oca/i18n/edi_purchase_oca.pot b/edi_purchase_oca/i18n/edi_purchase_oca.pot new file mode 100644 index 000000000..872766122 --- /dev/null +++ b/edi_purchase_oca/i18n/edi_purchase_oca.pot @@ -0,0 +1,39 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * edi_purchase_oca +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.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_purchase_oca +#: model_terms:ir.ui.view,arch_db:edi_purchase_oca.purchase_order_form +msgid "EDI" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.ui.menu,name:edi_purchase_oca.menu_purchase_edi_root +msgid "Exchange records" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model,name:edi_purchase_oca.model_purchase_order +msgid "Purchase Order" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.actions.act_window,name:edi_purchase_oca.act_open_edi_exchange_record_purchase_order_view +msgid "Purchase Order Exchange Record" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.ui.menu,name:edi_purchase_oca.menu_purchase_edi_exchange_record +msgid "Purchase Orders" +msgstr "" diff --git a/edi_purchase_oca/models/__init__.py b/edi_purchase_oca/models/__init__.py new file mode 100644 index 000000000..9f0353064 --- /dev/null +++ b/edi_purchase_oca/models/__init__.py @@ -0,0 +1 @@ +from . import purchase_order diff --git a/edi_purchase_oca/models/purchase_order.py b/edi_purchase_oca/models/purchase_order.py new file mode 100644 index 000000000..6ac69723e --- /dev/null +++ b/edi_purchase_oca/models/purchase_order.py @@ -0,0 +1,21 @@ +# Copyright 2022 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import models + + +class PurchaseOrder(models.Model): + _name = "purchase.order" + _inherit = ["purchase.order", "edi.exchange.consumer.mixin"] + + def button_confirm(self): + result = super().button_confirm() + if self: + self._event("on_button_confirm_purchase_order").notify(self) + return result + + def button_cancel(self): + result = super().button_cancel() + if self: + self._event("on_button_cancel_purchase_order").notify(self) + return result diff --git a/edi_purchase_oca/readme/CONTRIBUTORS.rst b/edi_purchase_oca/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..77dfbe89e --- /dev/null +++ b/edi_purchase_oca/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Lois Rilo diff --git a/edi_purchase_oca/readme/DESCRIPTION.rst b/edi_purchase_oca/readme/DESCRIPTION.rst new file mode 100644 index 000000000..9c5b5932c --- /dev/null +++ b/edi_purchase_oca/readme/DESCRIPTION.rst @@ -0,0 +1,14 @@ +This module intends to create a base to be extended by local edi rules +for purchase. + +In order to add a new integration, you need to create a listener: + +.. code-block:: python + + class MyEventListener(Component): + _name = "purchase.order.event.listener.demo" + _inherit = "base.event.listener" + _apply_on = ["purchase.order"] + + def on_button_confirm_purchase_order(self, move): + """Add your code here""" diff --git a/edi_purchase_oca/static/description/icon.png b/edi_purchase_oca/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a79752645ce327baadb6aba260751a044a5e4a8a GIT binary patch literal 5055 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 literal 0 HcmV?d00001 diff --git a/edi_purchase_oca/static/description/index.html b/edi_purchase_oca/static/description/index.html new file mode 100644 index 000000000..b7baa690b --- /dev/null +++ b/edi_purchase_oca/static/description/index.html @@ -0,0 +1,430 @@ + + + + + + +EDI Purchase + + + +
+

EDI Purchase

+ + +

Beta License: LGPL-3 OCA/edi Translate me on Weblate Try me on Runbot

+

This module intends to create a base to be extended by local edi rules +for purchase.

+

In order to add a new integration, you need to create a listener:

+
+class MyEventListener(Component):
+    _name = "purchase.order.event.listener.demo"
+    _inherit = "base.event.listener"
+    _apply_on = ["purchase.order"]
+
+    def on_button_confirm_purchase_order(self, move):
+        """Add your code here"""
+
+

Table of contents

+ +
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

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

+

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

+
+
+
+ + diff --git a/edi_purchase_oca/views/edi_exchange_record_views.xml b/edi_purchase_oca/views/edi_exchange_record_views.xml new file mode 100644 index 000000000..0413585df --- /dev/null +++ b/edi_purchase_oca/views/edi_exchange_record_views.xml @@ -0,0 +1,30 @@ + + + + + + Purchase Order Exchange Record + ir.actions.act_window + edi.exchange.record + tree,form + [('model', '=', 'purchase.order')] + {} + + + + diff --git a/edi_purchase_oca/views/purchase_order_views.xml b/edi_purchase_oca/views/purchase_order_views.xml new file mode 100644 index 000000000..6e17a3a3e --- /dev/null +++ b/edi_purchase_oca/views/purchase_order_views.xml @@ -0,0 +1,28 @@ + + + + + purchase.order.form - edi_purchase_oca + purchase.order + + + + + + + + From 42ddbb9c6e82898e52bf092063c0d3ec95463d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alix?= Date: Wed, 6 Apr 2022 12:13:58 +0200 Subject: [PATCH 02/26] [MIG] edi_purchase_oca: Migration to 14.0 [UPD] Update edi_purchase_oca.pot [UPD] README.rst [UPD] Update edi_purchase_oca.pot [UPD] Update edi_purchase_oca.pot [UPD] Update edi_purchase_oca.pot [UPD] README.rst --- edi_purchase_oca/README.rst | 23 +++--- edi_purchase_oca/__manifest__.py | 4 +- edi_purchase_oca/i18n/edi_purchase_oca.pot | 72 ++++++++++++++++++- .../static/description/index.html | 50 ++++++------- 4 files changed, 112 insertions(+), 37 deletions(-) diff --git a/edi_purchase_oca/README.rst b/edi_purchase_oca/README.rst index d54839902..0c30581b7 100644 --- a/edi_purchase_oca/README.rst +++ b/edi_purchase_oca/README.rst @@ -2,10 +2,13 @@ EDI Purchase ============ -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:8ab40ab13f4a26ea0ba04ff19e53af88e490d1b2e783699454ae6255422e00c3 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -14,16 +17,16 @@ EDI Purchase :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/13.0/edi_purchase_oca + :target: https://github.com/OCA/edi/tree/14.0/edi_purchase_oca :alt: OCA/edi .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/edi-13-0/edi-13-0-edi_purchase_oca + :target: https://translation.odoo-community.org/projects/edi-14-0/edi-14-0-edi_purchase_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/13.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=14.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module intends to create a base to be extended by local edi rules for purchase. @@ -50,8 +53,8 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -81,6 +84,6 @@ 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. +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_purchase_oca/__manifest__.py b/edi_purchase_oca/__manifest__.py index c9ff3c686..be446cd40 100644 --- a/edi_purchase_oca/__manifest__.py +++ b/edi_purchase_oca/__manifest__.py @@ -5,11 +5,11 @@ "name": "EDI Purchase", "summary": """ Define EDI Configuration for Purchase Orders""", - "version": "13.0.1.0.0", + "version": "14.0.1.0.0", "license": "LGPL-3", "author": "ForgeFlow, Odoo Community Association (OCA)", "website": "https://github.com/OCA/edi", - "depends": ["purchase", "edi", "component_event"], + "depends": ["purchase", "edi_oca", "component_event"], "data": ["views/purchase_order_views.xml", "views/edi_exchange_record_views.xml"], "demo": [], } diff --git a/edi_purchase_oca/i18n/edi_purchase_oca.pot b/edi_purchase_oca/i18n/edi_purchase_oca.pot index 872766122..3cf50cd17 100644 --- a/edi_purchase_oca/i18n/edi_purchase_oca.pot +++ b/edi_purchase_oca/i18n/edi_purchase_oca.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -18,11 +18,71 @@ msgstr "" msgid "EDI" msgstr "" +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__disable_edi_auto +msgid "Disable auto" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__display_name +msgid "Display Name" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__origin_edi_endpoint_id +msgid "EDI origin endpoint" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__origin_exchange_type_id +msgid "EDI origin exchange type" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__origin_exchange_record_id +msgid "EDI origin record" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,help:edi_purchase_oca.field_purchase_order__origin_exchange_record_id +msgid "EDI record that originated this document." +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__edi_config +msgid "Edi Config" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__edi_has_form_config +msgid "Edi Has Form Config" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__exchange_record_ids +msgid "Exchange Record" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__exchange_record_count +msgid "Exchange Record Count" +msgstr "" + #. module: edi_purchase_oca #: model:ir.ui.menu,name:edi_purchase_oca.menu_purchase_edi_root msgid "Exchange records" msgstr "" +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order__id +msgid "ID" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,field_description:edi_purchase_oca.field_purchase_order____last_update +msgid "Last Modified on" +msgstr "" + #. module: edi_purchase_oca #: model:ir.model,name:edi_purchase_oca.model_purchase_order msgid "Purchase Order" @@ -37,3 +97,13 @@ msgstr "" #: model:ir.ui.menu,name:edi_purchase_oca.menu_purchase_edi_exchange_record msgid "Purchase Orders" msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,help:edi_purchase_oca.field_purchase_order__origin_edi_endpoint_id +msgid "Record generated via this endpoint" +msgstr "" + +#. module: edi_purchase_oca +#: model:ir.model.fields,help:edi_purchase_oca.field_purchase_order__disable_edi_auto +msgid "When marked, EDI automatic processing will be avoided" +msgstr "" diff --git a/edi_purchase_oca/static/description/index.html b/edi_purchase_oca/static/description/index.html index b7baa690b..844cb4033 100644 --- a/edi_purchase_oca/static/description/index.html +++ b/edi_purchase_oca/static/description/index.html @@ -1,20 +1,20 @@ - + - + EDI Purchase - - -
-

EDI Purchase

- - -

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

-

This module intends to create a base to be extended by local edi rules -for purchase.

-

In order to add a new integration, you need to create a listener:

-
-class MyEventListener(Component):
-    _name = "purchase.order.event.listener.demo"
-    _inherit = "base.event.listener"
-    _apply_on = ["purchase.order"]
-
-    def on_button_confirm_purchase_order(self, move):
-        """Add your code here"""
-
-

Table of contents

- -
-

Bug Tracker

-

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

-

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

-
-
-

Credits

-
-

Authors

-
    -
  • ForgeFlow
  • -
-
- -
-

Maintainers

-

This module is maintained by the OCA.

-Odoo Community Association -

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

-

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

-

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

-
-
-
- + + + + EDI Purchase + + + +
+

EDI Purchase

+ + +

+ + Beta + + + License: LGPL-3 + + + OCA/edi-framework + + + Translate me on Weblate + + + Try me on Runboat + +

+

This module intends to create a base to be extended by local edi rules + for purchase. +

+

In order to add a new integration, you need to create a listener:

+
+                class
+                MyEventListener
+                (
+                Component
+                ):
+                
+                
+                _name
+                =
+                "purchase.order.event.listener.demo"
+                
+                
+                _inherit
+                =
+                "base.event.listener"
+                
+                
+                _apply_on
+                =
+                [
+                "purchase.order"
+                ]
+                
+
+                
+                def
+                on_button_confirm_purchase_order
+                (
+                self
+                ,
+                move
+                ):
+                
+                
+                """Add your code here"""
+            
+

+ Table of contents +

+
+ +
+
+

+ Bug Tracker +

+

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

+

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

+
+
+

+ Credits +

+
+

+ Authors +

+
    +
  • ForgeFlow
  • +
+
+
+

+ Contributors +

+ +
+
+

+ Maintainers +

+

This module is maintained by the OCA.

+ + Odoo Community Association + +

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

+

This module is part of the + OCA/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_purchase_oca/views/purchase_order_views.xml b/edi_purchase_oca/views/purchase_order_views.xml index 6e17a3a3e..b6d4c6799 100644 --- a/edi_purchase_oca/views/purchase_order_views.xml +++ b/edi_purchase_oca/views/purchase_order_views.xml @@ -7,12 +7,22 @@ purchase.order + + + + + + + + + + + + + + + + + diff --git a/edi_purchase_oca/views/res_partner_view.xml b/edi_purchase_oca/views/res_partner_view.xml index f950cc0d3..4985d326e 100644 --- a/edi_purchase_oca/views/res_partner_view.xml +++ b/edi_purchase_oca/views/res_partner_view.xml @@ -1,11 +1,10 @@ - res.partner.edi.purchase res.partner - + From f3e157d4b0f0ff7514af2102b4ddbbc331711e8f Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 15:09:52 +0200 Subject: [PATCH 12/26] [DOC] edi_purchase: update contributors --- edi_purchase_oca/readme/CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/edi_purchase_oca/readme/CONTRIBUTORS.md b/edi_purchase_oca/readme/CONTRIBUTORS.md index a18e9df0d..1ea50d1f7 100644 --- a/edi_purchase_oca/readme/CONTRIBUTORS.md +++ b/edi_purchase_oca/readme/CONTRIBUTORS.md @@ -1,3 +1,4 @@ * Lois Rilo * Simone Orsi * Phan Hong Phuc \<\> +* Maksym Yankin \ No newline at end of file From 31f0ab2f4ce64a8037c019f28c484fcf481aef60 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 20 May 2026 16:56:08 +0200 Subject: [PATCH 13/26] edi_purchase_oca: rework test setup --- edi_purchase_oca/tests/common.py | 13 ++----------- edi_purchase_oca/tests/test_generate.py | 2 +- edi_purchase_oca/tests/test_order.py | 11 ++++++++++- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/edi_purchase_oca/tests/common.py b/edi_purchase_oca/tests/common.py index 00f7f74e7..80d99c031 100644 --- a/edi_purchase_oca/tests/common.py +++ b/edi_purchase_oca/tests/common.py @@ -69,9 +69,9 @@ def _create_purchase_order(cls, **kw): return model.create(po_vals) @classmethod - def _setup_order(cls): + def _setup_order_records(cls): cls.vendor = cls.env["res.partner"].create( - {"name": "Azure Interior", "country_id": cls.env.company.country_id.id} + {"name": "ACME inc", "country_id": cls.env.company.country_id.id} ) cls.product = cls.env["product.product"].create( { @@ -80,12 +80,3 @@ def _setup_order(cls): "purchase_ok": True, } ) - return { - "order_line": [ - { - "product_id": cls.product.id, - "product_qty": 10, - "price_unit": 100.0, - } - ], - } diff --git a/edi_purchase_oca/tests/test_generate.py b/edi_purchase_oca/tests/test_generate.py index 1d10c3374..0f814b911 100644 --- a/edi_purchase_oca/tests/test_generate.py +++ b/edi_purchase_oca/tests/test_generate.py @@ -63,7 +63,7 @@ def setUpClass(cls): "snippet_do": cls._snippet_tpl.format(state="cancel"), } ) - cls._setup_order() + cls._setup_order_records() def test_new_order_no_conf_no_output(self): # No conf linked to the vendor -> no snippet executed. diff --git a/edi_purchase_oca/tests/test_order.py b/edi_purchase_oca/tests/test_order.py index 3285fa516..4fc5ad212 100644 --- a/edi_purchase_oca/tests/test_order.py +++ b/edi_purchase_oca/tests/test_order.py @@ -16,7 +16,16 @@ def setUpClass(cls): cls.exc_record_in = cls.backend.create_record( cls.exchange_type_in.code, {"edi_exchange_state": "input_received"} ) - order_vals = cls._setup_order() + cls._setup_order_records() + order_vals = { + "order_line": [ + { + "product_id": cls.product.id, + "product_qty": 10, + "price_unit": 100.0, + } + ], + } cls.order = cls._create_purchase_order( origin_exchange_record_id=cls.exc_record_in.id, **order_vals, From 30c0a96474cf0844301116cc75bd509105911ff4 Mon Sep 17 00:00:00 2001 From: Ricardoalso Date: Thu, 21 May 2026 13:21:01 +0200 Subject: [PATCH 14/26] [IMP] : pre-commit auto fixes --- edi_purchase_oca/README.rst | 26 +++++++++----- .../static/description/index.html | 35 ++++++++++++------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/edi_purchase_oca/README.rst b/edi_purchase_oca/README.rst index c86a88f7a..bc6dac5a1 100644 --- a/edi_purchase_oca/README.rst +++ b/edi_purchase_oca/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ============ EDI Purchase ============ @@ -13,23 +17,27 @@ EDI Purchase .. |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 +.. |badge2| image:: https://img.shields.io/badge/license-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--framework-lightgray.png?logo=github - :target: https://github.com/OCA/edi-framework/tree/18.0/edi_purchase_oca + :target: https://github.com/OCA/edi-framework/tree/19.0/edi_purchase_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_purchase_oca + :target: https://translation.odoo-community.org/projects/edi-framework-19-0/edi-framework-19-0-edi_purchase_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| -This module intends to create a base to be extended by local edi rules -for purchase. Assign the EDI Configuration on the partner form. +Handle purchase orders via EDI. + +This is a base module to plug purchase processes with the EDI framework. + +To handle inbound/outbound purchase orders, you need to create your own +integration modules on top of this base module. **Table of contents** @@ -42,7 +50,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. @@ -60,8 +68,8 @@ Contributors - Lois Rilo lois.rilo@forgeflow.com - Simone Orsi simone.orsi@camptocamp.com - - Phan Hong Phuc +- Maksym Yankin maksym.yankin@camptocamp.com Maintainers ----------- @@ -76,6 +84,6 @@ 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-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_purchase_oca/static/description/index.html b/edi_purchase_oca/static/description/index.html index f8825ba72..276344d74 100644 --- a/edi_purchase_oca/static/description/index.html +++ b/edi_purchase_oca/static/description/index.html @@ -3,7 +3,7 @@ -EDI Purchase +README.rst -
-

EDI Purchase

+
+ + +Odoo Community Association + +
+

EDI Purchase

-

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

-

This module intends to create a base to be extended by local edi rules -for purchase. Assign the EDI Configuration on the partner form.

+

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

+

Handle purchase orders via EDI.

+

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

+

To handle inbound/outbound purchase orders, you need to create your own +integration modules on top of this base module.

Table of contents

    @@ -385,32 +392,33 @@

    EDI Purchase

-

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

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ForgeFlow
  • Camptocamp
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -418,10 +426,11 @@

Maintainers

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

+
From a03e5ea7e61d24a7ba3a9a144bb510a8b749810b Mon Sep 17 00:00:00 2001 From: Ricardoalso Date: Thu, 21 May 2026 13:46:10 +0200 Subject: [PATCH 15/26] [MIG] edi_purchase_oca: Migration to 19.0 --- edi_purchase_oca/__manifest__.py | 2 +- edi_purchase_oca/tests/common.py | 9 +++++---- edi_purchase_oca/tests/test_generate.py | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/edi_purchase_oca/__manifest__.py b/edi_purchase_oca/__manifest__.py index 211961ea0..0155df0e9 100644 --- a/edi_purchase_oca/__manifest__.py +++ b/edi_purchase_oca/__manifest__.py @@ -5,7 +5,7 @@ "name": "EDI Purchase", "summary": """ Define EDI Configuration for Purchase Orders""", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "license": "LGPL-3", "author": "ForgeFlow, Camptocamp, Odoo Community Association (OCA)", "website": "https://github.com/OCA/edi-framework", diff --git a/edi_purchase_oca/tests/common.py b/edi_purchase_oca/tests/common.py index 80d99c031..3a921bacb 100644 --- a/edi_purchase_oca/tests/common.py +++ b/edi_purchase_oca/tests/common.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields -from odoo.fields import Command +from odoo.fields import Command, Domain from odoo.addons.edi_core_oca.tests.common import EDIBackendTestMixin @@ -11,7 +11,7 @@ class PurchaseEDIBackendTestMixin(EDIBackendTestMixin): @classmethod def _get_backend_type(cls): backend_type = cls.env["edi.backend.type"].search( - [("code", "=", "purchase_demo")], limit=1 + Domain([("code", "=", "purchase_demo")]), limit=1 ) if backend_type: return backend_type @@ -26,7 +26,7 @@ def _get_backend_type(cls): def _get_backend(cls): backend_type = cls._get_backend_type() backend = cls.env["edi.backend"].search( - [("backend_type_id", "=", backend_type.id)], limit=1 + Domain([("backend_type_id", "=", backend_type.id)]), limit=1 ) if backend: return backend @@ -43,7 +43,8 @@ def _create_exchange_type(cls, **kw): code = kw.get("code") if code: exchange_type = model.search( - [("code", "=", code), ("backend_id", "=", cls.backend.id)], limit=1 + Domain([("code", "=", code), ("backend_id", "=", cls.backend.id)]), + limit=1, ) if exchange_type: return exchange_type diff --git a/edi_purchase_oca/tests/test_generate.py b/edi_purchase_oca/tests/test_generate.py index 0f814b911..c3ae45525 100644 --- a/edi_purchase_oca/tests/test_generate.py +++ b/edi_purchase_oca/tests/test_generate.py @@ -29,6 +29,7 @@ class TestGenerateViaConf(TransactionCase, PurchaseEDIBackendTestMixin, OrderMix @classmethod def setUpClass(cls): super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls._setup_env() cls._setup_records() From 4cf37730d1114b4071210f212235cc37d6f16ac5 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 13:58:39 +0200 Subject: [PATCH 16/26] edi_record_metadata: dev status -> Beta --- edi_record_metadata_oca/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edi_record_metadata_oca/__manifest__.py b/edi_record_metadata_oca/__manifest__.py index 9ad020919..b7812f204 100644 --- a/edi_record_metadata_oca/__manifest__.py +++ b/edi_record_metadata_oca/__manifest__.py @@ -8,7 +8,7 @@ Allow to store metadata for related records. """, "version": "19.0.1.0.0", - "development_status": "Alpha", + "development_status": "Beta", "license": "LGPL-3", "website": "https://github.com/OCA/edi-framework", "author": "Camptocamp, Odoo Community Association (OCA)", From 04995c825b66a9641bfc174d1d4d82daf21f9a14 Mon Sep 17 00:00:00 2001 From: Arnau Date: Thu, 12 Mar 2026 11:18:28 +0100 Subject: [PATCH 17/26] [REF] edi_core: move back ``_trigger_edi_event_make_name`` to core --- edi_component_oca/models/edi_exchange_record.py | 10 ++-------- edi_core_oca/models/edi_exchange_record.py | 6 ++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/edi_component_oca/models/edi_exchange_record.py b/edi_component_oca/models/edi_exchange_record.py index 551d1fa6b..b6105c0d5 100644 --- a/edi_component_oca/models/edi_exchange_record.py +++ b/edi_component_oca/models/edi_exchange_record.py @@ -8,15 +8,9 @@ class EdiExchangeRecord(models.Model): _inherit = "edi.exchange.record" - def _trigger_edi_event_make_name(self, name, suffix=None): - return "on_edi_exchange_{name}{suffix}".format( - name=name, - suffix=("_" + suffix) if suffix else "", - ) - def _trigger_edi_event(self, name, suffix=None, target=None, **kw): """Trigger a component event linked to this backend and edi exchange.""" - name = self._trigger_edi_event_make_name(name, suffix=suffix) + event_name = self._trigger_edi_event_make_name(name, suffix=suffix) target = target or self - target._event(name).notify(self, **kw) + target._event(event_name).notify(self, **kw) return super()._trigger_edi_event(name, suffix=suffix, target=target, **kw) diff --git a/edi_core_oca/models/edi_exchange_record.py b/edi_core_oca/models/edi_exchange_record.py index fda905ab5..575eda0a6 100644 --- a/edi_core_oca/models/edi_exchange_record.py +++ b/edi_core_oca/models/edi_exchange_record.py @@ -532,6 +532,12 @@ def _trigger_edi_event(self, name, suffix=None, target=None, **kw): """Hook to be implemented in other modules""" pass + def _trigger_edi_event_make_name(self, name, suffix=None): + return "on_edi_exchange_{name}{suffix}".format( + name=name, + suffix=("_" + suffix) if suffix else "", + ) + def _notify_done(self): self._notify_related_record(self._exchange_status_message("process_ok")) self._trigger_edi_event("done") From 1829921c4ff178f377420b1b3cfd0667ef24899c Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 10:40:56 +0200 Subject: [PATCH 18/26] [IMP[ edi_core: add option for global edi.configuration Global configurations can be used to catch generic events not bound to specific partner releations. As such, they are the core framework replacement for component events. Co-authored-by: Arnau --- edi_core_oca/models/edi_configuration.py | 7 +++++++ edi_core_oca/views/edi_configuration_views.xml | 1 + 2 files changed, 8 insertions(+) diff --git a/edi_core_oca/models/edi_configuration.py b/edi_core_oca/models/edi_configuration.py index 81780196b..a5efd6d0f 100644 --- a/edi_core_oca/models/edi_configuration.py +++ b/edi_core_oca/models/edi_configuration.py @@ -67,6 +67,13 @@ class EdiConfiguration(models.Model): help="""Used to do something specific here. Receives: operation, edi_action, vals, old_vals.""", ) + # You can use this to avoid component events ;) + is_global = fields.Boolean( + string="Global Configuration", + help="If checked, this configuration will be executed for all records, " + "regardless of the partner relation.", + default=False, + ) @api.constrains("backend_id", "type_id") def _constrains_backend(self): diff --git a/edi_core_oca/views/edi_configuration_views.xml b/edi_core_oca/views/edi_configuration_views.xml index 053db7764..674e88f8b 100644 --- a/edi_core_oca/views/edi_configuration_views.xml +++ b/edi_core_oca/views/edi_configuration_views.xml @@ -74,6 +74,7 @@ name="model_id" options="{'no_create': True, 'no_create_edit': True}" /> + From 62dbaff61fbbab65fd30d4a49e8acefc2d4bd731 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 11:02:55 +0200 Subject: [PATCH 19/26] [IMP] edi_core: trigger events w/ global edi.conf Co-authored-by: Arnau --- edi_core_oca/data/edi_configuration.xml | 12 ++++++++++++ edi_core_oca/models/edi_exchange_record.py | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/edi_core_oca/data/edi_configuration.xml b/edi_core_oca/data/edi_configuration.xml index 565919c74..867212198 100644 --- a/edi_core_oca/data/edi_configuration.xml +++ b/edi_core_oca/data/edi_configuration.xml @@ -15,6 +15,18 @@ on_record_write Trigger when a record is updated + + + On record exchange done + on_edi_exchange_done + Trigger when a record exchange is done + + + On record exchange error + on_edi_exchange_error + Trigger when a record exchange has an error + + Send via email diff --git a/edi_core_oca/models/edi_exchange_record.py b/edi_core_oca/models/edi_exchange_record.py index 575eda0a6..b5b75f04f 100644 --- a/edi_core_oca/models/edi_exchange_record.py +++ b/edi_core_oca/models/edi_exchange_record.py @@ -529,8 +529,18 @@ def _notify_related_record(self, message, level="info"): rec._notify_related_record(message, level) def _trigger_edi_event(self, name, suffix=None, target=None, **kw): - """Hook to be implemented in other modules""" - pass + event_name = self._trigger_edi_event_make_name(name, suffix) + target = target or self + + global_configs = self.env["edi.configuration"].search( + [ + ("trigger", "=", event_name), + ("is_global", "=", True), + ] + ) + + for conf in global_configs: + conf.edi_exec_snippet_do(target, **kw) def _trigger_edi_event_make_name(self, name, suffix=None): return "on_edi_exchange_{name}{suffix}".format( From 53a07202e636e0d4683679c7e8c58d28e4494ad4 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 11:15:31 +0200 Subject: [PATCH 20/26] [IMP] edi_core: improve global edi.conf * full matching by type, backend and model * full test coverage --- edi_core_oca/models/edi_configuration.py | 29 +++ edi_core_oca/models/edi_exchange_record.py | 9 +- edi_core_oca/tests/test_edi_configuration.py | 251 +++++++++++++++++++ 3 files changed, 282 insertions(+), 7 deletions(-) diff --git a/edi_core_oca/models/edi_configuration.py b/edi_core_oca/models/edi_configuration.py index a5efd6d0f..042ebe135 100644 --- a/edi_core_oca/models/edi_configuration.py +++ b/edi_core_oca/models/edi_configuration.py @@ -207,6 +207,35 @@ def edi_get_conf(self, trigger, backend=None): domain.append(("backend_id", "in", backend_ids)) return self.filtered_domain(domain) + @api.model + def edi_get_conf_global(self, exchange_record, trigger): + """Return active global configurations matching the given event. + + Unlike :meth:`edi_get_conf` -- which runs on a recordset of + configurations already linked to a partner -- global configurations + are not bound to any partner. We therefore have to derive the + filtering keys from the originating exchange record: + + * ``trigger`` must match the event code + * ``is_global`` must be True + * ``type_id`` must match the exchange type or be empty (applies to all) + * ``backend_id`` must match the backend or be empty (applies to all) + * ``model_name`` must match the related record model or be empty + (applies to all) + """ + related_model = exchange_record.model + model_options = [False] + if related_model: + model_options.append(related_model) + domain = [ + ("trigger", "=", trigger), + ("is_global", "=", True), + ("type_id", "in", [exchange_record.type_id.id, False]), + ("backend_id", "in", [exchange_record.backend_id.id, False]), + ("model_name", "in", model_options), + ] + return self.search(domain) + def action_view_partners(self): # TODO: add tests partner_model = self.env["res.partner"] diff --git a/edi_core_oca/models/edi_exchange_record.py b/edi_core_oca/models/edi_exchange_record.py index b5b75f04f..d8d35eb39 100644 --- a/edi_core_oca/models/edi_exchange_record.py +++ b/edi_core_oca/models/edi_exchange_record.py @@ -531,14 +531,9 @@ def _notify_related_record(self, message, level="info"): def _trigger_edi_event(self, name, suffix=None, target=None, **kw): event_name = self._trigger_edi_event_make_name(name, suffix) target = target or self - - global_configs = self.env["edi.configuration"].search( - [ - ("trigger", "=", event_name), - ("is_global", "=", True), - ] + global_configs = self.env["edi.configuration"].edi_get_conf_global( + self, event_name ) - for conf in global_configs: conf.edi_exec_snippet_do(target, **kw) diff --git a/edi_core_oca/tests/test_edi_configuration.py b/edi_core_oca/tests/test_edi_configuration.py index 562f5b540..001df337a 100644 --- a/edi_core_oca/tests/test_edi_configuration.py +++ b/edi_core_oca/tests/test_edi_configuration.py @@ -158,3 +158,254 @@ def test_edi_code_snippet(self): ) # Check the new vals after execution self.assertEqual(vals, expected_value) + + +class TestEDIConfigurationGlobalEvents(EDIBackendCommonTestCase): + """Test the global event dispatch via edi.configuration. + + `EDIExchangeRecord._trigger_edi_event` looks up all `edi.configuration` + records flagged as `is_global` and matching the event trigger code, + then executes their `snippet_do` against the target record. + These tests verify the dispatch happens for all `notify_*` events + and that the proper target (exchange record vs related record) + is passed to the snippet. + """ + + # Snippet appends a marker per call so we can verify multiple invocations + # against different targets within the same transaction. + _marker_snippet = "conf.write({'description': (conf.description or '') + '|' + record._name})" + + @classmethod + def setUpClass(cls): + super().setUpClass() + vals = { + "model": cls.partner._name, + "res_id": cls.partner.id, + } + cls.record = cls.backend.create_record("test_csv_output", vals) + cls.trigger_model = cls.env["edi.configuration.trigger"] + cls.conf_model = cls.env["edi.configuration"] + # Reuse existing data triggers when available, create the missing ones. + cls.trigger_done = cls.env.ref("edi_core_oca.edi_config_trigger_record_done") + cls.trigger_error = cls.env.ref("edi_core_oca.edi_config_trigger_record_error") + cls.trigger_ack_received = cls._get_or_create_trigger( + "on_edi_exchange_done_ack_received", "On ACK received" + ) + cls.trigger_ack_missing = cls._get_or_create_trigger( + "on_edi_exchange_done_ack_missing", "On ACK missing" + ) + cls.trigger_ack_received_error = cls._get_or_create_trigger( + "on_edi_exchange_done_ack_received_error", "On ACK received error" + ) + cls.trigger_generate_complete = cls._get_or_create_trigger( + "on_edi_exchange_generate_complete", "On generate complete" + ) + + @classmethod + def _get_or_create_trigger(cls, code, name): + trigger = cls.trigger_model.search([("code", "=", code)], limit=1) + if not trigger: + trigger = cls.trigger_model.create({"name": name, "code": code}) + return trigger + + def _make_conf(self, trigger, name, is_global=True, snippet=None, **overrides): + vals = { + "name": name, + "active": True, + "backend_id": self.backend.id, + "type_id": self.exchange_type_out.id, + "trigger_id": trigger.id, + "is_global": is_global, + "snippet_do": snippet or self._marker_snippet, + } + vals.update(overrides) + return self.conf_model.create(vals) + + def test_notify_done_triggers_global_conf(self): + conf = self._make_conf(self.trigger_done, "Global Done") + self.record._notify_done() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_notify_error_triggers_global_conf(self): + conf = self._make_conf(self.trigger_error, "Global Error") + self.record._notify_error("send_ko") + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_notify_ack_received_triggers_global_conf(self): + conf = self._make_conf(self.trigger_ack_received, "Global ACK received") + self.record._notify_ack_received() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_notify_ack_missing_triggers_global_conf(self): + conf = self._make_conf(self.trigger_ack_missing, "Global ACK missing") + self.record._notify_ack_missing() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_notify_ack_received_error_triggers_global_conf(self): + conf = self._make_conf( + self.trigger_ack_received_error, "Global ACK received error" + ) + self.record._notify_ack_received_error() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_non_global_conf_is_ignored(self): + conf = self._make_conf(self.trigger_done, "Non Global Done", is_global=False) + self.record._notify_done() + self.assertFalse(conf.description) + + def test_inactive_global_conf_is_ignored(self): + conf = self._make_conf(self.trigger_done, "Inactive Global Done") + conf.active = False + self.record._notify_done() + self.assertFalse(conf.description) + + def test_notify_action_complete_dispatches_to_both_targets(self): + """`notify_action_complete` fires the event twice when the related + record exists: once with the exchange record as target, once with the + related record (partner here).""" + conf = self._make_conf( + self.trigger_generate_complete, "Global generate complete" + ) + # Sanity check: the exchange record has a related record. + self.assertTrue(self.record.related_record_exists) + self.record.notify_action_complete("generate") + # The snippet appended one marker per call: exchange record then partner. + self.assertEqual( + conf.description, + f"|{self.record._name}|{self.partner._name}", + ) + + def test_notify_action_complete_no_related_record(self): + """When no related record exists, the event fires only on the + exchange record itself.""" + conf = self._make_conf( + self.trigger_generate_complete, "Global generate complete - no related" + ) + # Create an exchange record with no related record. + orphan_record = self.backend.create_record( + "test_csv_output", {"model": False, "res_id": False} + ) + orphan_record.notify_action_complete("generate") + self.assertEqual(conf.description, f"|{orphan_record._name}") + + def test_snippet_receives_conf_and_record(self): + """The snippet eval context must expose both `conf` (the configuration) + and `record` (the target of the event).""" + snippet = ( + "conf.write({'description': 'conf=%s|record=%s' % " + "(conf.name, record.display_name)})" + ) + conf = self._make_conf(self.trigger_done, "Context check", snippet=snippet) + self.record._notify_done() + self.assertEqual( + conf.description, + f"conf={conf.name}|record={self.record.display_name}", + ) + + def test_multiple_global_confs_all_executed(self): + """All global confs matching the trigger are executed.""" + conf1 = self._make_conf(self.trigger_done, "Global Done 1") + conf2 = self._make_conf(self.trigger_done, "Global Done 2") + self.record._notify_done() + self.assertEqual(conf1.description, f"|{self.record._name}") + self.assertEqual(conf2.description, f"|{self.record._name}") + + # ------------------------------------------------------------------ + # Filtering tests for `edi_get_conf_global` + # ------------------------------------------------------------------ + def test_filter_by_type_mismatch(self): + """A conf bound to a different exchange type must not fire.""" + conf = self._make_conf( + self.trigger_done, + "Wrong type", + type_id=self.exchange_type_in.id, + ) + self.record._notify_done() + self.assertFalse(conf.description) + + def test_filter_by_type_empty_matches(self): + """A conf without a type matches any exchange record's type.""" + conf = self._make_conf(self.trigger_done, "No type", type_id=False) + self.record._notify_done() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_filter_by_backend_mismatch(self): + """A conf bound to a different backend must not fire.""" + other_backend = self.env["edi.backend"].create( + { + "name": "Other backend", + "backend_type_id": self.backend.backend_type_id.id, + } + ) + # `_constrains_backend` requires backend to be compatible with the type's + # backend if the type has one set. Detach the type from the conf to test + # only the backend filter. + conf = self._make_conf( + self.trigger_done, + "Wrong backend", + backend_id=other_backend.id, + type_id=False, + ) + self.record._notify_done() + self.assertFalse(conf.description) + + def test_filter_by_backend_empty_matches(self): + """A conf without a backend matches any exchange record's backend.""" + conf = self._make_conf( + self.trigger_done, + "No backend", + backend_id=False, + type_id=False, + ) + self.record._notify_done() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_filter_by_model_mismatch(self): + """A conf bound to a different model must not fire.""" + other_model = self.env["ir.model"]._get("res.users") + conf = self._make_conf( + self.trigger_done, + "Wrong model", + model_id=other_model.id, + ) + self.record._notify_done() + self.assertFalse(conf.description) + + def test_filter_by_model_match(self): + """A conf bound to the related record model fires.""" + partner_model = self.env["ir.model"]._get(self.partner._name) + conf = self._make_conf( + self.trigger_done, + "Matching model", + model_id=partner_model.id, + ) + self.record._notify_done() + self.assertEqual(conf.description, f"|{self.record._name}") + + def test_filter_by_model_orphan_record(self): + """A conf with a model is skipped on records with no related model.""" + partner_model = self.env["ir.model"]._get(self.partner._name) + conf_with_model = self._make_conf( + self.trigger_done, + "Model bound", + model_id=partner_model.id, + ) + conf_no_model = self._make_conf(self.trigger_done, "Model-less") + orphan_record = self.backend.create_record( + "test_csv_output", {"model": False, "res_id": False} + ) + orphan_record._notify_done() + self.assertFalse(conf_with_model.description) + self.assertEqual(conf_no_model.description, f"|{orphan_record._name}") + + def test_edi_get_conf_global_returns_only_matching(self): + """Direct check on the new helper method.""" + matching = self._make_conf(self.trigger_done, "Matching") + wrong_trigger = self._make_conf(self.trigger_error, "Wrong trigger") + non_global = self._make_conf(self.trigger_done, "Non global", is_global=False) + result = self.env["edi.configuration"].edi_get_conf_global( + self.record, self.trigger_done.code + ) + self.assertIn(matching, result) + self.assertNotIn(wrong_trigger, result) + self.assertNotIn(non_global, result) From 4afda1a56dc059e66fe98817919ecc300702cb80 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 11:38:31 +0200 Subject: [PATCH 21/26] [DOC] edi_core: add minimal docs for edi.conf --- edi_core_oca/readme/CONFIGURE.md | 95 ++++++++++++++++++++++++++++++ edi_core_oca/readme/DESCRIPTION.md | 9 ++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/edi_core_oca/readme/CONFIGURE.md b/edi_core_oca/readme/CONFIGURE.md index 48045deba..a1957bbe0 100644 --- a/edi_core_oca/readme/CONFIGURE.md +++ b/edi_core_oca/readme/CONFIGURE.md @@ -63,3 +63,98 @@ backend to be used for the exchange. In case of "Custom" kind, you'll have to define your own logic to do something. + +## Custom event handlers via `edi.configuration` + +The framework can dispatch EDI lifecycle events to user-defined +configurations, providing a declarative alternative to component events. +Each `edi.configuration` record links a **trigger** (an +`edi.configuration.trigger` code) to a **snippet** (`snippet_do`) that is +executed every time the matching event fires on an exchange record. + +Built-in events fired by `EDIExchangeRecord` include: + +- `on_edi_exchange_done` — exchange processed successfully +- `on_edi_exchange_error` — exchange ended in error +- `on_edi_exchange_done_ack_received` — ACK file received +- `on_edi_exchange_done_ack_missing` — expected ACK not received +- `on_edi_exchange_done_ack_received_error` — ACK received with errors +- `on_edi_exchange__complete` — generic action completion (e.g. + `generate_complete`, `send_complete`), fired once on the exchange + record and once on its related record when present + +The snippet receives at least two variables in its evaluation context: + +- `conf` — the current `edi.configuration` record +- `record` — the target of the event (either the `edi.exchange.record` + itself or its related business record) + +Plus the standard `edi_exec_snippet_do` extras (`operation`, +`edi_action`, `old_value`, `vals`, ...). + +Two complementary lookup modes are available, and they can be combined +freely on the same flow. + +### Global event configurations + +Use this mode when you want a configuration to react to events on **any +business record** that travels through EDI, with no per-partner setup. + +Tick **Global Configuration** (`is_global`) on the `edi.configuration`. +When an event fires, the framework calls +`edi.configuration.edi_get_conf_global(exchange_record, trigger)` which +selects all active global configurations whose `trigger` matches the +event code, filtered by the originating exchange record: + +- **Exchange type** (`type_id`): must match the exchange record's type, + or be left empty to apply to every type +- **Backend** (`backend_id`): must match the exchange record's backend, + or be left empty to apply to every backend +- **Model** (`model_id` / `model_name`): must match the related record + model (e.g. `sale.order`, `account.move`), or be left empty to apply + to every model + +Empty values mean "applies to all". Inactive configurations and +non-global configurations are ignored. All matching configurations are +executed in sequence. + +Typical use cases: + +- Posting a generic chatter message on every exchange that ends in error +- Pushing a notification to an external system every time an ACK is + received for a given backend +- Logging extra audit information for every exchange of a given type + +### Partner-specific (relation-based) event configurations + +Use this mode when the reaction must depend on the partner (or any +other related record) involved in the exchange. + +In this case configurations are **not** marked as global. Instead, the +business record exposes an `edi_config_ids` relation (via +`edi.exchange.consumer.mixin._edi_config_field_relation`, which by +default returns `self.env["edi.configuration"]` and can be overridden, +for example to point at `self.partner_id.edi_config_ids`). When an +event fires on the business record (e.g. on create, on write, +on send-via-email/EDI), the framework calls +`edi_confs.edi_get_conf(trigger)` on that relation and runs the +matching snippets. + +Compared with global configurations: + +- **Discovery** comes from the record's own relation, not from a + database-wide search; this is the right place to model "this partner + wants this behaviour" rules +- **Filtering** is reduced to `trigger` and (optionally) `backend_id`, + since the recordset is already narrowed by the relation +- The same `snippet_do` API applies, so a snippet can be reused + verbatim between global and partner-specific configurations + +Typical use cases: + +- Sending a specific EDI flow only for a subset of partners +- Customising the document generation per customer (e.g. different + email template, different transport) +- Switching between EDI and email delivery based on partner + preferences + diff --git a/edi_core_oca/readme/DESCRIPTION.md b/edi_core_oca/readme/DESCRIPTION.md index 8cfcb472b..f9aee7085 100644 --- a/edi_core_oca/readme/DESCRIPTION.md +++ b/edi_core_oca/readme/DESCRIPTION.md @@ -8,4 +8,11 @@ Provides following models: 3. EDI Exchange Type, to define file types of exchange 4. EDI Exchange Record, to define a record exchanged between systems -Also define a mixin to be inherited by records that will generate EDIs +Also define a mixin to be inherited by records that will generate EDIs. + +In addition, the module ships an ``edi.configuration`` mechanism that lets +users react to EDI events declaratively, by writing small Python snippets +attached to event triggers. This can be used as a lightweight alternative +to component event listeners: configurations can react globally (on any +exchange) or be scoped to a specific partner (or any related record), +exchange type, backend and target model. See ``CONFIGURE.md`` for details. From 51a32721a29ea2aa9864f473667e9bb3b1bac072 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 11:39:43 +0200 Subject: [PATCH 22/26] [DOC] edi_core: add readme/newsfragments --- edi_core_oca/readme/newsfragments/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 edi_core_oca/readme/newsfragments/.gitkeep diff --git a/edi_core_oca/readme/newsfragments/.gitkeep b/edi_core_oca/readme/newsfragments/.gitkeep new file mode 100644 index 000000000..e69de29bb From e013ca8c25f71afb46a988dfc72d337faf617827 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 11:54:21 +0200 Subject: [PATCH 23/26] [DOC] edi_core: update newfragments --- .../global-edi-conf-events.feature | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 edi_core_oca/readme/newsfragments/global-edi-conf-events.feature diff --git a/edi_core_oca/readme/newsfragments/global-edi-conf-events.feature b/edi_core_oca/readme/newsfragments/global-edi-conf-events.feature new file mode 100644 index 000000000..d2678fe28 --- /dev/null +++ b/edi_core_oca/readme/newsfragments/global-edi-conf-events.feature @@ -0,0 +1,20 @@ +Introduce a new system for **global EDI events** based on ``edi.configuration`` +that can replace the use of component events. + +Any ``edi.configuration`` flagged as ``is_global`` is now picked up by +``EDIExchangeRecord._trigger_edi_event`` and its ``snippet_do`` is executed +whenever the matching event fires (``done``, ``error``, ``ack_received``, +``ack_missing``, ``ack_received_error``, ``_complete``, ...). + +Filtering is performed via the new ``edi.configuration.edi_get_conf_global`` +model method, which selects active global configurations matching the event +trigger code and, when set, the exchange type, the backend and the related +record model carried by the exchange record (empty values still mean "applies +to all"). This lets integrators subscribe to EDI events declaratively from +the UI instead of writing component listeners. + +Full test coverage is included for the dispatch on all ``notify_*`` events +(both on the exchange record and on the related record target) and for the +new filtering rules. + +Last but not lease: add minimal docs for edi.configuration. From 9a479d1e6acf3dfdfb537ab065f2ff16fcb3e335 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 13:02:54 +0200 Subject: [PATCH 24/26] [FIX] edi_core: fix edi.configuration._constrains_backend No comparison if backend is not set or type is not set. --- edi_core_oca/models/edi_configuration.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/edi_core_oca/models/edi_configuration.py b/edi_core_oca/models/edi_configuration.py index 042ebe135..7a77fe9d8 100644 --- a/edi_core_oca/models/edi_configuration.py +++ b/edi_core_oca/models/edi_configuration.py @@ -78,12 +78,14 @@ class EdiConfiguration(models.Model): @api.constrains("backend_id", "type_id") def _constrains_backend(self): for rec in self: + if not rec.backend_id: + continue if rec.type_id.backend_id: if rec.type_id.backend_id != rec.backend_id: raise exceptions.ValidationError( self.env._("Backend must match with exchange type's backend!") ) - else: + elif rec.type_id: if rec.type_id.backend_type_id != rec.backend_id.backend_type_id: raise exceptions.ValidationError( self.env._( From cd9045d93c76620cb316fbe5281bb343a5f0583c Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 May 2026 13:03:37 +0200 Subject: [PATCH 25/26] fixup! [IMP] edi_core: improve global edi.conf --- edi_core_oca/tests/test_edi_configuration.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/edi_core_oca/tests/test_edi_configuration.py b/edi_core_oca/tests/test_edi_configuration.py index 001df337a..e6bfb21f1 100644 --- a/edi_core_oca/tests/test_edi_configuration.py +++ b/edi_core_oca/tests/test_edi_configuration.py @@ -173,7 +173,9 @@ class TestEDIConfigurationGlobalEvents(EDIBackendCommonTestCase): # Snippet appends a marker per call so we can verify multiple invocations # against different targets within the same transaction. - _marker_snippet = "conf.write({'description': (conf.description or '') + '|' + record._name})" + _marker_snippet = ( + "conf.write({'description': (conf.description or '') + '|' + record._name})" + ) @classmethod def setUpClass(cls): From 541bd605542ed95de528a7975abda6e88519573b Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 19 May 2026 12:52:36 +0200 Subject: [PATCH 26/26] edi_component: fix _trigger_edi_event to preserve event name The event name would be prefixed 2 times when calling super. --- edi_core_oca/models/edi_exchange_record.py | 1 + 1 file changed, 1 insertion(+) diff --git a/edi_core_oca/models/edi_exchange_record.py b/edi_core_oca/models/edi_exchange_record.py index d8d35eb39..ce150f044 100644 --- a/edi_core_oca/models/edi_exchange_record.py +++ b/edi_core_oca/models/edi_exchange_record.py @@ -529,6 +529,7 @@ def _notify_related_record(self, message, level="info"): rec._notify_related_record(message, level) def _trigger_edi_event(self, name, suffix=None, target=None, **kw): + """Trigger a component event linked to this backend and edi exchange.""" event_name = self._trigger_edi_event_make_name(name, suffix) target = target or self global_configs = self.env["edi.configuration"].edi_get_conf_global(