[IMP] web_widget_one2many_product_picker: Add option to ignore onchange warnings

pull/1858/head
Alexandre D. Díaz 2021-02-19 23:56:00 +01:00
parent 8d91637ed9
commit 78fdd8580c
12 changed files with 81 additions and 173 deletions

View File

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

View File

@ -4,7 +4,7 @@
{
'name': 'Web Widget One2Many Product Picker',
'summary': 'Widget to select products on one2many fields',
'version': '12.0.2.2.0',
'version': '12.0.2.3.0',
'category': 'Website',
'author': "Tecnativa, "
"Odoo Community Association (OCA)",

View File

@ -25,7 +25,7 @@ msgstr "Afegir"
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format
msgid "All"
msgstr "Tot"
@ -114,7 +114,7 @@ msgstr "Imatge variant mitjana ( calculada)"
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format
msgid "[No widget %s]"
msgstr "[Sense widget %s]"

View File

@ -25,7 +25,7 @@ msgstr "Añadir"
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format
msgid "All"
msgstr "Todo"
@ -114,7 +114,7 @@ msgstr "Imagen variante media (calculada)"
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format
msgid "[No widget %s]"
msgstr "[Sin widget %s]"

View File

@ -23,7 +23,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format
msgid "All"
msgstr ""
@ -84,12 +84,16 @@ msgstr ""
#. module: web_widget_one2many_product_picker
#: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_medium
msgid "This field holds the image used as image for the product variantor product image medium, limited to 512x512px."
msgid ""
"This field holds the image used as image for the product variantor product "
"image medium, limited to 512x512px."
msgstr ""
#. module: web_widget_one2many_product_picker
#: model:ir.model.fields,help:web_widget_one2many_product_picker.field_product_product__image_variant_big
msgid "This field holds the image used as image for the product variantor product image, limited to 1024x1024px."
msgid ""
"This field holds the image used as image for the product variantor product "
"image, limited to 1024x1024px."
msgstr ""
#. module: web_widget_one2many_product_picker
@ -104,7 +108,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format
msgid "[No widget %s]"
msgstr ""

View File

@ -22,7 +22,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:192
#: code:addons/web_widget_one2many_product_picker/static/src/js/widgets/field_one2many_product_picker.js:193
#, python-format
msgid "All"
msgstr ""
@ -103,7 +103,7 @@ msgstr ""
#. module: web_widget_one2many_product_picker
#. openerp-web
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:340
#: code:addons/web_widget_one2many_product_picker/static/src/js/views/One2ManyProductPicker/record.js:341
#, python-format
msgid "[No widget %s]"
msgstr ""

View File

@ -44,6 +44,8 @@ Widget options:
will lose part of its functionality as the document will be saved every time you
modify/create a record with the widget.
* ignore_warning > Enable/Disable display onchange warnings (False by default)
All widget options are optional.
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
modify/create a record with the widget.</p>
</li>
<li><p class="first">ignore_warning &gt; Enable/Disable display onchange warnings (False by default)</p>
</li>
</ul>
<p>All widget options are optional.
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 () {
var self = this;
var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
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;
this.$card.addClass("blocked");
return model.notifyChanges(record.id, changes).then(function () {
return model.notifyChanges(
record.id,
changes
).then(function () {
self._saveRecord();
});
},
@ -577,11 +581,15 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_incProductQty: function (amount) {
var self = this;
var model = this.options.basicFieldParams.model;
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
var record = model.get(this.state.id);
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
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._lazyUpdateRecord();
});

View File

@ -300,6 +300,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
});
this.$extraButtonsContainer = $(qweb.render("One2ManyProductPicker.ExtraButtons"));
this.$btnLoadMore = this.$extraButtonsContainer.find("#productPickerLoadMore");
this.search_data = this._sort_search_data(this.search_data);
return $.Deferred(function (d) {
var defs = self.appendSearchRecords(self.search_data, true);
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.
* 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,
editPrice: this.options.edit_price,
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)
.then(function (recordID) {
self.setPureVirtual(recordID, true);
self.updateRecordContext(recordID, {ignore_warning: true});
if (options.data) {
self._applyChangeNoWarnings(
self._applyChange(
recordID,
options.data,
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
* @param {Number} recordID
* @param {Object} changes
* @param {Object} options
* @returns {Deferred}
* @override
*/
_applyChangeNoWarnings: function (recordID, changes, options) {
var self = this;
var record = this.localData[recordID];
var field;
var defs = [];
options = options || {};
record._changes = record._changes || {};
if (!options.doNotSetDirty) {
record._isDirty = true;
_performOnChange: function (record, fields, viewType) {
if (record.context && record.context.ignore_warning) {
var this_mp = _.clone(this);
var super_call = this.trigger_up;
this_mp.trigger_up = function (event_name, data) {
if (event_name === 'warning' && data.type === "dialog") {
return; // Do nothing
}
var initialData = {};
this._visitChildren(record, function (elem) {
initialData[elem.id] = $.extend(true, {}, _.pick(elem, 'data', '_changes'));
});
// 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 super_call.apply(this, arguments);
}.bind(this);
return this._super.apply(this_mp, 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;
});
});
return this._super.apply(this, arguments);
},
});

View File

@ -439,7 +439,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
discount: "discount",
},
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._setValue(
{operation: "UPDATE", id: evt.data.id, data: evt.data.data}
{operation: "UPDATE", id: evt.data.id, data: evt.data.data},
).then(function () {
if (evt.data.callback) {
evt.data.callback();
@ -746,7 +746,8 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
*
* @override
*/
_setValue: function () {
_setValue: function (value, options) {
var self = this;
return this._super.apply(this, arguments).then(function () {
self.updateBadgeLines();