Merge PR #2190 into 13.0

Signed-off-by pedrobaeza
pull/2199/head
OCA-git-bot 2022-04-14 16:57:13 +00:00
commit c15b37dcd3
2 changed files with 109 additions and 64 deletions

View File

@ -5,6 +5,7 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
"use strict"; "use strict";
const BasicModel = require("web.BasicModel"); const BasicModel = require("web.BasicModel");
const rpc = require("web.rpc");
function dateToServer(date) { function dateToServer(date) {
return date return date
@ -41,7 +42,8 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
*/ */
_applyX2ManyChange: function(record, fieldName, command) { _applyX2ManyChange: function(record, fieldName, command) {
if (command.operation === "CLONE") { if (command.operation === "CLONE") {
return this._applyX2ManyChangeOmitOnchange.apply(this, arguments); // Return this._applyX2ManyChangeOmitOnchange.apply(this, arguments);
return this._cloneX2Many.apply(this, arguments);
} }
return this._super.apply(this, arguments); return this._super.apply(this, arguments);
}, },
@ -55,62 +57,81 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
* @param {Object} options * @param {Object} options
* @returns {Promise} * @returns {Promise}
*/ */
_applyX2ManyChangeOmitOnchange: function(record, fieldName, command, options) { _cloneX2Many: function(record, fieldName, command, options) {
var localID = const localID =
(record._changes && record._changes[fieldName]) || (record._changes && record._changes[fieldName]) ||
record.data[fieldName]; record.data[fieldName];
var list = this.localData[localID]; const list = this.localData[localID];
var position = (command && command.position) || "top"; const position = (command && command.position) || "bottom";
var viewType = (options && options.viewType) || record.viewType; const viewType = (options && options.viewType) || record.viewType;
var fieldInfo = record.fieldsInfo[viewType][fieldName]; const fieldInfo = record.fieldsInfo[viewType][fieldName];
var view = fieldInfo.views && fieldInfo.views[fieldInfo.mode]; const record_command = this.get(command.id);
var params = {
const params = {
fields: list.fields, fields: list.fields,
fieldsInfo: list.fieldsInfo, fieldsInfo: list.fieldsInfo,
parentID: list.id, parentID: list.id,
position: position, position: position,
viewType: view ? view.type : fieldInfo.viewType,
allowWarning: options && options.allowWarning, allowWarning: options && options.allowWarning,
viewType: viewType,
views: fieldInfo.views,
clone_parent_record_id: command.id,
}; };
if ( let read_data = Promise.resolve();
command.position === "bottom" && if (this.isNew(command.id)) {
list.orderedResIDs && // We need the 'copy_data' of the original parent record
list.orderedResIDs.length >= list.limit if (!_.isEmpty(record_command.clone_data)) {
) { params.clone_copy_data = record_command.clone_copy_data;
list.tempLimitIncrement = (list.tempLimitIncrement || 0) + 1; }
list.limit += 1; } else {
// Record state only has loaded data and only for the fields defined in the views.
// For this reason we need ensure copy all the model fields.
read_data = rpc.query({
model: list.model,
method: "copy_data",
args: [record_command.res_id],
kwargs: {context: record.getContext()},
});
} }
const record_state = this.get(command.id); return read_data.then(result => {
const clone_values = this._getValuesToClone(record_state); const clone_values = _.defaults(
return this._makeDefaultRecordOmitOnchange(list.model, params, clone_values) {},
.then(id => { this._getValuesToClone(record_command, params),
var ids = [id]; result
list._changes = list._changes || []; );
list._changes.push({ return this._makeCloneRecord(list.model, params, clone_values)
operation: "ADD", .then(id => {
id: id, const ids = [id];
position: position, list._changes = list._changes || [];
isNew: true, list._changes.push({
operation: "ADD",
id: id,
position: position,
isNew: true,
});
const record = this.localData[id];
list._cache[record.res_id] = id;
if (list.orderedResIDs) {
const index =
list.offset + (position !== "top" ? list.limit : 0);
list.orderedResIDs.splice(index, 0, record.res_id);
// List could be a copy of the original one
this.localData[list.id].orderedResIDs = list.orderedResIDs;
}
return ids;
})
.then(ids => {
this._readUngroupedList(list).then(() => {
const x2ManysDef = this._fetchX2ManysBatched(list);
const referencesDef = this._fetchReferencesBatched(list);
return Promise.all([x2ManysDef, referencesDef]).then(
() => ids
);
});
}); });
var record = this.localData[id]; });
list._cache[record.res_id] = id;
if (list.orderedResIDs) {
var index = list.offset + (position !== "top" ? list.limit : 0);
list.orderedResIDs.splice(index, 0, record.res_id);
// List could be a copy of the original one
this.localData[list.id].orderedResIDs = list.orderedResIDs;
}
return ids;
})
.then(ids => {
this._readUngroupedList(list).then(() => {
var x2ManysDef = this._fetchX2ManysBatched(list);
var referencesDef = this._fetchReferencesBatched(list);
return Promise.all([x2ManysDef, referencesDef]).then(() => ids);
});
});
}, },
/** /**
@ -160,20 +181,18 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
return Promise.all(defs).then(() => _.keys(changes)); return Promise.all(defs).then(() => _.keys(changes));
}, },
/** _makeCloneRecord: function(modelName, params, values) {
* Modified implementation of '_makeDefaultRecord' to allow create
* without trigger onchanges/default values
*
* @param {String} modelName
* @param {Object} params
* @param {Object} values
* @returns {Promise}
*/
_makeDefaultRecordOmitOnchange: function(modelName, params, values) {
const targetView = params.viewType; const targetView = params.viewType;
let fields = params.fields; let fields = params.fields;
const fieldsInfo = params.fieldsInfo; const fieldsInfo = params.fieldsInfo;
let fieldNames = Object.keys(fieldsInfo[targetView]);
// Get available fields
for (const view_type in params.views) {
fields = _.defaults({}, fields, params.views[view_type].fields);
}
let fieldNames = Object.keys(fields);
// Fields that are present in the originating view, that need to be initialized // Fields that are present in the originating view, that need to be initialized
// Hence preventing their value to crash when getting back to the originating view // Hence preventing their value to crash when getting back to the originating view
const parentRecord = const parentRecord =
@ -202,6 +221,11 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
res_ids: params.res_ids, res_ids: params.res_ids,
viewType: targetView, viewType: targetView,
}); });
// Extend dataPoint with clone info
record.clone_data = {
record_parent_id: params.clone_parent_record_id,
copy_data: params.clone_copy_data || values,
};
// We want to overwrite the default value of the handle field (if any), // We want to overwrite the default value of the handle field (if any),
// in order for new lines to be added at the correct position. // in order for new lines to be added at the correct position.
@ -236,9 +260,10 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
* Get the values formatted to clone * Get the values formatted to clone
* *
* @param {Object} line_state * @param {Object} line_state
* @param {Object} params
* @returns {Object} * @returns {Object}
*/ */
_getValuesToClone: function(line_state) { _getValuesToClone: function(line_state, params) {
const values_to_clone = {}; const values_to_clone = {};
const line_data = line_state.data; const line_data = line_state.data;
for (const field_name in line_data) { for (const field_name in line_data) {
@ -246,7 +271,7 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
continue; continue;
} }
const value = line_data[field_name]; const value = line_data[field_name];
const field_info = line_state.fields[field_name]; const field_info = params.fields[field_name];
if (!field_info) { if (!field_info) {
continue; continue;
} }
@ -255,12 +280,23 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
} else if (field_info.type === "many2one") { } else if (field_info.type === "many2one") {
const rec_id = value.data && value.data.id; const rec_id = value.data && value.data.id;
values_to_clone[field_name] = rec_id || false; values_to_clone[field_name] = rec_id || false;
} else if ( } else if (field_info.type === "many2many") {
field_info.type === "many2many" || values_to_clone[field_name] = [
field_info.type === "one2many" [
) { 6,
0,
_.map(value.data || [], item => {
return item.data.id;
}),
],
];
} else if (field_info.type === "one2many") {
values_to_clone[field_name] = _.map(value.data || [], item => { values_to_clone[field_name] = _.map(value.data || [], item => {
return item.data.id; return [
0,
0,
this._getValuesToClone(item, {fields: value.fields}),
];
}); });
} else if ( } else if (
field_info.type === "date" || field_info.type === "date" ||
@ -273,5 +309,14 @@ odoo.define("web_widget_one2many_tree_line_duplicate.BasicModel", function(requi
} }
return values_to_clone; return values_to_clone;
}, },
_generateChanges: function(record) {
let res = this._super.apply(this, arguments);
if (!_.isEmpty(record.clone_data)) {
// If a cloned record, ensure that all fields are written (and not only the view fields)
res = _.extend({}, record.clone_data.copy_data, res);
}
return res;
},
}); });
}); });

View File

@ -130,7 +130,7 @@ odoo.define(
this._setValue( this._setValue(
{ {
operation: "CLONE", // This operation is a special case implemented only in this module operation: "CLONE", // This operation is a special case implemented only in this module
position: this.editable || data.forceEditable, position: "bottom",
context: data.context, context: data.context,
id: ev.data.id, id: ev.data.id,
}, },