From 86ce386213d7ba3a22d1ff868d58657fd7097cc8 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 5 Jun 2026 07:06:40 +0000 Subject: [PATCH 1/4] Translated using Weblate (Italian) Currently translated at 100.0% (286 of 286 strings) Translation: edi-framework-19.0/edi-framework-19.0-edi_core_oca Translate-URL: https://translation.odoo-community.org/projects/edi-framework-19-0/edi-framework-19-0-edi_core_oca/it/ --- edi_core_oca/i18n/it.po | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/edi_core_oca/i18n/it.po b/edi_core_oca/i18n/it.po index 86758cb0d..b039537a1 100644 --- a/edi_core_oca/i18n/it.po +++ b/edi_core_oca/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 17.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-05-25 22:46+0000\n" +"PO-Revision-Date: 2026-06-05 09:46+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -157,7 +157,7 @@ msgstr "" #. module: edi_core_oca #: model:ir.model.fields,field_description:edi_core_oca.field_edi_exchange_type__exchange_record_count msgid "# Exchange Records" -msgstr "" +msgstr "N° record scambio" #. module: edi_core_oca #: model_terms:ir.ui.view,arch_db:edi_core_oca.edi_exchange_consumer_mixin_buttons @@ -319,7 +319,7 @@ msgstr "Applica a questo modello" #. module: edi_core_oca #: model:ir.actions.server,name:edi_core_oca.ir_cron_archive_old_edi_records_ir_actions_server msgid "Archive Old EDI Exchange Records" -msgstr "" +msgstr "Archivia i vecchi record EDI" #. module: edi_core_oca #: model_terms:ir.ui.view,arch_db:edi_core_oca.edi_backend_view_form @@ -352,12 +352,12 @@ msgstr "" #. module: edi_core_oca #: model:ir.model.fields,field_description:edi_core_oca.field_edi_backend__auto_archive_records_after_days msgid "Auto-archive records after (days)" -msgstr "" +msgstr "Auto archivia i record dopo (giorni)" #. module: edi_core_oca #: model:ir.model.fields,field_description:edi_core_oca.field_edi_backend__auto_delete_records_after_days msgid "Auto-delete archived records after (days)" -msgstr "" +msgstr "Auto cancella i record archiviati dopo (giorni)" #. module: edi_core_oca #: model:ir.model.fields,help:edi_core_oca.field_edi_backend__auto_archive_records_after_days @@ -365,6 +365,8 @@ msgid "" "Automatically archive EDI exchange records after X days. Set to <= 0 to " "disable auto-archiving." msgstr "" +"Archivia automaticamente i record di scambio EDI dopo X giorni. Impostare " +"inferiore o uguale a 0 per disabilitare l'auto archiviazione." #. module: edi_core_oca #: model:ir.model.fields,help:edi_core_oca.field_edi_backend__auto_delete_records_after_days @@ -372,6 +374,8 @@ msgid "" "Automatically delete archived EDI exchange records after X days. Set to <= 0 " "to disable auto-deletion." msgstr "" +"Cancella automaticamente i record di scambio EDI archiviati dopo X giorni. " +"Impostare inferiore o uguale a 0 per disabilitare l'auto cancellazione." #. module: edi_core_oca #: model:ir.model.fields,field_description:edi_core_oca.field_edi_configuration__backend_id @@ -528,7 +532,7 @@ msgstr "Gestore errore decodifica" #. module: edi_core_oca #: model:ir.actions.server,name:edi_core_oca.ir_cron_delete_old_archived_edi_records_ir_actions_server msgid "Delete Old Archived EDI Exchange Records" -msgstr "" +msgstr "Cancella i vecchi record di scambio EDI archiviati" #. module: edi_core_oca #: model:ir.model.fields,help:edi_core_oca.field_edi_configuration__description @@ -1547,7 +1551,7 @@ msgstr "Record ID=%d non è previsto che sia inviato!" #. module: edi_core_oca #: model_terms:ir.ui.view,arch_db:edi_core_oca.edi_backend_view_form msgid "Records retention" -msgstr "" +msgstr "Cancellazione record" #. module: edi_core_oca #: model_terms:ir.ui.view,arch_db:edi_core_oca.edi_exchange_record_view_form @@ -1808,6 +1812,10 @@ msgid "" "waiting for the cron to pass by. Requires auto generate flag to be active as " "well. The cron will skip these records unless forced." msgstr "" +"Quando attivi, i record di questo tipo verranno elaborati immediatamente, " +"senza attendere il completamento del cron. Richiede che anche il flag di " +"generazione automatica sia attivo. Il cron ignorerà questi record, a meno " +"che non venga forzato." #. module: edi_core_oca #: model:ir.model.fields,help:edi_core_oca.field_edi_exchange_consumer_mixin__edi_disable_auto From 95ddb9459b4f855b421274ecbcf81278309acb0a Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 5 Jun 2026 07:06:56 +0000 Subject: [PATCH 2/4] Translated using Weblate (Italian) Currently translated at 100.0% (56 of 56 strings) Translation: edi-framework-19.0/edi-framework-19.0-edi_endpoint_oca Translate-URL: https://translation.odoo-community.org/projects/edi-framework-19-0/edi-framework-19-0-edi_endpoint_oca/it/ --- edi_endpoint_oca/i18n/it.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edi_endpoint_oca/i18n/it.po b/edi_endpoint_oca/i18n/it.po index 18eeab1e1..aaa9dda9e 100644 --- a/edi_endpoint_oca/i18n/it.po +++ b/edi_endpoint_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: 2026-05-25 22:46+0000\n" +"PO-Revision-Date: 2026-06-05 09:46+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -71,7 +71,7 @@ msgstr "Documenti esempio codice" #. module: edi_endpoint_oca #: model:ir.model.fields,help:edi_endpoint_oca.field_edi_endpoint__cors msgid "Comma-separated list of allowed origins" -msgstr "" +msgstr "Elenco separato da virgola delle origini consentite" #. module: edi_endpoint_oca #: model:ir.model.fields,field_description:edi_endpoint_oca.field_edi_endpoint__company_id @@ -81,7 +81,7 @@ msgstr "Azienda" #. module: edi_endpoint_oca #: model:ir.model.fields,field_description:edi_endpoint_oca.field_edi_endpoint__cors msgid "Cors" -msgstr "" +msgstr "Cors" #. module: edi_endpoint_oca #. odoo-python From 397dd8a214aee187ecd5946544a086508b8beb0a Mon Sep 17 00:00:00 2001 From: Ricardoalso Date: Fri, 5 Jun 2026 14:16:54 +0200 Subject: [PATCH 3/4] [FIX] edi_core_oca: fire on_edi_exchange_error for all error states When using edi_notification_oca, EDI exchanges that failed during send, receive, or validation did not trigger any notification, leaving errors unnoticed and requiring manual detection. The backend only emitted "on_edi_exchange_error" on the process error path. Other error paths updated the state and posted chatter messages but did not fire the event. This change ensures the error event is emitted on all error transitions: exchange_send -> _notify_error("send_ko") exchange_receive -> _notify_error("receive_ko", "validate_ko") exchange_generate -> _notify_error("validate_ko") Calls are guarded by state changes to avoid duplicate notifications. Redundant chatter messages are removed since _notify_error already handles logging and event emission. --- edi_core_oca/models/edi_backend.py | 24 +++++++++++++++------ edi_core_oca/tests/common.py | 23 ++++++++++++++++++++ edi_core_oca/tests/test_backend_input.py | 10 +++++++++ edi_core_oca/tests/test_backend_output.py | 11 ++++++++++ edi_core_oca/tests/test_backend_validate.py | 22 +++++++++++++++++++ 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/edi_core_oca/models/edi_backend.py b/edi_core_oca/models/edi_backend.py index 6a065ae34..0f004b822 100644 --- a/edi_core_oca/models/edi_backend.py +++ b/edi_core_oca/models/edi_backend.py @@ -121,6 +121,7 @@ def exchange_generate(self, exchange_record, store=True, force=False, **kw): :param kw: keyword args to be propagated to output generate handler """ self.ensure_one() + old_state = exchange_record.edi_exchange_state if force and exchange_record.exchange_file: # Remove file to regenerate exchange_record.exchange_file = False @@ -148,7 +149,6 @@ def exchange_generate(self, exchange_record, store=True, force=False, **kw): traceback = _get_exception_traceback() error = _get_exception_msg(err) state = "validate_error" - message = exchange_record._exchange_status_message("validate_ko") exchange_record.update( { "edi_exchange_state": state, @@ -156,6 +156,15 @@ def exchange_generate(self, exchange_record, store=True, force=False, **kw): "exchange_error_traceback": traceback, } ) + if old_state != state: + exchange_record._notify_error("validate_ko") + # At this point `message` still holds the "generate_ok" success + # text set before validation ran. Generation succeeded but + # validation failed, so clear it: `_notify_error` has already + # posted the validation error (and fired the error event), and + # we must not let `notify_action_complete` below post the stale + # success message on top of it. + message = None exchange_record.notify_action_complete("generate", message=message) return message @@ -228,7 +237,7 @@ def exchange_send(self, exchange_record): check = self._output_check_send(exchange_record) if not check: return self._failed_output_check_send_msg() - state = exchange_record.edi_exchange_state + old_state = state = exchange_record.edi_exchange_state error = traceback = False message = None res = "" @@ -248,7 +257,6 @@ def exchange_send(self, exchange_record): traceback = _get_exception_traceback() error = _get_exception_msg(err) state = "output_error_on_send" - message = exchange_record._exchange_status_message("send_ko") res = f"Error: {error}" _logger.debug( "%s send failed. Marked as errored.", exchange_record.identifier @@ -281,6 +289,8 @@ def exchange_send(self, exchange_record): "exchanged_on": fields.Datetime.now(), } ) + if old_state != state and state == "output_error_on_send": + exchange_record._notify_error("send_ko") exchange_record.notify_action_complete("send", message=message) return res @@ -514,7 +524,7 @@ def exchange_receive(self, exchange_record): check = self._exchange_receive_check(exchange_record) if not check: return "Nothing to do. Likely already received." - state = exchange_record.edi_exchange_state + old_state = state = exchange_record.edi_exchange_state error = traceback = False message = None content = None @@ -528,7 +538,6 @@ def exchange_receive(self, exchange_record): traceback = _get_exception_traceback() error = _get_exception_msg(err) state = "validate_error" - message = exchange_record._exchange_status_message("validate_ko") res = f"Validation error: {error}" except self._swallable_exceptions() as err: if self.env.context.get("_edi_receive_break_on_error"): @@ -536,7 +545,6 @@ def exchange_receive(self, exchange_record): traceback = _get_exception_traceback() error = _get_exception_msg(err) state = "input_receive_error" - message = exchange_record._exchange_status_message("receive_ko") res = f"Input error: {error}" except (OperationalError, IntegrityError): # We don't want the finally block to be executed in this case as @@ -561,6 +569,10 @@ def exchange_receive(self, exchange_record): "exchanged_on": fields.Datetime.now(), } ) + if old_state != state and state == "input_receive_error": + exchange_record._notify_error("receive_ko") + if old_state != state and state == "validate_error": + exchange_record._notify_error("validate_ko") exchange_record.notify_action_complete("receive", message=message) return res diff --git a/edi_core_oca/tests/common.py b/edi_core_oca/tests/common.py index fe9bdb9d1..8f74be261 100644 --- a/edi_core_oca/tests/common.py +++ b/edi_core_oca/tests/common.py @@ -100,3 +100,26 @@ def setUpClass(cls): super().setUpClass() cls._setup_env() cls._setup_records() + + def _make_global_error_conf(self, exchange_type): + """Register a global ``edi.configuration`` bound to the + ``on_edi_exchange_error`` event. + + Its snippet writes a marker on the configuration so a test can assert + the error event actually fired. This is the observable behaviour that + distinguishes an errored exchange (which must notify, e.g. create the + activities handled by ``edi_notification_oca``) from one that merely + posts a chatter message via ``notify_action_complete``. + """ + trigger = self.env.ref("edi_core_oca.edi_config_trigger_record_error") + return self.env["edi.configuration"].create( + { + "name": "Test notify on error", + "active": True, + "backend_id": self.backend.id, + "type_id": exchange_type.id, + "trigger_id": trigger.id, + "is_global": True, + "snippet_do": "conf.write({'description': 'error-event-fired'})", + } + ) diff --git a/edi_core_oca/tests/test_backend_input.py b/edi_core_oca/tests/test_backend_input.py index 44065c927..eb9a04752 100644 --- a/edi_core_oca/tests/test_backend_input.py +++ b/edi_core_oca/tests/test_backend_input.py @@ -77,6 +77,16 @@ def test_receive_no_allow_empty_file_record(self): self.record, [{"edi_exchange_state": "input_receive_error"}] ) + def test_receive_no_allow_empty_file_triggers_notify_error(self): + self.record.edi_exchange_state = "input_pending" + conf = self._make_global_error_conf(self.record.type_id) + self.backend.with_context( + fake_output="", _edi_receive_break_on_error=False + ).exchange_receive(self.record) + # The error event must fire so downstream notifications (e.g. + # edi_notification_oca activities) are triggered. + self.assertEqual(conf.description, "error-event-fired") + def test_receive_allow_empty_file_record(self): self.record.edi_exchange_state = "input_pending" self.record.type_id.allow_empty_files_on_receive = True diff --git a/edi_core_oca/tests/test_backend_output.py b/edi_core_oca/tests/test_backend_output.py index 39f2d57a8..2b5ea7d41 100644 --- a/edi_core_oca/tests/test_backend_output.py +++ b/edi_core_oca/tests/test_backend_output.py @@ -100,6 +100,17 @@ def test_send_record_with_error(self): "OOPS! Something went wrong :(", self.record.exchange_error_traceback ) + def test_send_record_with_error_triggers_notify_error(self): + self.record.write({"edi_exchange_state": "output_pending"}) + self.record._set_file_content(f"TEST {self.record.id}") + conf = self._make_global_error_conf(self.record.type_id) + self.record.with_context( + test_break_send="OOPS! Something went wrong :(" + ).action_exchange_send() + # The error event must fire so downstream notifications (e.g. + # edi_notification_oca activities) are triggered. + self.assertEqual(conf.description, "error-event-fired") + def test_send_invalid_direction(self): vals = { "model": self.partner._name, diff --git a/edi_core_oca/tests/test_backend_validate.py b/edi_core_oca/tests/test_backend_validate.py index d3c585f8b..3c082e454 100644 --- a/edi_core_oca/tests/test_backend_validate.py +++ b/edi_core_oca/tests/test_backend_validate.py @@ -85,6 +85,17 @@ def test_receive_validate_record_error(self): ) self.assertIn("Data seems wrong!", self.record_in.exchange_error_traceback) + def test_receive_validate_record_error_triggers_notify_error(self): + self.record_in.write({"edi_exchange_state": "input_pending"}) + exc = EDIValidationError("Data seems wrong!") + conf = self._make_global_error_conf(self.record_in.type_id) + self.backend.with_context(test_break_input_validate=exc).exchange_receive( + self.record_in + ) + # The error event must fire so downstream notifications (e.g. + # edi_notification_oca activities) are triggered. + self.assertEqual(conf.description, "error-event-fired") + def test_generate_validate_record(self): self.record_out.write({"edi_exchange_state": "new"}) self.backend.exchange_generate(self.record_out) @@ -119,6 +130,17 @@ def test_generate_validate_record_error(self): ) self.assertIn("Data seems wrong!", self.record_out.exchange_error_traceback) + def test_generate_validate_record_error_triggers_notify_error(self): + self.record_out.write({"edi_exchange_state": "new"}) + exc = EDIValidationError("Data seems wrong!") + conf = self._make_global_error_conf(self.record_out.type_id) + self.backend.with_context(test_break_output_validate=exc).exchange_generate( + self.record_out + ) + # The error event must fire so downstream notifications (e.g. + # edi_notification_oca activities) are triggered. + self.assertEqual(conf.description, "error-event-fired") + def test_validate_record_error_regenerate(self): self.record_out.write({"edi_exchange_state": "new"}) exc = EDIValidationError("Data seems wrong!") From 67c4e88c88e5322e374519a036849ba4955c6969 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 5 Jun 2026 12:50:59 +0000 Subject: [PATCH 4/4] [BOT] post-merge updates --- README.md | 2 +- edi_core_oca/README.rst | 2 +- edi_core_oca/__manifest__.py | 2 +- edi_core_oca/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c5a5ead17..300bc3a5b 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [edi_component_oca](edi_component_oca/) | 19.0.1.1.0 | simahawk etobella | Allow to use Connector as a source in EDI -[edi_core_oca](edi_core_oca/) | 19.0.1.2.0 | simahawk etobella | Define backends, exchange types, exchange records, basic automation and views for handling EDI exchanges. +[edi_core_oca](edi_core_oca/) | 19.0.1.2.1 | simahawk etobella | Define backends, exchange types, exchange records, basic automation and views for handling EDI exchanges. [edi_endpoint_oca](edi_endpoint_oca/) | 19.0.1.1.1 | | Base module allowing configuration of custom endpoints for EDI framework. [edi_product_oca](edi_product_oca/) | 19.0.1.0.0 | | EDI framework configuration and base logic for products and units of measure [edi_purchase_oca](edi_purchase_oca/) | 19.0.1.0.0 | | Define EDI Configuration for Purchase Orders diff --git a/edi_core_oca/README.rst b/edi_core_oca/README.rst index dfe98e764..c1bd89935 100644 --- a/edi_core_oca/README.rst +++ b/edi_core_oca/README.rst @@ -11,7 +11,7 @@ EDI !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:46139d4cc31684944b8784e2503633ab59a96d8b072b42ee5ab30cd8f2177930 + !! source digest: sha256:de90b9bf70f5e4c8e52326e5549c47a2a3d9b91843ffb0a101d442d6fce3f8c3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/edi_core_oca/__manifest__.py b/edi_core_oca/__manifest__.py index 5496b6981..7537474e2 100644 --- a/edi_core_oca/__manifest__.py +++ b/edi_core_oca/__manifest__.py @@ -9,7 +9,7 @@ Define backends, exchange types, exchange records, basic automation and views for handling EDI exchanges. """, - "version": "19.0.1.2.0", + "version": "19.0.1.2.1", "website": "https://github.com/OCA/edi-framework", "development_status": "Beta", "license": "LGPL-3", diff --git a/edi_core_oca/static/description/index.html b/edi_core_oca/static/description/index.html index 03d5c155b..b06702882 100644 --- a/edi_core_oca/static/description/index.html +++ b/edi_core_oca/static/description/index.html @@ -372,7 +372,7 @@

EDI

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

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

Base EDI backend.