odoo-addon-automation-oca 16.0.1.5.2__py3-none-any.whl → 17.0.1.0.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. odoo/addons/automation_oca/README.rst +7 -7
  2. odoo/addons/automation_oca/__init__.py +1 -0
  3. odoo/addons/automation_oca/__manifest__.py +1 -1
  4. odoo/addons/automation_oca/data/cron.xml +0 -5
  5. odoo/addons/automation_oca/i18n/automation_oca.pot +95 -22
  6. odoo/addons/automation_oca/i18n/es.po +0 -13
  7. odoo/addons/automation_oca/i18n/fr.po +0 -13
  8. odoo/addons/automation_oca/i18n/it.po +2 -15
  9. odoo/addons/automation_oca/models/automation_configuration.py +28 -26
  10. odoo/addons/automation_oca/models/automation_configuration_step.py +38 -11
  11. odoo/addons/automation_oca/models/automation_filter.py +5 -1
  12. odoo/addons/automation_oca/models/automation_record.py +64 -52
  13. odoo/addons/automation_oca/models/automation_record_step.py +34 -15
  14. odoo/addons/automation_oca/models/automation_tag.py +0 -1
  15. odoo/addons/automation_oca/models/mail_activity.py +3 -3
  16. odoo/addons/automation_oca/models/mail_mail.py +17 -15
  17. odoo/addons/automation_oca/models/mail_thread.py +6 -11
  18. odoo/addons/automation_oca/static/description/index.html +5 -5
  19. odoo/addons/automation_oca/static/src/fields/automation_activity/automation_activity.esm.js +5 -4
  20. odoo/addons/automation_oca/static/src/fields/automation_graph/automation_graph.esm.js +21 -25
  21. odoo/addons/automation_oca/static/src/views/automation_kanban/automation_kanban.scss +3 -0
  22. odoo/addons/automation_oca/static/src/views/automation_kanban/automation_kanban_compiler.esm.js +2 -3
  23. odoo/addons/automation_oca/static/src/views/automation_kanban/automation_kanban_record.esm.js +1 -2
  24. odoo/addons/automation_oca/static/src/views/automation_kanban/automation_kanban_renderer.esm.js +1 -2
  25. odoo/addons/automation_oca/tests/__init__.py +1 -0
  26. odoo/addons/automation_oca/tests/common.py +2 -1
  27. odoo/addons/automation_oca/tests/models.py +10 -0
  28. odoo/addons/automation_oca/tests/test_automation_action.py +7 -8
  29. odoo/addons/automation_oca/tests/test_automation_activity.py +122 -10
  30. odoo/addons/automation_oca/tests/test_automation_base.py +73 -82
  31. odoo/addons/automation_oca/tests/test_automation_date.py +59 -0
  32. odoo/addons/automation_oca/tests/test_automation_mail.py +31 -50
  33. odoo/addons/automation_oca/tests/test_automation_security.py +5 -2
  34. odoo/addons/automation_oca/utils/__init__.py +1 -0
  35. odoo/addons/automation_oca/utils/query.py +45 -0
  36. odoo/addons/automation_oca/views/automation_configuration.xml +60 -51
  37. odoo/addons/automation_oca/views/automation_configuration_step.xml +86 -49
  38. odoo/addons/automation_oca/views/automation_filter.xml +1 -3
  39. odoo/addons/automation_oca/views/automation_record.xml +32 -19
  40. odoo/addons/automation_oca/views/automation_record_step.xml +4 -14
  41. odoo/addons/automation_oca/views/automation_tag.xml +3 -4
  42. odoo/addons/automation_oca/views/link_tracker_clicks.xml +2 -3
  43. odoo/addons/automation_oca/wizards/automation_configuration_test.py +1 -2
  44. odoo/addons/automation_oca/wizards/automation_configuration_test.xml +4 -6
  45. odoo/addons/automation_oca/wizards/mail_compose_message.py +2 -3
  46. {odoo_addon_automation_oca-16.0.1.5.2.dist-info → odoo_addon_automation_oca-17.0.1.0.0.5.dist-info}/METADATA +12 -12
  47. odoo_addon_automation_oca-17.0.1.0.0.5.dist-info/RECORD +66 -0
  48. {odoo_addon_automation_oca-16.0.1.5.2.dist-info → odoo_addon_automation_oca-17.0.1.0.0.5.dist-info}/WHEEL +1 -1
  49. odoo_addon_automation_oca-17.0.1.0.0.5.dist-info/top_level.txt +1 -0
  50. odoo_addon_automation_oca-16.0.1.5.2.dist-info/RECORD +0 -62
  51. odoo_addon_automation_oca-16.0.1.5.2.dist-info/top_level.txt +0 -1
@@ -10,7 +10,7 @@ class TestAutomationAction(AutomationTestCase):
10
10
  We will check the execution of the tasks and that we cannot execute them again
11
11
  """
12
12
  activity = self.create_server_action(trigger_interval=-1)
13
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
13
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
14
14
  self.configuration.start_automation()
15
15
  self.env["automation.configuration"].cron_automation()
16
16
  self.assertFalse(self.partner_01.comment)
@@ -26,7 +26,7 @@ class TestAutomationAction(AutomationTestCase):
26
26
  We will check the execution of the tasks and that we cannot execute them again
27
27
  """
28
28
  activity = self.create_server_action()
29
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
29
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
30
30
  self.configuration.start_automation()
31
31
  self.env["automation.configuration"].cron_automation()
32
32
  self.assertTrue(self.partner_01.comment)
@@ -56,17 +56,16 @@ class TestAutomationAction(AutomationTestCase):
56
56
  In this case, the task 1_1_1 will only be generated for partner 1 and task 1_2_1
57
57
  for partner 2
58
58
  """
59
- self.configuration.editable_domain = "[('id', 'in', [%s, %s])]" % (
60
- self.partner_01.id,
61
- self.partner_02.id,
59
+ self.configuration.editable_domain = (
60
+ f"[('id', 'in', [{self.partner_01.id}, {self.partner_02.id}])]"
62
61
  )
63
62
 
64
63
  activity_1 = self.create_server_action()
65
64
  activity_1_1 = self.create_server_action(
66
- parent_id=activity_1.id, domain="[('id', '=', %s)]" % self.partner_01.id
65
+ parent_id=activity_1.id, domain=f"[('id', '=', {self.partner_01.id})]"
67
66
  )
68
67
  activity_1_2 = self.create_server_action(
69
- parent_id=activity_1.id, domain="[('id', '=', %s)]" % self.partner_02.id
68
+ parent_id=activity_1.id, domain=f"[('id', '=', {self.partner_02.id})]"
70
69
  )
71
70
  activity_1_1_1 = self.create_server_action(parent_id=activity_1_1.id)
72
71
  activity_1_2_1 = self.create_server_action(parent_id=activity_1_2.id)
@@ -226,7 +225,7 @@ class TestAutomationAction(AutomationTestCase):
226
225
  """
227
226
  self.create_server_action(server_context='{"key_value": "My Value"}')
228
227
  self.partner_01.comment = False
229
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
228
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
230
229
  self.configuration.start_automation()
231
230
  self.env["automation.configuration"].cron_automation()
232
231
 
@@ -1,18 +1,28 @@
1
1
  # Copyright 2024 Dixmit
2
2
  # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
3
 
4
- from odoo.tests import Form
4
+ from odoo.exceptions import ValidationError
5
+ from odoo.tests import Form, new_test_user
5
6
 
6
7
  from .common import AutomationTestCase
7
8
 
8
9
 
9
10
  class TestAutomationActivity(AutomationTestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ super().setUpClass()
14
+ cls.user = new_test_user(
15
+ cls.env,
16
+ login="test_user_automation",
17
+ groups="base.group_user,base.group_partner_manager",
18
+ )
19
+
10
20
  def test_activity_execution(self):
11
21
  """
12
22
  We will check the execution of activity tasks (generation of an activity)
13
23
  """
14
24
  activity = self.create_activity_action()
15
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
25
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
16
26
  self.configuration.start_automation()
17
27
  self.env["automation.configuration"].cron_automation()
18
28
  self.assertFalse(self.partner_01.activity_ids)
@@ -44,6 +54,79 @@ class TestAutomationActivity(AutomationTestCase):
44
54
  ]
45
55
  )
46
56
 
57
+ def test_activity_execution_check_domain(self):
58
+ """
59
+ We will check the execution of activity tasks (generation of an activity)
60
+ """
61
+ activity = self.create_activity_action(
62
+ activity_verification_domain="[('name', '=', 'My Expected Name')]"
63
+ )
64
+ self.partner_01.name = "Not My Expected Name"
65
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
66
+ self.configuration.start_automation()
67
+ self.env["automation.configuration"].cron_automation()
68
+ self.assertFalse(self.partner_01.activity_ids)
69
+ self.env["automation.record.step"]._cron_automation_steps()
70
+ self.assertTrue(self.partner_01.activity_ids)
71
+ record_activity = self.env["automation.record.step"].search(
72
+ [("configuration_step_id", "=", activity.id)]
73
+ )
74
+ self.assertEqual(
75
+ record_activity, self.partner_01.activity_ids.automation_record_step_id
76
+ )
77
+ self.assertFalse(record_activity.activity_done_on)
78
+ record_activity.invalidate_recordset()
79
+ self.assertFalse(
80
+ [
81
+ step
82
+ for step in record_activity.step_actions
83
+ if step["done"] and step["icon"] == "fa fa-clock-o"
84
+ ]
85
+ )
86
+ with self.assertRaises(ValidationError):
87
+ self.partner_01.activity_ids.action_feedback()
88
+ self.assertFalse(record_activity.activity_done_on)
89
+ self.partner_01.name = "My Expected Name"
90
+ self.partner_01.activity_ids.action_feedback()
91
+ self.assertTrue(record_activity.activity_done_on)
92
+
93
+ def test_activity_execution_permission(self):
94
+ """
95
+ We will check the execution of activity tasks (generation of an activity)
96
+ """
97
+ activity = self.create_activity_action()
98
+ self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
99
+ self.configuration.start_automation()
100
+ self.env["automation.configuration"].cron_automation()
101
+ self.assertFalse(self.partner_01.activity_ids)
102
+ self.env["automation.record.step"]._cron_automation_steps()
103
+ self.assertTrue(self.partner_01.activity_ids)
104
+ record_activity = self.env["automation.record.step"].search(
105
+ [("configuration_step_id", "=", activity.id)]
106
+ )
107
+ self.assertEqual(
108
+ record_activity, self.partner_01.activity_ids.automation_record_step_id
109
+ )
110
+ self.assertFalse(record_activity.activity_done_on)
111
+ record_activity.invalidate_recordset()
112
+ self.assertFalse(
113
+ [
114
+ step
115
+ for step in record_activity.step_actions
116
+ if step["done"] and step["icon"] == "fa fa-clock-o"
117
+ ]
118
+ )
119
+ self.partner_01.activity_ids.with_user(self.user.id).action_feedback()
120
+ self.assertTrue(record_activity.activity_done_on)
121
+ record_activity.invalidate_recordset()
122
+ self.assertTrue(
123
+ [
124
+ step
125
+ for step in record_activity.step_actions
126
+ if step["done"] and step["icon"] == "fa fa-clock-o"
127
+ ]
128
+ )
129
+
47
130
  def test_activity_execution_child(self):
48
131
  """
49
132
  We will check the execution of the child task (activity_done) is only scheduled
@@ -53,7 +136,7 @@ class TestAutomationActivity(AutomationTestCase):
53
136
  child_activity = self.create_server_action(
54
137
  parent_id=activity.id, trigger_type="activity_done"
55
138
  )
56
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
139
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
57
140
  self.configuration.start_automation()
58
141
  self.env["automation.configuration"].cron_automation()
59
142
  self.env["automation.record.step"]._cron_automation_steps()
@@ -81,7 +164,7 @@ class TestAutomationActivity(AutomationTestCase):
81
164
  child_activity = self.create_server_action(
82
165
  parent_id=activity.id, trigger_type="activity_done"
83
166
  )
84
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
167
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
85
168
  self.configuration.start_automation()
86
169
  self.env["automation.configuration"].cron_automation()
87
170
  self.env["automation.record.step"]._cron_automation_steps()
@@ -101,16 +184,45 @@ class TestAutomationActivity(AutomationTestCase):
101
184
  self.assertFalse(record_child_activity.scheduled_date)
102
185
  self.assertEqual(record_child_activity.state, "rejected")
103
186
 
187
+ def test_activity_execution_on_cancel_permission(self):
188
+ """
189
+ We will check the execution of the child task (activity_done) is only scheduled
190
+ after the activity is done
191
+ """
192
+ activity = self.create_activity_action()
193
+ child_activity = self.create_server_action(
194
+ parent_id=activity.id, trigger_type="activity_done"
195
+ )
196
+ self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
197
+ self.configuration.start_automation()
198
+ self.env["automation.configuration"].cron_automation()
199
+ self.env["automation.record.step"]._cron_automation_steps()
200
+ record_activity = self.env["automation.record.step"].search(
201
+ [("configuration_step_id", "=", activity.id)]
202
+ )
203
+ record_child_activity = self.env["automation.record.step"].search(
204
+ [("configuration_step_id", "=", child_activity.id)]
205
+ )
206
+ self.assertEqual(
207
+ record_activity, self.partner_01.activity_ids.automation_record_step_id
208
+ )
209
+ self.assertFalse(record_activity.activity_done_on)
210
+ self.assertFalse(record_child_activity.scheduled_date)
211
+ self.partner_01.activity_ids.with_user(self.user.id).unlink()
212
+ self.assertFalse(record_activity.activity_done_on)
213
+ self.assertFalse(record_child_activity.scheduled_date)
214
+ self.assertEqual(record_child_activity.state, "rejected")
215
+
104
216
  def test_activity_execution_cancel_child(self):
105
217
  """
106
- We will check the execution of the child task (activity_cancel) is only scheduled
107
- after the activity is cancel
218
+ We will check the execution of the child task (activity_cancel) is
219
+ only scheduled after the activity is cancelled
108
220
  """
109
221
  activity = self.create_activity_action()
110
222
  child_activity = self.create_server_action(
111
223
  parent_id=activity.id, trigger_type="activity_cancel"
112
224
  )
113
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
225
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
114
226
  self.configuration.start_automation()
115
227
  self.env["automation.configuration"].cron_automation()
116
228
  self.env["automation.record.step"]._cron_automation_steps()
@@ -138,7 +250,7 @@ class TestAutomationActivity(AutomationTestCase):
138
250
  child_activity = self.create_server_action(
139
251
  parent_id=activity.id, trigger_type="activity_cancel"
140
252
  )
141
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
253
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
142
254
  self.configuration.start_automation()
143
255
  self.env["automation.configuration"].cron_automation()
144
256
  self.env["automation.record.step"]._cron_automation_steps()
@@ -167,7 +279,7 @@ class TestAutomationActivity(AutomationTestCase):
167
279
  child_activity = self.create_server_action(
168
280
  parent_id=activity.id, trigger_type="activity_not_done"
169
281
  )
170
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
282
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
171
283
  self.configuration.start_automation()
172
284
  self.env["automation.configuration"].cron_automation()
173
285
  self.env["automation.record.step"]._cron_automation_steps()
@@ -198,7 +310,7 @@ class TestAutomationActivity(AutomationTestCase):
198
310
  child_activity = self.create_server_action(
199
311
  parent_id=activity.id, trigger_type="activity_not_done"
200
312
  )
201
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
313
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
202
314
  self.configuration.start_automation()
203
315
  self.env["automation.configuration"].cron_automation()
204
316
  self.env["automation.record.step"]._cron_automation_steps()
@@ -7,8 +7,11 @@ from freezegun import freeze_time
7
7
 
8
8
  from odoo.exceptions import ValidationError
9
9
  from odoo.tests import Form
10
+ from odoo.tools import mute_logger
10
11
  from odoo.tools.safe_eval import safe_eval
11
12
 
13
+ from odoo.addons.mail.tests.common import mail_new_test_user
14
+
12
15
  from .common import AutomationTestCase
13
16
 
14
17
 
@@ -135,7 +138,7 @@ class TestAutomationBase(AutomationTestCase):
135
138
  the records that fulfill the domain
136
139
  """
137
140
  self.create_server_action()
138
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
141
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
139
142
  self.configuration.start_automation()
140
143
  self.env["automation.configuration"].cron_automation()
141
144
  self.assertEqual(
@@ -162,7 +165,7 @@ class TestAutomationBase(AutomationTestCase):
162
165
  Check that the error is raised properly and stored the full error
163
166
  """
164
167
  activity = self.create_server_action(server_action_id=self.error_action.id)
165
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
168
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
166
169
  self.configuration.start_automation()
167
170
  self.env["automation.configuration"].cron_automation()
168
171
  record = self.env["automation.record.step"].search(
@@ -178,7 +181,7 @@ class TestAutomationBase(AutomationTestCase):
178
181
  Check the record computed fields of record
179
182
  """
180
183
  self.create_server_action(server_action_id=self.error_action.id)
181
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
184
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
182
185
  self.configuration.start_automation()
183
186
  self.env["automation.configuration"].cron_automation()
184
187
  record = self.env["automation.record"].search(
@@ -194,7 +197,7 @@ class TestAutomationBase(AutomationTestCase):
194
197
  Testing that expired actions are not executed
195
198
  """
196
199
  activity = self.create_server_action(expiry=True, trigger_interval=1)
197
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
200
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
198
201
  self.configuration.start_automation()
199
202
  self.env["automation.configuration"].cron_automation()
200
203
  record_activity = self.env["automation.record.step"].search(
@@ -209,7 +212,7 @@ class TestAutomationBase(AutomationTestCase):
209
212
  Testing that cancelled actions are not executed
210
213
  """
211
214
  activity = self.create_server_action()
212
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
215
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
213
216
  self.configuration.start_automation()
214
217
  self.env["automation.configuration"].cron_automation()
215
218
  record_activity = self.env["automation.record.step"].search(
@@ -221,12 +224,44 @@ class TestAutomationBase(AutomationTestCase):
221
224
  self.env["automation.record.step"]._cron_automation_steps()
222
225
  self.assertEqual("cancel", record_activity.state)
223
226
 
227
+ def test_retry_exception(self):
228
+ """
229
+ Testing that cancelled actions are not executed
230
+ """
231
+ activity = self.create_server_action()
232
+ self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
233
+ self.configuration.start_automation()
234
+ self.env["automation.configuration"].cron_automation()
235
+ record_activity = self.env["automation.record.step"].search(
236
+ [("configuration_step_id", "=", activity.id)]
237
+ )
238
+ self.assertEqual("scheduled", record_activity.state)
239
+ with self.assertRaises(ValidationError):
240
+ record_activity.retry()
241
+
242
+ def test_retry(self):
243
+ """
244
+ Testing that cancelled actions are not executed
245
+ """
246
+ activity = self.create_server_action()
247
+ self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
248
+ self.configuration.start_automation()
249
+ self.env["automation.configuration"].cron_automation()
250
+ record_activity = self.env["automation.record.step"].search(
251
+ [("configuration_step_id", "=", activity.id)]
252
+ )
253
+ self.assertEqual("scheduled", record_activity.state)
254
+ record_activity.cancel()
255
+ self.assertEqual("cancel", record_activity.state)
256
+ record_activity.retry()
257
+ self.assertEqual("scheduled", record_activity.state)
258
+
224
259
  def test_counter(self):
225
260
  """
226
261
  Check the counter function
227
262
  """
228
263
  self.create_server_action(server_action_id=self.error_action.id)
229
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
264
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
230
265
  self.configuration.start_automation()
231
266
  self.assertEqual(0, self.configuration.record_count)
232
267
  self.assertEqual(0, self.configuration.record_test_count)
@@ -274,7 +309,7 @@ class TestAutomationBase(AutomationTestCase):
274
309
  activity_02 = self.create_server_action(server_action_id=self.error_action.id)
275
310
  activity_03 = self.create_mail_activity()
276
311
  child_activity = self.create_server_action(parent_id=activity_01.id)
277
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
312
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
278
313
  self.configuration.start_automation()
279
314
  self.env["automation.configuration"].cron_automation()
280
315
  self.assertEqual(0, self.configuration.activity_mail_count)
@@ -348,9 +383,7 @@ class TestAutomationBase(AutomationTestCase):
348
383
  with freeze_time("2022-01-01"):
349
384
  activity = self.create_server_action(trigger_interval=1)
350
385
  self.assertEqual(1, activity.trigger_interval_hours)
351
- self.configuration.editable_domain = (
352
- "[('id', '=', %s)]" % self.partner_01.id
353
- )
386
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
354
387
  self.configuration.start_automation()
355
388
  self.env["automation.configuration"].cron_automation()
356
389
  record_activity = self.env["automation.record.step"].search(
@@ -367,9 +400,7 @@ class TestAutomationBase(AutomationTestCase):
367
400
  trigger_interval=1, trigger_interval_type="days"
368
401
  )
369
402
  self.assertEqual(24, activity.trigger_interval_hours)
370
- self.configuration.editable_domain = (
371
- "[('id', '=', %s)]" % self.partner_01.id
372
- )
403
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
373
404
  self.configuration.start_automation()
374
405
  self.env["automation.configuration"].cron_automation()
375
406
  record_activity = self.env["automation.record.step"].search(
@@ -400,7 +431,7 @@ class TestAutomationBase(AutomationTestCase):
400
431
 
401
432
  def test_field_not_field_unicity(self):
402
433
  self.configuration.editable_domain = (
403
- "[('id', 'in', %s)]" % (self.partner_01 | self.partner_02).ids
434
+ f"[('id', 'in', [{self.partner_01.id}, {self.partner_02.id}])]"
404
435
  )
405
436
  self.configuration.start_automation()
406
437
  self.env["automation.configuration"].cron_automation()
@@ -415,7 +446,7 @@ class TestAutomationBase(AutomationTestCase):
415
446
 
416
447
  def test_field_field_unicity(self):
417
448
  self.configuration.editable_domain = (
418
- "[('id', 'in', %s)]" % (self.partner_01 | self.partner_02).ids
449
+ f"[('id', 'in', [{self.partner_01.id}, {self.partner_02.id}])]"
419
450
  )
420
451
  self.configuration.field_id = self.env.ref("base.field_res_partner__email")
421
452
  self.configuration.start_automation()
@@ -497,11 +528,11 @@ class TestAutomationBase(AutomationTestCase):
497
528
  with Form(
498
529
  self.env["automation.configuration.test"].with_context(
499
530
  default_configuration_id=self.configuration.id,
500
- defaul_model=self.configuration.model,
531
+ default_model=self.configuration.model,
501
532
  )
502
533
  ) as f:
503
534
  self.assertTrue(f.resource_ref)
504
- f.resource_ref = "%s,%s" % (self.partner_01._name, self.partner_01.id)
535
+ f.resource_ref = f"{self.partner_01._name},{self.partner_01.id}"
505
536
  wizard = f.save()
506
537
  wizard_action = wizard.test_record()
507
538
  record = self.env[wizard_action["res_model"]].browse(wizard_action["res_id"])
@@ -559,9 +590,9 @@ class TestAutomationBase(AutomationTestCase):
559
590
  )
560
591
  self.create_server_action()
561
592
  self.create_server_action(configuration_id=configuration_2.id)
562
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
593
+ self.configuration.editable_domain = f"[('id', '=', {self.partner_01.id})]"
563
594
  self.configuration.start_automation()
564
- configuration_2.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
595
+ configuration_2.editable_domain = f"[('id', '=', {self.partner_01.id})]"
565
596
  configuration_2.start_automation()
566
597
  self.env["automation.configuration"].cron_automation()
567
598
  record_activity = self.env["automation.record"].search(
@@ -569,14 +600,35 @@ class TestAutomationBase(AutomationTestCase):
569
600
  )
570
601
  self.assertEqual(2, len(record_activity))
571
602
 
603
+ @mute_logger("odoo.addons.automation_oca.models.automation_record")
572
604
  def test_generation_orphan_record(self):
605
+ self.user_automation = mail_new_test_user(
606
+ self.env,
607
+ login="user_automation",
608
+ name="User automation",
609
+ email="user_automation@test.example.com",
610
+ company_id=self.env.user.company_id.id,
611
+ notification_type="inbox",
612
+ groups="base.user_admin, automation_oca.group_automation_manager",
613
+ )
573
614
  self.configuration.editable_domain = (
574
- "['|', ('id', '=', %s), ('id', '=', %s)]"
575
- % (self.partner_01.id, self.partner_02.id)
615
+ f"['|', ('id', '=', {self.partner_01.id}),"
616
+ f" ('id', '=', {self.partner_02.id})]"
576
617
  )
577
618
  self.configuration.start_automation()
578
619
  self.env["automation.configuration"].cron_automation()
579
620
  self.partner_01.unlink()
621
+ # We need two searches because in the first one, we access as a non-superuser to
622
+ # avoid the first return of the private method _search of automation.record and
623
+ # thus be able to access the part where orphaned records are filtered. The
624
+ # second search is to finally get the query we need, which is the one performed
625
+ # by accessing as a superuser.
626
+ automation_record_obj = self.env["automation.record"].with_user(
627
+ self.user_automation.id
628
+ )
629
+ records = automation_record_obj.search(
630
+ [("configuration_id", "=", self.configuration.id), ("is_test", "=", False)]
631
+ )
580
632
  records = self.env["automation.record"].search(
581
633
  [("configuration_id", "=", self.configuration.id), ("is_test", "=", False)]
582
634
  )
@@ -586,64 +638,3 @@ class TestAutomationBase(AutomationTestCase):
586
638
  self.assertTrue(
587
639
  orphan_record_found, "No record named 'Orphan Record' was found"
588
640
  )
589
-
590
- def test_delete_step_executed(self):
591
- """
592
- Testing that deleting a step will keep the results of the executed related steps
593
- """
594
- activity = self.create_server_action()
595
- child_activity = self.create_server_action(parent_id=activity.id)
596
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
597
- self.configuration.start_automation()
598
- self.env["automation.configuration"].cron_automation()
599
- record_activity = self.env["automation.record.step"].search(
600
- [("configuration_step_id", "=", activity.id)]
601
- )
602
- self.assertEqual("scheduled", record_activity.state)
603
- self.assertFalse(
604
- self.env["automation.record.step"].search(
605
- [("configuration_step_id", "=", child_activity.id)]
606
- )
607
- )
608
- self.env["automation.record.step"]._cron_automation_steps()
609
- self.assertEqual("done", record_activity.state)
610
- record_child_activity = self.env["automation.record.step"].search(
611
- [("configuration_step_id", "=", child_activity.id)]
612
- )
613
- self.assertEqual("scheduled", record_child_activity.state)
614
- self.env["automation.record.step"]._cron_automation_steps()
615
- self.assertEqual("done", record_child_activity.state)
616
- child_activity.unlink()
617
- child_activity.flush_recordset()
618
- self.assertEqual("action", record_child_activity.step_type)
619
-
620
- def test_delete_step_to_execute(self):
621
- """
622
- Testing that deleting a step will make pending actions related
623
- to be rejected
624
- """
625
- activity = self.create_server_action()
626
- child_activity = self.create_server_action(parent_id=activity.id)
627
- self.configuration.editable_domain = "[('id', '=', %s)]" % self.partner_01.id
628
- self.configuration.start_automation()
629
- self.env["automation.configuration"].cron_automation()
630
- record_activity = self.env["automation.record.step"].search(
631
- [("configuration_step_id", "=", activity.id)]
632
- )
633
- self.assertEqual("scheduled", record_activity.state)
634
- self.assertFalse(
635
- self.env["automation.record.step"].search(
636
- [("configuration_step_id", "=", child_activity.id)]
637
- )
638
- )
639
- self.env["automation.record.step"]._cron_automation_steps()
640
- self.assertEqual("done", record_activity.state)
641
- record_child_activity = self.env["automation.record.step"].search(
642
- [("configuration_step_id", "=", child_activity.id)]
643
- )
644
- self.assertEqual("scheduled", record_child_activity.state)
645
- child_activity.unlink()
646
- child_activity.flush_recordset()
647
- self.assertEqual("action", record_child_activity.step_type)
648
- self.env["automation.record.step"]._cron_automation_steps()
649
- self.assertEqual("rejected", record_child_activity.state)
@@ -0,0 +1,59 @@
1
+ # Copyright 2024 Dixmit
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+
4
+ from datetime import datetime
5
+
6
+ from freezegun import freeze_time
7
+ from odoo_test_helper import FakeModelLoader
8
+
9
+ from .common import AutomationTestCase
10
+
11
+
12
+ class TestAutomationDate(AutomationTestCase):
13
+ @classmethod
14
+ def setUpClass(cls):
15
+ super().setUpClass()
16
+ cls.loader = FakeModelLoader(cls.env, cls.__module__)
17
+ cls.loader.backup_registry()
18
+
19
+ # The fake class is imported here !! After the backup_registry
20
+ from .models import ResPartner
21
+
22
+ cls.loader.update_registry((ResPartner,))
23
+
24
+ @classmethod
25
+ def tearDownClass(cls):
26
+ cls.loader.restore_registry()
27
+ super().tearDownClass()
28
+
29
+ def test_schedule_date_force(self):
30
+ partner_01 = self.env["res.partner"].create(
31
+ {
32
+ "name": "Demo partner",
33
+ "comment": "Demo",
34
+ "email": "test@test.com",
35
+ "date": "2025-01-01",
36
+ }
37
+ )
38
+ with freeze_time("2024-01-01 00:00:00"):
39
+ activity = self.create_server_action(
40
+ trigger_date_kind="date",
41
+ trigger_date_field_id=self.env["ir.model.fields"]
42
+ .search(
43
+ [
44
+ ("name", "=", "date"),
45
+ ("model", "=", "res.partner"),
46
+ ]
47
+ )
48
+ .id,
49
+ trigger_interval=1,
50
+ trigger_interval_type="days",
51
+ )
52
+ self.configuration.editable_domain = f"[('id', '=', {partner_01.id})]"
53
+ self.configuration.start_automation()
54
+ self.env["automation.configuration"].cron_automation()
55
+ record_activity = self.env["automation.record.step"].search(
56
+ [("configuration_step_id", "=", activity.id)]
57
+ )
58
+ self.assertEqual("scheduled", record_activity.state)
59
+ self.assertEqual(record_activity.scheduled_date, datetime(2025, 1, 2))