diff --git a/barcode_action/README.rst b/barcode_action/README.rst
new file mode 100644
index 0000000..05452d4
--- /dev/null
+++ b/barcode_action/README.rst
@@ -0,0 +1,74 @@
+=======================
+Barcode action launcher
+=======================
+
+This module allows to use barcodes as launchers of actions.
+
+The action will launch a function that uses the barcode in order to return an action.
+
+Usage
+=====
+Actions must be configured with the following data in the context:
+* model: Model where we can find the method (required)
+* method: Method to execute (required)
+* res_id: Id as base (optional)
+
+The method must return an action. Installing this module with demo data will
+install a demo application that allows the system administrator to find a
+partner by the external reference encoded in a barcode.
+
+Go to *Settings / Find partners* and scan a barcode that contains the
+internal reference of an existing partner. As soon as you read the barcode
+the system will redirect you to that partner's form view.
+
+Technical implementation of this example:
+
+Action::
+
+
+
+
+
+Python code::
+
+ import json
+ from odoo import api, models, _
+ from odoo.tools.safe_eval import safe_eval
+
+
+ class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ @api.multi
+ def find_res_partner_by_ref_using_barcode(self, barcode):
+ partner = self.search([('ref', '=', barcode)], limit=1)
+ if not partner:
+ action = self.env.ref('res_partner_find')
+ result = action.read()[0]
+ context = safe_eval(result['context'])
+ context.update({
+ 'default_state': 'warning',
+ 'default_status': _('Partner with Internal Reference '
+ '%s cannot be found') % barcode
+ })
+ result['context'] = json.dumps(context)
+ return result
+ action = self.env.ref('base.action_partner_form')
+ result = action.read()[0]
+ res = self.env.ref('base.view_partner_form', False)
+ result['views'] = [(res and res.id or False, 'form')]
+ result['res_id'] = partner.id
+ return result
+
+Contributors
+============
+* Enric Tobella
+* Jordi Ballester
diff --git a/barcode_action/__init__.py b/barcode_action/__init__.py
new file mode 100644
index 0000000..134df27
--- /dev/null
+++ b/barcode_action/__init__.py
@@ -0,0 +1,2 @@
+from . import wizard
+from . import models
diff --git a/barcode_action/__manifest__.py b/barcode_action/__manifest__.py
new file mode 100644
index 0000000..1396c77
--- /dev/null
+++ b/barcode_action/__manifest__.py
@@ -0,0 +1,25 @@
+# Copyright 2017 Creu Blanca
+# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+{
+ 'name': 'Barcode action launcher',
+ 'version': '11.0.1.0.0',
+ 'category': 'Extra Tools',
+ 'website': 'https://github.com/OCA/server-ux',
+ 'author': 'Creu Blanca, Eficent, Odoo Community Association (OCA)',
+ 'license': 'AGPL-3',
+ 'installable': True,
+ 'application': False,
+ 'summary': 'Allows to use barcodes as a launcher',
+ 'depends': [
+ 'barcodes',
+ ],
+ 'data': [
+ 'views/barcode_templates.xml',
+ 'wizard/barcode_action_view.xml',
+ ],
+ 'demo': [
+ 'demo/barcode_action_demo.xml'
+ ],
+}
diff --git a/barcode_action/demo/barcode_action_demo.xml b/barcode_action/demo/barcode_action_demo.xml
new file mode 100644
index 0000000..c976611
--- /dev/null
+++ b/barcode_action/demo/barcode_action_demo.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/barcode_action/models/__init__.py b/barcode_action/models/__init__.py
new file mode 100644
index 0000000..91fed54
--- /dev/null
+++ b/barcode_action/models/__init__.py
@@ -0,0 +1 @@
+from . import res_partner
diff --git a/barcode_action/models/res_partner.py b/barcode_action/models/res_partner.py
new file mode 100644
index 0000000..8a8a563
--- /dev/null
+++ b/barcode_action/models/res_partner.py
@@ -0,0 +1,31 @@
+# Copyright 2018 Creu Blanca
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+import json
+from odoo import api, models, _
+from odoo.tools.safe_eval import safe_eval
+
+
+class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ @api.multi
+ def find_res_partner_by_ref_using_barcode(self, barcode):
+ partner = self.search([('ref', '=', barcode)], limit=1)
+ if not partner:
+ action = self.env.ref('barcode_action.res_partner_find')
+ result = action.read()[0]
+ context = safe_eval(result['context'])
+ context.update({
+ 'default_state': 'warning',
+ 'default_status': _('Partner with Internal Reference '
+ '%s cannot be found') % barcode
+ })
+ result['context'] = json.dumps(context)
+ return result
+ action = self.env.ref('base.action_partner_form')
+ result = action.read()[0]
+ res = self.env.ref('base.view_partner_form', False)
+ result['views'] = [(res and res.id or False, 'form')]
+ result['res_id'] = partner.id
+ return result
diff --git a/barcode_action/readme/CONTRIBUTORS.rst b/barcode_action/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000..6296b24
--- /dev/null
+++ b/barcode_action/readme/CONTRIBUTORS.rst
@@ -0,0 +1,3 @@
+* Enric Tobella
+* Jordi Ballester
+
diff --git a/barcode_action/readme/DESCRIPTION.rst b/barcode_action/readme/DESCRIPTION.rst
new file mode 100644
index 0000000..40178e3
--- /dev/null
+++ b/barcode_action/readme/DESCRIPTION.rst
@@ -0,0 +1,3 @@
+This module allows to use barcodes as launchers of actions.
+
+The action will launch a function that uses the barcode in order to return an action.
diff --git a/barcode_action/readme/USAGE.rst b/barcode_action/readme/USAGE.rst
new file mode 100644
index 0000000..d43eb9d
--- /dev/null
+++ b/barcode_action/readme/USAGE.rst
@@ -0,0 +1,59 @@
+Actions must be configured with the following data in the context:
+* model: Model where we can find the method (required)
+* method: Method to execute (required)
+* res_id: Id as base (optional)
+
+The method must return an action. Installing this module with demo data will
+install a demo application that allows the system administrator to find a
+partner by the external reference encoded in a barcode.
+
+Go to *Settings / Find partners* and scan a barcode that contains the
+internal reference of an existing partner. As soon as you read the barcode
+the system will redirect you to that partner's form view.
+
+Technical implementation of this example:
+
+Action::
+
+
+
+
+
+Python code::
+
+ import json
+ from odoo import api, models, _
+ from odoo.tools.safe_eval import safe_eval
+
+
+ class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ @api.multi
+ def find_res_partner_by_ref_using_barcode(self, barcode):
+ partner = self.search([('ref', '=', barcode)], limit=1)
+ if not partner:
+ action = self.env.ref('res_partner_find')
+ result = action.read()[0]
+ context = safe_eval(result['context'])
+ context.update({
+ 'default_state': 'warning',
+ 'default_status': _('Partner with Internal Reference '
+ '%s cannot be found') % barcode
+ })
+ result['context'] = json.dumps(context)
+ return result
+ action = self.env.ref('base.action_partner_form')
+ result = action.read()[0]
+ res = self.env.ref('base.view_partner_form', False)
+ result['views'] = [(res and res.id or False, 'form')]
+ result['res_id'] = partner.id
+ return result
diff --git a/barcode_action/static/description/icon.png b/barcode_action/static/description/icon.png
new file mode 100644
index 0000000..3a0328b
Binary files /dev/null and b/barcode_action/static/description/icon.png differ
diff --git a/barcode_action/static/src/js/action_barcode_form.js b/barcode_action/static/src/js/action_barcode_form.js
new file mode 100644
index 0000000..e53c381
--- /dev/null
+++ b/barcode_action/static/src/js/action_barcode_form.js
@@ -0,0 +1,23 @@
+odoo.define('barcode_action.form', function (require) {
+"use strict";
+
+var FormController = require('web.FormController');
+
+FormController.include({
+ _barcodeHandleAction: function (barcode, activeBarcode) {
+ var record = this.model.get(this.handle);
+ var self = this;
+ return self._rpc({
+ model: record.data.model,
+ method: record.data.method,
+ args: [[record.data.res_id], barcode],
+ }).done(function (action) {
+ if (action){
+ self._barcodeStopListening();
+ self.do_action(action);
+ }
+ });
+ },
+});
+
+});
diff --git a/barcode_action/static/src/js/action_barcode_widget.js b/barcode_action/static/src/js/action_barcode_widget.js
new file mode 100644
index 0000000..5e5bbdf
--- /dev/null
+++ b/barcode_action/static/src/js/action_barcode_widget.js
@@ -0,0 +1,24 @@
+odoo.define('barcode_action.field', function (require) {
+"use strict";
+
+var AbstractField = require('web.AbstractField');
+var field_registry = require('web.field_registry');
+
+var ActionBarcodeField = AbstractField.extend({
+ init: function() {
+ this._super.apply(this, arguments);
+ this.trigger_up('activeBarcode', {
+ name: this.name,
+ commands: {
+ barcode: '_barcodeHandleAction',
+ }
+ });
+ },
+});
+field_registry.add('action_barcode_handler', ActionBarcodeField);
+
+return {
+ ActionBarcodeField:ActionBarcodeField,
+};
+
+});
diff --git a/barcode_action/tests/__init__.py b/barcode_action/tests/__init__.py
new file mode 100644
index 0000000..1050b9e
--- /dev/null
+++ b/barcode_action/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_partner_find
diff --git a/barcode_action/tests/test_partner_find.py b/barcode_action/tests/test_partner_find.py
new file mode 100644
index 0000000..ad57923
--- /dev/null
+++ b/barcode_action/tests/test_partner_find.py
@@ -0,0 +1,24 @@
+# Copyright 2018 Creu Blanca
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from odoo.tests.common import TransactionCase
+
+
+class TestPartnerFind(TransactionCase):
+
+ def test_partner(self):
+ partner_obj = self.env['res.partner']
+ ref = 'testing_partner_internal_reference'
+ partner = partner_obj.create({
+ 'name': 'Testing partner',
+ 'ref': ref,
+ })
+ # We should find the partner when the ref is found
+ self.assertEqual(
+ partner.id,
+ partner_obj.find_res_partner_by_ref_using_barcode(ref).get(
+ 'res_id', False))
+ # No partner is found, then there is no res_id on the result
+ self.assertFalse(
+ partner_obj.find_res_partner_by_ref_using_barcode(
+ '%s-%s' % (ref, ref)).get('res_id', False))
diff --git a/barcode_action/views/barcode_templates.xml b/barcode_action/views/barcode_templates.xml
new file mode 100644
index 0000000..52d3bcd
--- /dev/null
+++ b/barcode_action/views/barcode_templates.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/barcode_action/wizard/__init__.py b/barcode_action/wizard/__init__.py
new file mode 100644
index 0000000..3808e0e
--- /dev/null
+++ b/barcode_action/wizard/__init__.py
@@ -0,0 +1 @@
+from . import barcode_action
diff --git a/barcode_action/wizard/barcode_action.py b/barcode_action/wizard/barcode_action.py
new file mode 100644
index 0000000..c54924e
--- /dev/null
+++ b/barcode_action/wizard/barcode_action.py
@@ -0,0 +1,22 @@
+from odoo import fields, models
+
+
+class BarcodeAction(models.TransientModel):
+ _name = 'barcode.action'
+ _inherit = "barcodes.barcode_events_mixin"
+
+ model = fields.Char(
+ required=True, readonly=True
+ )
+ res_id = fields.Integer()
+ method = fields.Char(
+ required=True, readonly=True
+ )
+ state = fields.Selection([
+ ('waiting', 'Waiting'),
+ ('warning', 'Warning')
+ ], default='waiting', readonly=True, )
+ status = fields.Text(
+ readonly=True,
+ default="Start scanning",
+ )
diff --git a/barcode_action/wizard/barcode_action_view.xml b/barcode_action/wizard/barcode_action_view.xml
new file mode 100644
index 0000000..9abe0bb
--- /dev/null
+++ b/barcode_action/wizard/barcode_action_view.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+ barcode.action.form
+ barcode.action
+
+
+
+
+
+
+
+