summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>2014-09-26 16:40:29 +0200
committerFrédéric van der Essen <fvdessen@gmail.com>2014-11-25 18:21:38 +0100
commit42661572f9138a4f10697535210effbbdf35b9dd (patch)
tree05678d4ea63e03a65a0da53aed6fad7e937f47c9 /addons
parentc54a46e508d682670865de3bade83863c6404dc1 (diff)
[WIP] pos_restaurant, point_of_sale: almost done
Conflicts: addons/point_of_sale/static/src/js/screens.js addons/point_of_sale/static/src/xml/pos.xml
Diffstat (limited to 'addons')
-rw-r--r--addons/point_of_sale/static/src/js/models.js7
-rw-r--r--addons/point_of_sale/static/src/js/screens.js23
-rw-r--r--addons/point_of_sale/static/src/js/widgets.js111
-rw-r--r--addons/point_of_sale/static/src/xml/pos.xml54
-rw-r--r--addons/pos_restaurant/static/src/css/restaurant.css26
-rw-r--r--addons/pos_restaurant/static/src/js/floors.js74
-rw-r--r--addons/pos_restaurant/static/src/xml/floors.xml10
7 files changed, 226 insertions, 79 deletions
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index e7b401e9bfa..d22c35cd036 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -447,7 +447,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
// order and a valid selected order
on_removed_order: function(removed_order,index,reason){
var order_list = this.get_order_list();
- if( (reason === 'abandon' || removed_order.temporary) && this.order_list.length > 0){
+ if( (reason === 'abandon' || removed_order.temporary) && order_list.length > 0){
// when we intentionally remove an unfinished order, and there is another existing one
this.set_order(order_list[index] || order_list[order_list.length -1]);
}else{
@@ -482,7 +482,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
//removes the current order
delete_current_order: function(){
- this.get('selectedOrder').destroy({'reason':'abandon'});
+ var order = this.get_order();
+ if (order) {
+ order.destroy({'reason':'abandon'});
+ }
},
// saves the order locally and try to send it to the backend.
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index 6219969739b..46614f1e2ae 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -24,17 +24,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
module.ScreenSelector = instance.web.Class.extend({
init: function(options){
this.pos = options.pos;
-
- this.screen_set = options.screen_set || {};
-
- this.popup_set = options.popup_set || {};
-
+ this.screen_set = options.screen_set || {};
+ this.popup_set = options.popup_set || {};
this.default_screen = options.default_screen;
-
- this.current_popup = null;
-
- this.current_mode = options.default_mode || 'cashier';
-
+ this.startup_screen = options.startup_screen;
+ this.current_popup = null;
+ this.current_mode = options.default_mode || 'cashier';
this.current_screen = null;
for(screen_name in this.screen_set){
@@ -45,9 +40,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.popup_set[popup_name].hide();
}
- this.pos.get_order().set_screen_data({
- 'screen': this.default_screen,
- });
+ if (this.pos.get_order()) {
+ this.pos.get_order().set_screen_data({
+ 'screen': this.default_screen,
+ });
+ }
this.pos.bind('change:selectedOrder', this.load_saved_screen, this);
},
diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js
index 4f2c069d501..dba0328b3d1 100644
--- a/addons/point_of_sale/static/src/js/widgets.js
+++ b/addons/point_of_sale/static/src/js/widgets.js
@@ -115,7 +115,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.client_change_handler = function(event){
self.update_summary();
}
- this.bind_order_events();
+ if (this.pos.get_order()) {
+ this.bind_order_events();
+ }
},
enable_numpad: function(){
this.disable_numpad(); //ensure we don't register the callbacks twice
@@ -133,12 +135,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
}
},
set_editable: function(editable){
- this.editable = editable;
- if(editable){
- this.enable_numpad();
- }else{
- this.disable_numpad();
- this.pos.get_order().deselectLine();
+ var order = this.pos.get_order();
+ if (order) {
+ this.editable = editable;
+ if (editable) {
+ this.enable_numpad();
+ }else{
+ this.disable_numpad();
+ order.deselectLine();
+ }
}
},
set_value: function(val) {
@@ -215,6 +220,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.pos_widget.numpad.state.reset();
var order = this.pos.get_order();
+ if (!order) {
+ return;
+ }
var orderlines = order.get('orderLines').models;
var el_str = openerp.qweb.render('OrderWidget',{widget:this, order:order, orderlines:orderlines});
@@ -251,6 +259,64 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
});
+ module.OrderSelectorWidget = module.PosBaseWidget.extend({
+ template: 'OrderSelectorWidget',
+ init: function(parent, options) {
+ this._super(parent, options);
+ this.pos.get('orders').bind('add remove change',this.renderElement,this);
+ this.pos.bind('change:selectedOrder',this.renderElement,this);
+ },
+ get_order_by_uid: function(uid) {
+ var orders = this.pos.get_order_list();
+ for (var i = 0; i < orders.length; i++) {
+ if (orders[i].uid === uid) {
+ return orders[i];
+ }
+ }
+ return undefined;
+ },
+ order_click_handler: function(event,$el) {
+ var order = this.get_order_by_uid($el.data('uid'));
+ if (order) {
+ this.pos.set_order(order);
+ }
+ },
+ neworder_click_handler: function(event, $el) {
+ this.pos.add_new_order();
+ },
+ deleteorder_click_handler: function(event, $el) {
+ var self = this;
+ var order = this.pos.get_order();
+ if (!order) {
+ return;
+ } else if ( !order.is_empty() ){
+ this.screen_selector.show_popup('confirm',{
+ message: _t('Destroy Current Order ?'),
+ comment: _t('You will lose any data associated with the current order'),
+ confirm: function(){
+ self.pos.delete_current_order();
+ },
+ });
+ } else {
+ this.pos.delete_current_order();
+ }
+ },
+ renderElement: function(){
+ var self = this;
+ console.log('Re-Rendering Orders...',this.pos.get_order_list());
+ this._super();
+ this.$('.order-button.select-order').click(function(event){
+ self.order_click_handler(event,$(this));
+ });
+ this.$('.neworder-button').click(function(event){
+ self.neworder_click_handler(event,$(this));
+ });
+ this.$('.deleteorder-button').click(function(event){
+ self.deleteorder_click_handler(event,$(this));
+ });
+ },
+ });
+
module.OrderButtonWidget = module.PosBaseWidget.extend({
template:'OrderButtonWidget',
init: function(parent, options) {
@@ -864,34 +930,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
self.renderElement();
- self.$('.neworder-button').click(function(){
- self.pos.add_new_order();
- });
-
- self.$('.deleteorder-button').click(function(){
- if( !self.pos.get_order().is_empty() ){
- self.screen_selector.show_popup('confirm',{
- message: _t('Destroy Current Order ?'),
- comment: _t('You will lose any data associated with the current order'),
- confirm: function(){
- self.pos.delete_current_order();
- },
- });
- }else{
- self.pos.delete_current_order();
- }
- });
-
- //when a new order is created, add an order button widget
- self.pos.get('orders').bind('add', function(new_order){
- var new_order_button = new module.OrderButtonWidget(null, {
- order: new_order,
- pos: self.pos
- });
- new_order_button.appendTo(this.$('.orders'));
- new_order_button.selectOrder();
- }, self);
-
self.pos.add_new_order();
self.build_widgets();
@@ -1018,6 +1056,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
// -------- Misc ---------
+ this.order_selector = new module.OrderSelectorWidget(this,{});
+ this.order_selector.replace(this.$('.placeholder-OrderSelectorWidget'));
+
this.notification = new module.SynchNotificationWidget(this,{});
this.notification.appendTo(this.$('.pos-rightheader'));
diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml
index 85f6badec96..c98c9eb0fed 100644
--- a/addons/point_of_sale/static/src/xml/pos.xml
+++ b/addons/point_of_sale/static/src/xml/pos.xml
@@ -11,11 +11,7 @@
<span class="placeholder-UsernameWidget"></span>
</div>
<div class="pos-rightheader">
- <div class="order-selector">
- <span class="orders touch-scrollable"></span>
- <span class="order-button square neworder-button"><i class='fa fa-plus' /></span>
- <span class="order-button square deleteorder-button"><i class='fa fa-minus' /></span>
- </div>
+ <span class="placeholder-OrderSelectorWidget"></span>
<!-- here goes header buttons -->
</div>
</div>
@@ -1111,23 +1107,39 @@
</tr>
</t>
- <t t-name="OrderButtonWidget">
- <span class="order-button select-order">
- <t t-if='widget.selected'>
- <span class='order-sequence'>
- <t t-esc='widget.order.sequence_number' />
- </span>
- <t t-if="widget.order.get_client()">
- <i class='fa fa-user'/>
+ <t t-name="OrderSelectorWidget">
+ <div class="order-selector">
+ <span class="orders touch-scrollable">
+
+ <t t-foreach="widget.pos.get_order_list()" t-as="order">
+ <t t-if='order === widget.pos.get_order()'>
+ <span class="order-button select-order selected" t-att-data-uid="order.uid">
+ <span class='order-sequence'>
+ <t t-esc='order.sequence_number' />
+ </span>
+ <t t-if="order.get_client()">
+ <i class='fa fa-user'/>
+ </t>
+ <t t-esc="(order.get_client() ? order.get_client_name()+' : ':'Unknown Customer: ') + order.get('creationDate').toString('t')"/>
+ </span>
+ </t>
+ <t t-if='order !== widget.pos.get_order()'>
+ <span class="order-button select-order" t-att-data-uid="order.uid">
+ <span class='order-sequence'>
+ <t t-esc='order.sequence_number' />
+ </span>
+ </span>
+ </t>
</t>
- <t t-esc="(widget.order.get_client() ? widget.order.get_client_name()+' : ':'Unknown Customer: ') + moment(widget.order.get('creationDate')).format('LT')"/>
- </t>
- <t t-if='!widget.selected'>
- <span class='order-sequence'>
- <t t-esc='widget.order.sequence_number' />
- </span>
- </t>
- </span>
+
+ </span>
+ <span class="order-button square neworder-button">
+ <i class='fa fa-plus' />
+ </span>
+ <span class="order-button square deleteorder-button">
+ <i class='fa fa-minus' />
+ </span>
+ </div>
</t>
<t t-name="UsernameWidget">
diff --git a/addons/pos_restaurant/static/src/css/restaurant.css b/addons/pos_restaurant/static/src/css/restaurant.css
index 162b29c710a..8e7a353cbff 100644
--- a/addons/pos_restaurant/static/src/css/restaurant.css
+++ b/addons/pos_restaurant/static/src/css/restaurant.css
@@ -180,7 +180,33 @@
.floor-map .table .table-handle.left { left: 0; }
.floor-map .table .table-handle.right { left: 100%; }
+.floor-map .table .order-count {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ background: black;
+ width: 20px;
+ margin-top: -10px;
+ margin-left: -10px;
+ height: 20px;
+ line-height: 20px;
+ border-radius: 10px;
+}
+
+/* ------ FLOOR BUTTON IN THE ORDER SELECTOR ------- */
+
+.pos .order-button.floor-button {
+ background: #35D374;
+ font-weight: bold;
+ font-size: 16px;
+ min-width: 128px;
+ padding-left: 16px;
+ padding-right: 16px;
+}
+.pos .order-button.floor-button .fa{
+ font-size: 24px;
+}
diff --git a/addons/pos_restaurant/static/src/js/floors.js b/addons/pos_restaurant/static/src/js/floors.js
index f661de5ae23..e55ba6e7b90 100644
--- a/addons/pos_restaurant/static/src/js/floors.js
+++ b/addons/pos_restaurant/static/src/js/floors.js
@@ -1,4 +1,5 @@
function openerp_restaurant_floors(instance,module){
+ var QWeb = instance.web.qweb;
var _t = instance.web._t;
// At POS Startup, load the floors, and add them to the pos model
@@ -26,6 +27,7 @@ function openerp_restaurant_floors(instance,module){
var floor = self.floors_by_id[tables[i].floor_id[0]];
if (floor) {
floor.tables.push(tables[i]);
+ tables[i].floor = floor;
}
}
},
@@ -212,7 +214,17 @@ function openerp_restaurant_floors(instance,module){
var model = new instance.web.Model('restaurant.table');
var fields = _.find(this.pos.models,function(model){ return model.model === 'restaurant.table'; }).fields;
- model.call('create_from_ui',[this.table]).then(function(table_id){
+ // we need a serializable copy of the table, containing only the fields defined on the server
+ var serializable_table = {};
+ for (var i = 0; i < fields.length; i++) {
+ if (typeof this.table[fields[i]] !== 'undefined') {
+ serializable_table[fields[i]] = this.table[fields[i]];
+ }
+ }
+ // and the id ...
+ serializable_table.id = this.table.id
+
+ model.call('create_from_ui',[serializable_table]).then(function(table_id){
model.query(fields).filter([['id','=',table_id]]).first().then(function(table){
for (field in table) {
self.table[field] = table[field];
@@ -253,6 +265,7 @@ function openerp_restaurant_floors(instance,module){
},
renderElement: function(){
var self = this;
+ this.order_count = this.pos.get_table_orders(this.table).length;
this._super();
this.$el.on('mouseup', function(event){ self.click_handler(event,$(this)); });
@@ -281,16 +294,17 @@ function openerp_restaurant_floors(instance,module){
this.selected_table = null;
this.editing = false;
},
- show: function(){
- this._super();
- this.pos_widget.$('.order-selector').addClass('oe_invisible');
- },
hide: function(){
this._super();
if (this.editing) {
this.toggle_editing();
}
- this.pos_widget.$('.order-selector').removeClass('oe_invisible');
+ },
+ show: function(){
+ this._super();
+ for (var i = 0; i < this.table_widgets.length; i++) {
+ this.table_widgets[i].renderElement();
+ }
},
click_floor_button: function(event,$el){
var floor = this.pos.floors_by_id[$el.data('id')];
@@ -559,13 +573,35 @@ function openerp_restaurant_floors(instance,module){
}
});
+ // We need to modify the OrderSelector to hide itself when we're on
+ // the floor plan
+ module.OrderSelectorWidget.include({
+ floor_button_click_handler: function(){
+ this.pos.set_table(null);
+ },
+ renderElement: function(){
+ var self = this;
+ this._super();
+ if (this.pos.get_order()) {
+ if (this.pos.table && this.pos.table.floor) {
+ this.$('.orders').prepend(QWeb.render('BackToFloorButton',{floor:this.pos.table.floor}));
+ this.$('.floor-button').click(function(){
+ self.floor_button_click_handler();
+ });
+ }
+ this.$el.removeClass('oe_invisible');
+ } else {
+ this.$el.addClass('oe_invisible');
+ }
+ },
+ });
+
// We need to change the way the regular UI sees the orders, it
// needs to only see the orders associated with the current table,
// and when an order is validated, it needs to go back to the floor map.
//
// And when we change the table, we must create an order for that table
// if there is none.
-
var _super_posmodel = module.PosModel.prototype;
module.PosModel = module.PosModel.extend({
initialize: function(session, attributes) {
@@ -588,6 +624,16 @@ function openerp_restaurant_floors(instance,module){
}
},
+ // we need to prevent the creation of orders when there is no
+ // table selected.
+ add_new_order: function() {
+ if (this.table) {
+ _super_posmodel.add_new_order.call(this);
+ } else {
+ console.warn("WARNING: orders cannot be created when there is no active table in restaurant mode");
+ }
+ },
+
// get the list of unpaid orders (associated to the current table)
get_order_list: function() {
var orders = _super_posmodel.get_order_list.call(this);
@@ -604,12 +650,24 @@ function openerp_restaurant_floors(instance,module){
}
},
+ // get the list of orders associated to a table. FIXME: should be O(1)
+ get_table_orders: function(table) {
+ var orders = _super_posmodel.get_order_list.call(this);
+ var t_orders = [];
+ for (var i = 0; i < orders.length; i++) {
+ if (orders[i].table === table) {
+ t_orders.push(orders[i]);
+ }
+ }
+ return t_orders;
+ },
+
// When we validate an order we go back to the floor plan.
// When we cancel an order and there is multiple orders
// on the table, stay on the table.
on_removed_order: function(removed_order,index,reason){
var order_list = this.get_order_list();
- if( (reason === 'abandon' || removed_order.temporary) && this.order_list.length > 0){
+ if( (reason === 'abandon' || removed_order.temporary) && order_list.length > 0){
this.set_order(order_list[index] || order_list[order_list.length -1]);
}else{
// back to the floor plan
diff --git a/addons/pos_restaurant/static/src/xml/floors.xml b/addons/pos_restaurant/static/src/xml/floors.xml
index 8b2e2a5d4fe..16efe1f1aa7 100644
--- a/addons/pos_restaurant/static/src/xml/floors.xml
+++ b/addons/pos_restaurant/static/src/xml/floors.xml
@@ -4,6 +4,9 @@
<t t-name="TableWidget">
<t t-if='!widget.selected'>
<div class='table' t-att-style='widget.table_style_str()'>
+ <t t-if='widget.order_count'>
+ <span class='order-count'><t t-esc='widget.order_count'/></span>
+ </t>
<span class='label'>
<t t-esc='widget.table.name' />
</span>
@@ -26,6 +29,13 @@
</t>
</t>
+ <t t-name="BackToFloorButton">
+ <span class="order-button floor-button">
+ <i class='fa fa-angle-double-left'/>
+ <t t-esc="floor.name"/>
+ </span>
+ </t>
+
<t t-name="FloorScreenWidget">
<div class='floor-screen screen'>
<div class='screen-content-flexbox'>