From 555386706fc7beb78a33a30ae473329bc05a581c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 20 Apr 2023 08:16:42 +0000 Subject: [PATCH] [FIX] mail: uninstallation When modules get uninstalled, first the uninstall process will drop all the fields (removing all the columns) then it drops all the models (removing the tables). When uninstalling mail, this means the various (res_)model(_id) fields don't exist anymore by the time we're deleting models, so the queries blow up. Skip this step if we're unlinking the mail models, it means the tables have already been dropped, so there's nothing to delete anymore. This should not use `ondelete` because we *do* want to delete records from those tables when deleting modules which depend on mail, and thus have mail stuff associated with their own models which we're deleting. X-original-commit: e43155f940c1f0ba30378d110fc371012d791e32 Part-of: odoo/odoo#121522 --- addons/mail/models/ir_model.py | 39 +++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/addons/mail/models/ir_model.py b/addons/mail/models/ir_model.py index d2a296e6849..30084eb1a7b 100644 --- a/addons/mail/models/ir_model.py +++ b/addons/mail/models/ir_model.py @@ -20,26 +20,35 @@ class IrModel(models.Model): ) def unlink(self): + """ Delete mail data (followers, messages, activities) associated with + the models being deleted. + """ if not self: return True # Delete followers, messages and attachments for models that will be unlinked. + mail_models = self.search([ + ('model', 'in', ('mail.activity', 'mail.activity.type', 'mail.followers', 'mail.message')) + ], order='id') + + if not (self & mail_models): + models = tuple(self.mapped('model')) + model_ids = tuple(self.ids) + + query = "DELETE FROM mail_activity WHERE res_model_id IN %s" + self.env.cr.execute(query, [model_ids]) + + query = "DELETE FROM mail_activity_type WHERE res_model IN %s" + self.env.cr.execute(query, [models]) + + query = "DELETE FROM mail_followers WHERE res_model IN %s" + self.env.cr.execute(query, [models]) + + query = "DELETE FROM mail_message WHERE model in %s" + self.env.cr.execute(query, [models]) + + # Get files attached solely to the models being deleted (and none other) models = tuple(self.mapped('model')) - model_ids = tuple(self.ids) - - query = "DELETE FROM mail_activity WHERE res_model_id IN %s" - self.env.cr.execute(query, [model_ids]) - - query = "DELETE FROM mail_activity_type WHERE res_model IN %s" - self.env.cr.execute(query, [models]) - - query = "DELETE FROM mail_followers WHERE res_model IN %s" - self.env.cr.execute(query, [models]) - - query = "DELETE FROM mail_message WHERE model in %s" - self.env.cr.execute(query, [models]) - - # Get files attached solely by the models query = """ SELECT DISTINCT store_fname FROM ir_attachment