diff options
| author | Frédéric van der Essen <fvdessen@gmail.com> | 2015-02-01 00:41:18 +0100 |
|---|---|---|
| committer | Frédéric van der Essen <fvdessen@gmail.com> | 2015-02-02 16:29:32 +0100 |
| commit | 3335a79e6b6de83c82c290b4591e89f8e6ca5742 (patch) | |
| tree | d00539dc581cac869d8ee9eb2b5450d62c3bdf51 | |
| parent | 386f5f99d63e4565ab3bcf756b9d39dc136a5d52 (diff) | |
[IMP] point_of_sale, pos_restaurant: Table seats
| -rw-r--r-- | addons/point_of_sale/point_of_sale_view.xml | 2 | ||||
| -rw-r--r-- | addons/point_of_sale/static/src/css/pos.css | 17 | ||||
| -rw-r--r-- | addons/point_of_sale/static/src/js/popups.js | 2 | ||||
| -rw-r--r-- | addons/point_of_sale/static/src/xml/pos.xml | 27 | ||||
| -rw-r--r-- | addons/pos_restaurant/restaurant.py | 19 | ||||
| -rw-r--r-- | addons/pos_restaurant/restaurant_view.xml | 22 | ||||
| -rw-r--r-- | addons/pos_restaurant/static/src/css/restaurant.css | 51 | ||||
| -rw-r--r-- | addons/pos_restaurant/static/src/js/floors.js | 120 | ||||
| -rw-r--r-- | addons/pos_restaurant/static/src/js/multiprint.js | 7 | ||||
| -rw-r--r-- | addons/pos_restaurant/static/src/js/splitbill.js | 3 | ||||
| -rw-r--r-- | addons/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 @@ <field name="state" widget="statusbar" statusbar_visible="draft,paid,done" statusbar_colors='{"cancel":"red"}'/> </header> <sheet> - <group col="4" colspan="4"> + <group col="4" colspan="4" name="order_fields"> <field name="name"/> <field name="date_order"/> <field name="session_id" required="1"/> 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 @@ <div>Served by <t t-esc='receipt.cashier' /></div> </div> </t> + <t t-if='!receipt.customer_count'> + <div>Guests: <t t-esc='receipt.customer_count' /></div> + </t> </div> <br /><br /> @@ -981,17 +984,29 @@ <button class="input-button number-char" data-action='1'>1</button> <button class="input-button number-char" data-action='2'>2</button> <button class="input-button number-char" data-action='3'>3</button> - <button class="mode-button add" data-action='+10'>+10</button> + <t t-if="widget.options.cheap"> + <button class="mode-button add" data-action='+1'>+1</button> + </t><t t-if="!widget.options.cheap"> + <button class="mode-button add" data-action='+10'>+10</button> + </t> <br /> <button class="input-button number-char" data-action='4'>4</button> <button class="input-button number-char" data-action='5'>5</button> <button class="input-button number-char" data-action='6'>6</button> - <button class="mode-button add" data-action='+20'>+20</button> + <t t-if="widget.options.cheap"> + <button class="mode-button add" data-action='+2'>+2</button> + </t><t t-if="!widget.options.cheap"> + <button class="mode-button add" data-action='+20'>+20</button> + </t> <br /> <button class="input-button number-char" data-action='7'>7</button> <button class="input-button number-char" data-action='8'>8</button> <button class="input-button number-char" data-action='9'>9</button> - <button class="mode-button add" data-action='+50'>+50</button> + <t t-if="widget.options.cheap"> + <button class="mode-button add" data-action='+5'>+5</button> + </t><t t-if="!widget.options.cheap"> + <button class="mode-button add" data-action='+50'>+50</button> + </t> <br /> <button class="input-button numpad-char" data-action='CLEAR' >C</button> <button class="input-button number-char" data-action='0'>0</button> @@ -1002,12 +1017,12 @@ <br /> </div> <div class="footer"> - <div class="button confirm"> - Ok - </div> <div class="button cancel"> Cancel </div> + <div class="button confirm"> + Ok + </div> </div> </div> </div> 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 @@ <openerp> <data> + + <!-- POS ORDERS --> + + <record model="ir.ui.view" id="view_pos_pos_form"> + <field name="name">pos.order.form.view.inherit</field> + <field name="model">pos.order</field> + <field name="inherit_id" ref="point_of_sale.view_pos_pos_form"></field> + <field name="arch" type="xml"> + <xpath expr="//group[@name='order_fields']" position="inside"> + <field name="table_id"/> + <field name="customer_count"/> + </xpath> + </field> + </record> + <!-- RESTAURANTS FLOORS --> <record model="ir.ui.view" id="view_restaurant_floor_form"> @@ -19,6 +34,7 @@ <field name="table_ids"> <tree string='Tables'> <field name="name" /> + <field name="seats" /> <field name="shape" /> </tree> </field> @@ -62,10 +78,12 @@ <form string="Restaurant Table"> <group col="2"> <field name="name" /> + <field name="floor_id" /> + <field name="seats" /> + </group> + <group col="4" string="Appearance"> <field name="shape" /> <field name="color" /> - </group> - <group col="4"> <field name="position_h" /> <field name="position_v" /> <field name="width" /> 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 @@ </t> </t> + <t t-name="TableGuestsButton"> + <div class='control-button'> + <span class='control-button-number'> + <t t-esc="widget.guests()" /> + </span> + Guests + </div> + </t> + <t t-name="TableWidget"> <t t-if='!widget.selected'> <div class='table' t-att-style='widget.table_style_str()'> + <span + t-if="widget.table.shape !== 'round'" + t-att-class='"table-cover " + (widget.fill >= 1 ? "full" : "")' + t-att-style='"height: " + Math.ceil(widget.fill * 100) + "%;"' + ></span> <t t-if='widget.order_count'> <span t-att-class='"order-count " + (widget.notifications.printing ? "notify-printing":"")'><t t-esc='widget.order_count'/></span> </t> <span class='label'> <t t-esc='widget.table.name' /> </span> + <span class="table-seats"><t t-esc="widget.table.seats" /></span> </div> </t> <t t-if='widget.selected'> @@ -33,6 +48,7 @@ <span class='label'> <t t-esc='widget.table.name' /> </span> + <span class="table-seats"><t t-esc="widget.table.seats" /></span> <span class='table-handle top'></span> <span class='table-handle bottom'></span> <span class='table-handle left'></span> @@ -82,6 +98,9 @@ <span class='edit-button rename needs-selection'> <i class='fa fa-font'></i> </span> + <span class='edit-button seats needs-selection'> + <i class='fa fa-user'></i> + </span> <span class='edit-button shape needs-selection'> <span class='button-option square'><i class='fa fa-square-o'></i></span> <span class='button-option round oe_hidden'><i class='fa fa-circle-o'></i></span> |
