3
0
Fork 0

[IMP] web_widget_one2many_product_picker: Add option to ignore onchange warnings

12.0
Alexandre D. Díaz 2021-02-19 23:56:00 +01:00
parent 94c8c6553b
commit b72d8bd8cc
7 changed files with 65 additions and 161 deletions

View File

@ -86,6 +86,8 @@ Widget options:
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget. modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
All widget options are optional. All widget options are optional.
Notice that you can call '_' method to use translations. This only can be used with this widget. Notice that you can call '_' method to use translations. This only can be used with this widget.

View File

@ -44,6 +44,8 @@ Widget options:
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget. modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
All widget options are optional. All widget options are optional.
Notice that you can call '_' method to use translations. This only can be used with this widget. Notice that you can call '_' method to use translations. This only can be used with this widget.

View File

@ -471,6 +471,8 @@ You need to define the view fields. The view must be of <tt class="docutils lite
will lose part of its functionality as the document will be saved every time you will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget.</p> modify/create a record with the widget.</p>
</li> </li>
<li><p class="first">ignore_warning &gt; Enable/Disable display onchange warnings (False by default)</p>
</li>
</ul> </ul>
<p>All widget options are optional. <p>All widget options are optional.
Notice that you can call _ method to use translations. This only can be used with this widget.</p> Notice that you can call _ method to use translations. This only can be used with this widget.</p>

View File

@ -557,6 +557,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_addProduct: function () { _addProduct: function () {
var self = this; var self = this;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id); var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty); var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
if (changes[this.options.fieldMap.product_uom_qty] === 0) { if (changes[this.options.fieldMap.product_uom_qty] === 0) {
@ -564,7 +565,10 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
} }
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
this.$card.addClass("blocked"); this.$card.addClass("blocked");
return model.notifyChanges(record.id, changes).then(function () { return model.notifyChanges(
record.id,
changes
).then(function () {
self._saveRecord(); self._saveRecord();
}); });
}, },
@ -577,11 +581,15 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_incProductQty: function (amount) { _incProductQty: function (amount) {
var self = this; var self = this;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id); var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty); var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
changes[this.options.fieldMap.product_uom_qty] += amount; changes[this.options.fieldMap.product_uom_qty] += amount;
return model.notifyChanges(record.id, changes).then(function () { return model.notifyChanges(
record.id,
changes
).then(function () {
self._processDynamicFields(); self._processDynamicFields();
self._lazyUpdateRecord(); self._lazyUpdateRecord();
}); });

View File

@ -300,6 +300,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
}); });
this.$extraButtonsContainer = $(qweb.render("One2ManyProductPicker.ExtraButtons")); this.$extraButtonsContainer = $(qweb.render("One2ManyProductPicker.ExtraButtons"));
this.$btnLoadMore = this.$extraButtonsContainer.find("#productPickerLoadMore"); this.$btnLoadMore = this.$extraButtonsContainer.find("#productPickerLoadMore");
this.search_data = this._sort_search_data(this.search_data);
return $.Deferred(function (d) { return $.Deferred(function (d) {
var defs = self.appendSearchRecords(self.search_data, true); var defs = self.appendSearchRecords(self.search_data, true);
defs[0].then(function () { defs[0].then(function () {
@ -316,6 +317,31 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
}); });
}, },
/**
* @param {Array} datas
* @returns {Array}
*/
_sort_search_data: function (datas) {
if (this.search_group.name === "main_lines") {
var field_name = this.options.field_map.product;
for (var index_datas in datas) {
var data = datas[index_datas];
for (var index_state in this.state.data) {
var state_data = this.state.data[index_state];
if (state_data.data[field_name].res_id === data.id) {
data._order_value = state_data.res_id;
}
}
}
var sorted_datas = _.chain(datas).sortBy('_order_value').map(function(item) {
return _.omit(item, '_order_value');
}).value().reverse();
return sorted_datas;
}
return datas;
},
/** /**
* Compare search results with current lines. * Compare search results with current lines.
* Link a current state with the 'search record'. * Link a current state with the 'search record'.
@ -385,6 +411,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
editDiscount: this.options.edit_discount, editDiscount: this.options.edit_discount,
editPrice: this.options.edit_price, editPrice: this.options.edit_price,
autoSave: this.options.auto_save, autoSave: this.options.auto_save,
ignoreWarning: this.options.ignore_warning,
}); });
}, },

View File

@ -79,8 +79,9 @@ odoo.define("web_widget_one2many_product_picker.BasicModel", function (require)
self._makeDefaultRecord(list.model, params) self._makeDefaultRecord(list.model, params)
.then(function (recordID) { .then(function (recordID) {
self.setPureVirtual(recordID, true); self.setPureVirtual(recordID, true);
self.updateRecordContext(recordID, {ignore_warning: true});
if (options.data) { if (options.data) {
self._applyChangeNoWarnings( self._applyChange(
recordID, recordID,
options.data, options.data,
params params
@ -95,165 +96,26 @@ odoo.define("web_widget_one2many_product_picker.BasicModel", function (require)
}, },
/** /**
* Cloned '_applyChange' but without warning messages * Adds support to avoid show onchange warnings.
* The implementation is a pure hack that clone
* the context and do a monkey path the
* 'trigger_up' method.
* *
* @private * @override
* @param {Number} recordID
* @param {Object} changes
* @param {Object} options
* @returns {Deferred}
*/ */
_applyChangeNoWarnings: function (recordID, changes, options) { _performOnChange: function (record, fields, viewType) {
var self = this; if (record.context && record.context.ignore_warning) {
var record = this.localData[recordID]; var this_mp = _.clone(this);
var field; var super_call = this.trigger_up;
var defs = []; this_mp.trigger_up = function (event_name, data) {
options = options || {}; if (event_name === 'warning' && data.type === "dialog") {
record._changes = record._changes || {}; return; // Do nothing
if (!options.doNotSetDirty) {
record._isDirty = true;
} }
var initialData = {}; return super_call.apply(this, arguments);
this._visitChildren(record, function (elem) { }.bind(this);
initialData[elem.id] = $.extend(true, {}, _.pick(elem, 'data', '_changes')); return this._super.apply(this_mp, arguments);
});
// Apply changes to local data
for (var fieldName in changes) {
field = record.fields[fieldName];
if (field && (field.type === 'one2many' || field.type === 'many2many')) {
defs.push(this._applyX2ManyChange(
record,
fieldName,
changes[fieldName],
options.viewType,
options.allowWarning));
} else if (field && (field.type === 'many2one' || field.type === 'reference')) {
defs.push(this._applyX2OneChange(record, fieldName, changes[fieldName]));
} else {
record._changes[fieldName] = changes[fieldName];
} }
} return this._super.apply(this, arguments);
if (options.notifyChange === false) {
return $.Deferred().resolve(_.keys(changes));
}
return $.when.apply($, defs).then(function () {
// The fields that have changed and that have an on_change
var onChangeFields = [];
for (var fieldName in changes) {
field = record.fields[fieldName];
if (field && field.onChange) {
var isX2Many = (
field.type === 'one2many' ||
field.type === 'many2many'
);
if (
!isX2Many ||
(
self._isX2ManyValid(
record._changes[fieldName] ||
record.data[fieldName]
)
)
) {
onChangeFields.push(fieldName);
}
}
}
var onchangeDef = $.Deferred();
if (onChangeFields.length) {
self._performOnChangeNoWarnings(record, onChangeFields, options.viewType)
.then(function (result) {
delete record._warning;
onchangeDef.resolve(
_.keys(changes).concat(
Object.keys((result && result.value) || {})));
}).fail(function () {
self._visitChildren(record, function (elem) {
_.extend(elem, initialData[elem.id]);
});
// Safe fix for stable version, for opw-2267444
if (!options.force_fail) {
onchangeDef.resolve({});
} else {
onchangeDef.reject({});
}
});
} else {
onchangeDef = $.Deferred().resolve(_.keys(changes));
}
return onchangeDef.then(function (fieldNames) {
_.each(fieldNames, function (name) {
if (
record._changes &&
record._changes[name] === record.data[name]
) {
delete record._changes[name];
record._isDirty = !_.isEmpty(record._changes);
}
});
return self._fetchSpecialData(record).then(function (fieldNames2) {
// Return the names of the fields that changed (onchange or
// associated special data change)
return _.union(fieldNames, fieldNames2);
});
});
});
},
/**
* Cloned '_performOnChange' but without warning messages
*
* @private
* @param {Object} record
* @param {Object} fields
* @param {String} viewType
* @returns {Deferred}
*/
_performOnChangeNoWarnings: function (record, fields, viewType) {
var self = this;
var onchangeSpec = this._buildOnchangeSpecs(record, viewType);
if (!onchangeSpec) {
return $.when();
}
var idList = record.data.id ? [record.data.id] : [];
var options = {
full: true,
};
if (fields.length === 1) {
fields = fields[0];
// If only one field changed, add its context to the RPC context
options.fieldName = fields;
}
var context = this._getContext(record, options);
var currentData = this._generateOnChangeData(record, {changesOnly: false});
return self._rpc({
model: record.model,
method: 'onchange',
args: [idList, currentData, fields, onchangeSpec, context],
}).then(function (result) {
if (!record._changes) {
// If the _changes key does not exist anymore, it means that
// it was removed by discarding the changes after the rpc
// to onchange. So, in that case, the proper response is to
// ignore the onchange.
return;
}
if (result.domain) {
record._domains = _.extend(record._domains, result.domain);
}
return self._applyOnChange(result.value, record).then(function () {
return result;
});
});
}, },
}); });

View File

@ -439,7 +439,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
discount: "discount", discount: "discount",
}, },
auto_save: false, auto_save: false,
allow_warning: true, ignore_warning: false,
}; };
}, },
@ -662,7 +662,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
}); });
// This will trigger an "state" update // This will trigger an "state" update
this._setValue( this._setValue(
{operation: "UPDATE", id: evt.data.id, data: evt.data.data} {operation: "UPDATE", id: evt.data.id, data: evt.data.data},
).then(function () { ).then(function () {
if (evt.data.callback) { if (evt.data.callback) {
evt.data.callback(); evt.data.callback();
@ -746,7 +746,8 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
* *
* @override * @override
*/ */
_setValue: function () {
_setValue: function (value, options) {
var self = this; var self = this;
return this._super.apply(this, arguments).then(function () { return this._super.apply(this, arguments).then(function () {
self.updateBadgeLines(); self.updateBadgeLines();