Skip to content

Commit 09ca2e3

Browse files
committed
[IMP] queue jobs to store res_id and res_model
1 parent 9f54353 commit 09ca2e3

File tree

7 files changed

+261
-0
lines changed

7 files changed

+261
-0
lines changed

spp_base_common/__manifest__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"maintainers": ["jeremi", "gonzalesedwin1123", "emjay0921"],
1414
"depends": [
1515
"base",
16+
"queue_job",
1617
"theme_openspp_muk",
1718
"spp_user_roles",
1819
"spp_area_base",
@@ -29,6 +30,7 @@
2930
"security/ir.model.access.csv",
3031
"views/main_view.xml",
3132
"views/phone_validation_view.xml",
33+
"views/queue_job_views.xml",
3234
],
3335
"assets": {
3436
"web.assets_backend": [

spp_base_common/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
from . import base
12
from . import ir_module_module
23
from . import phone_validation
34
from . import phone_number
5+
from . import queue_job
46
from . import res_partner

spp_base_common/models/base.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
2+
3+
from odoo import api, models
4+
5+
6+
class Base(models.AbstractModel):
7+
"""Extend base model to automatically populate res_id in queue jobs."""
8+
9+
_inherit = "base"
10+
11+
@api.model
12+
def _job_store_values(self, job):
13+
"""
14+
Override to automatically populate res_id and res_model in queue jobs.
15+
16+
This method is called when a job is being stored in the database.
17+
It extracts the record ID from the recordset that created the job
18+
and stores it in res_id field for later monitoring.
19+
20+
:param job: current queue_job.job.Job instance.
21+
:return: dictionary for setting job values.
22+
"""
23+
vals = super()._job_store_values(job)
24+
25+
# Get the recordset that is creating the job
26+
recordset = job.recordset
27+
28+
# If the recordset has a single record, store its ID
29+
if recordset and len(recordset) == 1:
30+
vals["res_id"] = recordset.id
31+
vals["res_model"] = recordset._name
32+
# If the recordset has multiple records, store the first ID
33+
elif recordset and len(recordset) > 1:
34+
vals["res_id"] = recordset[0].id
35+
vals["res_model"] = recordset._name
36+
37+
return vals
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
2+
3+
from odoo import fields, models
4+
5+
6+
class QueueJob(models.Model):
7+
"""Extend queue.job to add res_id field for record tracking."""
8+
9+
_inherit = "queue.job"
10+
11+
res_id = fields.Integer(
12+
string="Record ID",
13+
help="ID of the record that created this job",
14+
index=True,
15+
)
16+
res_model = fields.Char(
17+
string="Record Model",
18+
help="Model name of the record that created this job",
19+
index=True,
20+
)

spp_base_common/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from . import test_ir_module_module
22
from . import test_phone_number_validation
3+
from . import test_queue_job_res_id
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
2+
3+
import logging
4+
5+
from odoo.tests.common import TransactionCase
6+
7+
_logger = logging.getLogger(__name__)
8+
9+
10+
class TestQueueJobResId(TransactionCase):
11+
"""Test automatic population of res_id in queue jobs."""
12+
13+
@classmethod
14+
def setUpClass(cls):
15+
super().setUpClass()
16+
# Set context to avoid job queue delay for testing
17+
cls.env = cls.env(
18+
context=dict(
19+
cls.env.context,
20+
test_queue_job_no_delay=True,
21+
)
22+
)
23+
24+
def test_01_single_record_job_creation(self):
25+
"""Test that res_id is populated when a single record creates a job."""
26+
# Create a test partner record
27+
partner = self.env["res.partner"].create(
28+
{
29+
"name": "Test Partner for Queue Job",
30+
"email": "test@example.com",
31+
}
32+
)
33+
34+
# Create a method that can be delayed (using existing method)
35+
# We'll use a simple method that exists on res.partner
36+
job = partner.with_delay().write({"phone": "1234567890"})
37+
38+
# Verify job was created
39+
self.assertTrue(job, "Job should be created")
40+
41+
# Get the queue.job record
42+
queue_job = self.env["queue.job"].search([("uuid", "=", job.uuid)], limit=1)
43+
44+
# Verify res_id is populated correctly
45+
self.assertEqual(
46+
queue_job.res_id,
47+
partner.id,
48+
"res_id should be set to the partner ID",
49+
)
50+
self.assertEqual(
51+
queue_job.res_model,
52+
"res.partner",
53+
"res_model should be set to res.partner",
54+
)
55+
self.assertEqual(
56+
queue_job.model_name,
57+
"res.partner",
58+
"model_name should be res.partner",
59+
)
60+
61+
def test_02_multiple_records_job_creation(self):
62+
"""Test that res_id is populated when multiple records create a job."""
63+
# Create multiple test partner records
64+
partners = self.env["res.partner"].create(
65+
[
66+
{"name": "Test Partner 1", "email": "test1@example.com"},
67+
{"name": "Test Partner 2", "email": "test2@example.com"},
68+
{"name": "Test Partner 3", "email": "test3@example.com"},
69+
]
70+
)
71+
72+
# Create a job with multiple records
73+
job = partners.with_delay().write({"phone": "9876543210"})
74+
75+
# Verify job was created
76+
self.assertTrue(job, "Job should be created")
77+
78+
# Get the queue.job record
79+
queue_job = self.env["queue.job"].search([("uuid", "=", job.uuid)], limit=1)
80+
81+
# Verify res_id is populated with first record's ID
82+
self.assertEqual(
83+
queue_job.res_id,
84+
partners[0].id,
85+
"res_id should be set to the first partner ID",
86+
)
87+
self.assertEqual(
88+
queue_job.res_model,
89+
"res.partner",
90+
"res_model should be set to res.partner",
91+
)
92+
93+
def test_03_res_id_field_indexed(self):
94+
"""Test that res_id field is indexed for performance."""
95+
# Get the field information
96+
field = self.env["queue.job"]._fields.get("res_id")
97+
98+
# Verify field exists and is indexed
99+
self.assertTrue(field, "res_id field should exist")
100+
self.assertTrue(field.index, "res_id field should be indexed")
101+
102+
def test_04_res_model_field_indexed(self):
103+
"""Test that res_model field is indexed for performance."""
104+
# Get the field information
105+
field = self.env["queue.job"]._fields.get("res_model")
106+
107+
# Verify field exists and is indexed
108+
self.assertTrue(field, "res_model field should exist")
109+
self.assertTrue(field.index, "res_model field should be indexed")
110+
111+
def test_05_search_jobs_by_res_id(self):
112+
"""Test searching for jobs by res_id."""
113+
# Create a test partner record
114+
partner = self.env["res.partner"].create(
115+
{
116+
"name": "Test Partner for Search",
117+
"email": "search@example.com",
118+
}
119+
)
120+
121+
# Create multiple jobs for the same partner
122+
job1 = partner.with_delay().write({"phone": "1111111111"})
123+
job2 = partner.with_delay().write({"mobile": "2222222222"})
124+
125+
# Search for jobs by res_id
126+
jobs = self.env["queue.job"].search(
127+
[
128+
("res_id", "=", partner.id),
129+
("res_model", "=", "res.partner"),
130+
]
131+
)
132+
133+
# Verify we found at least the jobs we created
134+
job_uuids = jobs.mapped("uuid")
135+
self.assertIn(
136+
job1.uuid,
137+
job_uuids,
138+
"Should find first job by res_id",
139+
)
140+
self.assertIn(
141+
job2.uuid,
142+
job_uuids,
143+
"Should find second job by res_id",
144+
)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!-- Part of OpenSPP. See LICENSE file for full copyright and licensing details. -->
3+
<odoo>
4+
5+
<!-- Extend queue.job form view to show res_id and res_model -->
6+
<record id="view_queue_job_form_inherit" model="ir.ui.view">
7+
<field name="name">queue.job.form.inherit</field>
8+
<field name="model">queue.job</field>
9+
<field name="inherit_id" ref="queue_job.view_queue_job_form" />
10+
<field name="arch" type="xml">
11+
<!-- Add res_id and res_model after model_name -->
12+
<field name="channel" position="after">
13+
<field name="res_model" />
14+
<field name="res_id" />
15+
</field>
16+
</field>
17+
</record>
18+
19+
<!-- Extend queue.job tree view to show res_id and res_model -->
20+
<record id="view_queue_job_tree_inherit" model="ir.ui.view">
21+
<field name="name">queue.job.tree.inherit</field>
22+
<field name="model">queue.job</field>
23+
<field name="inherit_id" ref="queue_job.view_queue_job_tree" />
24+
<field name="arch" type="xml">
25+
<!-- Add res_model and res_id after model_name -->
26+
<field name="model_name" position="after">
27+
<field name="res_model" optional="show" />
28+
<field name="res_id" optional="show" />
29+
</field>
30+
</field>
31+
</record>
32+
33+
<!-- Extend queue.job search view to add res_id and res_model filters -->
34+
<record id="view_queue_job_search_inherit" model="ir.ui.view">
35+
<field name="name">queue.job.search.inherit</field>
36+
<field name="model">queue.job</field>
37+
<field name="inherit_id" ref="queue_job.view_queue_job_search" />
38+
<field name="arch" type="xml">
39+
<!-- Add res_model and res_id as searchable fields -->
40+
<field name="model_name" position="after">
41+
<field name="res_model" />
42+
<field name="res_id" />
43+
</field>
44+
<!-- Add group by for res_model -->
45+
<filter name="group_by_model_name" position="after">
46+
<filter
47+
name="group_by_res_model"
48+
string="Creator Model"
49+
context="{'group_by': 'res_model'}"
50+
/>
51+
</filter>
52+
</field>
53+
</record>
54+
55+
</odoo>

0 commit comments

Comments
 (0)