From 598621c2b9fe55ca112040069afde7e80e79e600 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Fri, 24 Jul 2026 20:34:04 +0200 Subject: [PATCH 1/4] [IMP] edi_queue_oca: update exc record state on failed jobs Rely on new on fail hooks from the queue job module. --- edi_queue_oca/data/job_function.xml | 4 ++++ edi_queue_oca/models/edi_exchange_record.py | 22 +++++++++++++++++++++ edi_queue_oca/tests/test_backend_jobs.py | 21 ++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/edi_queue_oca/data/job_function.xml b/edi_queue_oca/data/job_function.xml index aedc76dec..6183d9c3b 100644 --- a/edi_queue_oca/data/job_function.xml +++ b/edi_queue_oca/data/job_function.xml @@ -2,21 +2,25 @@ action_exchange_generate + _job_on_fail_generate action_exchange_send + _job_on_fail_send action_exchange_receive + _job_on_fail_receive action_exchange_process + _job_on_fail_process diff --git a/edi_queue_oca/models/edi_exchange_record.py b/edi_queue_oca/models/edi_exchange_record.py index 58915fa5a..21c606e15 100644 --- a/edi_queue_oca/models/edi_exchange_record.py +++ b/edi_queue_oca/models/edi_exchange_record.py @@ -91,3 +91,25 @@ def action_exchange_generate_send_chained(self): # Raise prio to max to send the record out as fast as possible. job1.on_done(self.delayable(priority=0).action_exchange_send()) job1.delay() + + def _job_on_fail_generate(self, **kw): + return self._job_on_fail_update("validate_error", **kw) + + def _job_on_fail_send(self, **kw): + return self._job_on_fail_update("output_error_on_send", **kw) + + def _job_on_fail_receive(self, **kw): + return self._job_on_fail_update("input_receive_error", **kw) + + def _job_on_fail_process(self, **kw): + return self._job_on_fail_update("input_processed_error", **kw) + + def _job_on_fail_update(self, failed_state, **kw): + self.ensure_one() + self.write( + { + "edi_exchange_state": failed_state, + "exchange_error": ": ".join([kw["exc_name"], kw["exc_message"]]), + "exchange_error_traceback": kw["exc_info"], + } + ) diff --git a/edi_queue_oca/tests/test_backend_jobs.py b/edi_queue_oca/tests/test_backend_jobs.py index 44c90eac7..c2ddb2060 100644 --- a/edi_queue_oca/tests/test_backend_jobs.py +++ b/edi_queue_oca/tests/test_backend_jobs.py @@ -159,3 +159,24 @@ def test_input_processed_error(self): # Check related jobs record.invalidate_recordset() self.assertEqual(created, self._get_related_jobs(record)) + + def test_on_fail_job(self): + vals = { + "model": self.partner._name, + "res_id": self.partner.id, + } + record = self.backend.create_record("test_csv_output", vals) + self.assertEqual(record.edi_exchange_state, "new") + job = record.action_exchange_generate() + exc_vals = { + "exc_info": "Dummy traceback", + "exc_name": "Dummy exception", + "exc_message": "Dummy message", + } + job.on_fail(exc_vals) + self.assertEqual(record.edi_exchange_state, "validate_error") + self.assertEqual( + record.exchange_error, + ": ".join([exc_vals["exc_name"], exc_vals["exc_message"]]), + ) + self.assertEqual(record.exchange_error_traceback, exc_vals["exc_info"]) From 14c4751255721b1d50dc6e8847bbd743b85dc1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Todorovich?= Date: Thu, 3 Sep 2026 13:28:41 -0300 Subject: [PATCH 2/4] [FIX] edi_queue_oca: set on_fail_method on existing job functions The on fail hooks introduced in b3290c735d29da133c44a6124b1ae05eb98d64bf are declared in a noupdate data file, so databases created before that commit never got `on_fail_method` on the exchange record job functions, and failed jobs do not update the exchange record state. Add a post-migration script to fill the missing values. --- edi_queue_oca/README.rst | 16 ++++------ edi_queue_oca/__manifest__.py | 2 +- .../migrations/18.0.1.0.3/post-migration.py | 30 +++++++++++++++++++ edi_queue_oca/static/description/index.html | 24 ++++++--------- 4 files changed, 46 insertions(+), 26 deletions(-) create mode 100644 edi_queue_oca/migrations/18.0.1.0.3/post-migration.py diff --git a/edi_queue_oca/README.rst b/edi_queue_oca/README.rst index c9b6f4945..dd84a7d8d 100644 --- a/edi_queue_oca/README.rst +++ b/edi_queue_oca/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ============= Edi Queue Oca ============= @@ -17,7 +13,7 @@ Edi Queue Oca .. |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/license-LGPL--3-blue.png +.. |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--framework-lightgray.png?logo=github @@ -65,11 +61,11 @@ Authors Contributors ------------ -- Simone Orsi -- Enric Tobella -- Manuel Regidor -- Thien Vo -- Jordi Masvidal +- Simone Orsi +- Enric Tobella +- Manuel Regidor +- Thien Vo +- Jordi Masvidal Maintainers ----------- diff --git a/edi_queue_oca/__manifest__.py b/edi_queue_oca/__manifest__.py index dec27cca5..e34d4ddf2 100644 --- a/edi_queue_oca/__manifest__.py +++ b/edi_queue_oca/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Edi Queue Oca", "summary": """Set Queue Jobs on EDI""", - "version": "18.0.1.0.2", + "version": "18.0.1.0.3", "license": "LGPL-3", "author": "Dixmit,Camptocamp,Odoo Community Association (OCA)", "website": "https://github.com/OCA/edi-framework", diff --git a/edi_queue_oca/migrations/18.0.1.0.3/post-migration.py b/edi_queue_oca/migrations/18.0.1.0.3/post-migration.py new file mode 100644 index 000000000..c0d734735 --- /dev/null +++ b/edi_queue_oca/migrations/18.0.1.0.3/post-migration.py @@ -0,0 +1,30 @@ +# Copyright 2026 Camptocamp SA (http://www.camptocamp.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging + +from odoo import SUPERUSER_ID, api + +_logger = logging.getLogger(__name__) + +# The job functions are declared in a ``noupdate`` data file, so databases +# created before the on fail hooks were added never got ``on_fail_method``. +ON_FAIL_METHODS = { + "edi_queue_oca.job_fun_exchange_record_generate": "_job_on_fail_generate", + "edi_queue_oca.job_fun_exchange_record_send": "_job_on_fail_send", + "edi_queue_oca.job_fun_exchange_record_receive": "_job_on_fail_receive", + "edi_queue_oca.job_fun_exchange_record_process": "_job_on_fail_process", +} + + +def migrate(cr, version): + env = api.Environment(cr, SUPERUSER_ID, {}) + for xmlid, method in ON_FAIL_METHODS.items(): + job_function = env.ref(xmlid, raise_if_not_found=False) + if not job_function: + _logger.warning("Job function %s not found, skipping", xmlid) + continue + if job_function.on_fail_method: + continue + _logger.info("Setting on_fail_method=%s on %s", method, xmlid) + job_function.on_fail_method = method diff --git a/edi_queue_oca/static/description/index.html b/edi_queue_oca/static/description/index.html index c65aff333..de5c87ae6 100644 --- a/edi_queue_oca/static/description/index.html +++ b/edi_queue_oca/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Edi Queue Oca -
+
+

Edi Queue Oca

- - -Odoo Community Association - -
-

Edi Queue Oca

-

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

+

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

This module integrates EDI with Queue Job and now the edi exchange records are generated using queue.

No need of doing a configuration on it, however, we can specify priority @@ -392,7 +387,7 @@

Edi Queue Oca

-

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 @@ -400,16 +395,16 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Dixmit
  • Camptocamp
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -432,6 +427,5 @@

Maintainers

-
From 7e49690dff3225f0814598be84cfa66167d4dc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Todorovich?= Date: Thu, 3 Sep 2026 14:11:55 -0300 Subject: [PATCH 3/4] [FIX] edi_queue_oca: on fail hook with non string exception message The hook joins `exc_name` and `exc_message` as strings, but the message stored by queue_job is the first argument of the exception, which is the errno for an OSError and may also be missing. The join then raises a TypeError and the exchange record is not updated. --- edi_queue_oca/models/edi_exchange_record.py | 9 ++++-- edi_queue_oca/tests/test_backend_jobs.py | 35 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/edi_queue_oca/models/edi_exchange_record.py b/edi_queue_oca/models/edi_exchange_record.py index 21c606e15..6f420947f 100644 --- a/edi_queue_oca/models/edi_exchange_record.py +++ b/edi_queue_oca/models/edi_exchange_record.py @@ -106,10 +106,15 @@ def _job_on_fail_process(self, **kw): def _job_on_fail_update(self, failed_state, **kw): self.ensure_one() + # ``exc_message`` is the first argument of the exception: it is not + # always a string (e.g. the errno of an ``OSError``) and may be missing. + error = ": ".join( + str(kw[k]) for k in ("exc_name", "exc_message") if kw.get(k) is not None + ) self.write( { "edi_exchange_state": failed_state, - "exchange_error": ": ".join([kw["exc_name"], kw["exc_message"]]), - "exchange_error_traceback": kw["exc_info"], + "exchange_error": error, + "exchange_error_traceback": kw.get("exc_info"), } ) diff --git a/edi_queue_oca/tests/test_backend_jobs.py b/edi_queue_oca/tests/test_backend_jobs.py index c2ddb2060..71521d12a 100644 --- a/edi_queue_oca/tests/test_backend_jobs.py +++ b/edi_queue_oca/tests/test_backend_jobs.py @@ -180,3 +180,38 @@ def test_on_fail_job(self): ": ".join([exc_vals["exc_name"], exc_vals["exc_message"]]), ) self.assertEqual(record.exchange_error_traceback, exc_vals["exc_info"]) + + def test_on_fail_job_non_string_message(self): + # The message is the first argument of the exception, which is the + # errno for an OSError, or may be missing altogether. + vals = { + "model": self.partner._name, + "res_id": self.partner.id, + } + record = self.backend.create_record("test_csv_output", vals) + job = record.action_exchange_generate() + job.on_fail( + { + "exc_info": "Dummy traceback", + "exc_name": "PermissionError", + "exc_message": 13, + } + ) + self.assertEqual(record.edi_exchange_state, "validate_error") + self.assertEqual(record.exchange_error, "PermissionError: 13") + job.on_fail( + { + "exc_info": "Dummy traceback", + "exc_name": "JobFoundDead", + "exc_message": None, + } + ) + self.assertEqual(record.exchange_error, "JobFoundDead") + job.on_fail( + { + "exc_info": "Dummy traceback", + "exc_name": None, + "exc_message": "Something went wrong", + } + ) + self.assertEqual(record.exchange_error, "Something went wrong") From 83ff2d7580cfa075e44207e07ded872c768b94fd Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 14 Sep 2026 10:40:18 +0200 Subject: [PATCH 4/4] [IMP] edi_queue_oca: use the right version --- edi_queue_oca/__manifest__.py | 2 +- .../migrations/{18.0.1.0.3 => 18.0.1.1.0}/post-migration.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename edi_queue_oca/migrations/{18.0.1.0.3 => 18.0.1.1.0}/post-migration.py (100%) diff --git a/edi_queue_oca/__manifest__.py b/edi_queue_oca/__manifest__.py index e34d4ddf2..83c928408 100644 --- a/edi_queue_oca/__manifest__.py +++ b/edi_queue_oca/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Edi Queue Oca", "summary": """Set Queue Jobs on EDI""", - "version": "18.0.1.0.3", + "version": "18.0.1.1.0", "license": "LGPL-3", "author": "Dixmit,Camptocamp,Odoo Community Association (OCA)", "website": "https://github.com/OCA/edi-framework", diff --git a/edi_queue_oca/migrations/18.0.1.0.3/post-migration.py b/edi_queue_oca/migrations/18.0.1.1.0/post-migration.py similarity index 100% rename from edi_queue_oca/migrations/18.0.1.0.3/post-migration.py rename to edi_queue_oca/migrations/18.0.1.1.0/post-migration.py