forked from Techsystech/web
[IMP] web_widget_one2many_product_picker: Add option to ignore onchange warnings
parent
94c8c6553b
commit
b72d8bd8cc
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 > 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>
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue