diff --git a/web_readonly_bypass/README.rst b/web_readonly_bypass/README.rst index ffd799b0..095d9295 100644 --- a/web_readonly_bypass/README.rst +++ b/web_readonly_bypass/README.rst @@ -22,7 +22,7 @@ This module changes the behaviour of Odoo by propagating on_change modifications to readonly fields to the backend create and write methods. -To change that behavior you have to set context on ``ur.actions.act_window``:: +To change that behavior you have to set context on ``ir.actions.act_window``:: {'readonly_by_pass': True} @@ -36,13 +36,13 @@ or by telling fields allowed to change:: -For further information, please visit: +On one2many fields, you can also pass the context in the field definition: -* https://www.odoo.com/forum/help-1 + .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/162/8.0 + :target: https://runbot.odoo-community.org/runbot/162/10.0 Bug Tracker @@ -50,8 +50,7 @@ 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 -`here `_. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback. Credits @@ -63,6 +62,10 @@ Contributors * Jonathan Nemry * Laetitia Gangloff * Pierre Verkest +* Kalpana Hemnani +* Agathe Mollé +* Simone Orsi + Maintainer ---------- diff --git a/web_readonly_bypass/__manifest__.py b/web_readonly_bypass/__manifest__.py index 9d3f7681..8163e0fa 100644 --- a/web_readonly_bypass/__manifest__.py +++ b/web_readonly_bypass/__manifest__.py @@ -1,33 +1,13 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# This file is part of web_readonly_bypass, -# an Odoo module. -# -# Copyright (c) 2015 ACSONE SA/NV () -# -# web_readonly_bypass is free software: -# you can redistribute it and/or modify it under the terms of the GNU -# Affero General Public License as published by the Free Software -# Foundation,either version 3 of the License, or (at your option) any -# later version. -# -# web_readonly_bypass is distributed -# in the hope that it will be useful, but WITHOUT ANY WARRANTY; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with web_readonly_bypass. -# If not, see . -# -############################################################################## +# Copyright (c) 2015 ACSONE SA/NV () +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + { 'name': 'Read Only ByPass', - 'version': '9.0.1.0.0', + 'version': '10.0.1.0.1', "author": "ACSONE SA/NV, Odoo Community Association (OCA)", - "maintainer": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "http://www.acsone.eu", + "license": "LGPL-3", 'category': 'Technical Settings', 'depends': [ 'web', @@ -36,6 +16,6 @@ 'data': [ 'views/readonly_bypass.xml', ], - 'installable': False, + 'installable': True, 'auto_install': False, } diff --git a/web_readonly_bypass/static/src/js/readonly_bypass.js b/web_readonly_bypass/static/src/js/readonly_bypass.js index ea3f460e..b9b2ebe4 100644 --- a/web_readonly_bypass/static/src/js/readonly_bypass.js +++ b/web_readonly_bypass/static/src/js/readonly_bypass.js @@ -1,9 +1,10 @@ -"use strict"; -(function(){ - var instance = openerp; - var QWeb = instance.web.qweb, _t = instance.web._t; +odoo.define('web_readonly_bypass', function(require) { + 'use strict'; - instance.web_readonly_bypass = { + var data = require('web.data'), + pyeval = require('web.pyeval'); + + var readonly_bypass = { /** * ignore readonly: place options['readonly_fields'] into the data * if nothing is specified into the context @@ -26,7 +27,7 @@ } }); } - data = $.extend(data,readonly_by_pass_fields); + data = $.extend(data, readonly_by_pass_fields); }, /** @@ -59,15 +60,13 @@ }, }; - var readonly_bypass = instance.web_readonly_bypass; - - instance.web.BufferedDataSet.include({ + data.BufferedDataSet.include({ init : function() { this._super.apply(this, arguments); }, /** - * Creates Overriding + * Create Overriding * * @param {Object} data field values to set on the new record * @param {Object} options Dictionary that can contain the following keys: @@ -77,13 +76,12 @@ */ create : function(data, options) { var self = this; - var context = instance.web.pyeval.eval('contexts', - self.context.__eval_context); + var context = pyeval.eval('contexts', self.context.get_eval_context()); readonly_bypass.ignore_readonly(data, options, true, context); return self._super(data,options); }, /** - * Creates Overriding + * Write Overriding * * @param {Object} data field values to set on the new record * @param {Object} options Dictionary that can contain the following keys: @@ -93,15 +91,14 @@ */ write : function(id, data, options) { var self = this; - var context = instance.web.pyeval.eval('contexts', - self.context.__eval_context); + var context = pyeval.eval('contexts', self.context.get_eval_context()); readonly_bypass.ignore_readonly(data, options, false, context); return self._super(id,data,options); }, }); - instance.web.DataSet.include({ + data.DataSet.include({ /* BufferedDataSet: case of 'add an item' into a form view */ @@ -138,4 +135,46 @@ }, }); -})(); + + data.ProxyDataSet.include({ + /* + ProxyDataSet: case of 'pop-up' + */ + init : function() { + this._super.apply(this, arguments); + }, + /** + * Create Overriding + * + * @param {Object} data field values to set on the new record + * @param {Object} options Dictionary that can contain the following keys: + * - readonly_fields: Values from readonly fields that were updated by + * on_changes. Only used by the BufferedDataSet to make the o2m work correctly. + * @returns super {$.Deferred} + */ + create : function(data, options) { + var self = this; + var context = pyeval.eval('contexts', self.context.get_eval_context()); + readonly_bypass.ignore_readonly(data, options, true, context); + return self._super(data,options); + }, + /** + * Write Overriding + * + * @param {Object} data field values to set on the new record + * @param {Object} options Dictionary that can contain the following keys: + * - readonly_fields: Values from readonly fields that were updated by + * on_changes. Only used by the BufferedDataSet to make the o2m work correctly. + * @returns super {$.Deferred} + */ + write : function(id, data, options) { + var self = this; + var context = pyeval.eval('contexts', self.context.get_eval_context()); + readonly_bypass.ignore_readonly(data, options, false, context); + return self._super(id,data,options); + }, + + }); + + return readonly_bypass; +}); diff --git a/web_readonly_bypass/static/test/web_readonly_bypass.js b/web_readonly_bypass/static/test/web_readonly_bypass.js index fbc44f72..2a2e02d8 100644 --- a/web_readonly_bypass/static/test/web_readonly_bypass.js +++ b/web_readonly_bypass/static/test/web_readonly_bypass.js @@ -1,166 +1,166 @@ -openerp.testing.section( 'web_readonly_bypass', {}, -function(test){ - test('ignore_readonly', function(instance){ - var data = {}; - var mode_create = true; - var options = {}; - var context = {}; - instance.web_readonly_bypass.ignore_readonly(data, options, - mode_create, context); - deepEqual(data, - {}, - "Empty context and options mode create" - ); - - mode_create = false; - data = {}; - instance.web_readonly_bypass.ignore_readonly(data, options, - mode_create, context); - deepEqual(data, - {}, - "Empty context and options mode write" - ); - - mode_create = false; - data = {}; - context = {'readonly_by_pass': true}; - options = {'readonly_fields': {'field_1': 'va1-1', - 'field_2': false, +odoo.define_section('web_readonly_bypass', ['web_readonly_bypass'], function(test) { +"use strict"; + + + test('ignore_readonly', function(assert, ro_bypass){ + var data = {}; + var mode_create = true; + var options = {}; + var context = {}; + ro_bypass.ignore_readonly(data, options, mode_create, context); + assert.deepEqual(data, + {}, + "Empty context and options mode create" + ); + + mode_create = false; + data = {}; + ro_bypass.ignore_readonly(data, options, mode_create, context); + assert.deepEqual(data, + {}, + "Empty context and options mode write" + ); + + mode_create = false; + data = {}; + context = {'readonly_by_pass': true}; + options = {'readonly_fields': {'field_1': 'va1-1', + 'field_2': false, + 'field_3': 'val-3'}}; + ro_bypass.ignore_readonly(data, options, mode_create, context); + + assert.deepEqual(data, + {'field_1': 'va1-1', 'field_2': false, 'field_3': 'val-3'}, + "all fields mode write" + ); + + mode_create = true; + data = {}; + context = {'readonly_by_pass': true}; + options = {'readonly_fields': {'field_1': 'va1-1', + 'field_2': false, + 'field_3': 'val-3'}}; + ro_bypass.ignore_readonly(data, options, mode_create, context); + + assert.deepEqual(data, + {'field_1': 'va1-1', 'field_3': 'val-3'}, + "all fields mode create (false value are escaped)" + ); + + mode_create = true; + data = {}; + context = {}; + options = {'readonly_fields': {'field_1': 'va1-1', + 'field_2': false, + 'field_3': 'val-3'}}; + ro_bypass.ignore_readonly(data, options, mode_create, context); + + assert.deepEqual(data, + {}, + "without context, default, we won't save readonly fields" + ); + }); + + test('retrieve_readonly_by_pass_fields', ['web_readonly_bypass'], function(assert, ro_bypass){ + var context = {'readonly_by_pass': true} + var options = {'readonly_fields': {'field_1': 'va1-1', + 'field_2': 'val-2', 'field_3': 'val-3'}}; - instance.web_readonly_bypass.ignore_readonly(data, options, - mode_create, context); - deepEqual(data, - {'field_1': 'va1-1', 'field_2': false, 'field_3': 'val-3'}, - "all fields mode write" - ); - - mode_create = true; - data = {}; - context = {'readonly_by_pass': true}; - options = {'readonly_fields': {'field_1': 'va1-1', - 'field_2': false, - 'field_3': 'val-3'}}; - instance.web_readonly_bypass.ignore_readonly(data, options, - mode_create, context); - deepEqual(data, - {'field_1': 'va1-1', 'field_3': 'val-3'}, - "all fields mode create (false value are escaped)" - ); - - mode_create = true; - data = {}; - context = {}; - options = {'readonly_fields': {'field_1': 'va1-1', - 'field_2': false, - 'field_3': 'val-3'}}; - instance.web_readonly_bypass.ignore_readonly(data, options, - mode_create, context); - deepEqual(data, - {}, - "without context, default, we won't save readonly fields" - ); - }); - - test('retrieve_readonly_by_pass_fields', function(instance){ - var context = {'readonly_by_pass': true} - var options = {'readonly_fields': {'field_1': 'va1-1', - 'field_2': 'val-2', - 'field_3': 'val-3'}}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {'field_1': 'va1-1', 'field_2': 'val-2', 'field_3': 'val-3'}, - "All fields should be accepted!" - ); - - context = {'readonly_by_pass': ['field_1', 'field_3']}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {'field_1': 'va1-1','field_3': 'val-3'}, - "two field s1" - ); - - context = {'readonly_by_pass': ['field_1',]}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {'field_1': 'va1-1'}, - "Only field 1" - ); - - context = {'readonly_by_pass': []}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "Empty context field" - ); - - context = null; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "Null context" - ); - - context = false; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "false context" - ); - - context = {'readonly_by_pass': true} - options = {'readonly_fields': {'field_1': 'va1-1'}}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {'field_1': 'va1-1'}, - "Only one option" - ); - - - options = {'readonly_fields': {}}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "Empty readonly_fields option" - ); - - options = {}; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "Empty option" - ); - - options = null; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "null option" - ); - - options = false; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "false option" - ); - - context = false; - deepEqual( - instance.web_readonly_bypass.retrieve_readonly_by_pass_fields( - options, context), - {}, - "false option and false context" - ); - }); + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {'field_1': 'va1-1', 'field_2': 'val-2', 'field_3': 'val-3'}, + "All fields should be accepted!" + ); + + context = {'readonly_by_pass': ['field_1', 'field_3']}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {'field_1': 'va1-1','field_3': 'val-3'}, + "two field s1" + ); + + context = {'readonly_by_pass': ['field_1',]}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {'field_1': 'va1-1'}, + "Only field 1" + ); + + context = {'readonly_by_pass': []}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "Empty context field" + ); + + context = null; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "Null context" + ); + + context = false; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "false context" + ); + + context = {'readonly_by_pass': true} + options = {'readonly_fields': {'field_1': 'va1-1'}}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {'field_1': 'va1-1'}, + "Only one option" + ); + + + options = {'readonly_fields': {}}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "Empty readonly_fields option" + ); + + options = {}; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "Empty option" + ); + + options = null; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "null option" + ); + + options = false; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "false option" + ); + + context = false; + assert.deepEqual( + ro_bypass.retrieve_readonly_by_pass_fields( + options, context), + {}, + "false option and false context" + ); + }); }); diff --git a/web_readonly_bypass/tests/__init__.py b/web_readonly_bypass/tests/__init__.py new file mode 100644 index 00000000..6dab214a --- /dev/null +++ b/web_readonly_bypass/tests/__init__.py @@ -0,0 +1 @@ +from . import test_ui diff --git a/web_readonly_bypass/tests/test_ui.py b/web_readonly_bypass/tests/test_ui.py new file mode 100644 index 00000000..6b14af62 --- /dev/null +++ b/web_readonly_bypass/tests/test_ui.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017 Simone Orsi +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo.tests import HttpCase + + +class TestUi(HttpCase): + + def test_ui_web(self): + self.phantom_js( + "/web/tests?module=web_readonly_bypass", + "", + login="admin", + ) diff --git a/web_readonly_bypass/views/readonly_bypass.xml b/web_readonly_bypass/views/readonly_bypass.xml index 32c584c0..63935cc7 100644 --- a/web_readonly_bypass/views/readonly_bypass.xml +++ b/web_readonly_bypass/views/readonly_bypass.xml @@ -1,15 +1,14 @@ - - - - - - + + + + +