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 c8ddeff7d..6bf5b4bb3 100644
--- a/edi_queue_oca/models/edi_exchange_record.py
+++ b/edi_queue_oca/models/edi_exchange_record.py
@@ -102,3 +102,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 61ac106bd..c5c246e09 100644
--- a/edi_queue_oca/tests/test_backend_jobs.py
+++ b/edi_queue_oca/tests/test_backend_jobs.py
@@ -165,3 +165,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"])
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 000000000..cc626322b
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1 @@
+odoo-addon-queue_job @ git+https://github.com/OCA/queue.git@refs/pull/955/head#subdirectory=queue_job