From c0247e6a8d6057710908be941dec6a846c31cd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 24 Aug 2017 09:57:02 +0200 Subject: [FIX] web: correct evaluation for x2many fields in onchanges Before this commit, it could happen that a x2many field was considered invalid, which prevent triggering onchanges, even though each of its required fields are properly set. Here is such a scenario: We have a one2many field something_ids in a form view, with an inline tree view, which contains a field X. The field X is required on the model, but marked required="0" in the inline view. In that case, we incorrectly evaluated the required modifiers: since the attrs did not contain the required attribute, we fell back on the field_get value, which is true in this case. But this is not correct, the fieldviewget already computed the actual modifiers and took into account the fact that it was overridden. We need to only look at the modifiers. --- .../static/tests/fields/relational_fields_tests.js | 37 ++++++++++++++++++++++ 1 file changed, 37 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 89f4601efc4..a2504af38bb 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -5352,6 +5352,43 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('onchange and required fields with override in arch', function (assert) { + assert.expect(4); + + this.data.partner.onchanges = { + turtles: function (obj) {} + }; + this.data.turtle.fields.turtle_foo.required = true; + this.data.partner.records[0].turtles = []; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + mockRPC: function (route, args) { + assert.step(args.method); + return this._super.apply(this, arguments); + }, + }); + form.$buttons.find('.o_form_button_edit').click(); + + // triggers an onchange on partner, because the new record is valid + form.$('.o_field_x2many_list_row_add a').click(); + + assert.verifySteps(['read', 'default_get', 'onchange']); + form.destroy(); + }); + + QUnit.module('FieldMany2Many'); -- cgit v1.2.3 From d93726f9ac6d64a39cd95f35cf61a898e4cd2009 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 28 Aug 2017 16:14:31 +0200 Subject: [FIX] web,mail: only send fields in view for onchanges The field 'display_name' is automatically added to the list of fields to fetch when fetching a record. Before this rev., its value was also sent alongside the fields in the view for onchange RPCs. It shouldn't: only the fields in the view should be sent. It produced a weird bug in the res.partner form view: open a contact (company), add a sub-contact, save -> the display_name of the contact was then '' (and 'Contacts' was displayed in the breadcrumbs instead of the display_name of the opened contact). This is because 'display_name' was sent to the onchange, which returned '' as value (because of another bug python side). So as it's value changed, when saving, the new display_name was sent to the server (even if this field was actually readonly). Before this rev., we also always fetched 'display_name' when fetching list of records (read or search_read). This wasn't a bug per se, but it might be a computed field, and it isn't necessary, so we stop fetching it in that case if it isn't in the view (as it was done in saas-15, before the new views). --- addons/web/static/tests/fields/relational_fields_tests.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 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 a2504af38bb..92a24066408 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2521,6 +2521,7 @@ QUnit.module('relational_fields', { arch:'
' + '' + '' + + '' + '' + '' + '
' + @@ -3499,7 +3500,7 @@ QUnit.module('relational_fields', { rpcCount++; if (args.method === 'write') { assert.deepEqual(args.args[1].p, [[0, false, { - display_name: false, int_field: 123, product_id: 41 + int_field: 123, product_id: 41 }]]); } return this._super(route, args); @@ -3736,7 +3737,7 @@ QUnit.module('relational_fields', { if (args.method === 'default_get') { var expected = counter === 0 ? [[4, 2, false]] : - [[4, 2, false], [0, false, {display_name: false, turtle_foo: 'hammer'}]]; + [[4, 2, false], [0, false, {turtle_foo: 'hammer'}]]; assert.deepEqual(args.kwargs.context.turtles, expected, "should have properly evaluated turtles key in context"); counter++; @@ -5544,6 +5545,7 @@ QUnit.module('relational_fields', { arch:'' + '' + '' + + '' + '' + '' + '
' + -- cgit v1.2.3 From c5bf53682e159343ee0c707f6d7f2da972d6add2 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 29 Aug 2017 11:57:33 +0200 Subject: [FIX] web: prevent 'load' event from being handled twice In grouped list view, when a pager is clicked inside a group, a 'load' event is triggered to reload the data with the new offset. The event is handled by the list's controller. However, when the list is in the modal, the event must be stop propagated by the controller of the modal, so that it doesn't go up to the controller of the view displayed behind the modal. It happens for example by reproducing the following steps: - go to Lunch - add a line - search more products - group by vendor in the modal - unfold a group - click on the pager (the group must contain more than 80 records) Before this rev., it crashed because the controller of the form view tried to handle the event. --- .../static/tests/fields/relational_fields_tests.js | 65 ++++++++++++++++++++++ 1 file changed, 65 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 92a24066408..e211d120fe2 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -6885,6 +6885,71 @@ QUnit.module('relational_fields', { list.destroy(); }); + QUnit.test('search more in many2one: group and use the pager', function (assert) { + assert.expect(2); + + this.data.partner.records.push({ + id: 5, + display_name: "Partner 4", + }, { + id: 6, + display_name: "Partner 5", + }, { + id: 7, + display_name: "Partner 6", + }, { + id: 8, + display_name: "Partner 7", + }, { + id: 9, + display_name: "Partner 8", + }, { + id: 10, + display_name: "Partner 9", + }); + + this.data.partner.fields.datetime.searchable = true; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '' + + '' + + '' + + '', + + res_id: 1, + archs: { + 'partner,false,list': '', + 'partner,false,search': '' + + ' ' + + '', + }, + viewOptions: { + mode: 'edit', + }, + }); + + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + form.$('.o_field_many2one input').click(); + $dropdown.find('.o_m2o_dropdown_option:contains(Search)').mouseenter().click(); // Open Search More + + $('.modal .o_searchview_more').click(); // Magnifying class for more filters + $('.modal .o_search_options .o_group_by_menu a:contains(Bar)').click(); // group by 'Bar' + + $('.modal .o_group_header:first').click(); + assert.strictEqual($('.modal tbody:nth(1) .o_data_row').length, 7, + "should display 7 records in the first page"); + $('.modal .o_group_header:first .o_pager_next').click(); + assert.strictEqual($('.modal tbody:nth(1) .o_data_row').length, 1, + "should display 1 record in the second page"); + + form.destroy(); + }); + QUnit.test('field many2many_tags keeps focus when being edited', function (assert) { assert.expect(7); -- cgit v1.2.3 From f1082f15525ccf42b1fb95fb7da0211eaf64fcb9 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 30 Aug 2017 10:38:53 +0200 Subject: [FIX] web: don't send virtual id on save The problem occurred on form views with an x2many field with a default value containing CREATE commands, i.e. when opening such a form view in create mode, the x2many field is pre-filled with some (non-existing yet) subrecords. If the user then edited those subrecords, and then clicked on 'Save' to create the main record, an 'UPDATE' command was sent alongside the 'CREATE' one for the x2many, and the id of the 'UPDATE' command was a virtual id (as the subrecord didn't exist yet), and it crashed. This could happen in MRP: - 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: the many2many already contains a subrecord - edit the lot field of that subrecord - click on 'Record Production' --- .../static/tests/fields/relational_fields_tests.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 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 e211d120fe2..6337d74326e 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -998,14 +998,15 @@ QUnit.module('relational_fields', { }); QUnit.test('list in form: default_get with x2many create', function (assert) { - assert.expect(3); + assert.expect(5); + var displayName = 'brandon is the new timmy'; this.data.partner.onchanges.timmy = function (obj) { assert.deepEqual( obj.timmy, [ [6, false, []], - [0, false, {display_name: 'brandon is the new timmy', name: 'brandon'}] + [0, false, {display_name: displayName, name: 'brandon'}] ], "should have properly created the x2many command list"); obj.int_field = obj.timmy.length; @@ -1029,6 +1030,15 @@ QUnit.module('relational_fields', { if (args.method === 'default_get') { return $.when({timmy: [[0, 0, {display_name: 'brandon is the new timmy', name: 'brandon'}]]}); } + if (args.method === 'create') { + assert.deepEqual(args.args[0], { + int_field: 2, + timmy: [ + [6, false, []], + [0, false, {display_name: displayName, name: 'brandon'}], + ], + }, "should send the correct values to create"); + } return this._super.apply(this, arguments); }, }); @@ -1038,6 +1048,12 @@ QUnit.module('relational_fields', { assert.strictEqual($('input.o_field_integer').val(), '2', "should have called and executed the onchange properly"); + // edit the subrecord and save + displayName = 'new value'; + form.$('.o_data_cell').click(); + form.$('.o_data_cell input').val(displayName).trigger('input'); + form.$buttons.find('.o_form_button_save').click(); + form.destroy(); }); -- cgit v1.2.3