[FIX] web_widget_one2many_product_picker: Auto save

pull/1825/head
Alexandre D. Díaz 2021-02-17 19:01:53 +01:00
parent c78bdf4acc
commit 94c8c6553b
5 changed files with 138 additions and 32 deletions

View File

@ -179,6 +179,7 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickModifPriceForm
this.trigger_up("update_quick_record", { this.trigger_up("update_quick_record", {
id: record.id, id: record.id,
}); });
self.model.unsetDirty(self.handle);
this.getParent().destroy(); this.getParent().destroy();
} }
}, },

View File

@ -213,6 +213,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
is_virtual: this.is_virtual, is_virtual: this.is_virtual,
modified: record && record.context.product_picker_modified, modified: record && record.context.product_picker_modified,
active_model: '', active_model: '',
auto_save: this.options.autoSave,
}; };
}, },
@ -493,11 +494,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_calcPriceReduced: function () { _calcPriceReduced: function () {
var price_reduce = 0; var price_reduce = 0;
var field_map = this.options.fieldMap; var field_map = this.options.fieldMap;
var state_data = this.state.data; var model = this.options.basicFieldParams.model;
if (state_data && state_data[field_map.discount]) { var record = model.get(this.state.id);
if (record && record.data[field_map.discount]) {
price_reduce = tools.priceReduce( price_reduce = tools.priceReduce(
state_data[field_map.price_unit], record.data[field_map.price_unit],
state_data[field_map.discount]); record.data[field_map.discount]);
} }
return price_reduce && tools.monetary( return price_reduce && tools.monetary(
price_reduce, price_reduce,
@ -516,28 +518,36 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
var record = model.get(this.state.id); var record = model.get(this.state.id);
return model.save(record.id, { return model.save(record.id, {
stayInEdit: true,
reload: true,
savePoint: true, savePoint: true,
viewType: "form",
}).then(function () { }).then(function () {
var record = model.get(self.state.id); var record = model.get(self.state.id);
self.trigger_up("create_quick_record", { self.trigger_up("create_quick_record", {
id: record.id, id: record.id,
callback: function () {
self.$card.find('.o_catch_attention').removeClass('o_catch_attention');
}
}); });
model.unsetDirty(self.state.id); model.unsetDirty(self.state.id);
self.$card.find('.o_catch_attention').removeClass('o_catch_attention');
}); });
}, },
/** /**
* @private * @private
*/ */
_updateRecord: function (changes) { _updateRecord: function () {
var self = this;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
var record = model.get(this.state.id); var record = model.get(this.state.id);
this.trigger_up("update_quick_record", { this.trigger_up("update_quick_record", {
id: record.id, id: record.id,
callback: function () {
self.$card.find('.o_catch_attention').removeClass('o_catch_attention');
}
}); });
model.unsetDirty(this.state.id); model.unsetDirty(this.state.id);
this.$card.find('.o_catch_attention').removeClass('o_catch_attention');
}, },
/** /**
@ -546,13 +556,15 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
*/ */
_addProduct: function () { _addProduct: function () {
var self = this; var self = this;
var changes = {}; var model = this.options.basicFieldParams.model;
if (this.state.data[this.options.fieldMap.product_uom_qty] === 0) { 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) {
changes[this.options.fieldMap.product_uom_qty] = 1; changes[this.options.fieldMap.product_uom_qty] = 1;
} }
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
this.$card.addClass("blocked"); this.$card.addClass("blocked");
return model.notifyChanges(this.state.id, changes).then(function () { return model.notifyChanges(record.id, changes).then(function () {
self._saveRecord(); self._saveRecord();
}); });
}, },
@ -564,12 +576,10 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
*/ */
_incProductQty: function (amount) { _incProductQty: function (amount) {
var self = this; var self = this;
this.state.data[this.options.fieldMap.product_uom_qty] += amount;
var model = this.options.basicFieldParams.model; var model = this.options.basicFieldParams.model;
var record = model.get(this.state.id); var record = model.get(this.state.id);
var state_data = record.data; var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
state_data[this.options.fieldMap.product_uom_qty] += amount; changes[this.options.fieldMap.product_uom_qty] += amount;
var changes = _.pick(state_data, this.options.fieldMap.product_uom_qty);
return model.notifyChanges(record.id, changes).then(function () { return model.notifyChanges(record.id, changes).then(function () {
self._processDynamicFields(); self._processDynamicFields();

View File

@ -104,8 +104,10 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
*/ */
updateState: function (state, params) { updateState: function (state, params) {
var self = this; var self = this;
var force_update = params.force;
delete params.force;
var sparams = _.extend({}, params, {noRender: true}); var sparams = _.extend({}, params, {noRender: true});
if (_.isEqual(this.state.data, state.data)) { if (!force_update && _.isEqual(this.state.data, state.data)) {
return this._super(state, sparams); return this._super(state, sparams);
} }
var old_state = _.clone(this.state.data); var old_state = _.clone(this.state.data);
@ -114,6 +116,22 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
}); });
}, },
/**
* Recreate the given widget by the state id
*
* @param {String} state_id
* @param {Object} new_state
*/
updateRecord: function (state_id, new_state) {
for (var eb = this.widgets.length-1; eb>=0; --eb) {
var widget = this.widgets[eb];
if (widget.state.id === state_id) {
widget.recreate(new_state);
break;
}
}
},
/** /**
* @private * @private
* @param {Array[Object]} states * @param {Array[Object]} states
@ -206,7 +224,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
var found = false; var found = false;
for (var e in this.state.data) { for (var e in this.state.data) {
var current_state = this.state.data[e]; var current_state = this.state.data[e];
if (current_state.id === old_state.id || (typeof current_state.data.id !== 'undefined' && current_state.data.id === old_state.data.id)) { if (current_state.id === old_state.id) {
found = true; found = true;
break; break;
} }
@ -215,6 +233,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
states_to_destroy.push(old_state); states_to_destroy.push(old_state);
} }
} }
this.state.data = _.compact(this.state.data);
this._removeRecords(states_to_destroy, this.state.data); this._removeRecords(states_to_destroy, this.state.data);
// Records to Update or Create // Records to Update or Create
@ -232,7 +252,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
// Already processed widget (deleted) // Already processed widget (deleted)
continue; continue;
} }
if (widget.state.id === state.id || (typeof state.data.id !== 'undefined' && widget.state.data.id === state.data.id)) { if (widget.state.id === state.id) {
widget.recreate(state); widget.recreate(state);
exists = true; exists = true;
break; break;
@ -255,6 +275,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
} }
} }
this.state.data = _.compact(this.state.data);
// Need add a new one? // Need add a new one?
if (!exists && search_record_index !== -1) { if (!exists && search_record_index !== -1) {
var new_search_record = _.extend({}, search_record, {__id: state.id}); var new_search_record = _.extend({}, search_record, {__id: state.id});
@ -362,6 +384,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
showDiscount: this.options.show_discount, showDiscount: this.options.show_discount,
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,
}); });
}, },

View File

@ -37,6 +37,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
update_subtotal: "_onUpdateSubtotal", update_subtotal: "_onUpdateSubtotal",
load_more: "_onLoadMore", load_more: "_onLoadMore",
loading_records: "_onLoadingRecords", loading_records: "_onLoadingRecords",
list_record_remove: "_onListRecordRemove",
}), }),
_auto_search_delay: 450, _auto_search_delay: 450,
@ -438,6 +439,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
discount: "discount", discount: "discount",
}, },
auto_save: false, auto_save: false,
allow_warning: true,
}; };
}, },
@ -525,7 +527,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
'name': 'main_lines', 'name': 'main_lines',
}; };
this._searchContext.domain = this._getLinesDomain(); this._searchContext.domain = this._getLinesDomain();
this._searchContext.order = false; this._searchContext.order = [{'name': 'sequence'}, {'name': 'id'}];
this._searchContext.activeTest = false; this._searchContext.activeTest = false;
this.doRenderSearchRecords(); this.doRenderSearchRecords();
}, },
@ -580,20 +582,45 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
* @param {CustomEvent} evt * @param {CustomEvent} evt
*/ */
_onCreateQuickRecord: function (evt) { _onCreateQuickRecord: function (evt) {
evt.stopPropagation();
var self = this; var self = this;
this.parent_controller.model.setPureVirtual(evt.data.id, false); this.parent_controller.model.setPureVirtual(evt.data.id, false);
if (!self.options.auto_save) {
self.parent_controller.model.updateRecordContext(evt.data.id, { if (this.options.auto_save) {
// Dont trigger state update
this._setValue(
{operation: "ADD", id: evt.data.id},
{notifyChange: false}
).then(function () {
if (self.options.auto_save) {
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function (rrr) {
// Because 'create' generates a new state and we can't know these new id we
// need force update the all the current states.
self._setValue(
{operation: "UPDATE", id: evt.data.id},
{doNotSetDirty: true}
).then(function () {
if (evt.data.callback) {
evt.data.callback();
}
});
});
} else if (evt.data.callback) {
evt.data.callback();
}
});
} else {
// This is used to know when need use 'yellow' color
this.parent_controller.model.updateRecordContext(evt.data.id, {
product_picker_modified: true, product_picker_modified: true,
}); });
} // This will trigger an "state" update
this._setValue({operation: "ADD", id: evt.data.id}).then(function () { this._setValue({operation: "ADD", id: evt.data.id}).then(function () {
if (self.options.auto_save) { if (evt.data.callback) {
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () { evt.data.callback();
self.renderer.updateState(self.value);
});
} }
}); });
}
}, },
/** /**
@ -603,17 +630,62 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
* @param {CustomEevent} evt * @param {CustomEevent} evt
*/ */
_onUpdateQuickRecord: function (evt) { _onUpdateQuickRecord: function (evt) {
evt.stopPropagation();
var self = this; var self = this;
if (!self.options.auto_save) {
self.parent_controller.model.updateRecordContext(evt.data.id, { if (this.options.auto_save) {
product_picker_modified: true, // Dont trigger state update
}); this._setValue(
} {operation: "UPDATE", id: evt.data.id, data: evt.data.data},
this._setValue({operation: "UPDATE", id: evt.data.id, data: evt.data.data}).then(function () { {notifyChange: false}
).then(function () {
if (self.options.auto_save) { if (self.options.auto_save) {
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () { self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () {
self.renderer.updateState(self.value); // Workaround to get updated values
self.parent_controller.model.reload(self.value.id).then(function (result) {
var new_data = self.parent_controller.model.get(result);
self.value.data = new_data.data;
self.renderer.updateState(self.value, {force: true});
if (evt.data.callback) {
evt.data.callback();
}
}); });
});
} else if (evt.data.callback) {
evt.data.callback();
}
});
} else {
// This is used to know when need use 'yellow' color
this.parent_controller.model.updateRecordContext(evt.data.id, {
product_picker_modified: true,
});
// This will trigger an "state" update
this._setValue(
{operation: "UPDATE", id: evt.data.id, data: evt.data.data}
).then(function () {
if (evt.data.callback) {
evt.data.callback();
}
});
}
},
/**
* Handle auto_save when remove a record
*/
_onListRecordRemove: function (evt) {
evt.stopPropagation();
var self = this;
this._setValue({operation: "DELETE", ids: [evt.data.id]}).then(function () {
if (self.options.auto_save) {
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () {
if (evt.data.callback) {
evt.data.callback();
}
});
} else if (evt.data.callback) {
evt.data.callback();
} }
}); });
}, },

View File

@ -70,7 +70,7 @@
<t t-name="One2ManyProductPicker.FlipCard"> <t t-name="One2ManyProductPicker.FlipCard">
<div class="oe_flip_container p-1 col-12 col-sm-8 col-md-6 col-lg-4 col-xl-3 col-xxl-2"> <div class="oe_flip_container p-1 col-12 col-sm-8 col-md-6 col-lg-4 col-xl-3 col-xxl-2">
<div t-attf-class="oe_flip_card {{!state &amp;&amp; 'disabled' || ''}}"> <div t-attf-class="oe_flip_card {{!state &amp;&amp; 'disabled' || (auto_save &amp;&amp; !is_virtual &amp;&amp; !state.data.id &amp;&amp; 'blocked') || ''}}">
<div class="oe_flip_card_inner text-center"> <div class="oe_flip_card_inner text-center">
<div t-attf-class="oe_flip_card_front p-0 {{(modified &amp;&amp; 'border-warning') || (state &amp;&amp; !is_virtual &amp;&amp; 'border-success') || ''}}"> <div t-attf-class="oe_flip_card_front p-0 {{(modified &amp;&amp; 'border-warning') || (state &amp;&amp; !is_virtual &amp;&amp; 'border-success') || ''}}">
<t t-if="state"> <t t-if="state">