diff --git a/fs_attachment/models/fs_storage.py b/fs_attachment/models/fs_storage.py index c7ac100da1..eb234a5e33 100644 --- a/fs_attachment/models/fs_storage.py +++ b/fs_attachment/models/fs_storage.py @@ -455,8 +455,18 @@ def recompute_urls(self) -> None: in staging are done in a different directory and will not impact the production. """ - attachments = self.env["ir.attachment"].search( - [("fs_storage_id", "in", self.ids)] - ) + # The weird "res_field = False OR res_field != False" domain + # is required! It's because of an override of _search in ir.attachment + # which adds ('res_field', '=', False) when the domain does not + # contain 'res_field'. + # https://github.com/odoo/odoo/blob/9032617120138848c63b3cfa5d1913c5e5ad76db/ + # odoo/addons/base/ir/ir_attachment.py#L344-L347 + domain = [ + ("fs_storage_id", "in", self.ids), + "|", + ("res_field", "=", False), + ("res_field", "!=", False), + ] + attachments = self.env["ir.attachment"].search(domain) attachments._compute_fs_url() attachments._compute_fs_url_path() diff --git a/fs_attachment/tests/test_fs_storage.py b/fs_attachment/tests/test_fs_storage.py index b0ca790eba..0538dcf0ac 100644 --- a/fs_attachment/tests/test_fs_storage.py +++ b/fs_attachment/tests/test_fs_storage.py @@ -323,3 +323,52 @@ def test_force_field_and_model_create_attachment(self): self.env.flush_all() self.assertFalse(attachment.fs_storage_code) + + def test_recompute_urls(self): + """ + Mark temp_backend as default and set its base_url. + Create one attachment in temp_backend that is linked to a field and one that is not. + * Check that after updating the base_url for the backend, executing recompute_urls + updates fs_url for both attachments, whether they are linked to a field or not + """ + self.temp_backend.base_url = "https://acsone.eu/media" + self.temp_backend.use_as_default_for_attachments = True + self.ir_attachment_model.create( + { + "name": "field.txt", + "raw": "Attachment linked to a field", + "res_model": "res.partner", + "res_field": "name", + } + ) + self.ir_attachment_model.create( + { + "name": "no_field.txt", + "raw": "Attachment not linked to a field", + } + ) + self.env.flush_all() + + self.env.cr.execute( + f""" + SELECT COUNT(*) + FROM ir_attachment + WHERE fs_storage_id = {self.temp_backend.id} + AND fs_url LIKE '{self.temp_backend.base_url}%' + """ + ) + self.assertEqual(self.env.cr.dictfetchall()[0].get("count"), 2) + + self.temp_backend.base_url = "https://forgeflow.com/media" + self.temp_backend.recompute_urls() + self.env.flush_all() + + self.env.cr.execute( + f""" + SELECT COUNT(*) + FROM ir_attachment + WHERE fs_storage_id = {self.temp_backend.id} + AND fs_url LIKE '{self.temp_backend.base_url}%' + """ + ) + self.assertEqual(self.env.cr.dictfetchall()[0].get("count"), 2)