From 3335a79e6b6de83c82c290b4591e89f8e6ca5742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Sun, 1 Feb 2015 00:41:18 +0100 Subject: [PATCH] [IMP] point_of_sale, pos_restaurant: Table seats --- addons/point_of_sale/point_of_sale_view.xml | 2 +- addons/point_of_sale/static/src/css/pos.css | 17 +++ addons/point_of_sale/static/src/js/popups.js | 2 +- addons/point_of_sale/static/src/xml/pos.xml | 27 +++- addons/pos_restaurant/restaurant.py | 19 ++- addons/pos_restaurant/restaurant_view.xml | 22 +++- .../static/src/css/restaurant.css | 51 ++++++-- addons/pos_restaurant/static/src/js/floors.js | 120 ++++++++++++++++-- .../static/src/js/multiprint.js | 7 - .../pos_restaurant/static/src/js/splitbill.js | 3 + .../pos_restaurant/static/src/xml/floors.xml | 19 +++ 11 files changed, 247 insertions(+), 42 deletions(-) diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index 2401574df33..64ddbc82fc5 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -22,7 +22,7 @@ - + diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index daf8c12e4c0..9ea9986d823 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -565,6 +565,20 @@ td { .pos .control-button .fa{ margin-right: 4px; } +.pos .control-button .control-button-number { + color: rgb(226, 226, 226); + background: rgb(85, 85, 85); + display: inline-block; + height: 28px; + vertical-align: middle; + font-weight: bold; + line-height: 28px; + width: 28px; + border-radius: 50%; + text-align: center; + margin-left: -16px; + margin-right: 4px; +} .pos .control-button.highlight, .pos .button.highlight { @@ -2117,6 +2131,9 @@ td { box-sizing: border-box; width: 80%; } +.pos .popup-number .popup-input { + text-align: center; +} .pos .popup input:focus, .pos .popup-input.active { outline: none; diff --git a/addons/point_of_sale/static/src/js/popups.js b/addons/point_of_sale/static/src/js/popups.js index e0db66f5392..314dc8556c8 100644 --- a/addons/point_of_sale/static/src/js/popups.js +++ b/addons/point_of_sale/static/src/js/popups.js @@ -194,7 +194,7 @@ openerp.point_of_sale.load_popups = function load_popups(instance, module) { var self = this; this._super(options); - this.inputbuffer = options.value || ''; + this.inputbuffer = '' + options.value || ''; this.renderElement(); this.firstinput = true; }, diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index cc094485f02..4c77b710982 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -666,6 +666,9 @@
Served by
+ +
Guests:
+


@@ -981,17 +984,29 @@ - + + + + +
- + + + + +
- + + + + +
@@ -1002,12 +1017,12 @@
diff --git a/addons/pos_restaurant/restaurant.py b/addons/pos_restaurant/restaurant.py index 70583f06c16..512b1e7cdc3 100644 --- a/addons/pos_restaurant/restaurant.py +++ b/addons/pos_restaurant/restaurant.py @@ -53,17 +53,19 @@ class restaurant_table(osv.osv): 'name': fields.char('Table Name', size=32, required=True, help='An internal identification of a table'), 'floor_id': fields.many2one('restaurant.floor','Floor'), 'shape': fields.selection([('square','Square'),('round','Round')],'Shape', required=True), - 'position_h': fields.float('Horizontal Position', help="The table's horizontal position from the left side to the table's center, in percentage of the floor's width"), - 'position_v': fields.float('Vertical Position', help="The table's vertical position from the top to the table's center, in percentage of the floor's height"), - 'width': fields.float('Width', help="The table's width in percentage of the floor's width"), - 'height': fields.float('Height', help="The table's height in percentage of the floor's height"), - 'color': fields.char('Color', size=32, help="The table's color"), + 'position_h': fields.float('Horizontal Position', help="The table's horizontal position from the left side to the table's center, in pixels"), + 'position_v': fields.float('Vertical Position', help="The table's vertical position from the top to the table's center, in pixels"), + 'width': fields.float('Width', help="The table's width in pixels"), + 'height': fields.float('Height', help="The table's height in pixels"), + 'seats': fields.integer('Seats', help="The default number of customer served at this table."), + 'color': fields.char('Color', help="The table's color, expressed as a valid 'background' CSS property value"), 'active': fields.boolean('Active',help='If false, the table is deactivated and will not be available in the point of sale'), 'pos_order_ids':fields.one2many('pos.order','table_id','Pos Orders', help='The orders served at this table'), } _defaults = { 'shape': 'square', + 'seats': 1, 'position_h': 10, 'position_v': 10, 'height': 50, @@ -121,4 +123,11 @@ class pos_order(osv.osv): _inherit = 'pos.order' _columns = { 'table_id': fields.many2one('restaurant.table','Table', help='The table where this order was served'), + 'customer_count' : fields.integer('Guests', help='The amount of customers that have been served by this order.'), } + + def _order_fields(self, cr, uid, ui_order, context=None): + fields = super(pos_order,self)._order_fields(cr,uid,ui_order,context) + fields['table_id'] = ui_order.get('table_id',0) + fields['customer_count'] = ui_order.get('customer_count',0) + return fields diff --git a/addons/pos_restaurant/restaurant_view.xml b/addons/pos_restaurant/restaurant_view.xml index 3094a681b48..27f323651b7 100644 --- a/addons/pos_restaurant/restaurant_view.xml +++ b/addons/pos_restaurant/restaurant_view.xml @@ -2,6 +2,21 @@ + + + + + pos.order.form.view.inherit + pos.order + + + + + + + + + @@ -19,6 +34,7 @@ + @@ -62,10 +78,12 @@
+ + + + - - diff --git a/addons/pos_restaurant/static/src/css/restaurant.css b/addons/pos_restaurant/static/src/css/restaurant.css index 1bbac339406..57d667670d8 100644 --- a/addons/pos_restaurant/static/src/css/restaurant.css +++ b/addons/pos_restaurant/static/src/css/restaurant.css @@ -49,6 +49,7 @@ background-repeat: no-repeat; overflow: hidden; background-size: cover; + transition: all 300ms ease-in-out; } @media screen and (min-width: 1024px) { @@ -80,11 +81,42 @@ border-radius: 3px; cursor: pointer; box-shadow: 0px 3px rgba(0,0,0,0.07); + transition: background, background-color 300ms ease-in-out; +} +.floor-map .table .table-cover { + display: block; + position: absolute; + left: 0; right: 0; bottom: 0; + border-radius: 0px 0px 3px 3px; + background: rgba(0,0,0,0.2); +} +.floor-map .table .table-cover.full { + border-radius: 3px 3px 3px 3px; +} +.floor-map .table .table-seats { + position: absolute; + display: inline-block; + bottom: 0; + left: 50%; + height: 20px; + width: 20px; + line-height: 20px; + font-size: 16px; + border-radius: 50%; + margin-left: -10px; + margin-bottom: 4px; + background: black; + color: white; + opacity: 0.2; + z-index: 3; } .floor-map .table .label { display: block; max-height: 100%; overflow: hidden; + position: relative; + bottom: 5px; + z-index: 5; } .floor-map .table.selected { outline: solid rgba(255,255,255,0.3); @@ -96,7 +128,7 @@ top: 0; right: 0; font-size: 20px; - margin: 4px; + margin: 8px; line-height: 32px; width: 32px; text-align: center; @@ -106,20 +138,20 @@ } .floor-map .edit-button.editing.active { background: #444; + border-color: transparent; color: white; } .floor-map .edit-bar { position: absolute; top: 0; right: 40px; - margin: 4px; - line-height: 32px; + margin: 8px; + line-height: 34px; text-align: center; border-radius: 5px; cursor: pointer; font-size: 20px; - border: solid 1px rgba(0,0,0,0.2); - background: #F0EEEE; + background: rgba(255,255,255,0.5); } .floor-map .edit-bar .edit-button { position: relative; @@ -127,14 +159,15 @@ display: inline-block; cursor: pointer; margin-right: -4px; - border-right: solid 1px rgba(0,0,0,0.1); + border-right: solid 1px rgba(0,0,0,0.2); transition: all 150ms linear; } .floor-map .edit-bar .edit-button.disabled { - opacity: 0.5; - border-right: solid 1px rgba(0,0,0,0.2); cursor: default; } +.floor-map .edit-bar .edit-button.disabled > * { + opacity: 0.5; +} .floor-map .edit-bar .color-picker { position: absolute; left: -106px; @@ -192,6 +225,7 @@ box-shadow: 0px 2px 3px rgba(0,0,0,0.2); cursor: grab; transition: all 150ms linear; + z-index: 100; } .floor-map .table.selected .table-handle:hover { width: 20px; @@ -217,6 +251,7 @@ line-height: 20px; border-radius: 10px; font-size: 16px; + z-index: 10; } .floor-map .table .order-count.notify-printing { background: red; diff --git a/addons/pos_restaurant/static/src/js/floors.js b/addons/pos_restaurant/static/src/js/floors.js index 7b5e7d6f9a0..fe13ed552c9 100644 --- a/addons/pos_restaurant/static/src/js/floors.js +++ b/addons/pos_restaurant/static/src/js/floors.js @@ -27,7 +27,7 @@ openerp.pos_restaurant.load_floors = function(instance,module){ // them with their floor. module.load_models({ model: 'restaurant.table', - fields: ['name','width','height','position_h','position_v','shape','floor_id','color'], + fields: ['name','width','height','position_h','position_v','shape','floor_id','color','seats'], loaded: function(self,tables){ self.tables_by_id = {}; for (var i = 0; i < tables.length; i++) { @@ -161,8 +161,8 @@ openerp.pos_restaurant.load_floors = function(instance,module){ } }, set_table_color: function(color){ - this.table.color = color; - this.renderElement(); + this.table.color = _.escape(color); + this.$el.css({'background': this.table.color}); }, set_table_name: function(name){ if (name) { @@ -170,6 +170,12 @@ openerp.pos_restaurant.load_floors = function(instance,module){ this.renderElement(); } }, + set_table_seats: function(seats){ + if (seats) { + this.table.seats = Number(seats); + this.renderElement(); + } + }, // The table's positioning is handled via css absolute positioning, // which is handled here. table_style: function(){ @@ -187,7 +193,7 @@ openerp.pos_restaurant.load_floors = function(instance,module){ unit(Math.max(table.width,table.height)/2) : '3px', }; if (table.color) { - style['background-color'] = table.color; + style['background'] = table.color; } if (table.height >= 150 && table.width >= 150) { style['font-size'] = '32px'; @@ -290,8 +296,10 @@ openerp.pos_restaurant.load_floors = function(instance,module){ }, renderElement: function(){ var self = this; - this.order_count = this.pos.get_table_orders(this.table).length; - this.notifications = this.get_notifications(); + this.order_count = this.pos.get_table_orders(this.table).length; + this.customer_count = this.pos.get_customer_count(this.table); + this.fill = Math.min(1,Math.max(0,this.customer_count / this.table.seats)); + this.notifications = this.get_notifications(); this._super(); this.$el.on('mouseup', function(event){ self.click_handler(event,$(this)); }); @@ -375,7 +383,7 @@ openerp.pos_restaurant.load_floors = function(instance,module){ event.stopPropagation(); event.preventDefault(); }); - this.renderElement(); + this.$('.floor-map').css({"background-color": _.escape(background)}); }, deselect_tables: function(){ for (var i = 0; i < this.table_widgets.length; i++) { @@ -437,6 +445,19 @@ openerp.pos_restaurant.load_floors = function(instance,module){ }); } }, + tool_change_seats: function(){ + var self = this; + if (this.selected_table) { + this.gui.show_popup('number',{ + 'title':_t('Number of Seats ?'), + 'cheap': true, + 'value': this.selected_table.table.seats, + 'confirm': function(value) { + self.selected_table.set_table_seats(value); + }, + }); + } + }, tool_duplicate_table: function(){ if (this.selected_table) { var tw = this.create_table(this.selected_table.table); @@ -448,12 +469,13 @@ openerp.pos_restaurant.load_floors = function(instance,module){ }, tool_new_table: function(){ var tw = this.create_table({ - 'position_v': 50, - 'position_h': 50, - 'width': 50, - 'height': 50, + 'position_v': 100, + 'position_h': 100, + 'width': 75, + 'height': 75, 'name': 'T1', 'shape': 'square', + 'seats': 1, }); this.select_table(tw); }, @@ -562,6 +584,10 @@ openerp.pos_restaurant.load_floors = function(instance,module){ self.tool_rename_table(); }); + this.$('.edit-button.seats').click(function(event){ + self.tool_change_seats(); + }); + this.$('.edit-button.trash').click(function(event){ self.tool_trash_table(); }); @@ -573,7 +599,6 @@ openerp.pos_restaurant.load_floors = function(instance,module){ this.$('.color-picker .color').click(function(event){ self.tool_colorpicker_pick(event,$(this)); - self.tool_colorpicker_close(); event.stopPropagation(); }); @@ -624,6 +649,13 @@ openerp.pos_restaurant.load_floors = function(instance,module){ if (!this.table) { this.table = this.pos.table; } + if (!this.customer_count) { + if (this.table) { + this.customer_count = this.table.seats; + } else { + this.customer_count = 1; + } + } this.save_to_db(); }, export_as_JSON: function() { @@ -632,19 +664,29 @@ openerp.pos_restaurant.load_floors = function(instance,module){ json.table_id = this.table ? this.table.id : false; json.floor = this.table ? this.table.floor.name : false; json.floor_id = this.table ? this.table.floor.id : false; + json.customer_count = this.customer_count; return json; }, init_from_JSON: function(json) { _super_order.init_from_JSON.apply(this,arguments); this.table = this.pos.tables_by_id[json.table_id]; this.floor = this.table ? this.pos.floors_by_id[json.floor_id] : undefined; + this.customer_count = json.customer_count || 1; }, export_for_printing: function() { var json = _super_order.export_for_printing.apply(this,arguments); json.table = this.table ? this.table.name : undefined; json.floor = this.table ? this.table.floor.name : undefined; + json.customer_count = this.get_customer_count(); return json; }, + get_customer_count: function(){ + return this.customer_count; + }, + set_customer_count: function(count) { + this.customer_count = Math.max(count,0); + this.trigger('change'); + }, }); // We need to modify the OrderSelector to hide itself when we're on @@ -759,6 +801,16 @@ openerp.pos_restaurant.load_floors = function(instance,module){ return t_orders; }, + // get customer count at table + get_customer_count: function(table) { + var orders = this.get_table_orders(table); + var count = 0; + for (var i = 0; i < orders.length; i++) { + count += orders[i].get_customer_count(); + } + return count; + }, + // 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. @@ -775,6 +827,50 @@ openerp.pos_restaurant.load_floors = function(instance,module){ _super_posmodel.on_removed_order.apply(this,arguments); } }, + + + }); + + module.TableGuestsButton = module.ActionButtonWidget.extend({ + template: 'TableGuestsButton', + guests: function() { + if (this.pos.get_order()) { + return this.pos.get_order().customer_count; + } else { + return 0; + } + }, + button_click: function() { + var self = this; + this.gui.show_popup('number', { + 'title': _t('Guests ?'), + 'cheap': true, + 'value': this.pos.get_order().customer_count, + 'confirm': function(value) { + value = Math.max(1,Number(value)); + self.pos.get_order().set_customer_count(value); + self.renderElement(); + }, + }); + }, + }); + + module.OrderWidget.include({ + update_summary: function(){ + this._super(); + if (this.getParent().action_buttons && + this.getParent().action_buttons.guests) { + this.getParent().action_buttons.guests.renderElement(); + } + }, + }); + + module.define_action_button({ + 'name': 'guests', + 'widget': module.TableGuestsButton, + 'condition': function(){ + return this.pos.config.iface_floorplan; + }, }); }; diff --git a/addons/pos_restaurant/static/src/js/multiprint.js b/addons/pos_restaurant/static/src/js/multiprint.js index 61b8c1663a4..fdb458c81a2 100644 --- a/addons/pos_restaurant/static/src/js/multiprint.js +++ b/addons/pos_restaurant/static/src/js/multiprint.js @@ -229,13 +229,6 @@ openerp.pos_restaurant.load_multiprint = function(instance,module){ order.saveChanges(); } }, - hilight: function(hi){ - if (hi) { - this.$el.addClass('highlight'); - } else { - this.$el.removeClass('highlight'); - } - }, }); module.define_action_button({ diff --git a/addons/pos_restaurant/static/src/js/splitbill.js b/addons/pos_restaurant/static/src/js/splitbill.js index cc640599512..f3d672ca7ac 100644 --- a/addons/pos_restaurant/static/src/js/splitbill.js +++ b/addons/pos_restaurant/static/src/js/splitbill.js @@ -125,6 +125,9 @@ openerp.pos_restaurant.load_splitbill = function(instance, module){ neworder.saveChanges(); } + neworder.set_customer_count(1); + order.set_customer_count(order.get_customer_count() - 1); + this.pos.get('orders').add(neworder); this.pos.set('selectedOrder',neworder); } diff --git a/addons/pos_restaurant/static/src/xml/floors.xml b/addons/pos_restaurant/static/src/xml/floors.xml index f401bb54f27..4406fc58749 100644 --- a/addons/pos_restaurant/static/src/xml/floors.xml +++ b/addons/pos_restaurant/static/src/xml/floors.xml @@ -17,15 +17,30 @@ + +
+ + + + Guests +
+
+
+ +
@@ -33,6 +48,7 @@ + @@ -82,6 +98,9 @@ + + +