From c300e5ede781f16b7d00cdcbc6bad227b265dd6b Mon Sep 17 00:00:00 2001 From: Khoi Nguyen Date: Thu, 3 Aug 2017 09:25:16 +0200 Subject: [FIX] web: reload right record when editing a many2one inside an x2many Before this revision, editing a many2one inside an x2many field did not cause an update of the x2many field upon saving. This is due to the fact that a field on a screen was deemed affected by a record change only if its value or a directly related record has been updated. This present revision looks for changes recursively, thereby including the case where an x2many field contains a many2one. The bug appeared for example in Manufacturing, when editing the product name of a BOM line. --- .../static/tests/fields/relational_fields_tests.js | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'addons/web/static/tests/fields/relational_fields_tests.js') diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 0ad9aa2a416..f9b6e9dfaeb 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1418,6 +1418,58 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('updating a many2one from a many2many', function (assert) { + assert.expect(4); + + this.data.turtle.records[1].turtle_trululu = 1; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + archs: { + 'partner,false,form': '
', + }, + mockRPC: function (route, args) { + if (args.method === 'get_formview_id') { + assert.deepEqual(args.args[0], [1], "should call get_formview_id with correct id"); + return $.when(false); + } + return this._super(route, args); + }, + }); + + // Opening the modal + form.$buttons.find('.o_form_button_edit').click(); + form.$('.o_data_row td:contains(first record)').click(); + form.$('.o_external_button').click(); + assert.strictEqual($('.modal').length, 1, + "should have one modal in body"); + + // Changing the 'trululu' value + $('.modal input[name="display_name"]').val('test').trigger('input'); + $('.modal button.btn-primary').click(); + + // Test whether the value has changed + assert.strictEqual($('.modal').length, 0, + "the modal should be closed"); + assert.equal(form.$('.o_data_cell:contains(test)').text(), 'test', + "the partner name should have been updated to 'test'"); + + form.destroy(); + }); + QUnit.module('FieldOne2Many'); QUnit.test('one2many basic properties', function (assert) { -- cgit v1.2.3 From 8a386b9a08d1dcd8eac66623f2743291bf677c00 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 7 Aug 2017 10:32:54 +0200 Subject: [FIX] web: BasicModel: domain returned by onchanges Onchange RPCs return an object that may contain a 'domain' key. When it does, its value is an object whose keys are field names and values are the new domain for the corresponding field. Commit 8473bde8 added the support of the 'domain' key, but stored it directly in the fieldsInfo (an object gathering information of the fields in the view, and which is shared between all records). This was wrong as the domain isn't necessarily the same for all records. To reproduce, with the UOMs activated, go to Sales > Quotation, in the form view, add an order line, set a product (e.g. Graphic Card), the onchange sets the domain for the uom field (matching uoms like 'unit', 'dozens'). Add a second line with a service product, the onchange returns another domain for the uom field (matching uoms like 'hours', days'). Click again on the uom field of the first line, the domain is the one of the second record, which is wrong. This rev. directly stores the domains returned by the onchange on the object representing the record, so that this information isn't shared between records anymore. --- .../static/tests/fields/relational_fields_tests.js | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'addons/web/static/tests/fields/relational_fields_tests.js') diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index f9b6e9dfaeb..d5f2315e89c 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1418,6 +1418,63 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('many2one in one2many: domain updated by an onchange', function (assert) { + assert.expect(3); + + this.data.partner.onchanges = { + trululu: function () {}, + }; + + var domain = []; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + mockRPC: function (route, args) { + if (args.method === 'onchange') { + return $.when({ + domain: { + trululu: domain, + }, + }); + } + if (args.method === 'name_search') { + assert.deepEqual(args.kwargs.args, domain, + "sent domain should be correct"); + } + return this._super(route, args); + }, + viewOptions: { + mode: 'edit', + }, + }); + + // add a first row with a specific domain for the m2o + domain = [['id', 'in', [10]]]; // domain for subrecord 1 + form.$('.o_field_x2many_list_row_add a').click(); // triggers the onchange + form.$('.o_field_widget[name=trululu] input').click(); // triggers the name_search + + // add a second row with another domain for the m2o + domain = [['id', 'in', [5]]]; // domain for subrecord 2 + form.$('.o_field_x2many_list_row_add a').click(); // triggers the onchange + form.$('.o_field_widget[name=trululu] input').click(); // triggers the name_search + + // check again the first row to ensure that the domain hasn't change + domain = [['id', 'in', [10]]]; // domain for subrecord 1 should have been kept + form.$('.o_data_row:first .o_data_cell').click(); + form.$('.o_field_widget[name=trululu] input').click(); // triggers the name_search + + form.destroy(); + }); + QUnit.test('updating a many2one from a many2many', function (assert) { assert.expect(4); -- cgit v1.2.3 From 587751aa0dbd095db99e93398cf98d705c35679c Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Fri, 4 Aug 2017 15:36:31 +0200 Subject: [FIX] web: prevent virtual datapoint creation when no default value Previously, it used to create a virtual datapoint even though there was no change on this field. If the field was a many2one, this datapoint triggered a name_get call afterwards, but giving the virtual id of the datapoint since there is no real record. The solution is to avoid creating a virtual datapoint when it is not needed at all, thus fixing the wrong name_get call. Steps to reproduce the bug: - Enable lots in Iventory - Choose a product which is a component of another (through mrp bom) - Set this product as tracked by lot - Set this product inventory quantity to 0 - Create a new manufacturing order for the product for which it is a component - Click on "Check Availability" - Click on Produce - You'll get an error as the web client tries to fetch the name_get of this datapoint even though the record does not exist. --- .../static/tests/fields/relational_fields_tests.js | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'addons/web/static/tests/fields/relational_fields_tests.js') diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index d5f2315e89c..9944c2704ca 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -922,6 +922,42 @@ QUnit.module('relational_fields', { }); }); + QUnit.test('list in form: create with one2many with many2one', function (assert) { + assert.expect(1); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + mockRPC: function (route, args) { + if (args.method === 'default_get') { + return $.when({p: [[0, 0, {display_name: 'new record'}]]}); + } else if (args.method === 'name_get') { + // This should not be called at all and thus is not accounted for + // in the assert.expect. If this is called, you broke this test. + assert.notOk(_.str.startsWith(args.args[0][0], 'virtual_'), + "should not call name_get for the m2o inside o2m which has no value"); + } + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual($('td.o_data_cell:first').text(), 'new record', + "should have created the new record in the o2m with the correct name"); + + form.destroy(); + }); + QUnit.test('autocompletion in a many2one, in form view with a domain', function (assert) { assert.expect(1); -- cgit v1.2.3 From e2252c35c15df9ccf9132c72348723790d76a676 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Fri, 4 Aug 2017 15:31:51 +0200 Subject: [FIX] web: handle create in many2many default_get Previously, we did not handle the case where the result of the m2m default get was a new record. In this case, we can't just send a replace all command giving the ids since the new record has no id. We decided to keep the replace all command even when it is empty to stay consistent with the o2m implementation, even though saas-15 did not behave like that. Steps to reproduce the bug: - Enable lots in Iventory - Choose a product which is a component of another (through mrp bom) - Set this product as tracked by lot - Set this product inventory quantity to 0 - Create a new manufacturing order for the product for which it is a component - Click on "Check Availability" - Click on Produce - You'll get an error as the id given to the onchange is a virtual one, rather than a create which would not include an id. --- .../static/tests/fields/relational_fields_tests.js | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'addons/web/static/tests/fields/relational_fields_tests.js') diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 9944c2704ca..6d4c68d245f 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -958,6 +958,50 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('list in form: default_get with x2many create', function (assert) { + assert.expect(3); + + this.data.partner.onchanges.timmy = function (obj) { + assert.deepEqual( + obj.timmy, + [ + [6, false, []], + [0, false, {display_name: 'brandon is the new timmy', name: 'brandon'}] + ], + "should have properly created the x2many command list"); + obj.int_field = obj.timmy.length; + }; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + mockRPC: function (route, args) { + if (args.method === 'default_get') { + return $.when({timmy: [[0, 0, {display_name: 'brandon is the new timmy', name: 'brandon'}]]}); + } + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual($('td.o_data_cell:first').text(), 'brandon is the new timmy', + "should have created the new record in the m2m with the correct name"); + assert.strictEqual($('input.o_field_integer').val(), '2', + "should have called and executed the onchange properly"); + + form.destroy(); + }); + QUnit.test('autocompletion in a many2one, in form view with a domain', function (assert) { assert.expect(1); -- cgit v1.2.3 From 1e8f6d01ffe324348ce5d75f8643f170f6478657 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 9 Aug 2017 09:21:13 +0200 Subject: [FIX] web,*: send correct context on button clicked *account_asset When a button of type 'action' is clicked (execute a given action), special keys must be set in the context (active_id, active_ids and active_model). They must be computed regarding the record containing the clicked button, i.e. if we are in a modal, it must be the id and model of the record displayed in the modal. Before this rev., we always sent the id and model of the record displayed in the background (i.e. the id and model of the url). This caused a bug in MRP that could be reproduced as follows: - open a manufacturing order in form view - click on edit - click on one of the line of the one2many, and click on the green icon to edit a product - click on the update product quantity button on top of it - the product field must be correctly filled, which was not the case before this rev. --- .../static/tests/fields/relational_fields_tests.js | 62 ++++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'addons/web/static/tests/fields/relational_fields_tests.js') diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 6d4c68d245f..29f8666455a 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1002,6 +1002,60 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('list in form: call button in sub view', function (assert) { + assert.expect(6); + + this.data.partner.records[0].p = [2]; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + mockRPC: function (route, args) { + if (route === '/web/dataset/call_kw/product/get_formview_id') { + return $.when(false); + } + return this._super.apply(this, arguments); + }, + intercepts: { + execute_action: function (event) { + assert.strictEqual(event.data.env.model, 'product', + 'should call with correct model in env'); + assert.strictEqual(event.data.env.currentID, 37, + 'should call with correct currentID in env'); + assert.deepEqual(event.data.env.resIDs, [37], + 'should call with correct resIDs in env'); + }, + }, + archs: { + 'product,false,form': '
' + + '
' + + '
' + + '
', + }, + }); + + form.$buttons.find('.o_form_button_edit').click(); + form.$('td.o_data_cell:first').click(); // edit first one2many line + form.$('.o_external_button').click(); // open product sub view in modal + $('button:contains("Just do it !")').click(); // click on action button + $('button:contains("Just don\'t do it !")').click(); // click on object button + + form.destroy(); + }); + QUnit.test('autocompletion in a many2one, in form view with a domain', function (assert) { assert.expect(1); @@ -4036,9 +4090,9 @@ QUnit.module('relational_fields', { res_id: 1, intercepts: { execute_action: function (event) { - assert.deepEqual(event.data.res_ids, [2], + assert.deepEqual(event.data.env.currentID, 2, 'should call with correct id'); - assert.strictEqual(event.data.model, 'partner', + assert.strictEqual(event.data.env.model, 'partner', 'should call with correct model'); assert.strictEqual(event.data.action_data.name, 'method_name', "should call correct method"); @@ -4080,9 +4134,9 @@ QUnit.module('relational_fields', { res_id: 1, intercepts: { execute_action: function (event) { - assert.deepEqual(event.data.res_ids, [2], + assert.deepEqual(event.data.env.currentID, 2, 'should call with correct id'); - assert.strictEqual(event.data.model, 'partner', + assert.strictEqual(event.data.env.model, 'partner', 'should call with correct model'); assert.strictEqual(event.data.action_data.name, 'method_name', "should call correct method"); -- cgit v1.2.3