[WIP]barcode interface: allow to enter qty when highlight one line

bzr revid: csn@openerp.com-20140310165707-72sgol8cwlzlbb85
This commit is contained in:
Cedric Snauwaert 2014-03-10 17:57:07 +01:00
parent a2bf8d640c
commit ca880533ee
4 changed files with 185 additions and 63 deletions

View File

@ -54,6 +54,42 @@
color: #6d2c70;
}
/*Blinking text*/
.blink_me {
-webkit-animation-name: blinker;
-webkit-animation-duration: 1s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-moz-animation-name: blinker;
-moz-animation-duration: 1s;
-moz-animation-timing-function: linear;
-moz-animation-iteration-count: infinite;
animation-name: blinker;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@-moz-keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
@-webkit-keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
@keyframes blinker {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
/*hide OpenERP leftbar, table should use all width by default and display vertical scrollbar if needed*/
.oe_leftbar {
display: none;

View File

@ -64,6 +64,7 @@ function openerp_picking_widgets(instance){
renderElement: function(){
var self = this;
this._super();
this.disconnect_numpad();
this.$('.js_pack_scan').click(function(){
var id = parseInt($(this).attr('op-id'));
self.getParent().scan_product_id(id);
@ -75,10 +76,30 @@ function openerp_picking_widgets(instance){
else{
$(this).addClass('warning');
}
self.check_change_quantity();
});
//remove navigtion bar from default openerp GUI
$('td.navbar').html('<div></div>');
},
check_change_quantity: function(){
var self = this;
if (this.$('.js_pack_op_line.warning:not(.hidden)').length === 1){
cur_id = this.$('.js_pack_op_line.warning:not(.hidden)')[0].attributes.getNamedItem('data-id').value;
op_id = parseInt(cur_id);
this.$('.js_pack_op_line:not(.hidden)[data-id='+op_id+'] > .js_row_qty').addClass('blink_me');
var value = [0,0]
_.each(this.rows, function(row){
if (row.cols.id === op_id){
value = [row.cols.rem, row.cols.qty, row.cols.uom];
}
});
this.connect_numpad(value, op_id);
}
else{
this.disconnect_numpad();
this.$('.js_row_qty.blink_me').removeClass('blink_me');
}
},
on_searchbox: function(query){
//hide line that has no location matching the query and highlight location that match the query
if (query !== '') {
@ -98,14 +119,12 @@ function openerp_picking_widgets(instance){
//get ids of visible on the screen
pack_op_ids = []
if (this.$('.js_pack_op_line.warning:not(.js_pack_op_line.hidden)').length > 0){
console.log('some selected');
this.$('.js_pack_op_line.warning:not(.js_pack_op_line.hidden)').each(function(){
cur_id = this.attributes.getNamedItem('data-id').value;
pack_op_ids.push(parseInt(cur_id));
});
}
else{
console.log('nothing selected');
this.$('.js_pack_op_line:not(.js_pack_op_line.hidden)').each(function(){
cur_id = this.attributes.getNamedItem('data-id').value;
pack_op_ids.push(parseInt(cur_id));
@ -120,7 +139,58 @@ function openerp_picking_widgets(instance){
});
//return only those visible with rem qty > 0 and container empty
return _.intersection(pack_op_ids, list);
}
},
unhighlight: function(){
this.$('.js_pack_op_line.warning').removeClass('warning');
this.$('.js_row_qty.blink_me').removeClass('blink_me');
},
connect_numpad: function(value, op_id){
var self = this;
var numpad = [];
var numpad_timestamp;
var processed = value[0];
var total = value[1];
var uom = '';
if (value[2] !== undefined){ uom = value[2]; }
this.refresh = function(){
if (numpad.length === 0){
self.$('.js_row_qty.blink_me').text(processed + ' / ' + total + ' ' + uom);
}
else {
self.$('.js_row_qty.blink_me').text(parseInt(numpad.join('')) + ' / ' + total + ' ' + uom);
}
}
this.numpad_handler = function(e){
console.log(e.keyCode);
if(numpad_timestamp + 1500 < new Date().getTime()){
numpad = [];
}
if(e.keyCode === 27){ // ESC
numpad = [];
}
else if(e.keyCode === 8){ // BACKSPACE
numpad.pop();
}else if(e.keyCode >= 48 && e.keyCode <= 57){ // NUMPAD NUMBERS
numpad.push(e.keyCode - 48);
}else if(e.keyCode === 13){ // ENTER
self.unhighlight();
self.disconnect_numpad();
if(numpad.length > 0){
self.getParent().set_operation_quantity(parseInt(numpad.join('')), op_id);
}
// numpad = [];
}
self.refresh();
numpad_timestamp = new Date().getTime();
};
$('body').on('keydown', this.numpad_handler);
},
disconnect_numpad: function(){
jQuery.event.trigger({ type : 'keydown', which : 27 });
$('body').off('keydown', this.numpad_handler);
},
});
// module.PackageEditorWidget = instance.web.Widget.extend({
@ -462,7 +532,7 @@ function openerp_picking_widgets(instance){
this._super();
var self = this;
instance.webclient.set_content_full_screen(true);
this.connect_numpad();
// this.connect_numpad();
this.barcode_scanner.connect(function(ean){
self.scan(ean);
});
@ -574,19 +644,16 @@ function openerp_picking_widgets(instance){
new instance.web.Model('stock.picking')
.call('process_barcode_from_ui', [self.picking.id, ean])
.then(function(result){
if (typeof(result)!="boolean"){
if (result.filter_loc !== false){
//check if we have receive a location as answer
if (result.filter_loc !== undefined){
self.$('.oe_searchbox').val(result.filter_loc);
self.on_searchbox(result.filter_loc);
}
}
else{
console.log(result.operation_id);
if (result.operation_id !== false){
return self.refresh_ui(self.picking.id);
//TODO add a then to highlight the line that was scanned, do same to scan_product_id
// .then(function(product_id){
// self.
// });
}
});
},
@ -594,7 +661,7 @@ function openerp_picking_widgets(instance){
var self = this;
new instance.web.Model('stock.picking')
.call('process_product_id_from_ui', [self.picking.id, product_id])
.then(function(){
.then(function(result){
return self.refresh_ui(self.picking.id);
});
},
@ -740,53 +807,64 @@ function openerp_picking_widgets(instance){
return null;
}
},
set_operation_quantity: function(quantity){
set_operation_quantity: function(quantity, op_id){
var self = this;
var op = this.get_selected_operation();
if( !op ){
//TODO typing the ean of a product manually ?
//(scanning the barcode is already handled somewhere else, and i don't know how to differenciate the 2 operations)
// and the result is that if i uncomment the next line, scanning a product counts it twice
//self.scan(quantity);
}
else {if(typeof quantity === 'number' && quantity >= 0){
if(quantity >= 0){
new instance.web.Model('stock.pack.operation')
.call('write',[[op],{'product_qty': quantity }])
.call('write',[[op_id],{'qty_done': quantity }])
.then(function(){
self.refresh_ui(self.picking.id);
});
}}
}
},
connect_numpad: function(){
var self = this;
var numpad = [];
var numpad_timestamp;
// set_operation_quantity: function(quantity){
// var self = this;
// var op = this.get_selected_operation();
// if( !op ){
// //TODO typing the ean of a product manually ?
// //(scanning the barcode is already handled somewhere else, and i don't know how to differenciate the 2 operations)
// // and the result is that if i uncomment the next line, scanning a product counts it twice
// //self.scan(quantity);
// }
// else {if(typeof quantity === 'number' && quantity >= 0){
// new instance.web.Model('stock.pack.operation')
// .call('write',[[op],{'product_qty': quantity }])
// .then(function(){
// self.refresh_ui(self.picking.id);
// });
// }}
// },
// connect_numpad: function(){
// var self = this;
// var numpad = [];
// var numpad_timestamp;
this.numpad_handler = function(e){
if(numpad_timestamp + 1500 < new Date().getTime()){
numpad = [];
}
if(e.keyCode === 27 || e.keyCode === 8){ // ESC or BACKSPACE
numpad = [];
}else if(e.keyCode >= 48 && e.keyCode <= 57){ // NUMPAD NUMBERS
numpad.push(e.keyCode - 48);
}else if(e.keyCode === 13){ // ENTER
if(numpad.length > 0){
self.set_operation_quantity(parseInt(numpad.join('')));
}
numpad = [];
}else{
numpad = [];
}
numpad_timestamp = new Date().getTime();
};
$('body').on('keypress', this.numpad_handler);
},
disconnect_numpad: function(){
$('body').off('keypress', this.numpad_handler);
},
// this.numpad_handler = function(e){
// if(numpad_timestamp + 1500 < new Date().getTime()){
// numpad = [];
// }
// if(e.keyCode === 27 || e.keyCode === 8){ // ESC or BACKSPACE
// numpad = [];
// }else if(e.keyCode >= 48 && e.keyCode <= 57){ // NUMPAD NUMBERS
// numpad.push(e.keyCode - 48);
// }else if(e.keyCode === 13){ // ENTER
// if(numpad.length > 0){
// self.set_operation_quantity(parseInt(numpad.join('')));
// }
// numpad = [];
// }else{
// numpad = [];
// }
// numpad_timestamp = new Date().getTime();
// };
// $('body').on('keypress', this.numpad_handler);
// },
// disconnect_numpad: function(){
// $('body').off('keypress', this.numpad_handler);
// },
quit: function(){
this.destroy();
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_picking_type_form']], ['res_id']).pipe(function(res) {
@ -795,7 +873,7 @@ function openerp_picking_widgets(instance){
},
destroy: function(){
this._super();
this.disconnect_numpad();
// this.disconnect_numpad();
this.barcode_scanner.disconnect();
$('body').off('keyup',this.hotkey_handler);
instance.webclient.set_content_full_screen(false);

View File

@ -51,13 +51,14 @@
<h2><strong><div class='oe_pick_list_header'>
Operations Informations
</div></strong></h2>
<table class='table table-condensed'>
<table class='table table-condensed js_op_table_todo'>
<thead>
<tr>
<th class="text-center">Product</th>
<th class='text-center'>Quantity</th>
<th>From</th>
<th>To</th>
<th>Container</th>
</tr>
</thead>
@ -65,12 +66,13 @@
<t t-foreach="widget.get_rows()" t-as="row">
<tr t-att-class="row.classes + ' js_pack_op_line'" t-att-data-id="row.cols.id">
<td class="text-center"> <span class='btn btn-default pull-left js_pack_scan' t-att-op-id='row.cols.product_id'></span> <t t-esc="row.cols.product" /> </td>
<td class='text-center'><t t-esc="row.cols.rem" /> / <t t-esc="row.cols.qty" /> <t t-esc="row.cols.uom" /></td>
<td class='text-center js_row_qty'><t t-esc="row.cols.rem" /> / <t t-esc="row.cols.qty" /> <t t-esc="row.cols.uom" /></td>
<td class="js_loc"> <t t-esc="row.cols.loc" />
<t t-if="row.cols.lot" ><span> : <t t-esc="row.cols.lot" /></span></t>
<t t-if="row.cols.pack" ><span> : <t t-esc="row.cols.pack" /></span></t>
<t t-if="row.cols.lot" ><span> : <t t-esc="row.cols.lot" /></span></t>
</td>
<td class="js_loc"> <t t-esc="row.cols.dest" /> </td>
<td class=""><t t-esc="row.cols.container"></t></td>
</tr>
</t>
</tbody>

View File

@ -1263,29 +1263,35 @@ class stock_picking(osv.osv):
product_obj = self.pool.get('product.product')
stock_operation_obj = self.pool.get('stock.pack.operation')
stock_location_obj = self.pool.get('stock.location')
answer = {'filter_loc': False, 'operation_id': False}
#check if the barcode correspond to a location
matching_location_ids = stock_location_obj.search(cr, uid, [('loc_barcode', '=', barcode_str)], context=context)
if matching_location_ids:
#if we have a location, return immediatly with the location name
location = stock_location_obj.browse(cr, uid, matching_location_ids[0], context=None)
return {'filter_loc': stock_location_obj._name_get(cr, uid, location, context=None)}
answer['filter_loc'] = stock_location_obj._name_get(cr, uid, location, context=None)
return answer
# return {'filter_loc': stock_location_obj._name_get(cr, uid, location, context=None)}
#check if the barcode correspond to a product
matching_product_ids = product_obj.search(cr, uid, ['|', ('ean13', '=', barcode_str), ('default_code', '=', barcode_str)], context=context)
if matching_product_ids:
self.process_product_id_from_ui(cr, uid, picking_id, matching_product_ids[0], context=context)
op_id = self.process_product_id_from_ui(cr, uid, picking_id, matching_product_ids[0], context=context)
answer['operation_id'] = op_id
return answer
#check if the barcode correspond to a lot
matching_lot_ids = lot_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
if matching_lot_ids:
lot = lot_obj.browse(cr, uid, matching_lot_ids[0], context=context)
stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', lot.product_id.id), ('lot_id', '=', lot.id)], context=context)
op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', lot.product_id.id), ('lot_id', '=', lot.id)], context=context)
answer['operation_id'] = op_id
return answer
#check if the barcode correspond to a package
matching_package_ids = package_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
if matching_package_ids:
stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', matching_package_ids[0])], context=context)
return False
op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', matching_package_ids[0])], context=context)
answer['operation_id'] = op_id
return answer
return answer
class stock_production_lot(osv.osv):
_name = 'stock.production.lot'
@ -3688,7 +3694,7 @@ class stock_pack_operation(osv.osv):
update_dict['product_uom_id'] = uom_id
values.update(update_dict)
operation_id = self.create(cr, uid, values, context=context)
return True
return operation_id
class stock_move_operation_link(osv.osv):