[WIP] pos_restaurant: floor and tables in the pos

This commit is contained in:
Frederic van der Essen
2014-11-25 17:10:10 +01:00
committed by Frédéric van der Essen
parent 52c3b52bf0
commit fdaff3e52b
9 changed files with 286 additions and 0 deletions
@@ -134,6 +134,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
set_default_screen: function(){
this.set_current_screen(this.default_screen);
},
change_default_screen: function(screen){
this.default_screen = screen;
},
});
module.ScreenWidget = module.PosBaseWidget.extend({
+1
View File
@@ -48,6 +48,7 @@ This module adds several restaurant features to the Point of Sale:
'static/src/xml/multiprint.xml',
'static/src/xml/splitbill.xml',
'static/src/xml/printbill.xml',
'static/src/xml/floors.xml',
],
'installable': True,
'auto_install': False,
+28
View File
@@ -28,6 +28,33 @@ from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
class restaurant_floor(osv.osv):
_name = 'restaurant.floor'
_columns = {
'name': fields.char('Floor Name', size=32, required=True, help='An internal identification of the restaurant floor'),
'pos_config_id': fields.many2one('pos.config','Point of Sale'),
'background_image': fields.binary('Background Image', help='A background image used to display a floor layout in the point of sale interface'),
'table_ids': fields.one2many('restaurant.table','floor_id','Tables', help='The list of tables in this floor'),
}
class restaurant_table(osv.osv):
_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.integer('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.integer('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.integer('Width', help="The table's width in percentage of the floor's width"),
'height': fields.integer('Height', help="The table's height in percentage of the floor's height"),
'color': fields.char('Color', size=32, help="The table's color"),
}
_defaults = {
'shape': 'square',
'height': 10,
'width': 10,
}
class restaurant_printer(osv.osv):
_name = 'restaurant.printer'
@@ -46,6 +73,7 @@ class pos_config(osv.osv):
_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'),
'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 = {
+86
View File
@@ -1,6 +1,91 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- RESTAURANTS FLOORS -->
<record model="ir.ui.view" id="view_restaurant_floor_form">
<field name="name">Restaurant Floors</field>
<field name="model">restaurant.floor</field>
<field name="arch" type="xml">
<form string="Restaurant Floor">
<sheet>
<group col="4">
<field name="name" />
<field name="pos_config_id" />
</group>
<field name="table_ids">
<tree string='Tables'>
<field name="name" />
<field name="shape" />
<field name="width" />
<field name="height" />
<field name="position_h" />
<field name="position_v" />
</tree>
</field>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_restaurant_floor_tree">
<field name="name">Restaurant Floors</field>
<field name="model">restaurant.floor</field>
<field name="arch" type="xml">
<tree string="Restaurant Floors">
<field name="name" />
<field name="pos_config_id" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="action_restaurant_floor_form">
<field name="name">Restaurant Floors</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">restaurant.floor</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add a Restaurant Floor.
</p><p>
A restaurant floor represents the place where customers are served, this is where you can
define and position the tables.
</p>
</field>
</record>
<record model="ir.ui.view" id="view_restaurant_table_form">
<field name="name">Restaurant Table</field>
<field name="model">restaurant.table</field>
<field name="arch" type="xml">
<form string="Restaurant Table">
<group col="2">
<field name="name" />
<field name="shape" />
<field name="color" />
</group>
<group col="4">
<field name="position_h" />
<field name="position_v" />
<field name="width" />
<field name="height" />
</group>
</form>
</field>
</record>
<menuitem
parent="point_of_sale.menu_point_config_product"
action="action_restaurant_floor_form"
id="menu_restaurant_floor_all"
sequence="30"
groups="point_of_sale.group_pos_manager"/>
<!-- RESTAURANT PRINTERS -->
<record model="ir.ui.view" id="view_restaurant_printer_form">
<field name="name">Order Printer</field>
<field name="model">restaurant.printer</field>
@@ -64,6 +149,7 @@
<group string="Bar &amp; Restaurant" >
<field name="iface_splitbill" />
<field name="iface_printbill" />
<field name="floor_ids" />
<field name="printer_ids" />
</group>
</sheet>
@@ -1,2 +1,56 @@
/* --- Restaurant Specific CSS --- */
.screen .screen-content-flexbox {
margin: 0px auto;
max-width: 1024px;
text-align: left;
height: 100%;
overflow: hidden;
position: relative;
display: flex;
flex-flow: column nowrap;
}
/* ------ FLOOR SELECTOR ------- */
.floor-selector {
line-height: 48px;
font-size: 18px;
border-bottom: solid 1px rgb(196,196,196);
display: flex;
text-align: center;
width: 100%;
}
.floor-selector .button {
cursor: pointer;
border-left: dashed 1px rgb(196,196,196);
flex: 1;
}
.floor-selector .button:first-child {
border-left: none;
}
.floor-selector .button.active {
background: rgb(210, 231, 210);
}
/* ------ FLOOR MAP ------- */
.floor-map {
flex: 1;
position: relative;
width: auto;
margin: 8px;
border-radius: 3px;
background: rgba(0,0,0,0.1);
}
.floor-map .table{
position: absolute;
text-align: center;
font-size: 18px;
color: white;
background: rgb(53, 211, 116);
border-radius: 3px;
cursor: pointer;
}
@@ -0,0 +1,86 @@
function openerp_restaurant_floors(instance,module){
module.PosModel.prototype.models.push({
model: 'restaurant.floor',
fields: ['name','background_image','table_ids'],
domain: function(self){ return [['pos_config_id','=',self.config.id]] },
loaded: function(self,floors){
self.floors = floors;
self.floors_by_id = {};
for (var i = 0; i < floors.length; i++) {
floors[i].tables = [];
self.floors_by_id[floors[i].id] = floors[i];
}
},
});
module.PosModel.prototype.models.push({
model: 'restaurant.table',
fields: ['name','width','height','position_h','position_v','shape','floor_id','color'],
loaded: function(self,tables){
for (var i = 0; i < tables.length; i++) {
var floor = self.floors_by_id[tables[i].floor_id[0]];
if (floor) {
floor.tables.push(tables[i]);
}
}
},
});
module.FloorScreenWidget = module.ScreenWidget.extend({
template: 'FloorScreenWidget',
show_leftpane: false,
init: function(parent, options) {
this._super(parent, options);
this.floor = this.pos.floors[0];
},
click_floor_button: function(event,$el){
var floor = this.pos.floors_by_id[$el.data('id')];
if (floor !== this.floor) {
this.floor = floor;
this.renderElement();
}
},
table_style: function(table){
function unit(val){ return Math.floor(val * 10) + 'px'; }
var str = "";
var style = {
'width': unit(table.width),
'height': unit(table.height),
'line-height': unit(table.height),
'margin-left': unit(-table.width/2),
'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' ?
unit(Math.max(table.width,table.height)/2) : '3px',
};
for (s in style) {
str += s + ":" + style[s] + "; ";
}
return str;
},
renderElement: function(){
var self = this;
this._super();
this.$('.floor-selector .button').click(function(event){
self.click_floor_button(event,$(this));
});
},
});
module.PosWidget.include({
build_widgets: function(){
var self = this;
this._super();
if (this.pos.floors.length > 0) {
this.floors_screen = new module.FloorScreenWidget(this,{});
this.floors_screen.appendTo(this.$('.screens'));
this.screen_selector.add_screen('floors',this.floors_screen);
this.screen_selector.change_default_screen('floors');
}
},
});
}
@@ -8,4 +8,6 @@ openerp.pos_restaurant = function(instance){
openerp_restaurant_printbill(instance,module);
openerp_restaurant_floors(instance,module);
};
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="FloorScreenWidget">
<div class='floor-screen screen'>
<div class='screen-content-flexbox'>
<div class='floor-selector'>
<t t-foreach="widget.pos.floors" t-as="floor">
<t t-if="floor.id === widget.floor.id">
<span class='button button-floor active' t-att-data-id="floor.id"><t t-esc="floor.name" /></span>
</t>
<t t-if="floor.id !== widget.floor.id">
<span class='button button-floor' t-att-data-id="floor.id"><t t-esc="floor.name" /></span>
</t>
</t>
</div>
<div class='floor-map'>
<t t-foreach="widget.floor.tables" t-as="table">
<div class='table' t-att-style='widget.table_style(table)'><t t-esc='table.name' /></div>
</t>
</div>
</div>
</div>
</t>
</templates>
@@ -15,6 +15,7 @@
<script type="text/javascript" src="/pos_restaurant/static/src/js/multiprint.js"></script>
<script type="text/javascript" src="/pos_restaurant/static/src/js/splitbill.js"></script>
<script type="text/javascript" src="/pos_restaurant/static/src/js/printbill.js"></script>
<script type="text/javascript" src="/pos_restaurant/static/src/js/floors.js"></script>
<script type="text/javascript" src="/pos_restaurant/static/src/js/main.js"></script>
</xpath>
</template>