From 2d98708f929493c80e6845336d6d5bd50de9eba5 Mon Sep 17 00:00:00 2001 From: "Simon Genin (ges)" Date: Thu, 10 Sep 2020 08:10:49 +0000 Subject: [PATCH] [FIX] base: x2many edition on res.config.settings form views Before this, a one2many relation in a settings view would not work. After the save, the added data in the field would be cleared. Now, the data is still present. With the change made to BaseSettingsModel the 'base_settings_tests' need to only use the res.config.settings as fake data model. (relations towards other models are still ok though). The test file is therefore altered to comply to this new rule. Note that this commit only validates the good behavior on the frontend side, as a one2many relation towards a res.settings can't be done simply in python as it is a transient model (forbidden). Task ID: 2274168 closes odoo/odoo#57401 Signed-off-by: Aaron Bohy (aab) --- .../base/static/src/js/res_config_settings.js | 21 ++-- .../base/static/tests/base_settings_tests.js | 99 ++++++++++++++----- 2 files changed, 86 insertions(+), 34 deletions(-) diff --git a/odoo/addons/base/static/src/js/res_config_settings.js b/odoo/addons/base/static/src/js/res_config_settings.js index ab09eaa7c27..3b4fdc81115 100644 --- a/odoo/addons/base/static/src/js/res_config_settings.js +++ b/odoo/addons/base/static/src/js/res_config_settings.js @@ -307,17 +307,16 @@ var BaseSettingController = FormController.extend({ }); -var BaseSettingsModel = BasicModel.extend({ - /** - * @override - */ - save: function (recordID) { - var self = this; - return this._super.apply(this, arguments).then(function (result) { - // we remove here the res_id, because the record should still be - // considered new. We want the web client to always perform a - // default_get to fetch the settings anew. - delete self.localData[recordID].res_id; +const BaseSettingsModel = BasicModel.extend({ + save(recordID, options) { + const savePoint = options && options.savePoint; + return this._super.apply(this, arguments).then(result => { + if (!savePoint && this.localData[recordID].model === 'res.config.settings') { + // we remove here the res_id, because the record should still be + // considered new. We want the web client to always perform a + // onchange to fetch the settings anew. + delete this.localData[recordID].res_id; + } return result; }); }, diff --git a/odoo/addons/base/static/tests/base_settings_tests.js b/odoo/addons/base/static/tests/base_settings_tests.js index 2c3439d8082..213e93c1e1d 100644 --- a/odoo/addons/base/static/tests/base_settings_tests.js +++ b/odoo/addons/base/static/tests/base_settings_tests.js @@ -12,12 +12,16 @@ var createActionManager = testUtils.createActionManager; QUnit.module('base_settings_tests', { beforeEach: function () { this.data = { - project: { + 'res.config.settings': { fields: { foo: {string: "Foo", type: "boolean"}, bar: {string: "Bar", type: "boolean"}, + tasks: {string: "one2many field", type: "one2many", relation: 'task'}, }, }, + 'task': { + fields: {} + } }; } }, function () { @@ -29,7 +33,7 @@ QUnit.module('base_settings_tests', { var form = await createView({ View: BaseSettingsView, - model: 'project', + model: 'res.config.settings', data: this.data, arch: '
' + '
' + @@ -77,7 +81,7 @@ QUnit.module('base_settings_tests', { }); assert.hasAttrValue(form.$('.selected'), 'data-key',"crm","crm setting selected"); - assert.isVisible(form.$(".settings .app_settings_block"), "project settings show"); + assert.isVisible(form.$(".settings .app_settings_block"), "res.config.settings settings show"); await testUtils.fields.editAndTrigger(form.$('.searchInput'), 'b', 'keyup'); assert.strictEqual(form.$('.highlighter').html(), "B", "b word highlighted"); await testUtils.fields.editAndTrigger(form.$('.searchInput'), 'bx', 'keyup'); @@ -93,24 +97,25 @@ QUnit.module('base_settings_tests', { var actions = [{ id: 1, name: 'Settings view', - res_model: 'project', + res_model: 'res.config.settings', type: 'ir.actions.act_window', views: [[1, 'form']], }, { id: 4, name: 'Other action', - res_model: 'project', + res_model: 'task', type: 'ir.actions.act_window', views: [[2, 'list']], }]; var archs = { - 'project,1,form': '' + + 'res.config.settings,1,form': '' + '
' + '
' + '', - 'project,2,list': '', - 'project,false,search': '', + 'task,2,list': '', + 'res.config.settings,false,search': '', + 'task,false,search': '', }; var actionManager = await createActionManager({ @@ -149,18 +154,18 @@ QUnit.module('base_settings_tests', { var actions = [{ id: 1, name: 'Settings view', - res_model: 'project', + res_model: 'res.config.settings', type: 'ir.actions.act_window', views: [[1, 'form']], }, { id: 4, name: 'Other action', - res_model: 'project', + res_model: 'task', type: 'ir.actions.act_window', views: [[2, 'list']], }]; var archs = { - 'project,1,form': '
' + + 'res.config.settings,1,form': '' + '
' + '
' + '', - 'project,2,list': '', - 'project,false,search': '', + 'task,2,list': '', + 'res.config.settings,false,search': '', + 'task,false,search': '', }; var actionManager = await createActionManager({ @@ -245,7 +251,7 @@ QUnit.module('base_settings_tests', { var form = await createView({ View: BaseSettingsView, - model: 'project', + model: 'res.config.settings', data: this.data, arch: '
' + '
' + @@ -283,7 +289,7 @@ QUnit.module('base_settings_tests', { var form = await createView({ View: BaseSettingsView, - model: 'project', + model: 'res.config.settings', data: this.data, arch: '' + '
' + @@ -321,7 +327,7 @@ QUnit.module('base_settings_tests', { var form = await createView({ View: BaseSettingsView, - model: 'project', + model: 'res.config.settings', data: this.data, mockRPC: function (route, args) { if (args.method === "create" && !self.alreadySavedOnce) { @@ -366,32 +372,33 @@ QUnit.module('base_settings_tests', { const actions = [{ id: 1, name: 'First action', - res_model: 'project', + res_model: 'task', type: 'ir.actions.act_window', views: [[1, 'list']], }, { id: 2, name: 'Settings view', - res_model: 'project', + res_model: 'res.config.settings', type: 'ir.actions.act_window', views: [[2, 'form']], }, { id: 3, name: 'Other action', - res_model: 'project', + res_model: 'task', type: 'ir.actions.act_window', views: [[3, 'list']], }]; const archs = { - 'project,1,list': '', - 'project,2,form': ` + 'task,1,list': '', + 'res.config.settings,2,form': `
`, - 'project,3,list': '', - 'project,false,search': '', + 'task,3,list': '', + 'res.config.settings,false,search': '', + 'task,false,search': '', }; let loadViewsDef; @@ -424,5 +431,51 @@ QUnit.module('base_settings_tests', { actionManager.destroy(); }); + + QUnit.test('settings can contain one2many fields', async function (assert) { + assert.expect(2); + + const form = await createView({ + View: BaseSettingsView, + model: 'res.config.settings', + data: this.data, + arch: ` +
+
+
+
+
+
+
No Record Found
+
+ + + + +
+
+
+ `, + }); + + await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); + await testUtils.fields.editInput($('.modal-body input[name=display_name]'), 'Added Task'); + await testUtils.dom.click($('.modal-dialog footer button:first-child')); + + assert.strictEqual(form.$('table.o_list_table:eq(0) tr.o_data_row td.o_data_cell:eq(0)').text(), + 'Added Task', + 'The one2many relation item should have been added'); + + await testUtils.form.clickSave(form); + + assert.strictEqual(form.$('table.o_list_table:eq(0) tr.o_data_row td.o_data_cell:eq(0)').text(), + 'Added Task', + 'The one2many relation item should still be present'); + + form.destroy(); + }); + }); });