// 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{
//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.
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){
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);
},
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
}
},
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) {
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});
},
});
+ 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) {
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();
// -------- 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'));
<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>
</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">
.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;
+}
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
var floor = self.floors_by_id[tables[i].floor_id[0]];
if (floor) {
floor.tables.push(tables[i]);
+ tables[i].floor = floor;
}
}
},
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];
},
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)); });
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')];
}
});
+ // 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) {
}
},
+ // 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);
}
},
+ // 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
<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>
</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'>