diff --git a/dms/models/dms_security_mixin.py b/dms/models/dms_security_mixin.py index c6433c60e..d89c369c7 100644 --- a/dms/models/dms_security_mixin.py +++ b/dms/models/dms_security_mixin.py @@ -132,8 +132,11 @@ def _get_domain_by_inheritance(self, operation): continue domains.append([("res_model", "=", model._name), ("res_id", "=", False)]) # Check record access in batch too - group_ids = [i for i in group["res_id"] if i] # Hack to remove None res_id - related_ok = model.browse(group_ids)._filter_access_rules_python(operation) + res_ids = [i for i in group["res_id"] if i] # Hack to remove None res_id + # Apply exists to skip records that do not exist. (e.g. a res.partner deleted + # by database). + model_records = model.browse(res_ids).exists() + related_ok = model_records._filter_access_rules_python(operation) if not related_ok: continue domains.append( diff --git a/dms/models/ir_attachment.py b/dms/models/ir_attachment.py index b484c3c6a..b064a6dcf 100644 --- a/dms/models/ir_attachment.py +++ b/dms/models/ir_attachment.py @@ -1,6 +1,7 @@ # Copyright 2021 Tecnativa - Víctor Martínez # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import api, models +from odoo.tools import ormcache class IrAttachment(models.Model): @@ -35,9 +36,26 @@ def _dms_directories_create(self): } ) + @ormcache("model") + def _dms_operations_from_model(self, model): + # Apply sudo to prevent ir.rule from being applied. + item = self.env["dms.storage"].sudo().search([("model_ids.model", "=", model)]) + return bool(item) + def _dms_operations(self): + """Perform the operation only if there is a storage with linked models. + The directory (dms.directory) linked to the record (if it does not exist) + and the file (dms.file) with the linked attachment would be created. + """ for attachment in self: - if not attachment.res_model or not attachment.res_id: + if ( + not attachment.res_model + or not attachment.res_id + or ( + attachment.res_model + and not self._dms_operations_from_model(attachment.res_model) + ) + ): continue directories = attachment._get_dms_directories( attachment.res_model, attachment.res_id diff --git a/dms/models/storage.py b/dms/models/storage.py index a33b00937..8663585b1 100644 --- a/dms/models/storage.py +++ b/dms/models/storage.py @@ -145,3 +145,9 @@ def _compute_count_storage_directories(self): def _compute_count_storage_files(self): for record in self: record.count_storage_files = len(record.storage_file_ids) + + def write(self, values): + res = super().write(values) + if "model_ids" in values: + self.env["ir.attachment"].clear_caches() + return res diff --git a/dms/tests/test_storage_attachment.py b/dms/tests/test_storage_attachment.py index c977954af..b83553f64 100644 --- a/dms/tests/test_storage_attachment.py +++ b/dms/tests/test_storage_attachment.py @@ -29,6 +29,19 @@ def test_storage_attachment(self): self.assertFalse(file_01.exists()) self.assertFalse(directory.exists()) + @users("dms-manager") + def test_storage_attachment_record_db_unlink(self): + self._create_attachment("demo.txt") + self.assertTrue( + self.storage.storage_file_ids.filtered(lambda x: x.name == "demo.txt") + ) + directory = self._get_partner_directory() + self.assertEqual(directory.res_model, self.partner._name) + self.assertEqual(directory.res_id, self.partner.id) + directory.res_id = 0 # Trick to reference a non-existing record + directories = self.env["dms.directory"].search([]) + self.assertNotIn(directory.id, directories.ids) + @users("dms-manager") def test_storage_attachment_misc(self): attachment = self._create_attachment("demo.txt")