From a41db9a2cf410bb233b021651a5633180eaddf18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 25 Jul 2017 10:09:42 +0200 Subject: [FIX] web: allow record creation even if onchange returns warning Before this commit, the makeDefaultRecord could return a rejected deferred if the onchange returned a warning. This was useful in this usecase: the user is in a form view with a one2many (for example, an invoice with no customer set), then click on 'Add a line' (the invoice line). In that case, the onchange returns a warning, and we do not want to add the line at all, so the makeDefaultRecord is rejected. This works fine, but we then have another problem: when we create a new record from scratch, it may happen that a warning is returned (for example, if a vendor has its 'warning on invoice' flag set, then a purchase order is done with this vendor, then confirmed, then the stat button for 'vendor bills' is clicked, which opens a list view with the vendor in the context. Clicking on 'create' will return a warning, which is what we want). In that case, the record still needs to be created. To solve this issue, we simply add an option to the makeDefaultRecord function to prevent rejecting the deferred. --- addons/web/static/src/js/views/basic/basic_model.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 75a0ad02971..dfc8858664d 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -509,6 +509,7 @@ var BasicModel = AbstractModel.extend({ } if (params.type === 'record' && params.res_id === undefined) { + params.allowWarning = true; return this._makeDefaultRecord(params.modelName, params); } var dataPoint = this._makeDataPoint(params); @@ -2735,6 +2736,8 @@ var BasicModel = AbstractModel.extend({ * @private * @param {any} params * @param {string} modelName model name + * @param {boolean} [params.allowWarning=false] if true, the default record + * operation can complete, even if a warning is raised * @param {Object} params.context the context for the new record * @param {Object} params.fieldsInfo contains the fieldInfo of each view, * for each field @@ -2887,7 +2890,11 @@ var BasicModel = AbstractModel.extend({ .then(function () { return self._performOnChange(record, fields_key).then(function () { if (record._warning) { - return $.Deferred().reject(); + if (params.allowWarning) { + delete record._warning; + } else { + return $.Deferred().reject(); + } } }); }) -- cgit v1.2.3 From 2771b23a35c27165b54904a9e433202a5cd226af Mon Sep 17 00:00:00 2001 From: kujiu Date: Tue, 25 Jul 2017 13:43:37 +0200 Subject: [FIX] web: do not delete records for one2many with widget=many2many Some one2many fields are called with a many2many widget to unlink records instead of delete them. But this behavior was modified with the new views and the records were deleted anyway. In this commit, we restore the previous behavior, and create a FORGET command in basic model to do that. Note that the widget='many2many' is a hack, and a better way to accomplish this is to use a new custom option. But this would be a fix for master (PR #18413) --- .../web/static/src/js/views/basic/basic_model.js | 27 +++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index dfc8858664d..8f679207f00 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1295,9 +1295,12 @@ var BasicModel = AbstractModel.extend({ defs.push(this._applyChange(command.id, command.data)); } break; - case 'REMOVE': + case 'FORGET': + // Unlink the record of list. + list._forceM2MUnlink = true; + case 'DELETE': // filter out existing operations involving the current - // dataPoint, and add a 'REMOVE' operation only if there is + // dataPoint, and add a 'DELETE' or 'FORGET' operation only if there is // no 'ADD' operation for that dataPoint, as it would mean // that the record wasn't in the relation yet var idsToRemove = command.ids; @@ -1309,7 +1312,8 @@ var BasicModel = AbstractModel.extend({ return idInCommands; }); _.each(idsToRemove, function (id) { - list._changes.push({operation: 'REMOVE', id: id}); + var operation = list._forceM2MUnlink ? 'FORGET': 'DELETE'; + list._changes.push({operation: operation, id: id}); }); break; case 'REPLACE_WITH': @@ -1333,7 +1337,7 @@ var BasicModel = AbstractModel.extend({ return self.localData[localId]; }); removedDef = this._applyX2ManyChange(record, fieldName, { - operation: 'REMOVE', + operation: 'DELETE', ids: _.map(removedIds, function (resID) { return _.findWhere(listData, {res_id: resID}).id; }), @@ -1350,7 +1354,7 @@ var BasicModel = AbstractModel.extend({ }, /** * In dataPoints of type list for x2manys, the changes are stored as a list - * of operations (being of type 'ADD', 'REMOVE', 'UPDATE' or 'REMOVE_ALL'). + * of operations (being of type 'ADD', 'DELETE', 'FORGET', UPDATE' or 'REMOVE_ALL'). * This function applies the operation of such a dataPoint without altering * the original dataPoint. It returns a copy of the dataPoint in which the * 'count', 'data' and 'res_ids' keys have been updated. @@ -1384,7 +1388,8 @@ var BasicModel = AbstractModel.extend({ list.res_ids.push(resID); } break; - case 'REMOVE': + case 'FORGET': + case 'DELETE': list.count--; list.res_ids = _.without(list.res_ids, relRecord.res_id); break; @@ -2349,7 +2354,11 @@ var BasicModel = AbstractModel.extend({ } // add delete commands for (i = 0; i < removedIds.length; i++) { - commands[fieldName].push(x2ManyCommands.delete(removedIds[i])); + if (list._forceM2MUnlink) { + commands[fieldName].push(x2ManyCommands.forget(removedIds[i])); + } else { + commands[fieldName].push(x2ManyCommands.delete(removedIds[i])); + } } } } @@ -2602,7 +2611,9 @@ var BasicModel = AbstractModel.extend({ var isValid = true; var element = this.localData[id]; _.each(element._changes, function (command) { - if (command.operation === 'REMOVE' || command.operation === 'REMOVE_ALL') { + if (command.operation === 'DELETE' || + command.operation === 'FORGET' || + command.operation === 'REMOVE_ALL') { return; } var recordData = self.get(command.id, {raw: true}).data; -- cgit v1.2.3