diff --git a/addons/pos_restaurant/__openerp__.py b/addons/pos_restaurant/__openerp__.py index 6deaa86450b..72414a736ec 100644 --- a/addons/pos_restaurant/__openerp__.py +++ b/addons/pos_restaurant/__openerp__.py @@ -25,7 +25,7 @@ This module adds several restaurant features to the Point of Sale: 'views/pos_config_views.xml', 'views/pos_order_views.xml', 'views/pos_restaurant_views.xml', - 'views/pos_restauraunt_templates.xml', + 'views/pos_restaurant_templates.xml', ], 'qweb': [ 'static/src/xml/multiprint.xml', @@ -35,7 +35,7 @@ This module adds several restaurant features to the Point of Sale: 'static/src/xml/floors.xml', ], 'demo': [ - 'data/restaurant_demo.xml', + 'data/pos_restaurant_demo.xml', ], 'installable': True, 'auto_install': False, diff --git a/addons/pos_restaurant/data/pos_restaurant_demo.xml b/addons/pos_restaurant/data/pos_restaurant_demo.xml index 048b173bf96..b59401235ed 100644 --- a/addons/pos_restaurant/data/pos_restaurant_demo.xml +++ b/addons/pos_restaurant/data/pos_restaurant_demo.xml @@ -1,6 +1,5 @@ - - + @@ -331,6 +330,4 @@ 315 - - - + diff --git a/addons/pos_restaurant/models/pos_config.py b/addons/pos_restaurant/models/pos_config.py index 3d6ed5edded..2a0312b3fdb 100644 --- a/addons/pos_restaurant/models/pos_config.py +++ b/addons/pos_restaurant/models/pos_config.py @@ -1,19 +1,14 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp.osv import fields, osv +from odoo import fields, models -class pos_config(osv.osv): +class PosConfig(models.Model): _inherit = 'pos.config' - _columns = { - 'iface_splitbill': fields.boolean('Bill Splitting', help='Enables Bill Splitting in the Point of Sale'), - 'iface_printbill': fields.boolean('Bill Printing', help='Allows to print the Bill before payment'), - 'iface_orderline_notes': fields.boolean('Orderline Notes', help='Allow custom notes on Orderlines'), - 'floor_ids': fields.one2many('restaurant.floor','pos_config_id','Restaurant Floors', help='The restaurant floors served by this point of sale'), - 'printer_ids': fields.many2many('restaurant.printer','pos_config_printer_rel', 'config_id','printer_id',string='Order Printers'), - } - _defaults = { - 'iface_splitbill': False, - 'iface_printbill': False, - } + + iface_splitbill = fields.Boolean(string='Bill Splitting', help='Enables Bill Splitting in the Point of Sale') + iface_printbill = fields.Boolean(string='Bill Printing', help='Allows to print the Bill before payment') + iface_orderline_notes = fields.Boolean(string='Orderline Notes', help='Allow custom notes on Orderlines') + floor_ids = fields.One2many('restaurant.floor', 'pos_config_id', string='Restaurant Floors', help='The restaurant floors served by this point of sale') + printer_ids = fields.Many2many('restaurant.printer', 'pos_config_printer_rel', 'config_id', 'printer_id', string='Order Printers') diff --git a/addons/pos_restaurant/models/pos_order.py b/addons/pos_restaurant/models/pos_order.py index bcbf3117347..80598149010 100644 --- a/addons/pos_restaurant/models/pos_order.py +++ b/addons/pos_restaurant/models/pos_order.py @@ -1,18 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp.osv import fields, osv +from odoo import api, fields, models -class pos_order(osv.osv): +class PosOrder(models.Model): _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 + table_id = fields.Many2one('restaurant.table', string='Table', help='The table where this order was served') + customer_count = fields.Integer(string='Guests', help='The amount of customers that have been served by this order.') + + @api.model + def _order_fields(self, ui_order): + order_fields = super(PosOrder, self)._order_fields(ui_order) + order_fields['table_id'] = ui_order.get('table_id', False) + order_fields['customer_count'] = ui_order.get('customer_count', 0) + return order_fields diff --git a/addons/pos_restaurant/models/pos_restaurant.py b/addons/pos_restaurant/models/pos_restaurant.py index d06d1c26ef1..8ec67096904 100644 --- a/addons/pos_restaurant/models/pos_restaurant.py +++ b/addons/pos_restaurant/models/pos_restaurant.py @@ -1,86 +1,60 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import logging +from odoo import api, fields, models -import openerp -from openerp import tools -from openerp.osv import fields, osv -from openerp.tools.translate import _ -_logger = logging.getLogger(__name__) +class RestaurantFloor(models.Model): -class restaurant_floor(osv.osv): _name = 'restaurant.floor' - _columns = { - 'name': fields.char('Floor Name', required=True, help='An internal identification of the restaurant floor'), - 'pos_config_id': fields.many2one('pos.config','Point of Sale'), - 'background_color': fields.char('Background Color', help='The background color of the floor layout, (must be specified in a html-compatible format)'), - 'table_ids': fields.one2many('restaurant.table','floor_id','Tables', help='The list of tables in this floor'), - 'sequence': fields.integer('Sequence',help='Used to sort Floors'), - } - _defaults = { - 'sequence': 1, - 'background_color': 'rgb(210, 210, 210)', - } + name = fields.Char('Floor Name', required=True, help='An internal identification of the restaurant floor') + pos_config_id = fields.Many2one('pos.config', string='Point of Sale') + background_image = fields.Binary('Background Image', attachment=True, help='A background image used to display a floor layout in the point of sale interface') + background_color = fields.Char('Background Color', help='The background color of the floor layout, (must be specified in a html-compatible format)', default='rgb(210, 210, 210)') + table_ids = fields.One2many('restaurant.table', 'floor_id', string='Tables', help='The list of tables in this floor') + sequence = fields.Integer('Sequence', help='Used to sort Floors', default=1) - def set_background_color(self, cr, uid, id, background, context=None): - self.write(cr, uid, [id], {'background_color': background}, context=context) -class restaurant_table(osv.osv): +class RestaurantTable(models.Model): + _name = 'restaurant.table' - _columns = { - '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 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'), - } - _defaults = { - 'shape': 'square', - 'seats': 1, - 'position_h': 10, - 'position_v': 10, - 'height': 50, - 'width': 50, - 'active': True, - } + name = fields.Char('Table Name', required=True, help='An internal identification of a table') + floor_id = fields.Many2one('restaurant.floor', string='Floor') + shape = fields.Selection([('square', 'Square'), ('round', 'Round')], string='Shape', required=True, default='square') + position_h = fields.Float('Horizontal Position', default=10, + help="The table's horizontal position from the left side to the table's center, in pixels") + position_v = fields.Float('Vertical Position', default=10, + help="The table's vertical position from the top to the table's center, in pixels") + width = fields.Float('Width', default=50, help="The table's width in pixels") + height = fields.Float('Height', default=50, help="The table's height in pixels") + seats = fields.Integer('Seats', default=1, 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', default=True, help='If false, the table is deactivated and will not be available in the point of sale') - def create_from_ui(self, cr, uid, table, context=None): + @api.model + def create_from_ui(self, table): """ create or modify a table from the point of sale UI. table contains the table's fields. If it contains an id, it will modify the existing table. It then - returns the id of the table. """ + returns the id of the table. + """ + if table.get('floor_id'): + table['floor_id'] = table['floor_id'][0] - if table.get('floor_id',False): - floor_id = table['floor_id'][0] - table['floor_id'] = floor_id - - if table.get('id',False): # Modifiy existing table - table_id = table['id'] - del table['id'] - self.write(cr, uid, [table_id], table, context=context) + table_id = table.pop('id', False) + if table_id: + self.browse(table_id).write(table) else: - table_id = self.create(cr, uid, table, context=context) - + table_id = self.create(table).id return table_id -class restaurant_printer(osv.osv): + +class RestaurantPrinter(models.Model): + _name = 'restaurant.printer' - _columns = { - 'name' : fields.char('Printer Name', size=32, required=True, help='An internal identification of the printer'), - 'proxy_ip': fields.char('Proxy IP Address', size=32, help="The IP Address or hostname of the Printer's hardware proxy"), - 'product_categories_ids': fields.many2many('pos.category','printer_category_rel', 'printer_id','category_id',string='Printed Product Categories'), - } - - _defaults = { - 'name' : 'Printer', - } + name = fields.Char('Printer Name', required=True, default='Printer', help='An internal identification of the printer') + proxy_ip = fields.Char('Proxy IP Address', help="The IP Address or hostname of the Printer's hardware proxy") + product_categories_ids = fields.Many2many('pos.category', 'printer_category_rel', 'printer_id', 'category_id', string='Printed Product Categories') diff --git a/addons/pos_restaurant/static/src/js/floors.js b/addons/pos_restaurant/static/src/js/floors.js index f73998b37ed..df01bcbb9ad 100644 --- a/addons/pos_restaurant/static/src/js/floors.js +++ b/addons/pos_restaurant/static/src/js/floors.js @@ -34,7 +34,7 @@ models.load_models({ }); // At POS Startup, after the floors are loaded, load the tables, and associate -// them with their floor. +// them with their floor. models.load_models({ model: 'restaurant.table', fields: ['name','width','height','position_h','position_v','shape','floor_id','color','seats'], @@ -87,7 +87,7 @@ var TableWidget = PosBaseWidget.extend({ } else { self.getParent().deselect_tables(); } - } + } },50); } else { floorplan.pos.set_table(this.table); @@ -117,7 +117,7 @@ var TableWidget = PosBaseWidget.extend({ this.table.position_h += dx; $el.css(this.table_style()); - } + } }, // drag and dropping the resizing handles handle_dragstart_handler: function(event, $el, drag) { @@ -125,7 +125,7 @@ var TableWidget = PosBaseWidget.extend({ this.handle_dragging = true; this.handle_dragpos = this.event_position(event); this.handle = drag.target; - } + } }, handle_dragend_handler: function() { this.handle_dragging = false; @@ -143,7 +143,7 @@ var TableWidget = PosBaseWidget.extend({ var MIN_SIZE = 40; // smaller than this, and it becomes impossible to edit. - var tw = Math.max(MIN_SIZE, this.table.width); + var tw = Math.max(MIN_SIZE, this.table.width); var th = Math.max(MIN_SIZE, this.table.height); var tx = this.table.position_h; var ty = this.table.position_v; @@ -199,7 +199,7 @@ var TableWidget = PosBaseWidget.extend({ 'margin-top': unit(-table.height/2), 'top': unit(table.position_v + table.height/2), 'left': unit(table.position_h + table.width/2), - 'border-radius': table.shape === 'round' ? + 'border-radius': table.shape === 'round' ? unit(Math.max(table.width,table.height)/2) : '3px', }; if (table.color) { @@ -207,7 +207,7 @@ var TableWidget = PosBaseWidget.extend({ } if (table.height >= 150 && table.width >= 150) { style['font-size'] = '32px'; - } + } return style; }, @@ -264,14 +264,14 @@ var TableWidget = PosBaseWidget.extend({ event.preventDefault(); }); }, - // destroy the table. We do not really destroy it, we set it + // destroy the table. We do not really destroy it, we set it // to inactive so that it doesn't show up anymore, but it still // available on the database for the orders that depend on it. trash: function(){ var self = this; var model = new Model('restaurant.table'); return model.call('create_from_ui',[{'active':false,'id':this.table.id}]).then(function(table_id){ - // Removing all references from the table and the table_widget in in the UI ... + // Removing all references from the table and the table_widget in in the UI ... for (var i = 0; i < self.pos.floors.length; i++) { var floor = self.pos.floors[i]; for (var j = 0; j < floor.tables.length; j++) { @@ -337,7 +337,7 @@ var TableWidget = PosBaseWidget.extend({ this.$el.on('dragstart', function(event,drag){ self.dragstart_handler(event,$(this),drag); }); this.$el.on('drag', function(event,drag){ self.dragmove_handler(event,$(this),drag); }); this.$el.on('dragend', function(event,drag){ self.dragend_handler(event,$(this),drag); }); - + var handles = this.$el.find('.table-handle'); handles.on('dragstart', function(event,drag){ self.handle_dragstart_handler(event,$(this),drag); }); handles.on('drag', function(event,drag){ self.handle_dragmove_handler(event,$(this),drag); }); @@ -364,7 +364,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ }, hide: function(){ this._super(); - if (this.editing) { + if (this.editing) { this.toggle_editing(); } this.chrome.widget.order_selector.show(); @@ -372,7 +372,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ show: function(){ this._super(); this.chrome.widget.order_selector.hide(); - for (var i = 0; i < this.table_widgets.length; i++) { + for (var i = 0; i < this.table_widgets.length; i++) { this.table_widgets[i].renderElement(); } this.check_empty_floor(); @@ -389,7 +389,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ this.check_empty_floor(); } }, - background_image_url: function(floor) { + background_image_url: function(floor) { return '/web/image?model=restaurant.floor&id='+floor.id+'&field=background_image'; }, get_floor_style: function() { @@ -406,7 +406,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ var self = this; this.floor.background_color = background; (new Model('restaurant.floor')) - .call('set_background_color',[this.floor.id, background]).fail(function(err,event){ + .call('write',[[this.floor.id], {'background_color': background}]).fail(function(err, event){ self.gui.show_popup('error',{ 'title':_t('Changes could not be saved'), 'body': _t('You must be connected to the internet to save your changes.'), @@ -530,13 +530,13 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ for (var p in params) { table[p] = params[p]; } - + table.name = this.new_table_name(params.name); - delete table.id; + delete table.id; table.floor_id = [this.floor.id,'']; table.floor = this.floor; - + this.floor.tables.push(table); var tw = new TableWidget(this,{table: table}); tw.appendTo('.floor-map .tables'); @@ -584,7 +584,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ } }, update_toolbar: function(){ - + if (this.editing) { this.$('.edit-bar').removeClass('oe_hidden'); this.$('.edit-button.editing').addClass('active'); @@ -612,7 +612,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ var self = this; // cleanup table widgets from previous renders - for (var i = 0; i < this.table_widgets.length; i++) { + for (var i = 0; i < this.table_widgets.length; i++) { this.table_widgets[i].destroy(); } @@ -659,7 +659,7 @@ var FloorScreenWidget = screens.ScreenWidget.extend({ this.$('.edit-button.trash').click(function(){ self.tool_trash_table(); }); - + this.$('.color-picker .close-picker').click(function(event){ self.tool_colorpicker_close(); event.stopPropagation(); @@ -724,7 +724,7 @@ models.Order = models.Order.extend({ var json = _super_order.export_as_JSON.apply(this,arguments); json.table = this.table ? this.table.name : undefined; json.table_id = this.table ? this.table.id : false; - json.floor = this.table ? this.table.floor.name : 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; @@ -787,7 +787,7 @@ chrome.OrderSelectorWidget.include({ // 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. +// if there is none. var _super_posmodel = models.PosModel.prototype; models.PosModel = models.PosModel.extend({ initialize: function(session, attributes) { @@ -819,9 +819,9 @@ models.PosModel = models.PosModel.extend({ } else { this.table = table; var orders = this.get_order_list(); - if (orders.length) { + if (orders.length) { this.set_order(orders[0]); // and go to the first one ... - } else { + } else { this.add_new_order(); // or create a new order with the current table } } @@ -851,8 +851,8 @@ models.PosModel = models.PosModel.extend({ // 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_order_list: function() { + var orders = _super_posmodel.get_order_list.call(this); if (!this.config.iface_floorplan) { return orders; } else if (!this.table) { @@ -890,8 +890,8 @@ models.PosModel = models.PosModel.extend({ return count; }, - // When we validate an order we go back to the floor plan. - // When we cancel an order and there is multiple 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){ if (this.config.iface_floorplan) { @@ -907,7 +907,7 @@ models.PosModel = models.PosModel.extend({ } }, - + }); var TableGuestsButton = screens.ActionButtonWidget.extend({ @@ -937,7 +937,7 @@ var TableGuestsButton = screens.ActionButtonWidget.extend({ screens.OrderWidget.include({ update_summary: function(){ this._super(); - if (this.getParent().action_buttons && + if (this.getParent().action_buttons && this.getParent().action_buttons.guests) { this.getParent().action_buttons.guests.renderElement(); } diff --git a/addons/pos_restaurant/views/pos_restaurant_templates.xml b/addons/pos_restaurant/views/pos_restaurant_templates.xml index 9664d815bcc..179b9414270 100644 --- a/addons/pos_restaurant/views/pos_restaurant_templates.xml +++ b/addons/pos_restaurant/views/pos_restaurant_templates.xml @@ -1,6 +1,5 @@ - - + - - + diff --git a/addons/pos_restaurant/views/pos_restaurant_views.xml b/addons/pos_restaurant/views/pos_restaurant_views.xml index 1b3ef4bfba4..9a48fe2f4d0 100644 --- a/addons/pos_restaurant/views/pos_restaurant_views.xml +++ b/addons/pos_restaurant/views/pos_restaurant_views.xml @@ -1,10 +1,8 @@ - - - + - + Restaurant Floors restaurant.floor @@ -27,7 +25,7 @@ - + Restaurant Floors restaurant.floor @@ -39,7 +37,7 @@ - + Floor Plans ir.actions.act_window restaurant.floor @@ -55,7 +53,7 @@ - + Restaurant Table restaurant.table @@ -86,7 +84,7 @@ - + Order Printer restaurant.printer @@ -100,7 +98,7 @@ - + Order Printers ir.actions.act_window restaurant.printer @@ -121,7 +119,7 @@ - + Order Printers restaurant.printer @@ -140,5 +138,4 @@ sequence="30" groups="point_of_sale.group_pos_manager"/> - - +