[FIX] barcodes: don't redraw form twice

When scanning a command barcode, the view shouldn't be redrawn
after the operation corresponding to the command is executed,
for two reasons: first, it is useless as the view has already
been reloaded, and second, it may cause issues if it has been
destroyed meanwhile.

For example, when scanning barcode O-CMD.MAIN-MENU from a
picking form view: a do_action is performed to go back to the
main barcode client action (so the current form view is destroyed),
but an handler tried to redrawn the destroyed form view, which
produced a crash because the session was required by Date fields,
and it couldn't be provided (there were no more parent listening
to provide it).
This commit is contained in:
Aaron Bohy
2017-08-25 15:54:56 +02:00
parent 3d5b283675
commit dec1bdb44d
2 changed files with 58 additions and 2 deletions
@@ -240,8 +240,13 @@ FormController.include({
if (prefixed && !hasCommand) {
self.do_warn(_t('Error : Barcode command is undefined'), barcode);
}
return $.when.apply($, defs).then(function () {
self.update({}, {reload: false});
return self.alive($.when.apply($, defs)).then(function () {
if (!prefixed) {
// redraw the view if we scanned a real barcode (required if
// we manually apply the change in JS, e.g. incrementing the
// quantity)
self.update({}, {reload: false});
}
});
});
},
@@ -4,6 +4,7 @@ odoo.define('barcodes.tests', function (require) {
var barcodeEvents = require('barcodes.BarcodeEvents');
var testUtils = require('web.test_utils');
var FormController = require('web.FormController');
var FormView = require('web.FormView');
var createView = testUtils.createView;
@@ -121,6 +122,56 @@ QUnit.test('pager buttons', function (assert) {
form.destroy();
});
QUnit.test('do no update form twice after a command barcode scanned', function (assert) {
assert.expect(7);
var delay = barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms;
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = 0;
var formUpdate = FormController.prototype.update;
FormController.prototype.update = function () {
assert.step('update');
return formUpdate.apply(this, arguments);
};
var form = createView({
View: FormView,
model: 'product',
data: this.data,
arch: '<form>' +
'<field name="display_name"/>' +
'<field name="int_field" widget="field_float_scannable"/>' +
'</form>',
mockRPC: function (route, args) {
if (args.method === 'read') {
assert.step('read');
}
return this._super.apply(this, arguments);
},
res_id: 1,
viewOptions: {
ids: [1, 2],
index: 0,
},
});
assert.verifySteps(['read'], "update should not have been called yet");
// switch to next record
_.each(["O","-","C","M","D",".","P","A","G","E","R","-","N","E","X","T","Enter"], triggerKeypressEvent);
// a first update is done to reload the data (thus followed by a read), but
// update shouldn't be called afterwards
assert.verifySteps(['read', 'update', 'read']);
_.each(['5','4','3','9','8','2','6','7','1','2','5','2','Enter'], triggerKeypressEvent);
// a real barcode has been scanned -> an update should be requested (with
// option reload='false', so it isn't followed by a read)
assert.verifySteps(['read', 'update', 'read', 'update']);
form.destroy();
barcodeEvents.BarcodeEvents.max_time_between_keys_in_ms = delay;
FormController.prototype.update = formUpdate;
});
QUnit.test('widget field_float_scannable', function (assert) {
var done = assert.async();
assert.expect(11);