[FIX] Stock allow barcode input on stock.picking o2m kanban
This commit is contained in:
@@ -143,11 +143,18 @@ msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#. openerp-web
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:51
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:122
|
||||
#, python-format
|
||||
msgid "Error : Document not editable"
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#. openerp-web
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:56
|
||||
#, python-format
|
||||
msgid "Error : No last scanned barcode"
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#: model:ir.model.fields,field_description:barcodes.field_barcode_nomenclature_id
|
||||
#: model:ir.model.fields,field_description:barcodes.field_barcode_rule_id
|
||||
@@ -209,6 +216,13 @@ msgstr ""
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#. openerp-web
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:68
|
||||
#, python-format
|
||||
msgid "Set quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#: model:ir.ui.view,arch_db:barcodes.view_barcode_nomenclature_form
|
||||
msgid "Tables"
|
||||
@@ -244,11 +258,18 @@ msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#. openerp-web
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:51
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:122
|
||||
#, python-format
|
||||
msgid "To modify this document, please first start edition."
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#. openerp-web
|
||||
#: code:addons/barcodes/static/src/js/form_view_barcode_handler.js:56
|
||||
#, python-format
|
||||
msgid "To set the quantity please scan a barcode first."
|
||||
msgstr ""
|
||||
|
||||
#. module: barcodes
|
||||
#: model:ir.model.fields,field_description:barcodes.field_barcode_rule_type
|
||||
msgid "Type"
|
||||
|
||||
@@ -6,10 +6,30 @@ var utils = require('web.utils');
|
||||
var common = require('web.form_common');
|
||||
var BarcodeEvents = require('barcodes.BarcodeEvents');
|
||||
var BarcodeHandlerMixin = require('barcodes.BarcodeHandlerMixin');
|
||||
var KanbanRecord = require('web_kanban.Record');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
// web_kanban.Record and web.list_common.Record do not implement the
|
||||
// same interface and are thus inherently incompatible with each
|
||||
// other. Luckily barcodes keeps things pretty simple when it comes to
|
||||
// the records it wants to use. So if we give the KanbanRecord a get()
|
||||
// function that behaves like the one of web.list.Record, everything
|
||||
// is fine.
|
||||
KanbanRecord.include({
|
||||
get: function (key) {
|
||||
return this.values[key] && this.values[key].value;
|
||||
},
|
||||
});
|
||||
|
||||
var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
||||
init: function(parent, context) {
|
||||
this.__quantity_listener = _.bind(this._set_quantity_listener, this);
|
||||
BarcodeHandlerMixin.init.apply(this, arguments);
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
start: function() {
|
||||
this._super();
|
||||
this.form_view = this.field_manager;
|
||||
@@ -31,7 +51,64 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
||||
this.map_barcode_method['O-CMD.PAGER-NEXT'] = _.bind(this.form_view.pager.next, this.form_view.pager);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_display_no_edit_mode_warning: function() {
|
||||
this.do_warn(_t('Error : Document not editable'), _t('To modify this document, please first start edition.'));
|
||||
},
|
||||
|
||||
_display_no_last_scanned_warning: function() {
|
||||
this.do_warn(_t('Error : No last scanned barcode'), _t('To set the quantity please scan a barcode first.'));
|
||||
},
|
||||
|
||||
_set_quantity_listener: function(event) {
|
||||
var self = this;
|
||||
var character = String.fromCharCode(event.which);
|
||||
|
||||
if (this.form_view.get('actual_mode') === 'view') {
|
||||
this._display_no_edit_mode_warning();
|
||||
} else if ($(event.target).is('body') && /[0-9]/.test(character)) { // only catch the event if we're not focused in
|
||||
// another field and it's a number
|
||||
var field = this.form_view.fields[this.m2x_field];
|
||||
var view = field.viewmanager.active_view;
|
||||
|
||||
if (this.last_scanned_barcode) {
|
||||
var new_qty = window.prompt(_t('Set quantity'), character) || "0";
|
||||
new_qty = new_qty.replace(',', '.');
|
||||
var record = this._get_records(field).find(function(record) {
|
||||
return record.get('product_barcode') === self.last_scanned_barcode;
|
||||
});
|
||||
if (record) {
|
||||
var values = {};
|
||||
values[this.quantity_field] = parseFloat(new_qty);
|
||||
field.data_update(record.get('id'), values).then(function () {
|
||||
view.controller.reload_record(record);
|
||||
});
|
||||
} else {
|
||||
this._display_no_last_scanned_warning();
|
||||
}
|
||||
} else {
|
||||
this._display_no_last_scanned_warning();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
start_listening: function() {
|
||||
if (this.quantity_field && ! this.is_listening) {
|
||||
core.bus.on('keypress', this, this.__quantity_listener);
|
||||
}
|
||||
|
||||
BarcodeHandlerMixin.start_listening.call(this);
|
||||
},
|
||||
|
||||
stop_listening: function() {
|
||||
if (this.quantity_field && this.is_listening) {
|
||||
core.bus.off('keypress', this, this.__quantity_listener);
|
||||
delete this.last_scanned_barcode;
|
||||
}
|
||||
|
||||
BarcodeHandlerMixin.stop_listening.call(this);
|
||||
},
|
||||
|
||||
// Let subclasses add custom behaviour before onchange. Must return a deferred.
|
||||
// Resolve the deferred with true proceed with the onchange, false to prevent it.
|
||||
pre_onchange_hook: function(barcode) {
|
||||
@@ -40,6 +117,7 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
||||
|
||||
on_barcode_scanned: function(barcode) {
|
||||
var self = this;
|
||||
self.last_scanned_barcode = barcode;
|
||||
// Execute a harcoded action
|
||||
var action = this.map_barcode_method[barcode];
|
||||
if (typeof action === "function")
|
||||
@@ -48,7 +126,7 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
||||
return;
|
||||
// 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.'));
|
||||
this._display_no_edit_mode_warning();
|
||||
else {
|
||||
// Call hook method possibly implemented by subclass
|
||||
this.pre_onchange_hook(barcode).then(function(proceed) {
|
||||
@@ -71,6 +149,11 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_get_records: function(field) {
|
||||
return field.viewmanager.active_view.controller.records || // tree view
|
||||
field.viewmanager.active_view.controller.widgets; // kanban view
|
||||
},
|
||||
});
|
||||
|
||||
core.form_widget_registry.add('barcode_handler', FormViewBarcodeHandler);
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<notebook attrs="{'invisible':[('state','=','draft')]}">
|
||||
<page string="Inventory Details" >
|
||||
<button name="reset_real_qty" states="confirm" string="⇒ Set quantities to 0" type="object" class="oe_link oe_right" groups="stock.group_stock_user"/>
|
||||
<field name="line_ids" string="Inventory Details" context="{'default_location_id': location_id, 'default_product_id': product_id, 'default_prod_lot_id': lot_id, 'default_package_id': package_id, 'default_partner_id': partner_id}">
|
||||
<field name="line_ids" string="Inventory Details" context="{'default_location_id': location_id, 'default_product_id': product_id, 'default_prod_lot_id': lot_id, 'default_package_id': package_id, 'default_partner_id': partner_id}" mode="tree,kanban">
|
||||
<tree string="Inventory Details" editable="bottom" decoration-info="product_qty != theoretical_qty" decoration-danger="theoretical_qty < 0">
|
||||
<field name="product_id" domain="[('type','=','product')]" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="product_uom_id" groups="product.group_uom" string="UoM" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
@@ -126,6 +126,48 @@
|
||||
<field name="product_qty" string="Real Quantity"/>
|
||||
<field name="state" invisible="True"/>
|
||||
</tree>
|
||||
<kanban class="o_kanban_mobile">
|
||||
<field name="product_id" domain="[('type','=','product')]" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="product_uom_id" groups="product.group_uom" string="UoM" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="location_id" domain="[('id', 'child_of', parent.location_id)]" groups="stock.group_locations" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)"/>
|
||||
<field name="prod_lot_id" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" domain="[('product_id', '=', product_id)]" context="{'default_product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="package_id" domain="['|', ('location_id','=', False), ('location_id', '=', location_id)]" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" groups="stock.group_tracking_lot"/>
|
||||
<field name="partner_id" on_change="onchange_createline(location_id, product_id, product_uom_id, package_id, prod_lot_id, partner_id)" groups="stock.group_tracking_owner"/>
|
||||
<field name="theoretical_qty" readonly="1"/>
|
||||
<field name="product_qty" string="Real Quantity"/>
|
||||
<field name="state" invisible="True"/>
|
||||
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click_edit
|
||||
#{record.product_qty.raw_value!=record.theoretical_qty.raw_value ? 'oe_kanban_color_6' : ''}
|
||||
#{record.theoretical_qty.raw_value<0 ? 'oe_kanban_color_2' : ''}">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<strong>
|
||||
<field name='product_id'/>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-muted">
|
||||
<span><t t-esc='record.location_id.string'/>: <t t-esc='record.location_id.value'/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-muted">
|
||||
<span><t t-esc='record.theoretical_qty.string'/>: <t t-esc='record.theoretical_qty.value'/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-muted">
|
||||
<span><t t-esc='record.product_qty.string'/>: <t t-esc='record.product_qty.value'/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
<p></p>
|
||||
<h3 class="oe_grey">Notes</h3>
|
||||
@@ -840,7 +882,7 @@
|
||||
<button name="do_prepare_partial" type="object" string="Recompute" attrs="{'invisible': [('recompute_pack_op','=', False)]}"/>
|
||||
<field name="recompute_pack_op" invisible="1"/>
|
||||
<field name="pack_operation_ids" invisible="1"/>
|
||||
<field name="pack_operation_product_ids" options="{'reload_on_button': True}" context="{'default_picking_id': id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id}">
|
||||
<field name="pack_operation_product_ids" options="{'reload_on_button': True}" context="{'default_picking_id': id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id}" mode="tree,kanban">
|
||||
<tree editable="bottom" decoration-muted="result_package_id" decoration-danger="qty_done>product_qty" decoration-success="qty_done==product_qty and state!='done' and not result_package_id">
|
||||
<field name="package_id" groups="stock.group_tracking_lot" invisible="1"/>
|
||||
<field name="product_id" on_change="product_id_change(product_id, product_uom_id, product_qty)" required="1" attrs="{'readonly': [('fresh_record', '=', False)]}"/>
|
||||
@@ -861,6 +903,53 @@
|
||||
<button name="show_details" string="Modify" type="object" icon="fa-pencil" groups="stock.group_locations"
|
||||
states="confirmed,assigned,waiting,partially_available"/>
|
||||
</tree>
|
||||
<kanban class="o_kanban_mobile">
|
||||
<field name="package_id" groups="stock.group_tracking_lot" invisible="1"/>
|
||||
<field name="product_id" on_change="product_id_change(product_id, product_uom_id, product_qty)" required="1" attrs="{'readonly': [('fresh_record', '=', False)]}"/>
|
||||
<field name="fresh_record" invisible="1"/>
|
||||
<field name="product_uom_id" attrs="{'readonly': [('fresh_record', '=', False)]}" groups="product.group_uom"/>
|
||||
<field name="lots_visible" invisible="1"/>
|
||||
<field name="owner_id" groups="stock.group_tracking_owner"/>
|
||||
<field name="location_id" domain="[('id', 'child_of', parent.location_id)]" invisible="1"/>
|
||||
<field name="location_dest_id" domain="[('id', 'child_of', parent.location_dest_id)]" invisible="1"/>
|
||||
<field name="from_loc" groups="stock.group_locations,stock.group_tracking_lot"/>
|
||||
<field name="to_loc" groups="stock.group_locations,stock.group_tracking_lot"/>
|
||||
<field name="result_package_id" groups="stock.group_tracking_lot" context="{'location_id': location_dest_id}" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="product_qty" readonly="1" attrs="{'required': [('product_id', '!=', False)]}"/>
|
||||
<field name="qty_done" attrs="{'readonly': [('lots_visible', '=', True)]}"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_card oe_kanban_global_click
|
||||
#{record.qty_done.raw_value>record.product_qty.raw_value ? 'oe_kanban_color_2' : ''}
|
||||
#{record.qty_done.raw_value==record.product_qty.raw_value && record.state.raw_value!='done' && ! record.result_package_id.raw_value ? 'oe_kanban_color_3' : ''}">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<strong><span><t t-esc="record.product_id.value"/></span></strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 text-muted">
|
||||
<span><t t-esc="record.from_loc.string"/>: <t t-esc="record.from_loc.value"/></span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-muted">
|
||||
<span><t t-esc="record.to_loc.string"/>: <t t-esc="record.to_loc.value"/></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 text-muted">
|
||||
<span><t t-esc="record.product_qty.string"/>: <t t-esc="record.product_qty.value"/></span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-muted">
|
||||
<span>
|
||||
<t t-esc="record.qty_done.string"/>: <t t-esc="record.qty_done.value"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
<field name="picking_type_entire_packs" invisible="1"/>
|
||||
<field name="pack_operation_pack_ids" options="{'reload_on_button': True}" attrs="{'invisible': [('pack_operation_pack_ids', '=', []), ('picking_type_entire_packs', '=', False)]}" context="{'default_picking_id': id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_picking_id': id}" groups="stock.group_tracking_lot">
|
||||
|
||||
Reference in New Issue
Block a user