From 58cf9b6754c44f9847787938b4019d8740faffda Mon Sep 17 00:00:00 2001 From: jbm-odoo Date: Tue, 6 Aug 2019 11:12:36 +0000 Subject: [PATCH] [FIX] base: Open One2many with not yet updated values When we have an onchange that modify items in One2many's lines (for example the quantity of each line based on general quantity) and we click on a record immediately after changing the field that trigger the onchange, we have the the old value in the dialog box. Indeed the dialog opens before the onchange has return the new values, so the old one are used. This case appears only if the One2many's line was never saved. With this fix, we wait that the model is free of mutex, and so the onchange is terminated before displaying it. closes odoo/odoo#35306 Signed-off-by: Simon Lejeune (sle) --- .../src/js/views/form/form_controller.js | 5 +- addons/web/static/tests/views/form_tests.js | 68 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js index c80f939ddee..e3896738d52 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -680,7 +680,7 @@ var FormController = BasicController.extend({ * @private * @param {OdooEvent} ev */ - _onOpenOne2ManyRecord: function (ev) { + _onOpenOne2ManyRecord: async function (ev) { ev.stopPropagation(); var data = ev.data; var record; @@ -688,6 +688,9 @@ var FormController = BasicController.extend({ record = this.model.get(data.id, {raw: true}); } + // Sync with the mutex to wait for potential onchanges + await this.model.mutex.getUnlockedDef(); + new dialogs.FormViewDialog(this, { context: data.context, domain: data.domain, diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 854066020e3..765beb7ed08 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -3309,6 +3309,74 @@ QUnit.module('Views', { form.destroy(); }); + QUnit.test('properly apply onchange on one2many fields direct click', async function (assert) { + assert.expect(3); + + var def = testUtils.makeTestPromise(); + + this.data.partner.records[0].p = [2, 4]; + this.data.partner.onchanges = { + int_field: function (obj) { + obj.p = [ + [5], + [1, 2, {display_name: "updated record 1", int_field: obj.int_field}], + [1, 4, {display_name: "updated record 2", int_field: obj.int_field * 2}], + ]; + }, + }; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + mockRPC: function (route, args) { + if (args.method === 'onchange') { + var self = this; + var my_args = arguments; + var my_super = this._super; + return def.then(() => { + return my_super.apply(self, my_args) + }); + } + return this._super.apply(this, arguments); + }, + archs: { + 'partner,false,form': '
' + }, + viewOptions: { + mode: 'edit', + }, + }); + // Trigger the onchange + await testUtils.fields.editInput(form.$('input[name=int_field]'), '2'); + + // Open first record in one2many + await testUtils.dom.click(form.$('.o_data_row:first')); + + assert.containsNone(document.body, '.modal'); + + def.resolve(); + await testUtils.nextTick(); + + assert.containsOnce(document.body, '.modal'); + assert.strictEqual($('.modal').find('input[name=int_field]').val(), '2'); + + form.destroy(); + }); + QUnit.test('update many2many value in one2many after onchange', async function (assert) { assert.expect(2);