[ADD] barcodes: onchange-like mechanism to react to scans in form view

For a model to use it, it must :
- Inherit barcodes.barcode_events_mixin and override on_barcode_scanned(self, barcode)
- Add <field name=barcode_scanned widget=barcode_handler/> to each form view that
  should listen to barcode events and trigger on_barcode_scanned.

The method on_barcode_scanned works just like an onchange.
This commit is contained in:
Arthur Maniet
2015-09-01 13:25:52 +02:00
parent c1cc4b830b
commit 2df4060c77
5 changed files with 111 additions and 0 deletions
+4
View File
@@ -1 +1,5 @@
# -*- coding: utf-8 -*-
import barcodes
import models
+3
View File
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import barcode_events_mixin
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from openerp import models, fields, api
class BarcodeEventsMixin(models.AbstractModel):
""" Mixin class for objects reacting when a barcode is scanned in their form views
which contains `<field name="_barcode_scanned" widget="barcode_handler"/>`.
Models using this mixin must implement the method on_barcode_scanned. It works
like an onchange and receives the scanned barcode in parameter.
"""
_name = 'barcodes.barcode_events_mixin'
_barcode_scanned = fields.Char("Barcode Scanned", help="Value of the last barcode scanned.", store=False)
@api.onchange('_barcode_scanned')
def _on_barcode_scanned(self):
barcode = self._barcode_scanned
if barcode:
self._barcode_scanned = ""
return self.on_barcode_scanned(barcode)
def on_barcode_scanned(self, barcode):
raise NotImplementedError("In order to use barcodes.barcode_events_mixin, method on_barcode_scanned must be implemented")
@@ -0,0 +1,79 @@
odoo.define('barcodes.FormViewBarcodeHandler', function(require) {
"use strict";
var core = require('web.core');
var utils = require('web.utils');
var common = require('web.form_common');
var _t = core._t;
var FormViewBarcodeHandler = common.AbstractField.extend({
start: function() {
this._super();
this.form_view = this.field_manager;
core.bus.on('barcode_scanned', this, this.on_barcode_scanned);
// Hardcoded barcode actions
this.map_barcode_method = {
'O-CMD.NEW': _.bind(this.form_view.on_button_new, this.form_view),
'O-CMD.CANCEL': _.bind(this.form_view.on_button_cancel, this.form_view),
// FIXME: on_button_save shouldn't mix view and model concerns (it expects to be used as onclick handler)
'O-CMD.SAVE': _.bind(this.form_view.on_button_save, this.form_view, {target: $('.o_cp_buttons .o_form_button_save')}),
};
// Old design pager actions
if (this.form_view.execute_pager_action) {
this.map_barcode_method['O-CMD.PAGER-PREV'] = _.bind(this.form_view.execute_pager_action, this.form_view, 'previous');
this.map_barcode_method['O-CMD.PAGER-NEXT'] = _.bind(this.form_view.execute_pager_action, this.form_view, 'next');
// New design pager actions
} else if (this.form_view.pager) {
this.map_barcode_method['O-CMD.PAGER-PREV'] = _.bind(this.form_view.pager.previous, this.form_view.pager);
this.map_barcode_method['O-CMD.PAGER-NEXT'] = _.bind(this.form_view.pager.next, this.form_view.pager);
}
},
// Let subclasses add custom behaviour before onchange
// Return false in order to proceed with the onchange, anything else to prevent it.
pre_onchange_hook: function(barcode) {
return false;
},
on_barcode_scanned: function(barcode) {
var self = this;
// Execute a harcoded action
var action = this.map_barcode_method[barcode];
if (typeof action === "function")
return $.when(action());
// Warn the user if form view is not editable
else if (this.form_view.get('actual_mode') === 'view')
this.do_warn(_t('Error : Document not editable'), _t('To modify this document, please first start edition.'));
else {
// Call hook method possibly implemented by subclass
$.when(this.pre_onchange_hook(barcode)).then(function(result) {
if (result !== false) {
return result;
} else {
// Wait for hypothetical ongoing onchange to finish
self.form_view.onchanges_mutex.exec(function() {
// A real onchange is triggered when a value actually changes (which can correspond
// to a widget's blur event per example). Commit the value of fields before
// programmatically triggering an onchange to be consistent with this.
var mutex_commit_value = new utils.Mutex();
_.each(self.form_view.fields, function(field) {
mutex_commit_value.exec(_.bind(field.commit_value, field));
});
return mutex_commit_value.def.then(function(){
// Trigger the barcode onchange
self.set_value(barcode);
});
});
}
});
}
},
});
core.form_widget_registry.add('barcode_handler', FormViewBarcodeHandler);
return FormViewBarcodeHandler;
});
+1
View File
@@ -6,6 +6,7 @@
<xpath expr="." position="inside">
<script type="text/javascript" src="/barcodes/static/src/js/barcode_parser.js"></script>
<script type="text/javascript" src="/barcodes/static/src/js/barcode_events.js"></script>
<script type="text/javascript" src="/barcodes/static/src/js/form_view_barcode_handler.js"></script>
</xpath>
</template>