From 6d852c6f481c72ae0c0b6f99d02a18740dee70e3 Mon Sep 17 00:00:00 2001 From: MonsieurB Date: Tue, 11 Dec 2018 11:42:12 +0100 Subject: [PATCH] merge pr #1253 --- onchange_helper/README.rst | 11 ++++ onchange_helper/models/__init__.py | 1 - onchange_helper/models/base.py | 86 +++++++++++++++--------------- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/onchange_helper/README.rst b/onchange_helper/README.rst index 622fbe8dd..7d70feca6 100644 --- a/onchange_helper/README.rst +++ b/onchange_helper/README.rst @@ -24,6 +24,17 @@ Example if you want to create a sale order and you want to get the values relati Then, `vals` will be updated with partner_invoice_id, partner_shipping_id, pricelist_id, etc... +You can also use it on existing record for example: + + `vals = {'partner_shipping_id': 1}` + + `vals = sale.play_onchanges(vals, ['partner_shipping_id'])` + +Then the onchange will be played with the vals passed and the existing vals of the sale. `vals` will be updated with partner_invoice_id, pricelist_id, etc.. + + +Behind the scene, `play_onchanges` will execute **all the methods** registered for the list of changed fields, so you do not have to call manually each onchange. To avoid performance issue when the method is called on a record, the record will be transformed into a memory record before calling the registered methods to avoid to trigger SQL updates command when values are assigned to the record by the onchange + Bug Tracker =========== diff --git a/onchange_helper/models/__init__.py b/onchange_helper/models/__init__.py index 08f5a5618..2c7ece331 100644 --- a/onchange_helper/models/__init__.py +++ b/onchange_helper/models/__init__.py @@ -1,3 +1,2 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - from . import base diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index fdc0457a3..8386567f6 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -2,50 +2,52 @@ # Copyright 2016-2017 Camptocamp (http://www.camptocamp.com/) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, models - - -def get_new_values(model, record, on_change_result): - vals = on_change_result.get('value', {}) - new_values = {} - for fieldname, value in vals.items(): - if fieldname not in record: - column = model._fields[fieldname] - if value and column.type == 'many2one': - value = value[0] # many2one are tuple (id, name) - new_values[fieldname] = value - return new_values - - -@api.model -def play_onchanges(self, values, onchange_fields): - onchange_specs = self._onchange_spec() - # we need all fields in the dict even the empty ones - # otherwise 'onchange()' will not apply changes to them - all_values = values.copy() - for field in self._fields: - if field not in all_values: - all_values[field] = False - - # we work on a temporary record - new_record = self.new(all_values) - - new_values = {} - for field in onchange_fields: - onchange_values = new_record.onchange(all_values, - field, onchange_specs) - new_values.update(get_new_values(self, values, onchange_values)) - all_values.update(new_values) - - res = {f: v for f, v in all_values.items() - if f in values or f in new_values} - return res +from odoo import api, models class Base(models.AbstractModel): _inherit = 'base' - def _setup_complete(self): - if not hasattr(models.BaseModel, 'play_onchanges'): - setattr(models.BaseModel, 'play_onchanges', play_onchanges) - return super(Base, self)._setup_complete() + @api.model + def _get_new_values(self, record, on_change_result): + vals = on_change_result.get('value', {}) + new_values = {} + for fieldname, value in vals.iteritems(): + if fieldname not in record: + column = self._fields[fieldname] + if value and column.type == 'many2one': + value = value[0] # many2one are tuple (id, name) + new_values[fieldname] = value + return new_values + + def play_onchanges(self, values, onchange_fields): + onchange_specs = self._onchange_spec() + # we need all fields in the dict even the empty ones + # otherwise 'onchange()' will not apply changes to them + all_values = values.copy() + for field in self._fields: + if field not in all_values: + all_values[field] = False + + # If self is a record (play onchange on existing record) + # we take the value of the field + # If self is an empty record we will have an empty value + if self: + self.ensure_one() + record_values = self._convert_to_write(self.read()[0]) + else: + record_values = {} + for field in self._fields: + if field not in all_values: + all_values[field] = record_values.get(field, False) + + new_values = {} + for field in onchange_fields: + onchange_values = self.onchange(all_values, field, onchange_specs) + new_values.update(self._get_new_values(values, onchange_values)) + all_values.update(new_values) + + return { + f: v for f, v in all_values.iteritems() + if not self._fields[f].compute + and (f in values or f in new_values)}