This affects the widget handle from OpenERP 7 to Odoo 10.
I would like to ask if it is possible to reload the data from the one2many field in a form view after dragging the record up/down using the widget handle. We've got this working on a list view such that the view gets refreshed each time a record was dragged up/down hence, the new values gets reflected. However, it does not work in form view when I add the one2many field.
This can be tested by doing the following:
1. In Odoo10 project.project object, create a related field for the sequence and have it displayed in the list view under Project/ Configuration/ Projects
2. Drag the records using the widget handle (the plus icon) either up/down. Notice that the related field does not get displayed with the new values. Refreshing the page is the only thing that can be done to view the new value. We had solved this by adding a list.view.reload_contetn(); in the js script but it fails to load in one2many field.
I would like to use this widget to allow users to move records from multiple bank statement records in a form view using one2many field since I need to display 2 tables (2 one2many fields) side by side. As you may know, the bank statement has a concept of rolling bank balance such that the sequence of the record affect the current balance of the succeeding record.
Below is my js code for reference. It is written for openerp 7 using old API. This is working fine for list view.
We have extended the "setup_resequence_rows" function of the web module (web/static/src/js/view_list.js). This executes the method "check_sequence" which is responsible for writing new values. The "list.view.reload_content()" function was called at .done to refresh the list view with new values.
js script
=====================================
openerp.till_reconciliation_ept = function (instance) {
var _t = instance.web._t;
var QWeb = instance.web.qweb;
var Groups_ept = instance.web.ListView.Groups;
instance.web.ListView.Groups.include(/** @lends instance.web.ListView.Groups# */{
passthrough_events: 'action deleted row_link',
setup_resequence_rows: function (list, dataset) {
// drag and drop enabled if list is not sorted and there is a
// visible column with @widget=handle or "sequence" column in the view.
if ((dataset.sort && dataset.sort())
|| !_(this.columns).any(function (column) {
return column.widget === 'handle'
|| column.name === 'sequence';
})) {
return;
}
var sequence_field = _(this.columns).find(function (c) {
return c.widget === 'handle';
});
var seqname = sequence_field ? sequence_field.name : 'sequence';
// ondrop, move relevant record & fix sequences
list.$current.sortable({
axis: 'y',
items: '> tr[data-id]',
helper: 'clone'
});
if (sequence_field) {
list.$current.sortable('option', 'handle', '.oe_list_field_handle');
}
list.$current.sortable('option', {
start: function (e, ui) {
ui.placeholder.height(ui.item.height());
if (dataset.model === 'bank.statement.ept') {
current_record_ept = list.records.get(ui.item.data('id')).attributes
if (current_record_ept) {
if (current_record_ept.state === 'validated') {
alert("You can't change ranking of those records which is in Validate state");
list.view.reload_content()
return;
}
}
}
},
stop: function (event, ui) {
var to_move = list.records.get(ui.item.data('id')),
target_id = ui.item.prev().data('id'),
from_index = list.records.indexOf(to_move),
target = list.records.get(target_id);
if (list.records.at(from_index - 1) == target) {
return;
}
if (dataset.model === 'bank.statement.ept') {
var target_next_id = ui.item.next().data('id')
return dataset.alive(dataset._model.call('check_sequence', [[ui.item.data('id')], target_id, target_next_id], {context: dataset.get_context()}))
.then(function (result) {
if (!result) {
alert("You can't move bank statement across an already validated bank statement.");
list.view.reload_content()
}
// Added additional alert messages whe dragged to different date - Aldennis 19/10/2017
if (result == 3) { alert("You can't move down any record past previous transaction date");
list.view.reload_content()
}
if (result == 2) { alert("You can't move up record past upcoming transaction date");
list.view.reload_content()
}
return result
})
.done(function () {
list.view.reload_content()
})
}
list.records.remove(to_move);
var to = target_id ? list.records.indexOf(target) + 1 : 0;
list.records.add(to_move, {at: to});
// resequencing time!
var record, index = to,
// if drag to 1st row (to = 0), start sequencing from 0
// (exclusive lower bound)
seq = to ? list.records.at(to - 1).get(seqname) : 0;
while (++seq, record = list.records.at(index++)) {
// write are independent from one another, so we can just
// launch them all at the same time and we don't really
// give a fig about when they're done
// FIXME: breaks on o2ms (e.g. Accounting > Financial
// Accounting > Taxes > Taxes, child tax accounts)
// when synchronous (without setTimeout)
(function (dataset, id, seq) {
$.async_when().done(function () {
var attrs = {};
attrs[seqname] = seq;
dataset.write(id, attrs);
});
}(dataset, record.get('id'), seq));
record.set(seqname, seq);
}
}
});
},
});
};
python method
===========================
def check_sequence(self, cr, uid, ids, target_id, target_next_id, context={}):
"""
This method is execute from the sortable widget of JavaScript.
Checking the sequence with to restrict move of transaction between the validated
transaction and resequencing it based on the current operation.
:param cr: the current row, from the database cursor,
:param uid: the current users ID for security checks,
:param ids: ids of object of bank.statement.ept,
:param target_id: previous record of the current moving record,
:param target_next_id: next record of the current moving record,
:param context: context arguments, like lang, time zone,
:return: True if done otherwise return null and raise warning from Javascript.
"""
to_move = self.browse(cr, uid, ids[0], context=context)
order = False
records = []
to_move_process_date = to_move.process_date
if target_next_id :
# While record is moving in between existing records whether it can be down or up.
target = self.browse(cr, uid, target_next_id, context=context)
to_move_seq = to_move.sequence
to_index = target.sequence
if to_move_seq > to_index :
# While moving record down.
order = 'movedown'
bank_statement_ids = self.search(cr, uid, [('sequence','>', to_index), ('sequence','<', to_move_seq), ('state','=','validated')], limit=1)
if bank_statement_ids :
return;
target = self.browse(cr, uid, target_id, context=context)
to_move_seq = to_move.sequence
to_index = target.sequence
target_process_date = target.process_date
# Prevent moving down record past any record with previous date - Aldennis
if to_move_process_date > target_process_date:
return 3
records_to_modify = to_move_seq - to_index
if records_to_modify == 1:
self.write(cr, uid, ids, {'sequence': to_move_seq - 1}, context=context)
self.write(cr, uid, [target_id], {'sequence': to_move_seq}, context=context)
return True
self.write(cr, uid, ids, {'sequence': to_index}, context=context)
records = self.search(cr, uid, [('id', 'not in', ids), ('sequence','>=', to_index), ('sequence','<', to_move_seq)])
else :
# While moving record up.
order = 'moveup'
target = self.browse(cr, uid, target_next_id, context=context)
to_move_seq = to_move.sequence
to_index = target.sequence
target_process_date = target.process_date
bank_statement_ids = self.search(cr, uid, [('sequence','>', to_move_seq), ('sequence','<', to_index), ('state','=','validated')], limit=1)
if bank_statement_ids :
return;
# Prevent moving up record past any record with upcoming date - Aldennis
if to_move_process_date < target_process_date:
return 2
records_to_modify = to_index - to_move_seq
if records_to_modify == 1:
self.write(cr, uid, ids, {'sequence': to_move_seq + 1}, context=context)
self.write(cr, uid, [target_next_id], {'sequence': to_move_seq}, context=context)
return True
self.write(cr, uid, ids, {'sequence': to_index}, context=context)
records = self.search(cr, uid, [('id', 'not in', ids), ('sequence', '>', to_move_seq), ('sequence','<=', to_index)])
else:
# While record is moving at the last of view.
order = 'movedown'
to_seq = to_move.sequence
bank_statement_ids = self.search(cr, uid, [('sequence', '<', to_seq), ('state', '=', 'validated')], limit=1)
if bank_statement_ids:
return;
self.write(cr, uid, ids, {'sequence': 0}, context=context)
records = self.search(cr, uid, [('id', 'not in', ids), ('sequence', '>=', 0), ('sequence','<=', to_seq)])
self.re_allocate_sequence(cr, uid, records, order, context=context)
# Recalculate all subsequent records balance
self._compute_balance(cr, uid, records, ['balance','calculate_balance'], args=None, context=context)
return True
Reorder records in tree view using handle widget: https://learnopenerp.blogspot.com/2022/05/use-handle-widget-to-reorder-records-in-tree-view-odoo15.html