[WIP] pos_restaurant: floor and tables in the pos
authorFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>
Mon, 8 Sep 2014 09:35:03 +0000 (11:35 +0200)
committerFrédéric van der Essen <fvdessen@gmail.com>
Tue, 25 Nov 2014 16:10:10 +0000 (17:10 +0100)
addons/point_of_sale/static/src/js/screens.js
addons/pos_restaurant/__openerp__.py
addons/pos_restaurant/restaurant.py
addons/pos_restaurant/restaurant_view.xml
addons/pos_restaurant/static/src/css/restaurant.css
addons/pos_restaurant/static/src/js/floors.js [new file with mode: 0644]
addons/pos_restaurant/static/src/js/main.js
addons/pos_restaurant/static/src/xml/floors.xml [new file with mode: 0644]
addons/pos_restaurant/views/templates.xml

index f92fb50..56f538a 100644 (file)
@@ -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({
index edb5b0b..119efa4 100644 (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,
index c7d02a3..69a1e3f 100644 (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 = {
index 84adc88..27d5e2c 100644 (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>
                     <group string="Bar &amp; Restaurant" >
                         <field name="iface_splitbill" />
                         <field name="iface_printbill" />
+                        <field name="floor_ids" />
                         <field name="printer_ids" />
                     </group>
                 </sheet>
index 0ffebfc..de1afd0 100644 (file)
@@ -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;
+}
+
+
diff --git a/addons/pos_restaurant/static/src/js/floors.js b/addons/pos_restaurant/static/src/js/floors.js
new file mode 100644 (file)
index 0000000..a097cd0
--- /dev/null
@@ -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');
+            }
+        },
+    });
+
+}
index 606eef8..6967ba9 100644 (file)
@@ -8,4 +8,6 @@ openerp.pos_restaurant = function(instance){
 
     openerp_restaurant_printbill(instance,module);
 
+    openerp_restaurant_floors(instance,module);
+
 };
diff --git a/addons/pos_restaurant/static/src/xml/floors.xml b/addons/pos_restaurant/static/src/xml/floors.xml
new file mode 100644 (file)
index 0000000..0126d9f
--- /dev/null
@@ -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>
index 10c269b..bd2610c 100644 (file)
@@ -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>