Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit af0ef5d

Browse files
pauloamedKangOl
andcommittedMay 8, 2024·
[IMP] util/records: enforce cascade removal for actions
The implementation of the python inheritance mechanism between the base class `ir.actions.actions` and its child classes (eg. `ir.actions.act_window`) does not allow the creation of foreign keys when `ir.actions.actions` is a M2O field of another model when it is being referenced in favour of polymorphism; what leads to the not execution of some constraints, one of them being the `ondelete='cascade'` constraint, which is set in PSQL level. That said, when a `ir.actions.actions` record is deleted, if it is being referenced as a M2O field by another model (eg. `ir.filters`), records from this second model won't be affected, what leads to undesired behaviour: a MissingError in the UI, indicating that the action was deleted. Such behaviour of not creating foreign keys and thus constraints is specific to `ir.actions.actions`. This commit remedies this specific case, removing records with a M2O field to `ir.actions.actions` if `ondelete=cascade`, or setting this field to NULL if `ondelete=set null`, when the action referenced in such field is removed using `upgrade-util`. Co-authored-by: Christophe Simonis <[email protected]>
1 parent 3787631 commit af0ef5d

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed
 

‎src/util/records.py

+48
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,50 @@ def remove_asset(cr, name):
310310
# fmt:on
311311

312312

313+
def remove_action(cr, xml_id=None, action_id=None):
314+
assert bool(xml_id) ^ bool(action_id)
315+
316+
action_model = None
317+
if action_id:
318+
cr.execute("SELECT type FROM ir_actions WHERE id=%s", [action_id])
319+
[action_model] = cr.fetchone()
320+
else:
321+
module, _, name = xml_id.partition(".")
322+
cr.execute("SELECT model, res_id FROM ir_model_data WHERE module=%s AND name=%s", [module, name])
323+
action_model, action_id = cr.fetchone()
324+
if action_model not in {ihn.model for ihn in for_each_inherit(cr, "ir.actions.actions")}:
325+
raise ValueError(
326+
"%r should point to a model inheriting from 'ir.actions.actions', not a %r" % (xml_id, action_model)
327+
)
328+
329+
if not version_gte("12.0"):
330+
return remove_records(cr, action_model, [action_id])
331+
332+
cr.execute(
333+
"""
334+
SELECT name,
335+
model,
336+
on_delete
337+
FROM ir_model_fields
338+
WHERE relation = 'ir.actions.actions'
339+
AND on_delete IN ( 'cascade', 'set null' )
340+
AND ttype = 'many2one'
341+
"""
342+
)
343+
344+
for column_name, model, on_delete in cr.fetchall():
345+
model_table = table_of_model(cr, model)
346+
if on_delete == "cascade":
347+
query = format_query(cr, "SELECT id FROM {} WHERE {} = %s", model_table, column_name)
348+
cr.execute(query, (action_id,))
349+
remove_records(cr, model, [id_ for (id_,) in cr.fetchall()])
350+
else:
351+
query = format_query(cr, "UPDATE {} SET {} = NULL WHERE {} = %s", model_table, column_name, column_name)
352+
cr.execute(query, (action_id,))
353+
354+
return remove_records(cr, action_model, [action_id])
355+
356+
313357
def remove_record(cr, name):
314358
"""
315359
Remove a record and its references corresponding to the given :term:`xml_id <external identifier>`.
@@ -352,6 +396,10 @@ def remove_record(cr, name):
352396
_logger.log(NEARLYWARN, "Removing group %r", name)
353397
return remove_group(cr, group_id=res_id)
354398

399+
if model in {ihn.model for ihn in for_each_inherit(cr, "ir.actions.actions")}:
400+
_logger.log(NEARLYWARN, "Removing action %r", name)
401+
return remove_action(cr, action_id=res_id)
402+
355403
return remove_records(cr, model, [res_id])
356404

357405

0 commit comments

Comments
 (0)
Please sign in to comment.