diff --git a/addons/point_of_sale/models/res_config_settings.py b/addons/point_of_sale/models/res_config_settings.py index a30fd024f81..8b5f1bf08f7 100644 --- a/addons/point_of_sale/models/res_config_settings.py +++ b/addons/point_of_sale/models/res_config_settings.py @@ -150,7 +150,7 @@ class ResConfigSettings(models.TransientModel): # STEP: Finally, we write the value of 'pos' fields to 'pos_config_id'. for pos_config_id, pos_fields_vals in pos_config_id_to_fields_vals_map.items(): pos_config = self.env['pos.config'].browse(pos_config_id) - pos_config.write(pos_fields_vals) + pos_config.with_context(from_settings_view=True).write(pos_fields_vals) return result diff --git a/addons/pos_self_order/models/pos_config.py b/addons/pos_self_order/models/pos_config.py index 48146d3fca7..2fba64aa115 100644 --- a/addons/pos_self_order/models/pos_config.py +++ b/addons/pos_self_order/models/pos_config.py @@ -11,7 +11,7 @@ from werkzeug.urls import url_quote from odoo.exceptions import UserError from odoo.tools import image_to_base64 -from odoo import api, fields, models, _, service +from odoo import api, fields, models, _, service, Command from odoo.tools import file_open, split_every @@ -153,6 +153,23 @@ class PosConfig(models.Model): if (not vals.get('module_pos_restaurant') and not record.module_pos_restaurant) and vals.get('self_ordering_mode') == 'mobile': vals['self_ordering_pay_after'] = 'each' + if 'self_ordering_image_home_ids' in vals and self.env.context.get('from_settings_view'): + linked_ids = set(record.self_ordering_image_home_ids.ids) + + # Changes in the splash screen field always results to an array of link commands or a single set command. + # We inspect the commands to determine which attachments should be unlinked. + # We only care about the link command. We can consider set command as absolute as it will replace all. + for command in vals['self_ordering_image_home_ids']: + if command[0] == 4: + _id = command[1] + if _id in linked_ids: + linked_ids.remove(_id) + + # Remaining items in linked_ids should be unlinked. + unlink_commands = [Command.unlink(_id) for _id in linked_ids] + + vals['self_ordering_image_home_ids'] = unlink_commands + vals['self_ordering_image_home_ids'] + return super().write(vals) @api.depends("module_pos_restaurant") diff --git a/addons/pos_self_order/tests/test_frontend.py b/addons/pos_self_order/tests/test_frontend.py index 8549c37a273..969d6b8ec71 100644 --- a/addons/pos_self_order/tests/test_frontend.py +++ b/addons/pos_self_order/tests/test_frontend.py @@ -70,3 +70,27 @@ class TestFrontendMobile(SelfOrderCommonTest): result = response.json() order_id = result['result']['id'] self.assertEqual(self.env['pos.order'].browse(order_id).fiscal_position_id.id, alternative_fp.id) + + def test_properly_delete_splash_screen_images(self): + """ Simulate what is done from the res.config.settings view when removing an image. """ + + self.pos_config.write({ + 'self_ordering_image_home_ids': [ + Command.clear(), + Command.create({'name': 'a1', 'datas': b'blob1234', 'mimetype': 'image/png'}), + Command.create({'name': 'a2', 'datas': b'blob2345', 'mimetype': 'image/png'}), + Command.create({'name': 'a3', 'datas': b'blob3456', 'mimetype': 'image/png'}), + ] + }) + + linked_ids = self.pos_config.self_ordering_image_home_ids.ids + second_id = linked_ids[1] + + # We'll unlink the second image and then save the settings. + # It will be a set of link commands for the images except the one we want to delete. + commands = [Command.link(id) for id in linked_ids if id != second_id] + self.pos_config.with_context(from_settings_view=True).write({ + 'self_ordering_image_home_ids': commands + }) + + self.assertTrue(second_id not in self.pos_config.self_ordering_image_home_ids.ids)