diff --git a/web_readonly_bypass/README.rst b/web_readonly_bypass/README.rst
new file mode 100644
index 00000000..ffd799b0
--- /dev/null
+++ b/web_readonly_bypass/README.rst
@@ -0,0 +1,80 @@
+.. 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
+
+================
+Read Only ByPass
+================
+
+This module provides a solution to the problem of the interaction between
+'readonly' attribute and 'on_change' attribute when used together. It allows
+saving onchange modifications to readonly fields.
+
+Behavior: add readonly fields changed by `on_change` methods to the values
+passed to write or create. If `readonly_by_pass` is in the context and
+True then it will by pass readonly fields and save its data provide by onchange
+method.
+
+Usage
+=====
+
+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``::
+
+
+ {'readonly_by_pass': True}
+
+
+or by telling fields allowed to change::
+
+
+
+ {'readonly_by_pass': ['readonly_field_1', 'readonly_field_2',]}
+
+
+
+For further information, please visit:
+
+* 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
+
+
+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 `_.
+
+
+Credits
+=======
+
+Contributors
+------------
+
+* Jonathan Nemry
+* Laetitia Gangloff
+* Pierre Verkest
+
+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 http://odoo-community.org.
diff --git a/web_readonly_bypass/__init__.py b/web_readonly_bypass/__init__.py
new file mode 100644
index 00000000..40a96afc
--- /dev/null
+++ b/web_readonly_bypass/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/web_readonly_bypass/__openerp__.py b/web_readonly_bypass/__openerp__.py
new file mode 100644
index 00000000..10f0098f
--- /dev/null
+++ b/web_readonly_bypass/__openerp__.py
@@ -0,0 +1,41 @@
+# -*- 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 .
+#
+##############################################################################
+{
+ 'name': 'Read Only ByPass',
+ 'version': '8.0.1.0.0',
+ "author": "ACSONE SA/NV, Odoo Community Association (OCA)",
+ "maintainer": "ACSONE SA/NV,Odoo Community Association (OCA)",
+ "website": "http://www.acsone.eu",
+ 'category': 'Technical Settings',
+ 'depends': [
+ 'web',
+ ],
+ 'summary': 'Allow to save onchange modifications to readonly fields',
+ 'data': [
+ 'views/readonly_bypass.xml',
+ ],
+ '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
new file mode 100644
index 00000000..ea3f460e
--- /dev/null
+++ b/web_readonly_bypass/static/src/js/readonly_bypass.js
@@ -0,0 +1,141 @@
+"use strict";
+(function(){
+ var instance = openerp;
+ var QWeb = instance.web.qweb, _t = instance.web._t;
+
+ instance.web_readonly_bypass = {
+ /**
+ * ignore readonly: place options['readonly_fields'] into the data
+ * if nothing is specified into the context
+ *
+ * create mode: remove read-only keys having a 'false' value
+ *
+ * @param {Object} data field values to possibly be updated
+ * @param {Object} options Dictionary that can contain the following keys:
+ * - readonly_fields: Values from readonly fields to merge into the data object
+ * @param boolean mode: True case of create, false case of write
+ * @param {Object} context->readonly_by_pass
+ */
+ ignore_readonly: function(data, options, mode, context){
+ var readonly_by_pass_fields = this.retrieve_readonly_by_pass_fields(
+ options, context);
+ if(mode){
+ $.each( readonly_by_pass_fields, function( key, value ) {
+ if(value==false){
+ delete(readonly_by_pass_fields[key]);
+ }
+ });
+ }
+ data = $.extend(data,readonly_by_pass_fields);
+ },
+
+ /**
+ * retrieve_readonly_by_pass_fields: retrieve readonly fields to save
+ * according context.
+ *
+ * @param {Object} options Dictionary that can contain the following keys:
+ * - readonly_fields: all values from readonly fields
+ * @param {Object} context->readonly_by_pass: Can be true if all
+ * all readonly fields should be saved or an array of field name to
+ * save ie: ['readonly_field_1', 'readonly_field_2']
+ * @returns {Object}: readonly key/value fields to save according context
+ */
+ retrieve_readonly_by_pass_fields: function(options, context){
+ var readonly_by_pass_fields = {};
+ if (options && 'readonly_fields' in options &&
+ options['readonly_fields'] && context &&
+ 'readonly_by_pass' in context && context['readonly_by_pass']){
+ if (_.isArray(context['readonly_by_pass'])){
+ $.each( options.readonly_fields, function( key, value ) {
+ if(_.contains(context['readonly_by_pass'], key)){
+ readonly_by_pass_fields[key] = value;
+ }
+ });
+ }else{
+ readonly_by_pass_fields = options.readonly_fields;
+ }
+ }
+ return readonly_by_pass_fields;
+ },
+ };
+
+ var readonly_bypass = instance.web_readonly_bypass;
+
+ instance.web.BufferedDataSet.include({
+
+ init : function() {
+ this._super.apply(this, arguments);
+ },
+ /**
+ * Creates 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 = instance.web.pyeval.eval('contexts',
+ self.context.__eval_context);
+ readonly_bypass.ignore_readonly(data, options, true, context);
+ return self._super(data,options);
+ },
+ /**
+ * Creates 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 = instance.web.pyeval.eval('contexts',
+ self.context.__eval_context);
+ readonly_bypass.ignore_readonly(data, options, false, context);
+ return self._super(id,data,options);
+ },
+
+ });
+
+ instance.web.DataSet.include({
+ /*
+ BufferedDataSet: case of 'add an item' into a form view
+ */
+ init : function() {
+ this._super.apply(this, arguments);
+ },
+ /**
+ * Creates 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;
+ readonly_bypass.ignore_readonly(data, options, true, self.context);
+ return self._super(data,options);
+ },
+ /**
+ * Creates 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;
+ readonly_bypass.ignore_readonly(data, options, false, self.context);
+ return self._super(id,data,options);
+ },
+
+ });
+})();
diff --git a/web_readonly_bypass/static/test/web_readonly_bypass.js b/web_readonly_bypass/static/test/web_readonly_bypass.js
new file mode 100644
index 00000000..fbc44f72
--- /dev/null
+++ b/web_readonly_bypass/static/test/web_readonly_bypass.js
@@ -0,0 +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,
+ '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"
+ );
+ });
+});
diff --git a/web_readonly_bypass/views/readonly_bypass.xml b/web_readonly_bypass/views/readonly_bypass.xml
new file mode 100644
index 00000000..32c584c0
--- /dev/null
+++ b/web_readonly_bypass/views/readonly_bypass.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+