summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric van der Essen <fva@openerp.com>2013-10-03 12:07:38 +0200
committerFrédéric van der Essen <fva@openerp.com>2013-10-03 12:07:38 +0200
commit671ea483bbedc8f9a92c2bc930d44bfa3bef2202 (patch)
treeab1e93b310261302a87e95173dae937c4a740ad6
parent5e5fc75451e166fa60d28aa5a23bb1dcf0bc636c (diff)
parent60792c9353ee59a3cbcd48610b9205761d357569 (diff)
[MERGE] stock_picking_ui: new picking selection menu
bzr revid: fva@openerp.com-20131003100738-zxj5x6f5m99luhar
-rw-r--r--addons/stock/static/src/css/picking.css46
-rw-r--r--addons/stock/static/src/js/main.js12
-rw-r--r--addons/stock/static/src/js/stock_picking_type.js1
-rw-r--r--addons/stock/static/src/js/widgets.js328
-rw-r--r--addons/stock/static/src/xml/picking.xml42
5 files changed, 342 insertions, 87 deletions
diff --git a/addons/stock/static/src/css/picking.css b/addons/stock/static/src/css/picking.css
index 2b1ecd26b1c..edf62fc7945 100644
--- a/addons/stock/static/src/css/picking.css
+++ b/addons/stock/static/src/css/picking.css
@@ -47,8 +47,8 @@
}
.oe_pick_widget .oe_pick_button{
display: inline-block;
- min-width: 120px;
- padding: 5px;
+ min-width: 64px;
+ padding: 5px 10px;
font-size: 18px;
border-radius: 3px;
margin: 10px 5px;
@@ -62,11 +62,34 @@
cursor: pointer;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
}
+.oe_pick_widget .oe_pick_button.oe_disabled {
+ cursor: default;
+ background: linear-gradient(#666666, #474747);
+ border: solid 1px rgb(44, 44, 44);
+ color: rgb(53, 53, 53);
+ box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.32) inset;
+}
+
+.oe_pick_widget .oe_pick_button:not(.oe_disabled):active,
+.oe_pick_widget .oe_pick_button:not(.oe_disabled).oe_active{
+ background: rgb(92, 84, 133);
+ box-shadow: 0px 1px 0px 1px rgba(0,0,0,0.3) inset;
+ margin: 11px 6px;
+ border: none;
+ color: white;
+ text-shadow: 0px 1px rgba(0,0,0, 0.3);
+}
+
+.oe_pick_widget .oe_pick_button.oe_small{
+ min-width: 0px;
+ width: 32px;
+}
.oe_pick_widget .oe_pick_right_toolbar{
float: right;
-}
-.oe_pick_widget .oe_pick_right_toolbar .oe_pick_button{
- margin-right: 10px;
+ border-left: solid 1px black;
+ padding-left: 8px;
+ padding-right: 8px;
+ margin-left: 8px;
}
.oe_pick_widget .oe_pick_col_small{ width: 60px; }
.oe_pick_widget .oe_pick_col_medium{ width: 100px; }
@@ -79,6 +102,19 @@
color: rgb(168, 6, 6);
}
+.oe_pick_widget .oe_pick_app_title{
+ font-size: 20px;
+ margin-top: 0px;
+}
+.oe_pick_widget .oe_pick_app_subtitle{
+ font-size: 16px;
+ font-weight: normal;
+}
+.oe_pick_widget .oe_pick_app_info{
+ margin-left: 4px;
+ opacity: 0.5;
+}
+
/* ----------------------- *
* PICKING TABLES *
* ----------------------- */
diff --git a/addons/stock/static/src/js/main.js b/addons/stock/static/src/js/main.js
deleted file mode 100644
index 08e93d29950..00000000000
--- a/addons/stock/static/src/js/main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-console.log('Executing picking module');
-
-openerp.stock = function(openerp){
-
- console.log('Loading stock picking module');
-
- openerp.stock = instance.stock || {};
- openerp_picking_widgets(openerp);
- openerp.web.client_actions.add('stock.ui', 'instance.stock.PickingMainWidget');
-};
-
-
diff --git a/addons/stock/static/src/js/stock_picking_type.js b/addons/stock/static/src/js/stock_picking_type.js
index 49886b8e689..5b87ba891dc 100644
--- a/addons/stock/static/src/js/stock_picking_type.js
+++ b/addons/stock/static/src/js/stock_picking_type.js
@@ -65,6 +65,5 @@ openerp.stock = function(openerp) {
openerp.stock = openerp.stock || {};
openerp_picking_widgets(openerp);
- openerp.web.client_actions.add('stock.ui', 'instance.stock.PickingMainWidget');
};
diff --git a/addons/stock/static/src/js/widgets.js b/addons/stock/static/src/js/widgets.js
index c8f91452adf..8244124714c 100644
--- a/addons/stock/static/src/js/widgets.js
+++ b/addons/stock/static/src/js/widgets.js
@@ -97,6 +97,104 @@ function openerp_picking_widgets(instance){
},
});
+ module.PickingMenuWidget = instance.web.Widget.extend({
+ template: 'PickingMenuWidget',
+ init: function(parent, params){
+ this._super(parent,params);
+ var self = this;
+
+ this.picking_types = [];
+ this.loaded = this.load();
+ this.scanning_type = 0;
+ this.barcode_scanner = new module.BarcodeScanner();
+ this.pickings_by_type = {};
+
+ },
+ load: function(){
+ var self = this;
+ return new instance.web.Model('stock.picking.type').get_func('search_read')([],[])
+ .then(function(types){
+ self.picking_types = types;
+
+ for(var i = 0; i < types.length; i++){
+ self.pickings_by_type[types[i].id] = [];
+ }
+ self.pickings_by_type[0] = [];
+
+ return new instance.web.Model('stock.picking').call('search_read',[ [['state','in',['confirmed','assigned']]], [] ], {context: new instance.web.CompoundContext()});
+
+ }).then(function(pickings){
+ self.pickings = pickings;
+
+ for(var i = 0; i < pickings.length; i++){
+ var picking = pickings[i];
+ self.pickings_by_type[picking.picking_type_id[0]].push(picking);
+ }
+ });
+ },
+ renderElement: function(){
+ this._super();
+ var self = this;
+ this.$('.js_pick_quit').click(function(){ self.quit(); });
+ this.$('.js_pick_scan').click(function(){ self.scan_picking($(this).data('id')); });
+ this.$('.js_pick_last').click(function(){ self.goto_picking($(this).data('id')); });
+ },
+ start: function(){
+ var self = this;
+ this.barcode_scanner.connect(function(barcode){
+ self.on_scan(barcode);
+ });
+ this.loaded.then(function(){
+ self.renderElement();
+ });
+ },
+ goto_picking: function(type_id){
+ this.do_action({
+ type: 'ir.actions.client',
+ tag: 'stock.ui',
+ target: 'current',
+ context: { active_id: type_id },
+ },{
+ clear_breadcrumbs: true,
+ });
+ },
+ scan_picking: function(id){
+ this.$('.js_pick_scan.oe_active').text(_t('Scan')).removeClass('oe_active');
+ if(id !== this.scanning_type){
+ this.$('.js_pick_scan[data-id='+id+']').text(_t('Please scan a barcode ...')).addClass('oe_active');
+ this.scanning_type = id;
+ }else{
+ this.scanning_type = 0;
+ }
+ },
+ on_scan: function(barcode){
+ for(var i = 0, len = this.pickings.length; i < len; i++){
+ var picking = this.pickings[i];
+ if(picking.picking_type_id[0] === this.scanning_type && picking.name.toUpperCase() === barcode.toUpperCase()){
+ this.do_action({
+ type: 'ir.actions.client',
+ tag: 'stock.ui',
+ target: 'current',
+ context: { picking_id: picking.id },
+ },{
+ clear_breadcrumbs: true,
+ });
+ }
+ }
+ this.$('.js_pick_scan.oe_active').text(_t('Scanned picking not found'));
+ },
+ quit: function(){
+ instance.webclient.set_content_full_screen(false);
+ window.location = '/'; // FIXME Ask niv how to do it correctly
+ },
+ destroy: function(){
+ this._super();
+ this.barcode_scanner.disconnect();
+ instance.webclient.set_content_full_screen(false);
+ },
+ });
+ openerp.web.client_actions.add('stock.menu', 'instance.stock.PickingMenuWidget');
+
module.PickingMainWidget = instance.web.Widget.extend({
template: 'PickingMainWidget',
init: function(parent,params){
@@ -104,31 +202,34 @@ function openerp_picking_widgets(instance){
var self = this;
this.picking = null;
+ this.pickings = [];
this.movelines = null;
this.operations = null;
this.packages = null;
- this.scan_timestamp = 0;
- this.numpad_buffer = [];
-
- window.pickwidget = this;
+ this.barcode_scanner = new module.BarcodeScanner();
+ this.picking_type_id = params.context.active_id || 0;
- console.log('Action params:', params);
- console.log('Session:',instance.session);
- this.loaded = this.load();
+ if(params.context.picking_id){
+ this.loaded = this.load(params.context.picking_id);
+ }else{
+ this.loaded = this.load();
+ }
},
+
+ // load the picking data from the server. If picking_id is undefined, it will take the first picking
+ // belonging to the category
load: function(picking_id){
var self = this;
- console.log('LOADING DATA FROM SERVER');
+
+ function load_picking_list(type_id){
+ var pickings = new $.Deferred();
- if(picking_id){
- var picking = new instance.web.Model('stock.picking').call('read',[[picking_id], []]);
- }else{
- var picking = new instance.web.Model('stock.picking')
- .call('get_picking_for_packing_ui')
- .then(function(picking_id){
- if(!picking_id){
+ new instance.web.Model('stock.picking')
+ .call('get_picking_for_packing_ui',[{'default_picking_type_id':type_id}])
+ .then(function(picking_ids){
+ if(!picking_ids || picking_ids.length === 0){
(new instance.web.Dialog(self,{
title: _t('No Picking Available'),
buttons: [{
@@ -139,28 +240,48 @@ function openerp_picking_widgets(instance){
}]
}, _t('<p>We could not find a picking to display.</p>'))).open();
- return (new $.Deferred()).reject();
+ pickings.reject();
}else{
- return new instance.web.Model('stock.picking').call('read',[[picking_id],[]]);
+ self.pickings = picking_ids;
+ pickings.resolve(picking_ids);
}
});
+
+ return pickings;
+ }
+
+ // if we have a specified picking id, we load that one, and we load the picking of the same type as the active list
+ if( picking_id ){
+ var loaded_picking = new instance.web.Model('stock.picking')
+ .call('read',[[picking_id], [], new instance.web.CompoundContext()])
+ .then(function(picking){
+ self.picking = picking[0];
+
+ return load_picking_list(self.picking.picking_type_id[0]);
+ });
+ }else{
+ // if we don't have a specified picking id, we load the pickings belong to the specified type, and then we take
+ // the first one of that list as the active picking
+ var loaded_picking = new $.Deferred();
+ load_picking_list(self.picking_type_id)
+ .then(function(){
+ return new instance.web.Model('stock.picking').call('read',[self.pickings[0],[], new instance.web.CompoundContext()]);
+ })
+ .then(function(picking){
+ self.picking = picking;
+ loaded_picking.resolve();
+ });
}
- var loaded = picking.then(function(picking){
- self.picking = picking instanceof Array ? picking[0] : picking;
- console.log('Picking:',self.picking);
- console.log('User Context:', instance.session.user_context);
- console.log('Context:', new instance.web.CompoundContext().eval());
+ var loaded = loaded_picking.then(function(){
return new instance.web.Model('stock.move').call('read',[self.picking.move_lines, [], new instance.web.CompoundContext()]);
}).then(function(movelines){
self.movelines = movelines;
- console.log('Move Lines:',movelines);
return new instance.web.Model('stock.pack.operation').call('read',[self.picking.pack_operation_ids, [], new instance.web.CompoundContext()]);
}).then(function(operations){
self.operations = operations;
- console.log('Operations:',self.operations);
var package_ids = [];
@@ -170,24 +291,29 @@ function openerp_picking_widgets(instance){
}
}
- console.log('Package ids:',package_ids);
return new instance.web.Model('stock.quant.package').call('read',[package_ids, [], new instance.web.CompoundContext()]);
}).then(function(packages){
self.packages = packages;
- console.log('Packages:', self.packages);
});
return loaded;
+
},
start: function(){
var self = this;
instance.webclient.set_content_full_screen(true);
- this.connect_barcode_scanner_and_numpad();
+ this.connect_numpad();
+ this.barcode_scanner.connect(function(ean){
+ self.scan(ean);
+ });
this.$('.js_pick_quit').click(function(){ self.quit(); });
this.$('.js_pick_pack').click(function(){ self.pack(); });
this.$('.js_pick_done').click(function(){ self.done(); });
+ this.$('.js_pick_prev').click(function(){ self.picking_prev(); });
+ this.$('.js_pick_next').click(function(){ self.picking_next(); });
+ this.$('.js_pick_menu').click(function(){ self.menu(); });
$.when(this.loaded).done(function(){
self.picking_editor = new module.PickingEditorWidget(self);
@@ -198,6 +324,19 @@ function openerp_picking_widgets(instance){
self.package_selector = new module.PackageSelectorWidget(self);
self.package_selector.replace(self.$('.oe_placeholder_package_selector'));
+
+ if( self.picking.id === self.pickings[0]){
+ self.$('.js_pick_prev').addClass('oe_disabled');
+ }else{
+ self.$('.js_pick_prev').removeClass('oe_disabled');
+ }
+
+ if( self.picking.id === self.pickings[self.pickings.length-1] ){
+ self.$('.js_pick_next').addClass('oe_disabled');
+ }else{
+ self.$('.js_pick_next').removeClass('oe_disabled');
+ }
+
});
@@ -209,57 +348,88 @@ function openerp_picking_widgets(instance){
var self = this;
return this.load(picking_id)
.then(function(){
- console.log('REFRESHING UI');
self.picking_editor.renderElement();
self.package_editor.renderElement();
self.package_selector.renderElement();
+ if( self.picking.id === self.pickings[0]){
+ self.$('.js_pick_prev').addClass('oe_disabled');
+ }else{
+ self.$('.js_pick_prev').removeClass('oe_disabled');
+ }
+
+ if( self.picking.id === self.pickings[self.pickings.length-1] ){
+ self.$('.js_pick_next').addClass('oe_disabled');
+ }else{
+ self.$('.js_pick_next').removeClass('oe_disabled');
+ }
});
},
+ menu: function(){
+ this.do_action({
+ type: 'ir.actions.client',
+ tag: 'stock.menu',
+ target: 'current',
+ },{
+ clear_breadcrumbs: true,
+ });
+
+ },
scan: function(ean){
var self = this;
- console.log('Scan: ',ean);
new instance.web.Model('stock.picking')
.call('get_barcode_and_return_todo_stuff', [self.picking.id, ean])
.then(function(){
return self.refresh_ui(self.picking.id);
});
- this.scan_timestamp = new Date().getTime();
},
pack: function(){
var self = this;
- console.log('Pack');
new instance.web.Model('stock.picking')
.call('action_pack',[[[self.picking.id]]])
.then(function(){
instance.session.user_context.current_package_id = false;
- console.log('Context Reset');
return self.refresh_ui(self.picking.id);
});
},
done: function(){
var self = this;
- console.log('Done');
new instance.web.Model('stock.picking')
.call('action_done_from_packing_ui',[self.picking.id])
.then(function(new_picking_id){
- console.log('New picking id:',new_picking_id);
return self.refresh_ui(new_picking_id);
});
},
print_package: function(package_id){
var self = this;
- console.log('Print Package:',package_id);
new instance.web.Model('stock.quant.package')
.call('action_print',[[package_id]])
.then(function(action){
- console.log('Print Package Repport Action:',action);
return self.do_action(action);
});
},
+ picking_next: function(){
+ for(var i = 0; i < this.pickings.length; i++){
+ if(this.pickings[i] === this.picking.id){
+ if(i < this.pickings.length -1){
+ this.refresh_ui(this.pickings[i+1]);
+ return;
+ }
+ }
+ }
+ },
+ picking_prev: function(){
+ for(var i = 0; i < this.pickings.length; i++){
+ if(this.pickings[i] === this.picking.id){
+ if(i > 0){
+ this.refresh_ui(this.pickings[i-1]);
+ return;
+ }
+ }
+ }
+ },
copy_package: function(package_id){
var self = this;
- console.log('Copy Package:',package_id);
new instance.web.Model('stock.quant.package')
.call('copy',[[package_id]])
.then(function(){
@@ -268,7 +438,6 @@ function openerp_picking_widgets(instance){
},
delete_package: function(package_id){
var self = this;
- console.log('Delete Package:',package_id);
new instance.web.Model('stock.quant.package')
.call('unlink',[[package_id]])
.then(function(){
@@ -276,13 +445,11 @@ function openerp_picking_widgets(instance){
});
},
deselect_package: function(){
- console.log('Deselect Package');
instance.session.user_context.current_package_id = false;
this.package_editor.renderElement();
this.package_selector.renderElement();
},
select_package: function(package_id){
- console.log('Select Package:',package_id);
instance.session.user_context.current_package_id = package_id;
this.package_editor.renderElement();
this.package_selector.renderElement();
@@ -322,15 +489,12 @@ function openerp_picking_widgets(instance){
var op = ops[ops.length-1];
if(quantity === '++'){
- console.log('Increase quantity!');
quantity = op.product_qty + 1;
}else if(quantity === '--'){
- console.log('Decrease quantity :(');
quantity = op.product_qty - 1;
}
if(typeof quantity === 'number' && quantity >= 0){
- console.log('Set quantity: ',quantity);
new instance.web.Model('stock.pack.operation')
.call('write',[[op.id],{'product_qty': quantity }])
.then(function(){
@@ -339,27 +503,14 @@ function openerp_picking_widgets(instance){
}
},
- connect_barcode_scanner_and_numpad: function(){
+ connect_numpad: function(){
var self = this;
- var numbers = [];
- var timestamp = 0;
var numpad = [];
var numpad_timestamp;
- // it is important to catch the keypress event and not keyup/keydown as keypress normalizes the input codes :)
- $('body').delegate('','keyup',function(e){
- //console.log('Key:',e.keyCode);
- if (e.keyCode >= 48 && e.keyCode < 58){
- if(timestamp + 30 < new Date().getTime()){
- numbers = [];
- }
- numbers.push(e.keyCode - 48);
- timestamp = new Date().getTime();
- if(numbers.length === 13){
- self.scan(numbers.join(''));
- numbers = [];
- }
- }else{
- numbers = [];
+
+ this.numpad_handler = function(e){
+ // upper row numbers are reserved for the barcode scanner
+ if( e.keyCode < 48 && e.keyCode >= 58){
if(numpad_timestamp + 1500 < new Date().getTime()){
numpad = [];
}
@@ -383,16 +534,59 @@ function openerp_picking_widgets(instance){
}
numpad_timestamp = new Date().getTime();
}
- });
+ };
+ $('body').on('keypress', this.numpad_handler);
},
- disconnect_barcode_scanner_and_numpad: function(){
- $('body').undelegate('', 'keyup')
+ disconnect_numpad: function(){
+ $('body').off('keypress', this.numpad_handler);
},
quit: function(){
- console.log('Quit');
- this.disconnect_barcode_scanner_and_numpad();
- instance.webclient.set_content_full_screen(false);
+ this.destroy();
window.location = '/'; // FIXME Ask niv how to do it correctly
},
+ destroy: function(){
+ this._super();
+ this.disconnect_numpad();
+ this.barcode_scanner.disconnect();
+ instance.webclient.set_content_full_screen(false);
+ },
});
+ openerp.web.client_actions.add('stock.ui', 'instance.stock.PickingMainWidget');
+
+ module.BarcodeScanner = instance.web.Class.extend({
+ connect: function(callback){
+ var code = "";
+ var timeStamp = 0;
+ var timeout = null;
+
+ this.handler = function(e){
+ if(e.which === 13){ //ignore returns
+ return;
+ }
+
+ if(timeStamp + 50 < new Date().getTime()){
+ code = "";
+ }
+
+ timeStamp = new Date().getTime();
+ clearTimeout(timeout);
+
+ code += String.fromCharCode(e.which);
+
+ timeout = setTimeout(function(){
+ if(code.length >= 3){
+ callback(code);
+ }
+ code = "";
+ },100);
+ };
+
+ $('body').on('keypress', this.handler);
+
+ },
+ disconnect: function(){
+ $('body').off('keypress', this.handler);
+ },
+ });
+
}
diff --git a/addons/stock/static/src/xml/picking.xml b/addons/stock/static/src/xml/picking.xml
index 77215e20729..71c0b260b3a 100644
--- a/addons/stock/static/src/xml/picking.xml
+++ b/addons/stock/static/src/xml/picking.xml
@@ -154,6 +154,42 @@
</div>
</t>
+ <t t-name="PickingMenuWidget">
+ <div class='oe_pick_widget'>
+ <table class='oe_pick_layout'>
+ <tr class='oe_pick_header_row'>
+ <td class='oe_pick_header'>
+
+ <div class='oe_pick_right_toolbar'>
+ <div class='oe_pick_button js_pick_quit'> Quit </div>
+ </div>
+
+ </td>
+ </tr>
+ <tr class='oe_pick_body_row'>
+ <td class='oe_pick_body_cont'>
+ <div class='oe_pick_body'>
+ <div class='oe_pick_app'>
+ <h3 class='oe_pick_app_title'>Pickings</h3>
+
+ <t t-foreach="widget.picking_types" t-as="type">
+ <h4 class='oe_pick_app_subtitle'> <t t-esc="type.name" /> </h4>
+ <t t-if="widget.pickings_by_type[type.id].length > 0">
+ <span class='oe_pick_button oe_medium js_pick_last' t-att-data-id="type.id">Last Picking</span>
+ <span class='oe_pick_button oe_medium js_pick_scan' t-att-data-id="type.id">Scan</span>
+ </t>
+ <t t-if="widget.pickings_by_type[type.id].length === 0">
+ <p class='oe_pick_app_info'>Nothing to process.</p>
+ </t>
+ </t>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </t>
+
<t t-name="PickingMainWidget">
<div class='oe_pick_widget'>
<table class='oe_pick_layout'>
@@ -161,16 +197,17 @@
<td class='oe_pick_header'>
<div class='oe_pick_right_toolbar'>
+ <div class='oe_pick_button js_pick_menu'> Menu </div>
<div class='oe_pick_button js_pick_quit'> Quit </div>
</div>
<div class='oe_pick_toolbar'>
+ <div class='oe_pick_button oe_small oe_disabled oe_left js_pick_prev'>&lt;</div>
<div class='oe_pick_button js_pick_pack'> Pack </div>
- <!-- <div class='oe_pick_button js_pick_reset'> Reset </div> -->
<div class='oe_pick_button js_pick_done'> Done </div>
+ <div class='oe_pick_button oe_small oe_disabled oe_right js_pick_next'>&gt;</div>
</div>
-
</td>
</tr>
<tr class='oe_pick_body_row'>
@@ -181,6 +218,7 @@
<div class='oe_placeholder_picking_editor'></div>
<div class='oe_placeholder_package_editor'></div>
<div class='oe_placeholder_package_selector'></div>
+ <div class='oe_placeholder_menu'></div>
</div>
</div>