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({
'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,
_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'
_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 = {
<?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 & Restaurant" >
<field name="iface_splitbill" />
<field name="iface_printbill" />
+ <field name="floor_ids" />
<field name="printer_ids" />
</group>
</sheet>
/* --- 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;
+}
+
+
--- /dev/null
+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');
+ }
+ },
+ });
+
+}
openerp_restaurant_printbill(instance,module);
+ openerp_restaurant_floors(instance,module);
+
};
--- /dev/null
+<?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>
<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>