From 07d9f3e078ec6af8db8e27d1f6d00cbfbaf36f73 Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Fri, 4 Nov 2016 19:15:35 +0100 Subject: [PATCH 01/15] Add onchange_helper module --- onchange_helper/README.rst | 67 ++++++++++++++++++++++++++++++ onchange_helper/__init__.py | 4 ++ onchange_helper/__openerp__.py | 15 +++++++ onchange_helper/models/__init__.py | 4 ++ onchange_helper/models/ir_rule.py | 50 ++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 onchange_helper/README.rst create mode 100644 onchange_helper/__init__.py create mode 100644 onchange_helper/__openerp__.py create mode 100644 onchange_helper/models/__init__.py create mode 100644 onchange_helper/models/ir_rule.py diff --git a/onchange_helper/README.rst b/onchange_helper/README.rst new file mode 100644 index 000000000..3af53e567 --- /dev/null +++ b/onchange_helper/README.rst @@ -0,0 +1,67 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=============== +Onchange Helper +=============== + +This is a technical module. Its goal is to ease the play of onchange method directly called from python file. + +Usage +===== + +To use this module, you need to: + +* depend on this module +* call `yourmodel.play_onchanges(values, ['field'])` + +Example if you want to create a sale order and you want to get the values relative to partner_id field (as if you fill the field from UI) + + `vals = {'partner_id: 1'}` + + `vals = self.env['sale.order'].play_onchange(vals, ['partner_id'])` + +Then, `vals` will be updated with partner_invoice_id, partner_shipping_id, pricelist_id, etc... + +For further information, please visit: + +* https://www.odoo.com/forum/help-1 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Guewen Baconnier +* Florian da Costa + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. + diff --git a/onchange_helper/__init__.py b/onchange_helper/__init__.py new file mode 100644 index 000000000..8d0394448 --- /dev/null +++ b/onchange_helper/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models diff --git a/onchange_helper/__openerp__.py b/onchange_helper/__openerp__.py new file mode 100644 index 000000000..abf6e1e85 --- /dev/null +++ b/onchange_helper/__openerp__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{'name': 'Onchange Helper', + 'version': '9.0.1.0.0', + 'author': 'Akretion,Camp2camp,Odoo Community Association (OCA)', + 'website': 'www.akretion.com', + 'license': 'AGPL-3', + 'category': 'Generic Modules', + 'depends': [ + 'base', + ], + 'installable': True, + } diff --git a/onchange_helper/models/__init__.py b/onchange_helper/models/__init__.py new file mode 100644 index 000000000..25bec87f2 --- /dev/null +++ b/onchange_helper/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import ir_rule diff --git a/onchange_helper/models/ir_rule.py b/onchange_helper/models/ir_rule.py new file mode 100644 index 000000000..ec751bc28 --- /dev/null +++ b/onchange_helper/models/ir_rule.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp 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.iteritems(): + if fieldname not in record: + column = model._fields[fieldname] + if 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.iteritems() + if f in values or f in new_values} + return res + + +class IrRule(models.Model): + _inherit = 'ir.rule' + + def _setup_complete(self, cr, uid): + if not hasattr(models.BaseModel, 'play_onchanges'): + setattr(models.BaseModel, 'play_onchanges', play_onchanges) + return super(IrRule, self)._setup_complete(cr, uid) From d92f334b8cdcc6191b59ddf3bbc9bae4ef90df70 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 27 Feb 2017 14:11:58 +0100 Subject: [PATCH 02/15] [MIG] module onchange_helper to v10.0 --- onchange_helper/README.rst | 8 ++------ onchange_helper/__init__.py | 3 +-- onchange_helper/__manifest__.py | 14 ++++++++++++++ onchange_helper/__openerp__.py | 15 --------------- onchange_helper/models/__init__.py | 3 +-- onchange_helper/models/ir_rule.py | 10 ++++++---- 6 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 onchange_helper/__manifest__.py delete mode 100644 onchange_helper/__openerp__.py diff --git a/onchange_helper/README.rst b/onchange_helper/README.rst index 3af53e567..48cca771e 100644 --- a/onchange_helper/README.rst +++ b/onchange_helper/README.rst @@ -6,7 +6,7 @@ Onchange Helper =============== -This is a technical module. Its goal is to ease the play of onchange method directly called from python file. +This is a technical module. Its goal is to ease the play of onchange method directly called from Python code. Usage ===== @@ -20,14 +20,10 @@ Example if you want to create a sale order and you want to get the values relati `vals = {'partner_id: 1'}` - `vals = self.env['sale.order'].play_onchange(vals, ['partner_id'])` + `vals = self.env['sale.order'].play_onchanges(vals, ['partner_id'])` Then, `vals` will be updated with partner_invoice_id, partner_shipping_id, pricelist_id, etc... -For further information, please visit: - -* https://www.odoo.com/forum/help-1 - Bug Tracker =========== diff --git a/onchange_helper/__init__.py b/onchange_helper/__init__.py index 8d0394448..cde864bae 100644 --- a/onchange_helper/__init__.py +++ b/onchange_helper/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import models diff --git a/onchange_helper/__manifest__.py b/onchange_helper/__manifest__.py new file mode 100644 index 000000000..0d1b9b6a1 --- /dev/null +++ b/onchange_helper/__manifest__.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# © 2016-2017 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{'name': 'Onchange Helper', + 'version': '10.0.1.0.0', + 'summary': 'Technical module that ease execution of onchange in Python code', + 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', + 'website': 'http://www.akretion.com', + 'license': 'AGPL-3', + 'category': 'Generic Modules', + 'depends': ['base'], + 'installable': True, + } diff --git a/onchange_helper/__openerp__.py b/onchange_helper/__openerp__.py deleted file mode 100644 index abf6e1e85..000000000 --- a/onchange_helper/__openerp__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -{'name': 'Onchange Helper', - 'version': '9.0.1.0.0', - 'author': 'Akretion,Camp2camp,Odoo Community Association (OCA)', - 'website': 'www.akretion.com', - 'license': 'AGPL-3', - 'category': 'Generic Modules', - 'depends': [ - 'base', - ], - 'installable': True, - } diff --git a/onchange_helper/models/__init__.py b/onchange_helper/models/__init__.py index 25bec87f2..0f0f860f3 100644 --- a/onchange_helper/models/__init__.py +++ b/onchange_helper/models/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from . import ir_rule diff --git a/onchange_helper/models/ir_rule.py b/onchange_helper/models/ir_rule.py index ec751bc28..4a20ef0dc 100644 --- a/onchange_helper/models/ir_rule.py +++ b/onchange_helper/models/ir_rule.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion (http://www.akretion.com) +# © 2016-2017 Akretion (http://www.akretion.com) +# © 2016-2017 Camptocamp (http://www.camptocamp.com/) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp import api, models + +from odoo import api, models def get_new_values(model, record, on_change_result): @@ -44,7 +46,7 @@ def play_onchanges(self, values, onchange_fields): class IrRule(models.Model): _inherit = 'ir.rule' - def _setup_complete(self, cr, uid): + def _setup_complete(self): if not hasattr(models.BaseModel, 'play_onchanges'): setattr(models.BaseModel, 'play_onchanges', play_onchanges) - return super(IrRule, self)._setup_complete(cr, uid) + return super(IrRule, self)._setup_complete() From e681d9b80e108dd252d63dcb598c40d4af03daed Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 28 Feb 2017 09:01:00 +0100 Subject: [PATCH 03/15] [FIX] avoid a crash when value is False for a M2O field --- onchange_helper/models/ir_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onchange_helper/models/ir_rule.py b/onchange_helper/models/ir_rule.py index 4a20ef0dc..b4f67af16 100644 --- a/onchange_helper/models/ir_rule.py +++ b/onchange_helper/models/ir_rule.py @@ -12,7 +12,7 @@ def get_new_values(model, record, on_change_result): for fieldname, value in vals.iteritems(): if fieldname not in record: column = model._fields[fieldname] - if column.type == 'many2one': + if value and column.type == 'many2one': value = value[0] # many2one are tuple (id, name) new_values[fieldname] = value return new_values From fe196852c1c10ee78843cb036f71595b878fd3f0 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 3 Jun 2017 09:44:44 +0200 Subject: [PATCH 04/15] OCA Transbot updated translations from Transifex --- onchange_helper/i18n/de.po | 24 ++++++++++++++++++++++++ onchange_helper/i18n/es.po | 24 ++++++++++++++++++++++++ onchange_helper/i18n/hr.po | 24 ++++++++++++++++++++++++ onchange_helper/i18n/sl.po | 24 ++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 onchange_helper/i18n/de.po create mode 100644 onchange_helper/i18n/es.po create mode 100644 onchange_helper/i18n/hr.po create mode 100644 onchange_helper/i18n/sl.po diff --git a/onchange_helper/i18n/de.po b/onchange_helper/i18n/de.po new file mode 100644 index 000000000..e47759dbe --- /dev/null +++ b/onchange_helper/i18n/de.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# Niki Waibel , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-01 14:59+0000\n" +"PO-Revision-Date: 2017-06-01 14:59+0000\n" +"Last-Translator: Niki Waibel , 2017\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_ir_rule +msgid "ir.rule" +msgstr "ir.rule" diff --git a/onchange_helper/i18n/es.po b/onchange_helper/i18n/es.po new file mode 100644 index 000000000..cf06c4ea0 --- /dev/null +++ b/onchange_helper/i18n/es.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# Fernando Lara , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-01 14:59+0000\n" +"PO-Revision-Date: 2017-06-01 14:59+0000\n" +"Last-Translator: Fernando Lara , 2017\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_ir_rule +msgid "ir.rule" +msgstr "ir.regla" diff --git a/onchange_helper/i18n/hr.po b/onchange_helper/i18n/hr.po new file mode 100644 index 000000000..b6c316ce2 --- /dev/null +++ b/onchange_helper/i18n/hr.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-01 14:59+0000\n" +"PO-Revision-Date: 2017-06-01 14:59+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_ir_rule +msgid "ir.rule" +msgstr "ir.rule" diff --git a/onchange_helper/i18n/sl.po b/onchange_helper/i18n/sl.po new file mode 100644 index 000000000..3b8f6692f --- /dev/null +++ b/onchange_helper/i18n/sl.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-01 14:59+0000\n" +"PO-Revision-Date: 2017-06-01 14:59+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_ir_rule +msgid "ir.rule" +msgstr "ir.rule" From 1c0b7b9971183ec8577965fd3be7d1a08c539cd7 Mon Sep 17 00:00:00 2001 From: Andrea Date: Sun, 14 Jan 2018 12:24:54 +0100 Subject: [PATCH 05/15] [11.0][MIG] onchange_helper + add tests --- onchange_helper/README.rst | 10 +++---- onchange_helper/__init__.py | 2 +- onchange_helper/__manifest__.py | 9 +++--- onchange_helper/models/__init__.py | 4 +-- .../models/{ir_rule.py => base.py} | 17 ++++++----- onchange_helper/tests/__init__.py | 3 ++ onchange_helper/tests/test_onchange_helper.py | 28 +++++++++++++++++++ 7 files changed, 51 insertions(+), 22 deletions(-) rename onchange_helper/models/{ir_rule.py => base.py} (77%) create mode 100644 onchange_helper/tests/__init__.py create mode 100644 onchange_helper/tests/test_onchange_helper.py diff --git a/onchange_helper/README.rst b/onchange_helper/README.rst index 48cca771e..622fbe8dd 100644 --- a/onchange_helper/README.rst +++ b/onchange_helper/README.rst @@ -1,5 +1,5 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: https://www.gnu.org/licenses/agpl :alt: License: AGPL-3 =============== @@ -18,7 +18,7 @@ To use this module, you need to: Example if you want to create a sale order and you want to get the values relative to partner_id field (as if you fill the field from UI) - `vals = {'partner_id: 1'}` + `vals = {'partner_id': 1}` `vals = self.env['sale.order'].play_onchanges(vals, ['partner_id'])` @@ -38,13 +38,14 @@ Credits Images ------ -* Odoo Community Association: `Icon `_. +* Odoo Community Association: `Icon `_. Contributors ------------ * Guewen Baconnier * Florian da Costa +* Andrea Stirpe Maintainer ---------- @@ -60,4 +61,3 @@ mission is to support the collaborative development of Odoo features and promote its widespread use. To contribute to this module, please visit https://odoo-community.org. - diff --git a/onchange_helper/__init__.py b/onchange_helper/__init__.py index cde864bae..31660d6a9 100644 --- a/onchange_helper/__init__.py +++ b/onchange_helper/__init__.py @@ -1,3 +1,3 @@ -# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import models diff --git a/onchange_helper/__manifest__.py b/onchange_helper/__manifest__.py index 0d1b9b6a1..82f03bcc1 100644 --- a/onchange_helper/__manifest__.py +++ b/onchange_helper/__manifest__.py @@ -1,12 +1,11 @@ -# -*- coding: utf-8 -*- -# © 2016-2017 Akretion (http://www.akretion.com) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# Copyright 2016-2017 Akretion (http://www.akretion.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). {'name': 'Onchange Helper', - 'version': '10.0.1.0.0', + 'version': '11.0.1.0.0', 'summary': 'Technical module that ease execution of onchange in Python code', 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', - 'website': 'http://www.akretion.com', + 'website': 'https://github.com/OCA/server-tools', 'license': 'AGPL-3', 'category': 'Generic Modules', 'depends': ['base'], diff --git a/onchange_helper/models/__init__.py b/onchange_helper/models/__init__.py index 0f0f860f3..08f5a5618 100644 --- a/onchange_helper/models/__init__.py +++ b/onchange_helper/models/__init__.py @@ -1,3 +1,3 @@ -# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from . import ir_rule +from . import base diff --git a/onchange_helper/models/ir_rule.py b/onchange_helper/models/base.py similarity index 77% rename from onchange_helper/models/ir_rule.py rename to onchange_helper/models/base.py index b4f67af16..fdc0457a3 100644 --- a/onchange_helper/models/ir_rule.py +++ b/onchange_helper/models/base.py @@ -1,7 +1,6 @@ -# -*- coding: utf-8 -*- -# © 2016-2017 Akretion (http://www.akretion.com) -# © 2016-2017 Camptocamp (http://www.camptocamp.com/) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# Copyright 2016-2017 Akretion (http://www.akretion.com) +# 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 @@ -9,7 +8,7 @@ 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.iteritems(): + for fieldname, value in vals.items(): if fieldname not in record: column = model._fields[fieldname] if value and column.type == 'many2one': @@ -38,15 +37,15 @@ def play_onchanges(self, values, onchange_fields): new_values.update(get_new_values(self, values, onchange_values)) all_values.update(new_values) - res = {f: v for f, v in all_values.iteritems() + res = {f: v for f, v in all_values.items() if f in values or f in new_values} return res -class IrRule(models.Model): - _inherit = 'ir.rule' +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(IrRule, self)._setup_complete() + return super(Base, self)._setup_complete() diff --git a/onchange_helper/tests/__init__.py b/onchange_helper/tests/__init__.py new file mode 100644 index 000000000..806c1a0d6 --- /dev/null +++ b/onchange_helper/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_onchange_helper diff --git a/onchange_helper/tests/test_onchange_helper.py b/onchange_helper/tests/test_onchange_helper.py new file mode 100644 index 000000000..adcff2c1a --- /dev/null +++ b/onchange_helper/tests/test_onchange_helper.py @@ -0,0 +1,28 @@ +# Copyright 2017 Onestein () +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestOnchangeHelper(TransactionCase): + + def test01_partner_parent(self): + main_partner = self.env.ref('base.main_partner') + input_vals = dict(partner_id=main_partner.id) + updated_vals = self.env['res.partner'].play_onchanges( + input_vals, + ['parent_id'] + ) + self.assertIn('commercial_partner_id', updated_vals) + self.assertIn('display_name', updated_vals) + self.assertIn('partner_id', updated_vals) + + def test02_partner_country(self): + partner_demo = self.env.ref('base.partner_demo') + input_vals = {'partner_id': partner_demo.id} + updated_vals = self.env['res.partner'].play_onchanges( + input_vals, + ['country_id'] + ) + self.assertIn('contact_address', updated_vals) + self.assertIn('partner_id', updated_vals) From 97342a27855f5164c5e7c7b041aef3b72924aa34 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sat, 3 Mar 2018 13:37:30 +0100 Subject: [PATCH 06/15] OCA Transbot updated translations from Transifex --- onchange_helper/i18n/cs_CZ.po | 24 ++++++++++++++++++++++++ onchange_helper/i18n/es.po | 16 ++++++++-------- onchange_helper/i18n/fr.po | 24 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 onchange_helper/i18n/cs_CZ.po create mode 100644 onchange_helper/i18n/fr.po diff --git a/onchange_helper/i18n/cs_CZ.po b/onchange_helper/i18n/cs_CZ.po new file mode 100644 index 000000000..ad91d04fb --- /dev/null +++ b/onchange_helper/i18n/cs_CZ.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# Lukáš Spurný , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: Lukáš Spurný , 2018\n" +"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/teams/23907/cs_CZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: cs_CZ\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "základny" diff --git a/onchange_helper/i18n/es.po b/onchange_helper/i18n/es.po index cf06c4ea0..da27dcc96 100644 --- a/onchange_helper/i18n/es.po +++ b/onchange_helper/i18n/es.po @@ -3,14 +3,14 @@ # * onchange_helper # # Translators: -# Fernando Lara , 2017 +# enjolras , 2018 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.0\n" +"Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-01 14:59+0000\n" -"PO-Revision-Date: 2017-06-01 14:59+0000\n" -"Last-Translator: Fernando Lara , 2017\n" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: enjolras , 2018\n" "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,6 +19,6 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: onchange_helper -#: model:ir.model,name:onchange_helper.model_ir_rule -msgid "ir.rule" -msgstr "ir.regla" +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "base" diff --git a/onchange_helper/i18n/fr.po b/onchange_helper/i18n/fr.po new file mode 100644 index 000000000..7b7765b65 --- /dev/null +++ b/onchange_helper/i18n/fr.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +# Translators: +# Quentin THEURET , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-03 10:08+0000\n" +"PO-Revision-Date: 2018-03-03 10:08+0000\n" +"Last-Translator: Quentin THEURET , 2018\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "base" From 5f8f1a0e5a56c39c6e08c90ad61d2e276e5b2996 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Sun, 17 Jun 2018 20:50:53 +0000 Subject: [PATCH 07/15] [UPD] Update onchange_helper.pot --- onchange_helper/i18n/cs_CZ.po | 7 ++++--- onchange_helper/i18n/de.po | 13 ++++++++----- onchange_helper/i18n/es.po | 4 ++-- onchange_helper/i18n/fr.po | 4 ++-- onchange_helper/i18n/hr.po | 16 ++++++++++------ onchange_helper/i18n/onchange_helper.pot | 20 ++++++++++++++++++++ onchange_helper/i18n/sl.po | 16 ++++++++++------ 7 files changed, 56 insertions(+), 24 deletions(-) create mode 100644 onchange_helper/i18n/onchange_helper.pot diff --git a/onchange_helper/i18n/cs_CZ.po b/onchange_helper/i18n/cs_CZ.po index ad91d04fb..cadc8d529 100644 --- a/onchange_helper/i18n/cs_CZ.po +++ b/onchange_helper/i18n/cs_CZ.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # Lukáš Spurný , 2018 msgid "" @@ -11,11 +11,12 @@ msgstr "" "POT-Creation-Date: 2018-03-03 10:08+0000\n" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: Lukáš Spurný , 2018\n" -"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/teams/23907/cs_CZ/)\n" +"Language-Team: Czech (Czech Republic) (https://www.transifex.com/oca/" +"teams/23907/cs_CZ/)\n" +"Language: cs_CZ\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #. module: onchange_helper diff --git a/onchange_helper/i18n/de.po b/onchange_helper/i18n/de.po index e47759dbe..b68ea6efa 100644 --- a/onchange_helper/i18n/de.po +++ b/onchange_helper/i18n/de.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # Niki Waibel , 2017 msgid "" @@ -12,13 +12,16 @@ msgstr "" "PO-Revision-Date: 2017-06-01 14:59+0000\n" "Last-Translator: Niki Waibel , 2017\n" "Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: onchange_helper -#: model:ir.model,name:onchange_helper.model_ir_rule -msgid "ir.rule" -msgstr "ir.rule" +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "" + +#~ msgid "ir.rule" +#~ msgstr "ir.rule" diff --git a/onchange_helper/i18n/es.po b/onchange_helper/i18n/es.po index da27dcc96..36b629cc9 100644 --- a/onchange_helper/i18n/es.po +++ b/onchange_helper/i18n/es.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # enjolras , 2018 msgid "" @@ -12,10 +12,10 @@ msgstr "" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: enjolras , 2018\n" "Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: onchange_helper diff --git a/onchange_helper/i18n/fr.po b/onchange_helper/i18n/fr.po index 7b7765b65..56625a21d 100644 --- a/onchange_helper/i18n/fr.po +++ b/onchange_helper/i18n/fr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # Quentin THEURET , 2018 msgid "" @@ -12,10 +12,10 @@ msgstr "" "PO-Revision-Date: 2018-03-03 10:08+0000\n" "Last-Translator: Quentin THEURET , 2018\n" "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. module: onchange_helper diff --git a/onchange_helper/i18n/hr.po b/onchange_helper/i18n/hr.po index b6c316ce2..f05aade44 100644 --- a/onchange_helper/i18n/hr.po +++ b/onchange_helper/i18n/hr.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,13 +12,17 @@ msgstr "" "PO-Revision-Date: 2017-06-01 14:59+0000\n" "Last-Translator: OCA Transbot , 2017\n" "Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: hr\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #. module: onchange_helper -#: model:ir.model,name:onchange_helper.model_ir_rule -msgid "ir.rule" -msgstr "ir.rule" +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "" + +#~ msgid "ir.rule" +#~ msgstr "ir.rule" diff --git a/onchange_helper/i18n/onchange_helper.pot b/onchange_helper/i18n/onchange_helper.pot new file mode 100644 index 000000000..720754925 --- /dev/null +++ b/onchange_helper/i18n/onchange_helper.pot @@ -0,0 +1,20 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * onchange_helper +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: onchange_helper +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "" + diff --git a/onchange_helper/i18n/sl.po b/onchange_helper/i18n/sl.po index 3b8f6692f..dafa549a7 100644 --- a/onchange_helper/i18n/sl.po +++ b/onchange_helper/i18n/sl.po @@ -1,7 +1,7 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * onchange_helper -# +# # Translators: # OCA Transbot , 2017 msgid "" @@ -12,13 +12,17 @@ msgstr "" "PO-Revision-Date: 2017-06-01 14:59+0000\n" "Last-Translator: OCA Transbot , 2017\n" "Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Language: sl\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" #. module: onchange_helper -#: model:ir.model,name:onchange_helper.model_ir_rule -msgid "ir.rule" -msgstr "ir.rule" +#: model:ir.model,name:onchange_helper.model_base +msgid "base" +msgstr "" + +#~ msgid "ir.rule" +#~ msgstr "ir.rule" From 340603078b874cf4566ccf8f6e8d40800bb4619a Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 17 Dec 2018 15:42:03 +0100 Subject: [PATCH 08/15] [12.0][MIG] - onchange_helper migration to 12.0 --- onchange_helper/__manifest__.py | 2 +- onchange_helper/readme/CONTRIBUTORS.rst | 3 +++ onchange_helper/readme/DESCRIPTION.rst | 1 + onchange_helper/readme/USAGE.rst | 12 ++++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 onchange_helper/readme/CONTRIBUTORS.rst create mode 100644 onchange_helper/readme/DESCRIPTION.rst create mode 100644 onchange_helper/readme/USAGE.rst diff --git a/onchange_helper/__manifest__.py b/onchange_helper/__manifest__.py index 82f03bcc1..993f7bc7b 100644 --- a/onchange_helper/__manifest__.py +++ b/onchange_helper/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). {'name': 'Onchange Helper', - 'version': '11.0.1.0.0', + 'version': '12.0.1.0.0', 'summary': 'Technical module that ease execution of onchange in Python code', 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', 'website': 'https://github.com/OCA/server-tools', diff --git a/onchange_helper/readme/CONTRIBUTORS.rst b/onchange_helper/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..85d5fd7e1 --- /dev/null +++ b/onchange_helper/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Guewen Baconnier +* Florian da Costa +* Andrea Stirpe \ No newline at end of file diff --git a/onchange_helper/readme/DESCRIPTION.rst b/onchange_helper/readme/DESCRIPTION.rst new file mode 100644 index 000000000..012f36c6f --- /dev/null +++ b/onchange_helper/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This is a technical module. Its goal is to ease the play of onchange method directly called from Python code. \ No newline at end of file diff --git a/onchange_helper/readme/USAGE.rst b/onchange_helper/readme/USAGE.rst new file mode 100644 index 000000000..183b6e728 --- /dev/null +++ b/onchange_helper/readme/USAGE.rst @@ -0,0 +1,12 @@ +To use this module, you need to: + +* depend on this module +* call `yourmodel.play_onchanges(values, ['field'])` + +Example if you want to create a sale order and you want to get the values relative to partner_id field (as if you fill the field from UI) + + `vals = {'partner_id': 1}` + + `vals = self.env['sale.order'].play_onchanges(vals, ['partner_id'])` + +Then, `vals` will be updated with partner_invoice_id, partner_shipping_id, pricelist_id, etc... From 68b059158ac4cb3066f5c984974959de6eebfc59 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 17 Dec 2018 16:01:44 +0100 Subject: [PATCH 09/15] [ADD] setup.py --- setup/onchange_helper/odoo/addons/onchange_helper | 1 + setup/onchange_helper/setup.py | 6 ++++++ 2 files changed, 7 insertions(+) create mode 120000 setup/onchange_helper/odoo/addons/onchange_helper create mode 100644 setup/onchange_helper/setup.py diff --git a/setup/onchange_helper/odoo/addons/onchange_helper b/setup/onchange_helper/odoo/addons/onchange_helper new file mode 120000 index 000000000..edc6c529e --- /dev/null +++ b/setup/onchange_helper/odoo/addons/onchange_helper @@ -0,0 +1 @@ +../../../../onchange_helper \ No newline at end of file diff --git a/setup/onchange_helper/setup.py b/setup/onchange_helper/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/onchange_helper/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 7e5ce25f5697198e91190ada46db7db4526851ef Mon Sep 17 00:00:00 2001 From: sebastienbeau Date: Mon, 17 Dec 2018 18:31:30 +0100 Subject: [PATCH 10/15] [FWP] - Forward porting changes from #1253 --- onchange_helper/__manifest__.py | 21 ++--- onchange_helper/models/base.py | 82 +++++++++---------- onchange_helper/readme/USAGE.rst | 10 +++ onchange_helper/tests/test_onchange_helper.py | 25 ++++-- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/onchange_helper/__manifest__.py b/onchange_helper/__manifest__.py index 993f7bc7b..d220bd481 100644 --- a/onchange_helper/__manifest__.py +++ b/onchange_helper/__manifest__.py @@ -1,13 +1,14 @@ # Copyright 2016-2017 Akretion (http://www.akretion.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -{'name': 'Onchange Helper', - 'version': '12.0.1.0.0', - 'summary': 'Technical module that ease execution of onchange in Python code', - 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', - 'website': 'https://github.com/OCA/server-tools', - 'license': 'AGPL-3', - 'category': 'Generic Modules', - 'depends': ['base'], - 'installable': True, - } +{ + 'name': 'Onchange Helper', + 'version': '12.0.1.0.0', + 'summary': 'Technical module that ease execution of onchange in Python code', + 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/server-tools', + 'license': 'AGPL-3', + 'category': 'Generic Modules', + 'depends': ['base'], + 'installable': True, +} diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index fdc0457a3..d0823dbb0 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -5,47 +5,47 @@ 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 - - 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.items(): + 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 + + @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() + # 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.items() + if not self._fields[f].compute and (f in values or f in new_values) + } diff --git a/onchange_helper/readme/USAGE.rst b/onchange_helper/readme/USAGE.rst index 183b6e728..82a4c163f 100644 --- a/onchange_helper/readme/USAGE.rst +++ b/onchange_helper/readme/USAGE.rst @@ -10,3 +10,13 @@ Example if you want to create a sale order and you want to get the values relati `vals = self.env['sale.order'].play_onchanges(vals, ['partner_id'])` 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 diff --git a/onchange_helper/tests/test_onchange_helper.py b/onchange_helper/tests/test_onchange_helper.py index adcff2c1a..848da864c 100644 --- a/onchange_helper/tests/test_onchange_helper.py +++ b/onchange_helper/tests/test_onchange_helper.py @@ -5,13 +5,11 @@ from odoo.tests.common import TransactionCase class TestOnchangeHelper(TransactionCase): - def test01_partner_parent(self): main_partner = self.env.ref('base.main_partner') input_vals = dict(partner_id=main_partner.id) updated_vals = self.env['res.partner'].play_onchanges( - input_vals, - ['parent_id'] + input_vals, ['parent_id'] ) self.assertIn('commercial_partner_id', updated_vals) self.assertIn('display_name', updated_vals) @@ -21,8 +19,25 @@ class TestOnchangeHelper(TransactionCase): partner_demo = self.env.ref('base.partner_demo') input_vals = {'partner_id': partner_demo.id} updated_vals = self.env['res.partner'].play_onchanges( - input_vals, - ['country_id'] + input_vals, ['country_id'] ) self.assertIn('contact_address', updated_vals) self.assertIn('partner_id', updated_vals) + + def test_playing_onchange_on_model(self): + result = self.env['res.partner'].play_onchanges( + {'company_type': 'company'}, ['company_type'] + ) + self.assertEqual(result['is_company'], True) + + def test_playing_onchange_on_record(self): + company = self.env.ref('base.main_company') + result = company.play_onchanges( + {'email': 'contact@akretion.com'}, ['email'] + ) + self.assertEqual( + result['rml_footer'], + u'Phone: +1 555 123 8069 | Email: contact@akretion.com | ' + u'Website: http://www.example.com', + ) + self.assertEqual(company.email, u'info@yourcompany.example.com') From a728a2985476aeeaec77a8c58f580538c82229f3 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 17 Dec 2018 18:58:25 +0100 Subject: [PATCH 11/15] [IMP] - Adapt unit tests --- onchange_helper/tests/test_onchange_helper.py | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/onchange_helper/tests/test_onchange_helper.py b/onchange_helper/tests/test_onchange_helper.py index 848da864c..9e746b6b1 100644 --- a/onchange_helper/tests/test_onchange_helper.py +++ b/onchange_helper/tests/test_onchange_helper.py @@ -7,37 +7,30 @@ from odoo.tests.common import TransactionCase class TestOnchangeHelper(TransactionCase): def test01_partner_parent(self): main_partner = self.env.ref('base.main_partner') - input_vals = dict(partner_id=main_partner.id) + input_vals = dict(parent_id=main_partner.id, type='contact') updated_vals = self.env['res.partner'].play_onchanges( input_vals, ['parent_id'] ) - self.assertIn('commercial_partner_id', updated_vals) - self.assertIn('display_name', updated_vals) - self.assertIn('partner_id', updated_vals) + self.assertIn('country_id', updated_vals) + self.assertIn('state_id', updated_vals) + self.assertIn('street', updated_vals) + self.assertIn('zip', updated_vals) + + self.assertEqual( + updated_vals['country_id'], main_partner.country_id.id + ) + self.assertEqual(updated_vals['state_id'], main_partner.state_id.id) + self.assertEqual(updated_vals['street'], main_partner.street) + self.assertEqual(updated_vals['zip'], main_partner.zip) def test02_partner_country(self): partner_demo = self.env.ref('base.partner_demo') - input_vals = {'partner_id': partner_demo.id} - updated_vals = self.env['res.partner'].play_onchanges( - input_vals, ['country_id'] - ) - self.assertIn('contact_address', updated_vals) - self.assertIn('partner_id', updated_vals) + input_vals = {'country_id': self.env.ref('base.us').id} + updated_vals = partner_demo.play_onchanges(input_vals, ['country_id']) + self.assertIn('country_id', updated_vals) def test_playing_onchange_on_model(self): result = self.env['res.partner'].play_onchanges( {'company_type': 'company'}, ['company_type'] ) self.assertEqual(result['is_company'], True) - - def test_playing_onchange_on_record(self): - company = self.env.ref('base.main_company') - result = company.play_onchanges( - {'email': 'contact@akretion.com'}, ['email'] - ) - self.assertEqual( - result['rml_footer'], - u'Phone: +1 555 123 8069 | Email: contact@akretion.com | ' - u'Website: http://www.example.com', - ) - self.assertEqual(company.email, u'info@yourcompany.example.com') From a22f10e2ad4df24d585284742491a2edcce9955a Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 17 Dec 2018 19:29:54 +0100 Subject: [PATCH 12/15] [IMP] - read may be harmful to performance --- onchange_helper/__manifest__.py | 3 ++- onchange_helper/models/base.py | 7 ++++++- onchange_helper/readme/CONTRIBUTORS.rst | 2 +- onchange_helper/readme/DESCRIPTION.rst | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/onchange_helper/__manifest__.py b/onchange_helper/__manifest__.py index d220bd481..386ae237e 100644 --- a/onchange_helper/__manifest__.py +++ b/onchange_helper/__manifest__.py @@ -4,7 +4,8 @@ { 'name': 'Onchange Helper', 'version': '12.0.1.0.0', - 'summary': 'Technical module that ease execution of onchange in Python code', + 'summary': 'Technical module that ease execution' + ' of onchange in Python code', 'author': 'Akretion,Camptocamp,Odoo Community Association (OCA)', 'website': 'https://github.com/OCA/server-tools', 'license': 'AGPL-3', diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index d0823dbb0..00d888bb8 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -31,7 +31,12 @@ class Base(models.AbstractModel): # 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]) + record_values = self._convert_to_write( + { + field_name: self[field_name] + for field_name, field in self._fields.items() + } + ) else: record_values = {} for field in self._fields: diff --git a/onchange_helper/readme/CONTRIBUTORS.rst b/onchange_helper/readme/CONTRIBUTORS.rst index 85d5fd7e1..f4084e979 100644 --- a/onchange_helper/readme/CONTRIBUTORS.rst +++ b/onchange_helper/readme/CONTRIBUTORS.rst @@ -1,3 +1,3 @@ * Guewen Baconnier * Florian da Costa -* Andrea Stirpe \ No newline at end of file +* Andrea Stirpe diff --git a/onchange_helper/readme/DESCRIPTION.rst b/onchange_helper/readme/DESCRIPTION.rst index 012f36c6f..23c01a8ef 100644 --- a/onchange_helper/readme/DESCRIPTION.rst +++ b/onchange_helper/readme/DESCRIPTION.rst @@ -1 +1 @@ -This is a technical module. Its goal is to ease the play of onchange method directly called from Python code. \ No newline at end of file +This is a technical module. Its goal is to ease the play of onchange method directly called from Python code. From 0f4f8bbd74769a782710e66769d202702f3a99b5 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Tue, 18 Dec 2018 17:29:51 +0100 Subject: [PATCH 13/15] [IMP] - get default values for non record onchange call other improvement: set onchange_specs to all fields as _onchange_spec() retrun onchange fields for default view return field value if it's set in onchange_fields (usuful to get default value for a field) --- onchange_helper/models/base.py | 11 ++++++++--- onchange_helper/readme/CONTRIBUTORS.rst | 1 + onchange_helper/readme/USAGE.rst | 11 +++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index 00d888bb8..ad685aad2 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -22,9 +22,12 @@ class Base(models.AbstractModel): @api.model def play_onchanges(self, values, onchange_fields): - onchange_specs = self._onchange_spec() + # _onchange_spec() will return onchange fields from the default view # we need all fields in the dict even the empty ones # otherwise 'onchange()' will not apply changes to them + onchange_specs = { + field_name: '1' for field_name, field in self._fields.items() + } all_values = values.copy() # If self is a record (play onchange on existing record) # we take the value of the field @@ -38,7 +41,8 @@ class Base(models.AbstractModel): } ) else: - record_values = {} + # We get default values, they may be used in onchange + record_values = self.default_get(self._fields.keys()) for field in self._fields: if field not in all_values: all_values[field] = record_values.get(field, False) @@ -52,5 +56,6 @@ class Base(models.AbstractModel): return { f: v for f, v in all_values.items() - if not self._fields[f].compute and (f in values or f in new_values) + if not self._fields[f].compute + and (f in values or f in new_values or f in onchange_fields) } diff --git a/onchange_helper/readme/CONTRIBUTORS.rst b/onchange_helper/readme/CONTRIBUTORS.rst index f4084e979..47a0cfe24 100644 --- a/onchange_helper/readme/CONTRIBUTORS.rst +++ b/onchange_helper/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Guewen Baconnier * Florian da Costa * Andrea Stirpe +* Souheil Bejaoui diff --git a/onchange_helper/readme/USAGE.rst b/onchange_helper/readme/USAGE.rst index 82a4c163f..e8b5a738c 100644 --- a/onchange_helper/readme/USAGE.rst +++ b/onchange_helper/readme/USAGE.rst @@ -11,6 +11,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... +Default values will be used to process onchange methods, if respective fields are not set in `vals`. +You can get them if you pass fields name in the list of fields. + + + `vals = {'partner_id': 1}` + + `vals = self.env['sale.order'].play_onchanges(vals, ['partner_id', 'date_order'])` + +`vals` will contain, in addition to the changed values, the default value for `date_order` + + You can also use it on existing record for example: `vals = {'partner_shipping_id': 1}` From cf21042954835d05fbaa59270899776ebb2a1a7a Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Wed, 19 Dec 2018 16:03:13 +0100 Subject: [PATCH 14/15] [UPD] - Update documentation --- onchange_helper/models/base.py | 8 ++++++++ onchange_helper/readme/USAGE.rst | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index ad685aad2..3863e4424 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -22,6 +22,14 @@ class Base(models.AbstractModel): @api.model def play_onchanges(self, values, onchange_fields): + """ + :param values: dict of input value that + :param onchange_fields: fields for which onchange methods will be + played + Order in onchange_fields is very important as onchanges methods will + be played in that order. + :return: changed values + """ # _onchange_spec() will return onchange fields from the default view # we need all fields in the dict even the empty ones # otherwise 'onchange()' will not apply changes to them diff --git a/onchange_helper/readme/USAGE.rst b/onchange_helper/readme/USAGE.rst index e8b5a738c..52da81375 100644 --- a/onchange_helper/readme/USAGE.rst +++ b/onchange_helper/readme/USAGE.rst @@ -31,3 +31,9 @@ You can also use it on existing record for example: 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 + + +Notes: + +- Order in onchange_fields is very important as onchanges methods will be played in that order. +- If you use memory object in `vals`, be award that onchange method in base model call `self.invalidate_cache()` that reset it. From 176916f536793047ed7f9355f2ee56d9872735c9 Mon Sep 17 00:00:00 2001 From: Benoit Date: Mon, 21 Jan 2019 14:06:40 +0100 Subject: [PATCH 15/15] [FIX] don't remove computed fields with inverse method of the onchange values --- onchange_helper/models/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onchange_helper/models/base.py b/onchange_helper/models/base.py index 3863e4424..4cc24ca2b 100644 --- a/onchange_helper/models/base.py +++ b/onchange_helper/models/base.py @@ -64,6 +64,6 @@ class Base(models.AbstractModel): return { f: v for f, v in all_values.items() - if not self._fields[f].compute + if not (self._fields[f].compute and not self._fields[f].inverse) and (f in values or f in new_values or f in onchange_fields) }