From 2993f3b2b9113690b73aa0c1a473cac40c8873b3 Mon Sep 17 00:00:00 2001 From: duongtq Date: Wed, 10 Jul 2024 12:14:22 +0700 Subject: [PATCH 1/5] [IMP] edi_oca: update docs for EDI Jobs --- edi_oca/readme/CONFIGURE.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/edi_oca/readme/CONFIGURE.rst b/edi_oca/readme/CONFIGURE.rst index acf6a0d286..24a1cede10 100644 --- a/edi_oca/readme/CONFIGURE.rst +++ b/edi_oca/readme/CONFIGURE.rst @@ -10,6 +10,15 @@ In order to define a new Exchange Record, we need to configure: * Backend * 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. + +* (2) **EDI User**: more conscious EDI user that might sometimes need to debug things a bit further and thus needs access to related queue jobs. + +* (3) **EDI Manager**: full configuration access. + Component definition ~~~~~~~~~~~~~~~~~~~~ From 892e21e6d3736075bc8b3cf406b9ad741a697aae Mon Sep 17 00:00:00 2001 From: Quoc Duong Date: Tue, 23 Jul 2024 10:06:54 +0700 Subject: [PATCH 2/5] [IMP] edi_oca: add btn to show all related queue jobs --- edi_oca/models/edi_exchange_record.py | 33 +++++++++++++++++++++ edi_oca/readme/CONFIGURE.rst | 2 +- edi_oca/security/ir_model_access.xml | 12 ++++++++ edi_oca/tests/test_backend_jobs.py | 16 ++++++++++ edi_oca/tests/test_security.py | 2 +- edi_oca/views/edi_exchange_record_views.xml | 17 +++++++++++ 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/edi_oca/models/edi_exchange_record.py b/edi_oca/models/edi_exchange_record.py index 27649f18f7..80109326c3 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 @@ -114,6 +115,9 @@ 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 = [ @@ -609,3 +613,32 @@ def delayable(self, **kw): def _job_retry_params(self): return {} + + 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["ir.actions.act_window"]._for_xml_id(xmlid) + # 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 24a1cede10..2a8047b9f0 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 7920b09069..6a80a34bfa 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 1807155381..893bca9ed0 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(), 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_recordset() + 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_recordset() + 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 1a7f671ff8..049fb17107 100644 --- a/edi_oca/tests/test_security.py +++ b/edi_oca/tests/test_security.py @@ -51,7 +51,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 71100e7d7c..51d4b5e681 100644 --- a/edi_oca/views/edi_exchange_record_views.xml +++ b/edi_oca/views/edi_exchange_record_views.xml @@ -94,6 +94,23 @@ /> +
+ +