diff --git a/edi_oca/README.rst b/edi_oca/README.rst
index 65507fa579..b46fe387d4 100644
--- a/edi_oca/README.rst
+++ b/edi_oca/README.rst
@@ -60,7 +60,7 @@ In order to define a new Exchange Record, we need to configure:
* Components
Jobs
-~~~~~~~~~~~~~~~~~~~~
+~~~~
1. Internal User: might be an EDI user without even knowing about it, triggering EDI flows by some of his actions on business records; does not need access to related queue jobs.
diff --git a/edi_oca/models/edi_exchange_record.py b/edi_oca/models/edi_exchange_record.py
index 13b3c94322..e49bc6c6ce 100644
--- a/edi_oca/models/edi_exchange_record.py
+++ b/edi_oca/models/edi_exchange_record.py
@@ -5,6 +5,7 @@
import base64
import logging
+from ast import literal_eval
from collections import defaultdict
from odoo import _, api, exceptions, fields, models
@@ -112,6 +113,10 @@ class EDIExchangeRecord(models.Model):
compute="_compute_retryable",
help="The record state can be rolled back manually in case of failure.",
)
+ related_queue_jobs_count = fields.Integer(
+ compute="_compute_related_queue_jobs_count"
+ )
+ company_id = fields.Many2one("res.company", string="Company")
_sql_constraints = [
("identifier_uniq", "unique(identifier)", "The identifier must be unique."),
@@ -620,3 +625,33 @@ def _inverse_res_id(self):
})
except (KeyError, ValueError, MissingError):
continue
+
+ def _compute_related_queue_jobs_count(self):
+ for rec in self:
+ # TODO: We should refactor the object field on queue_job to use jsonb field
+ # so that we can search directly into it.
+ rec.related_queue_jobs_count = rec.env["queue.job"].search_count(
+ [("func_string", "like", str(rec))]
+ )
+
+ def action_view_related_queue_jobs(self):
+ self.ensure_one()
+ xmlid = "queue_job.action_queue_job"
+ action = self.env.ref(xmlid).read()[0]
+ # Searching based on task name.
+ # Ex: `edi.exchange.record(1,).action_exchange_send()`
+ # TODO: We should refactor the object field on queue_job to use jsonb field
+ # so that we can search directly into it.
+ action["domain"] = [("func_string", "like", str(self))]
+ # Purge default search filters from ctx to avoid hiding records
+ ctx = action.get("context", {})
+ if isinstance(ctx, str):
+ ctx = literal_eval(ctx)
+ # Update the current contexts
+ ctx.update(self.env.context)
+ action["context"] = {
+ k: v for k, v in ctx.items() if not k.startswith("search_default_")
+ }
+ # Drop ID otherwise the context will be loaded from the action's record
+ action.pop("id")
+ return action
diff --git a/edi_oca/readme/CONFIGURE.rst b/edi_oca/readme/CONFIGURE.rst
index 9a2a834fc9..de8331ad77 100644
--- a/edi_oca/readme/CONFIGURE.rst
+++ b/edi_oca/readme/CONFIGURE.rst
@@ -11,7 +11,7 @@ In order to define a new Exchange Record, we need to configure:
* Components
Jobs
-~~~~~~~~~~~~~~~~~~~~
+~~~~
1. Internal User: might be an EDI user without even knowing about it, triggering EDI flows by some of his actions on business records; does not need access to related queue jobs.
diff --git a/edi_oca/security/ir_model_access.xml b/edi_oca/security/ir_model_access.xml
index 90b3461145..a398ca8269 100644
--- a/edi_oca/security/ir_model_access.xml
+++ b/edi_oca/security/ir_model_access.xml
@@ -45,6 +45,18 @@
+
+
+
+ access_queue_job edi user
+
+
+
+
+
+
+
+
access_edi_backend_type user
diff --git a/edi_oca/tests/test_backend_jobs.py b/edi_oca/tests/test_backend_jobs.py
index ac23a298ad..e0f70a4909 100644
--- a/edi_oca/tests/test_backend_jobs.py
+++ b/edi_oca/tests/test_backend_jobs.py
@@ -16,6 +16,12 @@ class EDIBackendTestJobsCase(EDIBackendCommonTestCase, JobMixin):
def _setup_context(cls):
return dict(super()._setup_context(), test_queue_job_no_delay=None)
+ def _get_related_jobs(self, record):
+ # Use domain in action to find all related jobs
+ record.ensure_one()
+ action = record.action_view_related_queue_jobs()
+ return self.env["queue.job"].search(action["domain"])
+
def test_output(self):
job_counter = self.job_counter()
vals = {
@@ -30,6 +36,8 @@ def test_output(self):
self.assertEqual(
created.name, "Generate output content for given exchange record."
)
+ # Check related jobs
+ self.assertEqual(created, self._get_related_jobs(record))
with mock.patch.object(
type(self.backend), "_exchange_generate"
) as mocked_generate, mock.patch.object(
@@ -48,6 +56,9 @@ def test_output(self):
self.assertEqual(res, "Exchange sent")
self.assertEqual(record.edi_exchange_state, "output_sent")
self.assertEqual(created[0].name, "Send exchange file.")
+ # Check related jobs
+ record.invalidate_cache()
+ self.assertEqual(created, self._get_related_jobs(record))
def test_output_fail_retry(self):
job_counter = self.job_counter()
@@ -76,6 +87,8 @@ def test_input(self):
created = job_counter.search_created()
self.assertEqual(len(created), 1)
self.assertEqual(created.name, "Retrieve an incoming document.")
+ # Check related jobs
+ self.assertEqual(created, self._get_related_jobs(record))
with mock.patch.object(
type(self.backend), "_exchange_receive"
) as mocked_receive, mock.patch.object(
@@ -115,3 +128,6 @@ def test_input_processed_error(self):
new_created = job_counter.search_created() - created
# Should not create new job
self.assertEqual(len(new_created), 0)
+ # Check related jobs
+ record.invalidate_cache()
+ self.assertEqual(created, self._get_related_jobs(record))
diff --git a/edi_oca/tests/test_security.py b/edi_oca/tests/test_security.py
index 84bcc4e05b..b6dda46426 100644
--- a/edi_oca/tests/test_security.py
+++ b/edi_oca/tests/test_security.py
@@ -49,7 +49,7 @@ def _setup_records(cls):
"name": "Poor Partner (not integrating one)",
"email": "poor.partner@ododo.com",
"login": "poorpartner",
- "groups_id": [(6, 0, [cls.env.ref("base.group_user").id])],
+ "groups_id": [(6, 0, [cls.env.ref("base_edi.group_edi_user").id])],
}
)
)
diff --git a/edi_oca/views/edi_exchange_record_views.xml b/edi_oca/views/edi_exchange_record_views.xml
index aa2d022fa0..67d9097bba 100644
--- a/edi_oca/views/edi_exchange_record_views.xml
+++ b/edi_oca/views/edi_exchange_record_views.xml
@@ -87,6 +87,23 @@
/>
+