[IMP] point_of_sale, pos_*: unpaid orders are saved in localstorage and persist betwe...
authorFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>
Mon, 3 Nov 2014 17:27:51 +0000 (18:27 +0100)
committerFrédéric van der Essen <fvdessen@gmail.com>
Wed, 26 Nov 2014 10:40:17 +0000 (11:40 +0100)
Conflicts:
addons/point_of_sale/static/src/js/models.js
addons/point_of_sale/static/src/js/screens.js
addons/pos_restaurant/static/src/js/multiprint.js
addons/pos_restaurant/static/src/js/notes.js

Conflicts:
addons/point_of_sale/static/src/js/models.js
addons/point_of_sale/static/src/js/screens.js
addons/point_of_sale/static/src/xml/pos.xml

13 files changed:
addons/point_of_sale/point_of_sale.py
addons/point_of_sale/static/src/js/db.js
addons/point_of_sale/static/src/js/devices.js
addons/point_of_sale/static/src/js/models.js
addons/point_of_sale/static/src/js/screens.js
addons/point_of_sale/static/src/js/widgets.js
addons/point_of_sale/static/src/xml/pos.xml
addons/pos_discount/static/src/js/discount.js
addons/pos_loyalty/static/src/js/loyalty.js
addons/pos_restaurant/static/src/js/floors.js
addons/pos_restaurant/static/src/js/multiprint.js
addons/pos_restaurant/static/src/js/notes.js [new file with mode: 0644]
addons/pos_restaurant/static/src/js/splitbill.js

index 13be548..dc773f1 100644 (file)
@@ -21,6 +21,7 @@
 
 import logging
 import time
+import uuid
 
 from openerp import tools
 from openerp.osv import fields, osv
@@ -81,6 +82,7 @@ class pos_config(osv.osv):
         'proxy_ip':       fields.char('IP Address', help='The hostname or ip address of the hardware proxy, Will be autodetected if left empty', size=45),
 
         'state' : fields.selection(POS_CONFIG_STATE, 'Status', required=True, readonly=True, copy=False),
+        'uuid'  : fields.char('uuid', readonly=True, help='A globally unique identifier for this pos configuration, used to prevent conflicts in client-generated data'),
         'sequence_id' : fields.many2one('ir.sequence', 'Order IDs Sequence', readonly=True,
             help="This sequence is automatically created by Odoo but you can change it "\
                 "to customize the reference numbers of your orders.", copy=False),
@@ -146,6 +148,8 @@ class pos_config(osv.osv):
             session = record.session_ids[0]
             result.append((record.id, record.name + ' ('+session.user_id.name+')')) #, '+states[session.state]+')'))
         return result
+    def _generate_uuid(self, cr, uid, context=None):
+        return str(uuid.uuid1())
 
     def _default_sale_journal(self, cr, uid, context=None):
         company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
@@ -169,6 +173,7 @@ class pos_config(osv.osv):
         return company_id
 
     _defaults = {
+        'uuid'  : _generate_uuid,
         'state' : POS_CONFIG_STATE[0][0],
         'journal_id': _default_sale_journal,
         'group_by' : True,
index 15a006d..90955b8 100644 (file)
@@ -13,6 +13,10 @@ function openerp_pos_db(instance, module){
             options = options || {};
             this.name = options.name || this.name;
             this.limit = options.limit || this.limit;
+            
+            if (options.uuid) {
+                this.name = this.name + '_' + options.uuid;
+            }
 
             //cache the data in memory to avoid roundtrips to the localstorage
             this.cache = {};
@@ -39,6 +43,15 @@ function openerp_pos_db(instance, module){
             this.packagings_by_product_tmpl_id = {};
             this.packagings_by_ean13 = {};
         },
+
+        /* 
+         * sets an uuid to prevent conflict in locally stored data between multiple databases running
+         * in the same browser at the same origin (Doing this is not advised !)
+         */
+        set_uuid: function(uuid){
+            this.name = this.name + '_' + uuid;
+        },
+
         /* returns the category object from its id. If you pass a list of id as parameters, you get
          * a list of category objects. 
          */  
@@ -302,7 +315,7 @@ function openerp_pos_db(instance, module){
             }
             var results = [];
             for(var i = 0; i < this.limit; i++){
-                r = re.exec(this.partner_search_string);
+                var r = re.exec(this.partner_search_string);
                 if(r){
                     var id = Number(r[1]);
                     results.push(this.get_partner_by_id(id));
@@ -378,6 +391,8 @@ function openerp_pos_db(instance, module){
             }
             return results;
         },
+
+        /* paid orders */
         add_order: function(order){
             var order_id = order.uid;
             var orders  = this.load('orders',[]);
@@ -417,5 +432,42 @@ function openerp_pos_db(instance, module){
             }
             return undefined;
         },
+
+        /* working orders */
+        save_unpaid_order: function(order){
+            var order_id = order.uid;
+            var orders = this.load('unpaid_orders',[]);
+            var serialized = order.export_as_JSON();
+
+            for (var i = 0; i < orders.length; i++) {
+                if (orders[i].id === order_id){
+                    orders[i].data = serialized;
+                    this.save('unpaid_orders',orders);
+                    return order_id;
+                }
+            }
+
+            orders.push({id: order_id, data: serialized});
+            this.save('unpaid_orders',orders);
+            return order_id;
+        },
+        remove_unpaid_order: function(order){
+            var orders = this.load('unpaid_orders',[]);
+            orders = _.filter(orders, function(o){
+                return o.id !== order.uid;
+            });
+            this.save('unpaid_orders',orders);
+        },
+        remove_all_unpaid_orders: function(){
+            this.save('unpaid_orders',[]);
+        },
+        get_unpaid_orders: function(){
+            var saved = this.load('unpaid_orders',[]);
+            var orders = [];
+            for (var i = 0; i < saved.length; i++) {
+                orders.push(saved[i].data);
+            }
+            return orders;
+        },
     });
 }
index b4d6037..ffcc8d8 100644 (file)
@@ -374,10 +374,8 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
         scale_read: function(){
             var self = this;
             var ret = new $.Deferred();
-            console.log('scale_read');
             this.message('scale_read',{})
                 .then(function(weight){
-                    console.log(weight)
                     ret.resolve(self.use_debug_weight ? self.debug_weight : weight);
                 }, function(){ //failed to read weight
                     ret.resolve(self.use_debug_weight ? self.debug_weight : {weight:0.0, unit:'Kg', info:'ok'});
index c737570..b04ab93 100644 (file)
@@ -199,11 +199,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             domain: function(self){ return [['state','=','opened'],['user_id','=',self.session.uid]]; },
             loaded: function(self,pos_sessions){
                 self.pos_session = pos_sessions[0]; 
-
-                var orders = self.db.get_orders();
-                for (var i = 0; i < orders.length; i++) {
-                    self.pos_session.sequence_number = Math.max(self.pos_session.sequence_number, orders[i].data.sequence_number+1);
-                }
             },
         },{
             model: 'pos.config',
@@ -226,9 +221,17 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                     'price':    self.config.barcode_price,
                 });
 
+
                 if (self.config.company_id[0] !== self.user.company_id[0]) {
                     throw new Error(_t("Error: The Point of Sale User must belong to the same company as the Point of Sale. You are probably trying to load the point of sale as an administrator in a multi-company setup, with the administrator account set to the wrong company."));
                 }
+
+                self.db.set_uuid(self.config.uuid);
+
+                var orders = self.db.get_orders();
+                for (var i = 0; i < orders.length; i++) {
+                    self.pos_session.sequence_number = Math.max(self.pos_session.sequence_number, orders[i].data.sequence_number+1);
+                }
             },
         },{
             model: 'stock.location',
@@ -472,11 +475,51 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
 
         //creates a new empty order and sets it as the current order
         add_new_order: function(){
-            var order = new module.Order({pos:this});
+            var order = new module.Order({},{pos:this});
             this.get('orders').add(order);
             this.set('selectedOrder', order);
             return order;
         },
+        // load the locally saved unpaid orders for this session.
+        load_orders: function(){
+            var jsons = this.db.get_unpaid_orders();
+            var orders = [];
+            var not_loaded_count = 0; 
+
+            for (var i = 0; i < jsons.length; i++) {
+                var json = jsons[i];
+                if (json.pos_session_id === this.pos_session.id) {
+                    orders.push(new module.Order({},{
+                        pos:  this,
+                        json: json,
+                    }));
+                } else {
+                    not_loaded_count += 1;
+                }
+            }
+
+            if (not_loaded_count) {
+                console.info('There are '+not_loaded_count+' locally saved unpaid orders belonging to another session');
+            }
+            
+            orders = orders.sort(function(a,b){
+                return a.sequence_number - b.sequence_number;
+            });
+
+            if (orders.length) {
+                this.get('orders').add(orders);
+            }
+        },
+
+        set_start_order: function(){
+            var orders = this.get('orders').models;
+            
+            if (orders.length && !this.get('selectedOrder')) {
+                this.set('selectedOrder',orders[0]);
+            } else {
+                this.add_new_order();
+            }
+        },
 
         // return the current order
         get_order: function(){
@@ -662,13 +705,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             }
 
             if(parsed_code.type === 'price'){
-                selectedOrder.addProduct(product, {price:parsed_code.value});
+                selectedOrder.add_product(product, {price:parsed_code.value});
             }else if(parsed_code.type === 'weight'){
-                selectedOrder.addProduct(product, {quantity:parsed_code.value, merge:false});
+                selectedOrder.add_product(product, {quantity:parsed_code.value, merge:false});
             }else if(parsed_code.type === 'discount'){
-                selectedOrder.addProduct(product, {discount:parsed_code.value, merge:false});
+                selectedOrder.add_product(product, {discount:parsed_code.value, merge:false});
             }else{
-                selectedOrder.addProduct(product);
+                selectedOrder.add_product(product);
             }
             return true;
         },
@@ -742,7 +785,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
         // rounded to zero
         set_quantity: function(quantity){
             if(quantity === 'remove'){
-                this.order.removeOrderline(this);
+                this.order.remove_orderline(this);
                 return;
             }else{
                 var quant = parseFloat(quantity) || 0;
@@ -987,7 +1030,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
     module.PaymentlineCollection = Backbone.Collection.extend({
         model: module.Paymentline,
     });
-    
 
     // An order more or less represents the content of a client's shopping cart (the OrderLines) 
     // plus the associated payment information (the Paymentlines) 
@@ -997,30 +1039,49 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
         initialize: function(attributes,options){
             Backbone.Model.prototype.initialize.apply(this, arguments);
             options  = options || {};
-            this.pos = attributes.pos; 
+
+            this.init_locked    = true;
+            this.pos            = options.pos; 
+            this.selected_orderline   = undefined;
+            this.selected_paymentline = undefined;
+            this.screen_data    = {};  // see ScreenSelector
+            this.temporary      = options.temporary || false;
+            this.creation_date  = new Date();
+            this.to_invoice     = false;
+            this.orderlines     = new module.OrderlineCollection();
+            this.paymentlines   = new module.PaymentlineCollection(); 
+            this.pos_session_id = this.pos.pos_session.id;
+
+            this.set({ client: null });
+
             if (options.json) {
                 this.init_from_JSON(options.json);
-                return this;
+            } else {
+                this.sequence_number = this.pos.pos_session.sequence_number++;
+                this.uid  = this.generate_unique_id();
+                this.name = _t("Order ") + this.uid; 
             }
-            this.sequence_number = this.pos.pos_session.sequence_number++;
-            this.uid =     this.generateUniqueId();
-            this.set({
-                creationDate:   new Date(),
-                orderLines:     new module.OrderlineCollection(),
-                paymentLines:   new module.PaymentlineCollection(),
-                name:           _t("Order ") + this.uid,
-                client:         null,
-            });
-            this.selected_orderline   = undefined;
-            this.selected_paymentline = undefined;
-            this.screen_data = {};  // see ScreenSelector
-            this.temporary = attributes.temporary || false;
-            this.to_invoice = false;
+
+            this.on('change',              this.save_to_db, this);
+            this.orderlines.on('change',   this.save_to_db, this);
+            this.paymentlines.on('change', this.save_to_db, this);
+
+            this.init_locked = false;
+            this.save_to_db();
+
             return this;
         },
+        save_to_db: function(){
+            if (!this.init_locked) {
+                this.pos.db.save_unpaid_order(this);
+            } 
+        },
         init_from_JSON: function(json) {
             this.sequence_number = json.sequence_number;
+            this.pos.pos_session.sequence_number = Math.max(this.sequence_number+1,this.pos.pos_session.sequence_number);
+            this.session_id    = json.pos_session_id;
             this.uid = json.uid;
+            this.name = _t("Order ") + this.uid;
             if (json.partner_id) {
                 var client = this.pos.db.get_partner_by_id(json.partner_id);
                 if (!client) {
@@ -1029,39 +1090,150 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             } else {
                 var client = null;
             }
-            this.set({
-                creationDate: new Date(),
-                orderLines: new module.OrderlineCollection(),
-                paymentLines: new module.PaymentlineCollection(),
-                name: _t("Order ") + this.uid,
-                client: client,
-            });
-            this.selected_orderline = undefined;
-            this.selected_paymentline = undefined;
-            this.screen_data = {};
+            this.set_client(client);
+
             this.temporary = false;     // FIXME
             this.to_invoice = false;    // FIXME
 
             var orderlines = json.lines;
             for (var i = 0; i < orderlines.length; i++) {
                 var orderline = orderlines[i][2];
-                this.addOrderline(new module.Orderline({}, {pos: this.pos, order: this, json: orderline}));
+                this.add_orderline(new module.Orderline({}, {pos: this.pos, order: this, json: orderline}));
             }
 
             var paymentlines = json.statement_ids;
             for (var i = 0; i < paymentlines.length; i++) {
                 var paymentline = paymentlines[i][2];
-                this.get('paymentLines').add(new module.Paymentline({},{pos: this.pos, json: paymentline}));
+                this.paymentlines.add(new module.Paymentline({},{pos: this.pos, json: paymentline}));
             }
         },
+        export_as_JSON: function() {
+            var orderLines, paymentLines;
+            orderLines = [];
+            this.orderlines.each(_.bind( function(item) {
+                return orderLines.push([0, 0, item.export_as_JSON()]);
+            }, this));
+            paymentLines = [];
+            this.paymentlines.each(_.bind( function(item) {
+                return paymentLines.push([0, 0, item.export_as_JSON()]);
+            }, this));
+            return {
+                name: this.get_name(),
+                amount_paid: this.get_total_paid(),
+                amount_total: this.get_total_with_tax(),
+                amount_tax: this.get_total_tax(),
+                amount_return: this.get_change(),
+                lines: orderLines,
+                statement_ids: paymentLines,
+                pos_session_id: this.pos_session_id,
+                partner_id: this.get_client() ? this.get_client().id : false,
+                user_id: this.pos.cashier ? this.pos.cashier.id : this.pos.user.id,
+                uid: this.uid,
+                sequence_number: this.sequence_number,
+            };
+        },
+        export_for_printing: function(){
+            var orderlines = [];
+            var self = this;
+
+            this.orderlines.each(function(orderline){
+                orderlines.push(orderline.export_for_printing());
+            });
+
+            var paymentlines = [];
+            this.paymentlines.each(function(paymentline){
+                paymentlines.push(paymentline.export_for_printing());
+            });
+            var client  = this.get('client');
+            var cashier = this.pos.cashier || this.pos.user;
+            var company = this.pos.company;
+            var shop    = this.pos.shop;
+            var date    = new Date();
+
+            function is_xml(subreceipt){
+                return subreceipt ? (subreceipt.split('\n')[0].indexOf('<!DOCTYPE QWEB') >= 0) : false;
+            }
+
+            function render_xml(subreceipt){
+                if (!is_xml(subreceipt)) {
+                    return subreceipt;
+                } else {
+                    subreceipt = subreceipt.split('\n').slice(1).join('\n');
+                    var qweb = new QWeb2.Engine();
+                        qweb.debug = instance.session.debug;
+                        qweb.default_dict = _.clone(QWeb.default_dict);
+                        qweb.add_template('<templates><t t-name="subreceipt">'+subreceipt+'</t></templates>');
+                    
+                    return qweb.render('subreceipt',{'pos':self.pos,'widget':self.pos.pos_widget,'order':self, 'receipt': receipt}) ;
+                }
+            }
+
+            var receipt = {
+                orderlines: orderlines,
+                paymentlines: paymentlines,
+                subtotal: this.get_subtotal(),
+                total_with_tax: this.get_total_with_tax(),
+                total_without_tax: this.get_total_without_tax(),
+                total_tax: this.get_total_tax(),
+                total_paid: this.get_total_paid(),
+                total_discount: this.get_total_discount(),
+                tax_details: this.get_tax_details(),
+                change: this.get_change(),
+                name : this.get_name(),
+                client: client ? client.name : null ,
+                invoice_id: null,   //TODO
+                cashier: cashier ? cashier.name : null,
+                header: this.pos.config.receipt_header || '',
+                footer: this.pos.config.receipt_footer || '',
+                precision: {
+                    price: 2,
+                    money: 2,
+                    quantity: 3,
+                },
+                date: { 
+                    year: date.getFullYear(), 
+                    month: date.getMonth(), 
+                    date: date.getDate(),       // day of the month 
+                    day: date.getDay(),         // day of the week 
+                    hour: date.getHours(), 
+                    minute: date.getMinutes() ,
+                    isostring: date.toISOString(),
+                    localestring: date.toLocaleString(),
+                }, 
+                company:{
+                    email: company.email,
+                    website: company.website,
+                    company_registry: company.company_registry,
+                    contact_address: company.partner_id[1], 
+                    vat: company.vat,
+                    name: company.name,
+                    phone: company.phone,
+                    logo:  this.pos.company_logo_base64,
+                },
+                shop:{
+                    name: shop.name,
+                },
+                currency: this.pos.currency,
+            };
+            
+            if (is_xml(this.pos.config.receipt_header)){
+                receipt.header_xml = render_xml(this.pos.config.receipt_header);
+            }
+
+            if (is_xml(this.pos.config.receipt_footer)){
+                receipt.footer_xml = render_xml(this.pos.config.receipt_footer);
+            }
+
+            return receipt;
+        },
         is_empty: function(){
-            return (this.get('orderLines').models.length === 0);
+            return this.orderlines.models.length === 0;
         },
+        generate_unique_id: function() {
+            // Generates a public identification number for the order.
+            // The generated number must be unique and sequential. They are made 12 digit long
+            // to fit into EAN-13 barcodes, should it be needed 
 
-        // Generates a public identification number for the order.
-        // The generated number must be unique and sequential. They are made 12 digit long
-        // to fit into EAN-13 barcodes, should it be needed 
-        generateUniqueId: function() {
             function zero_pad(num,size){
                 var s = ""+num;
                 while (s.length < size) {
@@ -1073,15 +1245,38 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                    zero_pad(this.pos.pos_session.login_number,3) +'-'+
                    zero_pad(this.sequence_number,4);
         },
-        addOrderline: function(line){
+        get_name: function() {
+            return this.name;
+        },
+        /* ---- Order Lines --- */
+        add_orderline: function(line){
             if(line.order){
-                line.order.removeOrderline(line);
+                line.order.remove_orderline(line);
             }
             line.order = this;
-            this.get('orderLines').add(line);
-            this.selectLine(this.getLastOrderline());
+            this.orderlines.add(line);
+            this.select_orderline(this.get_last_orderline());
         },
-        addProduct: function(product, options){
+        get_orderline: function(id){
+            var orderlines = this.orderlines.models;
+            for(var i = 0; i < orderlines.length; i++){
+                if(orderlines[i].id === id){
+                    return orderlines[i];
+                }
+            }
+            return null;
+        },
+        get_orderlines: function(){
+            return this.orderlines.models;
+        },
+        get_last_orderline: function(){
+            return this.orderlines.at(this.orderlines.length -1);
+        },
+        remove_orderline: function( line ){
+            this.orderlines.remove(line);
+            this.select_orderline(this.get_last_orderline());
+        },
+        add_product: function(product, options){
             options = options || {};
             var attr = JSON.parse(JSON.stringify(product));
             attr.pos = this.pos;
@@ -1104,75 +1299,111 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                 }
             }
 
-            var last_orderline = this.getLastOrderline();
+            var last_orderline = this.get_last_orderline();
             if( last_orderline && last_orderline.can_be_merged_with(line) && options.merge !== false){
                 last_orderline.merge(line);
             }else{
-                this.get('orderLines').add(line);
+                this.orderlines.add(line);
             }
-            this.selectLine(this.getLastOrderline());
+            this.select_orderline(this.get_last_orderline());
         },
-        removeOrderline: function( line ){
-            this.get('orderLines').remove(line);
-            this.selectLine(this.getLastOrderline());
+        get_selected_orderline: function(){
+            return this.selected_orderline;
         },
-        getOrderline: function(id){
-            var orderlines = this.get('orderLines').models;
-            for(var i = 0; i < orderlines.length; i++){
-                if(orderlines[i].id === id){
-                    return orderlines[i];
+        select_orderline: function(line){
+            if(line){
+                if(line !== this.selected_orderline){
+                    if(this.selected_orderline){
+                        this.selected_orderline.set_selected(false);
+                    }
+                    this.selected_orderline = line;
+                    this.selected_orderline.set_selected(true);
                 }
+            }else{
+                this.selected_orderline = undefined;
             }
-            return null;
         },
-        getLastOrderline: function(){
-            return this.get('orderLines').at(this.get('orderLines').length -1);
+        deselect_orderline: function(){
+            if(this.selected_orderline){
+                this.selected_orderline.set_selected(false);
+                this.selected_orderline = undefined;
+            }
         },
-        addPaymentline: function(cashregister) {
-            var paymentLines = this.get('paymentLines');
-            var newPaymentline = new module.Paymentline({},{cashregister:cashregister, pos:this.pos});
+        /* ---- Payment Lines --- */
+        add_paymentline: function(cashregister) {
+            var newPaymentline = new module.Paymentline({},{cashregister:cashregister, pos: this.pos});
             if(cashregister.journal.type !== 'cash' || this.pos.config.iface_precompute_cash){
-                newPaymentline.set_amount( Math.max(this.getDueLeft(),0) );
+                newPaymentline.set_amount( Math.max(this.get_due(),0) );
             }
-            paymentLines.add(newPaymentline);
-            this.selectPaymentline(newPaymentline);
+            this.paymentlines.add(newPaymentline);
+            this.select_paymentline(newPaymentline);
 
         },
-        removePaymentline: function(line){
+        get_paymentlines: function(){
+            return this.paymentlines.models;
+        },
+        remove_paymentline: function(line){
             if(this.selected_paymentline === line){
-                this.selectPaymentline(undefined);
+                this.select_paymentline(undefined);
             }
-            this.get('paymentLines').remove(line);
+            this.paymentlines.remove(line);
         },
-        getName: function() {
-            return this.get('name');
+        clean_empty_paymentlines: function() {
+            var lines = this.paymentlines.models;
+            var empty = [];
+            for ( var i = 0; i < lines.length; i++) {
+                if (!lines[i].get_amount()) {
+                    empty.push(lines[i]);
+                }
+            }
+            for ( var i = 0; i < empty.length; i++) {
+                this.remove_paymentline(empty[i]);
+            }
         },
-        getSubtotal : function(){
-            return (this.get('orderLines')).reduce((function(sum, orderLine){
+        select_paymentline: function(line){
+            if(line !== this.selected_paymentline){
+                if(this.selected_paymentline){
+                    this.selected_paymentline.set_selected(false);
+                }
+                this.selected_paymentline = line;
+                if(this.selected_paymentline){
+                    this.selected_paymentline.set_selected(true);
+                }
+                this.trigger('change:selected_paymentline',this.selected_paymentline);
+            }
+        },
+        /* ---- Payment Status --- */
+        get_subtotal : function(){
+            return this.orderlines.reduce((function(sum, orderLine){
                 return sum + orderLine.get_display_price();
             }), 0);
         },
-        getTotalTaxIncluded: function() {
-            return (this.get('orderLines')).reduce((function(sum, orderLine) {
+        get_total_with_tax: function() {
+            return this.orderlines.reduce((function(sum, orderLine) {
                 return sum + orderLine.get_price_with_tax();
             }), 0);
         },
-        getDiscountTotal: function() {
-            return (this.get('orderLines')).reduce((function(sum, orderLine) {
-                return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity());
+        get_total_without_tax: function() {
+            return this.orderlines.reduce((function(sum, orderLine) {
+                return sum + orderLine.get_price_without_tax();
             }), 0);
         },
-        getTotalTaxExcluded: function() {
-            return (this.get('orderLines')).reduce((function(sum, orderLine) {
-                return sum + orderLine.get_price_without_tax();
+        get_total_discount: function() {
+            return this.orderlines.reduce((function(sum, orderLine) {
+                return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity());
             }), 0);
         },
-        getTax: function() {
-            return (this.get('orderLines')).reduce((function(sum, orderLine) {
+        get_total_tax: function() {
+            return this.orderlines.reduce((function(sum, orderLine) {
                 return sum + orderLine.get_tax();
             }), 0);
         },
-        getTaxDetails: function(){
+        get_total_paid: function() {
+            return this.paymentlines.reduce((function(sum, paymentLine) {
+                return sum + paymentLine.get_amount();
+            }), 0);
+        },
+        get_tax_details: function(){
             var details = {};
             var fulldetails = [];
             var taxes_by_id = {};
@@ -1181,7 +1412,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                 taxes_by_id[this.pos.taxes[i].id] = this.pos.taxes[i];
             }
 
-            this.get('orderLines').each(function(line){
+            this.orderlines.each(function(line){
                 var ldetails = line.get_tax_details();
                 for(var id in ldetails){
                     if(ldetails.hasOwnProperty(id)){
@@ -1198,17 +1429,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
 
             return fulldetails;
         },
-        getPaidTotal: function() {
-            return (this.get('paymentLines')).reduce((function(sum, paymentLine) {
-                return sum + paymentLine.get_amount();
-            }), 0);
-        },
-        getChange: function(paymentline) {
+        get_change: function(paymentline) {
             if (!paymentline) {
-                var change = this.getPaidTotal() - this.getTotalTaxIncluded();
+                var change = this.get_total_paid() - this.get_total_with_tax();
             } else {
-                var change = -this.getTotalTaxIncluded(); 
-                var lines  = this.get('paymentLines').models;
+                var change = -this.get_total_with_tax(); 
+                var lines  = this.paymentlines.models;
                 for (var i = 0; i < lines.length; i++) {
                     change += lines[i].get_amount();
                     if (lines[i] === paymentline) {
@@ -1218,12 +1444,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             }
             return round_pr(Math.max(0,change), this.pos.currency.rounding);
         },
-        getDueLeft: function(paymentline) {
+        get_due: function(paymentline) {
             if (!paymentline) {
-                var due = this.getTotalTaxIncluded() - this.getPaidTotal();
+                var due = this.get_total_with_tax() - this.get_total_paid();
             } else {
-                var due = this.getTotalTaxIncluded();
-                var lines = this.get('paymentLines').models;
+                var due = this.get_total_with_tax();
+                var lines = this.paymentlines.models;
                 for (var i = 0; i < lines.length; i++) {
                     if (lines[i] === paymentline) {
                         break;
@@ -1234,17 +1460,29 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             }
             return round_pr(Math.max(0,due), this.pos.currency.rounding);
         },
-        isPaid: function(){
-            return this.getDueLeft() === 0;
+        is_paid: function(){
+            return this.get_due() === 0;
         },
-        isPaidWithCash: function(){
-            return !!this.get('paymentLines').find( function(pl){
+        is_paid_with_cash: function(){
+            return !!this.paymentlines.find( function(pl){
                 return pl.cashregister.journal.type === 'cash';
             });
         },
         finalize: function(){
             this.destroy();
         },
+        destroy: function(args){
+            Backbone.Model.prototype.destroy.apply(this,arguments);
+            this.pos.db.remove_unpaid_order(this);
+        },
+        /* ---- Invoice --- */
+        set_to_invoice: function(to_invoice) {
+            this.to_invoice = to_invoice;
+        },
+        is_to_invoice: function(){
+            return this.to_invoice;
+        },
+        /* ---- Client / Customer --- */
         // the client related to the current order.
         set_client: function(client){
             this.set('client',client);
@@ -1256,6 +1494,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
             var client = this.get('client');
             return client ? client.name : "";
         },
+        /* ---- Screen Status --- */
         // the order also stores the screen status, as the PoS supports
         // different active screens per order. This method is used to
         // store the screen status.
@@ -1268,183 +1507,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
                 }
             }
         },
-        set_to_invoice: function(to_invoice) {
-            this.to_invoice = to_invoice;
-        },
-        is_to_invoice: function(){
-            return this.to_invoice;
-        },
-        // remove all the paymentlines with zero money in it
-        clean_empty_paymentlines: function() {
-            var lines = this.get('paymentLines').models;
-            var empty = [];
-            for ( var i = 0; i < lines.length; i++) {
-                if (!lines[i].get_amount()) {
-                    empty.push(lines[i]);
-                }
-            }
-            for ( var i = 0; i < empty.length; i++) {
-                this.removePaymentline(empty[i]);
-            }
-        },
         //see set_screen_data
         get_screen_data: function(key){
             return this.screen_data[key];
         },
-        // exports a JSON for receipt printing
-        export_for_printing: function(){
-            var orderlines = [];
-            var self = this;
-
-            this.get('orderLines').each(function(orderline){
-                orderlines.push(orderline.export_for_printing());
-            });
-
-            var paymentlines = [];
-            this.get('paymentLines').each(function(paymentline){
-                paymentlines.push(paymentline.export_for_printing());
-            });
-            var client  = this.get('client');
-            var cashier = this.pos.cashier || this.pos.user;
-            var company = this.pos.company;
-            var shop    = this.pos.shop;
-            var date    = new Date();
-
-            function is_xml(subreceipt){
-                return subreceipt ? (subreceipt.split('\n')[0].indexOf('<!DOCTYPE QWEB') >= 0) : false;
-            }
-
-            function render_xml(subreceipt){
-                if (!is_xml(subreceipt)) {
-                    return subreceipt;
-                } else {
-                    subreceipt = subreceipt.split('\n').slice(1).join('\n');
-                    var qweb = new QWeb2.Engine();
-                        qweb.debug = instance.session.debug;
-                        qweb.default_dict = _.clone(QWeb.default_dict);
-                        qweb.add_template('<templates><t t-name="subreceipt">'+subreceipt+'</t></templates>');
-                    
-                    return qweb.render('subreceipt',{'pos':self.pos,'widget':self.pos.pos_widget,'order':self, 'receipt': receipt}) ;
-                }
-            }
-
-            var receipt = {
-                orderlines: orderlines,
-                paymentlines: paymentlines,
-                subtotal: this.getSubtotal(),
-                total_with_tax: this.getTotalTaxIncluded(),
-                total_without_tax: this.getTotalTaxExcluded(),
-                total_tax: this.getTax(),
-                total_paid: this.getPaidTotal(),
-                total_discount: this.getDiscountTotal(),
-                tax_details: this.getTaxDetails(),
-                change: this.getChange(),
-                name : this.getName(),
-                client: client ? client.name : null ,
-                invoice_id: null,   //TODO
-                cashier: cashier ? cashier.name : null,
-                header: this.pos.config.receipt_header || '',
-                footer: this.pos.config.receipt_footer || '',
-                precision: {
-                    price: 2,
-                    money: 2,
-                    quantity: 3,
-                },
-                date: { 
-                    year: date.getFullYear(), 
-                    month: date.getMonth(), 
-                    date: date.getDate(),       // day of the month 
-                    day: date.getDay(),         // day of the week 
-                    hour: date.getHours(), 
-                    minute: date.getMinutes() ,
-                    isostring: date.toISOString(),
-                    localestring: date.toLocaleString(),
-                }, 
-                company:{
-                    email: company.email,
-                    website: company.website,
-                    company_registry: company.company_registry,
-                    contact_address: company.partner_id[1], 
-                    vat: company.vat,
-                    name: company.name,
-                    phone: company.phone,
-                    logo:  this.pos.company_logo_base64,
-                },
-                shop:{
-                    name: shop.name,
-                },
-                currency: this.pos.currency,
-            };
-            
-            if (is_xml(this.pos.config.receipt_header)){
-                receipt.header_xml = render_xml(this.pos.config.receipt_header);
-            }
-
-            if (is_xml(this.pos.config.receipt_footer)){
-                receipt.footer_xml = render_xml(this.pos.config.receipt_footer);
-            }
-
-            return receipt;
-        },
-        export_as_JSON: function() {
-            var orderLines, paymentLines;
-            orderLines = [];
-            (this.get('orderLines')).each(_.bind( function(item) {
-                return orderLines.push([0, 0, item.export_as_JSON()]);
-            }, this));
-            paymentLines = [];
-            (this.get('paymentLines')).each(_.bind( function(item) {
-                return paymentLines.push([0, 0, item.export_as_JSON()]);
-            }, this));
-            return {
-                name: this.getName(),
-                amount_paid: this.getPaidTotal(),
-                amount_total: this.getTotalTaxIncluded(),
-                amount_tax: this.getTax(),
-                amount_return: this.getChange(),
-                lines: orderLines,
-                statement_ids: paymentLines,
-                pos_session_id: this.pos.pos_session.id,
-                partner_id: this.get_client() ? this.get_client().id : false,
-                user_id: this.pos.cashier ? this.pos.cashier.id : this.pos.user.id,
-                uid: this.uid,
-                sequence_number: this.sequence_number,
-            };
-        },
-        getSelectedLine: function(){
-            return this.selected_orderline;
-        },
-        selectLine: function(line){
-            if(line){
-                if(line !== this.selected_orderline){
-                    if(this.selected_orderline){
-                        this.selected_orderline.set_selected(false);
-                    }
-                    this.selected_orderline = line;
-                    this.selected_orderline.set_selected(true);
-                }
-            }else{
-                this.selected_orderline = undefined;
-            }
-        },
-        deselectLine: function(){
-            if(this.selected_orderline){
-                this.selected_orderline.set_selected(false);
-                this.selected_orderline = undefined;
-            }
-        },
-        selectPaymentline: function(line){
-            if(line !== this.selected_paymentline){
-                if(this.selected_paymentline){
-                    this.selected_paymentline.set_selected(false);
-                }
-                this.selected_paymentline = line;
-                if(this.selected_paymentline){
-                    this.selected_paymentline.set_selected(true);
-                }
-                this.trigger('change:selected_paymentline',this.selected_paymentline);
-            }
-        },
     });
 
     module.OrderCollection = Backbone.Collection.extend({
index b801d34..1f577b4 100644 (file)
@@ -207,7 +207,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
         // what happens when a discount barcode is scanned : the default behavior
         // is to set the discount on the last order.
         barcode_discount_action: function(code){
-            var last_orderline = this.pos.get_order().getLastOrderline();
+            var last_orderline = this.pos.get_order().get_last_orderline();
             if(last_orderline){
                 last_orderline.set_discount(code.value)
             }
@@ -357,6 +357,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
     module.ConfirmPopupWidget = module.PopUpWidget.extend({
         template: 'ConfirmPopupWidget',
         show: function(options){
+            options = options || {};
             var self = this;
             this._super();
 
@@ -470,16 +471,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
         template: 'ErrorInvoiceTransferPopupWidget',
     });
 
-    module.UnsentOrdersPopupWidget = module.PopUpWidget.extend({
+    module.UnsentOrdersPopupWidget = module.ConfirmPopupWidget.extend({
         template: 'UnsentOrdersPopupWidget',
-        show: function(options){
-            var self = this;
-            this._super(options);
-            this.renderElement();
-            this.$('.button.confirm').click(function(){
-                self.pos_widget.screen_selector.close_popup();
-            });
-        },
+    });
+
+    module.UnpaidOrdersPopupWidget = module.ConfirmPopupWidget.extend({
+        template: 'UnpaidOrdersPopupWidget',
     });
 
     module.ScaleScreenWidget = module.ScreenWidget.extend({
@@ -534,7 +531,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
             }
         },
         order_product: function(){
-            this.pos.get_order().addProduct(this.get_product(),{ quantity: this.weight });
+            this.pos.get_order().add_product(this.get_product(),{ quantity: this.weight });
         },
         get_product_name: function(){
             var product = this.get_product();
@@ -591,7 +588,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                     if(product.to_weight && self.pos.config.iface_electronic_scale){
                         self.pos_widget.screen_selector.set_current_screen('scale',{product: product});
                     }else{
-                        self.pos.get_order().addProduct(product);
+                        self.pos.get_order().add_product(product);
                     }
                 },
                 product_list: this.pos.db.get_product_by_category(0)
@@ -1068,8 +1065,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                     widget:this,
                     order: order,
                     receipt: order.export_for_printing(),
-                    orderlines: order.get('orderLines').models,
-                    paymentlines: order.get('paymentLines').models,
+                    orderlines: order.get_orderlines(),
+                    paymentlines: order.get_paymentlines(),
                 }));
         },
     });
@@ -1188,10 +1185,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
             return numpad;
         },
         click_delete_paymentline: function(cid){
-            var lines = this.pos.get_order().get('paymentLines').models;
+            var lines = this.pos.get_order().get_paymentlines();
             for ( var i = 0; i < lines.length; i++ ) {
                 if (lines[i].cid === cid) {
-                    this.pos.get_order().removePaymentline(lines[i]);
+                    this.pos.get_order().remove_paymentline(lines[i]);
                     this.reset_input();
                     this.render_paymentlines();
                     return;
@@ -1199,10 +1196,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
             }
         },
         click_paymentline: function(cid){
-            var lines = this.pos.get_order().get('paymentLines').models;
+            var lines = this.pos.get_order().get_paymentlines();
             for ( var i = 0; i < lines.length; i++ ) {
                 if (lines[i].cid === cid) {
-                    this.pos.get_order().selectPaymentline(lines[i]);
+                    this.pos.get_order().select_paymentline(lines[i]);
                     this.reset_input();
                     this.render_paymentlines();
                     return;
@@ -1216,7 +1213,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                 return;
             }
 
-            var lines = order.get('paymentLines').models;
+            var lines = order.get_paymentlines();
 
             this.$('.paymentlines-container').empty();
             var lines = $(QWeb.render('PaymentScreen-Paymentlines', { 
@@ -1243,7 +1240,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                     break;
                 }
             }
-            this.pos.get_order().addPaymentline( cashregister );
+            this.pos.get_order().add_paymentline( cashregister );
             this.reset_input();
             this.render_paymentlines();
         },
@@ -1332,7 +1329,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
             var order = this.pos.get_order();
             if (!order) {
                 return;
-            } else if (order.isPaid()) {
+            } else if (order.is_paid()) {
                 self.$('.next').addClass('highlight');
             }else{
                 self.$('.next').removeClass('highlight');
@@ -1358,7 +1355,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
 
             // FIXME: this check is there because the backend is unable to
             // process empty orders. This is not the right place to fix it.
-            if(order.get_orderlines().length === 0){
+            if (order.get_orderlines().length === 0) {
                 this.pos_widget.screen_selector.show_popup('error',{
                     'message': _t('Empty Order'),
                     'comment': _t('There must be at least one product in your order before it can be validated'),
@@ -1366,12 +1363,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                 return;
             }
 
-            if (!order.isPaid() || this.invoicing) {
+            if (!order.is_paid() || this.invoicing) {
                 return;
             }
 
             // The exact amount must be paid if there is no cash payment method defined.
-            if (Math.abs(order.getTotalTaxIncluded() - order.getPaidTotal()) > 0.00001) {
+            if (Math.abs(order.get_total_with_tax() - order.get_total_paid()) > 0.00001) {
                 var cash = false;
                 for (var i = 0; i < this.pos.cashregisters.length; i++) {
                     cash = cash || (this.pos.cashregisters[i].journal.type === 'cash');
@@ -1385,7 +1382,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
                 }
             }
 
-            if (order.isPaidWithCash() && this.pos.config.iface_cashdrawer) { 
+            if (order.is_paid_with_cash() && this.pos.config.iface_cashdrawer) { 
+
                     this.pos.proxy.open_cashbox();
             }
 
index 288eda2..14a607b 100644 (file)
@@ -111,7 +111,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
                 if(!self.editable){
                     return;
                 }
-                self.pos.get_order().selectLine(this.orderline);
+                self.pos.get_order().select_orderline(this.orderline);
                 self.pos_widget.numpad.state.reset();
             };
             this.client_change_handler = function(event){
@@ -144,20 +144,20 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
                     this.enable_numpad();
                 }else{
                     this.disable_numpad();
-                    order.deselectLine();
+                    order.deselect_orderline();
                 }
             }
         },
         set_value: function(val) {
                var order = this.pos.get_order();
-               if (this.editable && order.getSelectedLine()) {
+               if (this.editable && order.get_selected_orderline()) {
                 var mode = this.numpad_state.get('mode');
                 if( mode === 'quantity'){
-                    order.getSelectedLine().set_quantity(val);
+                    order.get_selected_orderline().set_quantity(val);
                 }else if( mode === 'discount'){
-                    order.getSelectedLine().set_discount(val);
+                    order.get_selected_orderline().set_discount(val);
                 }else if( mode === 'price'){
-                    order.getSelectedLine().set_unit_price(val);
+                    order.get_selected_orderline().set_unit_price(val);
                 }
                }
         },
@@ -167,27 +167,32 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
                 this.renderElement();
             }
         },
+        orderline_add: function(){
+            this.numpad_state.reset();
+            this.renderElement('and_scroll_to_bottom');
+        },
+        orderline_remove: function(line){
+            this.remove_orderline(line);
+            this.numpad_state.reset();
+            this.update_summary();
+        },
+        orderline_change: function(line){
+            this.rerender_orderline(line);
+            this.update_summary();
+        },
         bind_order_events: function() {
-
             var order = this.pos.get_order();
                 order.unbind('change:client', this.client_change_handler);
                 order.bind('change:client', this.client_change_handler);
 
-            var lines = order.get('orderLines');
-                lines.unbind();
-                lines.bind('add', function(){ 
-                        this.numpad_state.reset();
-                        this.renderElement(true);
-                    },this);
-                lines.bind('remove', function(line){
-                        this.remove_orderline(line);
-                        this.numpad_state.reset();
-                        this.update_summary();
-                    },this);
-                lines.bind('change', function(line){
-                        this.rerender_orderline(line);
-                        this.update_summary();
-                    },this);
+            var lines = order.orderlines;
+                lines.unbind('add',     this.orderline_add,    this);
+                lines.bind('add',       this.orderline_add,    this);
+                lines.unbind('remove',  this.orderline_remove, this);
+                lines.bind('remove',    this.orderline_remove, this); 
+                lines.unbind('change',  this.orderline_change, this);
+                lines.bind('change',    this.orderline_change, this);
+
         },
         render_orderline: function(orderline){
             var el_str  = openerp.qweb.render('Orderline',{widget:this, line:orderline}); 
@@ -201,7 +206,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
             return el_node;
         },
         remove_orderline: function(order_line){
-            if(this.pos.get_order().get('orderLines').length === 0){
+            if(this.pos.get_order().get_orderlines().length === 0){
                 this.renderElement();
             }else{
                 order_line.node.parentNode.removeChild(order_line.node);
@@ -225,7 +230,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
             if (!order) {
                 return;
             }
-            var orderlines = order.get('orderLines').models;
+            var orderlines = order.get_orderlines();
 
             var el_str  = openerp.qweb.render('OrderWidget',{widget:this, order:order, orderlines:orderlines});
 
@@ -252,8 +257,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
         },
         update_summary: function(){
             var order = this.pos.get_order();
-            var total     = order ? order.getTotalTaxIncluded() : 0;
-            var taxes     = order ? total - order.getTotalTaxExcluded() : 0;
+            var total     = order ? order.get_total_with_tax() : 0;
+            var taxes     = order ? total - order.get_total_without_tax() : 0;
 
             this.el.querySelector('.summary .total > .value').textContent = this.format_currency(total);
             this.el.querySelector('.summary .total .subentry .value').textContent = this.format_currency(taxes);
@@ -481,7 +486,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
             if(query){
                 var products = this.pos.db.search_product_in_category(category.id,query)
                 if(buy_result && products.length === 1){
-                        this.pos.get_order().addProduct(products[0]);
+                        this.pos.get_order().add_product(products[0]);
                         this.clear_search();
                 }else{
                     this.product_list_widget.set_product_list(products);
@@ -733,6 +738,19 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
                     },
                 });
             });
+            this.$('.button.show_unpaid_orders').click(function(){
+                self.pos.pos_widget.screen_selector.show_popup('unpaid-orders');
+            });
+            this.$('.button.delete_unpaid_orders').click(function(){
+                self.pos.pos_widget.screen_selector.show_popup('confirm',{
+                    message: _t('Delete Unpaid Orders ?'),
+                    comment: _t('This operation will permanently destroy all unpaid orders from all sessions that have been put in the local storage. You will lose all the data and exit the point of sale. This operation cannot be undone.'),
+                    confirm: function(){
+                        self.pos.db.remove_all_unpaid_orders();
+                        window.location = '/';
+                    },
+                });
+            });
             _.each(this.eans, function(ean, name){
                 self.$('.button.'+name).click(function(){
                     self.$('input.ean').val(ean);
@@ -889,7 +907,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
 
                 self.renderElement();
                 
-                self.pos.add_new_order();
+                self.pos.load_orders();
+                self.pos.set_start_order();
 
                 self.build_widgets();
 
@@ -1019,6 +1038,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
             this.unsent_orders_popup = new module.UnsentOrdersPopupWidget(this,{});
             this.unsent_orders_popup.appendTo(this.$el);
 
+            this.unpaid_orders_popup = new module.UnpaidOrdersPopupWidget(this,{});
+            this.unpaid_orders_popup.appendTo(this.$el);
+
             // --------  Misc ---------
 
             this.order_selector = new module.OrderSelectorWidget(this,{});
@@ -1091,6 +1113,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
                     'fullscreen': this.fullscreen_popup,
                     'selection': this.selection_popup,
                     'unsent-orders': this.unsent_orders_popup,
+                    'unpaid-orders': this.unpaid_orders_popup,
                 },
                 default_screen: 'products',
                 default_mode: 'cashier',
@@ -1147,7 +1170,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
             }
 
             var draft_order = _.find( self.pos.get('orders').models, function(order){
-                return order.get('orderLines').length !== 0 && order.get('paymentLines').length === 0;
+                return order.get_orderlines().length !== 0 && order.get_paymentlines().length === 0;
             });
             if(draft_order){
                 if (confirm(_t("Pending orders will be lost.\nAre you sure you want to leave this session?"))) {
index 185cd6e..8987c51 100644 (file)
         <t t-if="!paymentlines.length">
             <div class='paymentlines-empty'>
                 <div class='total'>
-                    <t t-esc="widget.format_currency(order.getTotalTaxIncluded())"/>
+                    <t t-esc="widget.format_currency(order.get_total_with_tax())"/>
                 </div>
                 <div class='message'>
                     Please select a payment method. 
                     <t t-foreach='paymentlines' t-as='line'>
                         <t t-if='line.selected'>
                             <tr class='paymentline selected'>
-                                <td class='col-due'> <t t-esc='widget.format_currency_no_symbol(order.getDueLeft(line))' /> </td>
+                                <td class='col-due'> <t t-esc='widget.format_currency_no_symbol(order.get_due(line))' /> </td>
                                 <td class='col-tendered edit'> 
                                     <t t-esc='widget.inputbuffer' />
                                     <!-- <t t-esc='line.get_amount()' /> -->
                                 </td>
-                                <t t-if='order.getChange(line)'>
+                                <t t-if='order.get_change(line)'>
                                     <td class='col-change highlight' > 
-                                        <t t-esc='widget.format_currency_no_symbol(order.getChange(line))' />
+                                        <t t-esc='widget.format_currency_no_symbol(order.get_change(line))' />
                                     </td>
                                 </t>
-                                <t t-if='!order.getChange(line)'>
+                                <t t-if='!order.get_change(line)'>
                                     <td class='col-change' ></td>
                                 </t>
                                     
                         </t>
                         <t t-if='!line.selected'>
                             <tr class='paymentline' t-att-data-cid='line.cid'>
-                                <td class='col-due'> <t t-esc='widget.format_currency_no_symbol(order.getDueLeft(line))' /> </td>
+                                <td class='col-due'> <t t-esc='widget.format_currency_no_symbol(order.get_due(line))' /> </td>
                                 <td class='col-tendered'> <t t-esc='widget.format_currency_no_symbol(line.get_amount())' /> </td>
                                 <td class='col-change'> 
-                                    <t t-if='order.getChange(line)'>
-                                        <t t-esc='widget.format_currency_no_symbol(order.getChange(line))' />
+                                    <t t-if='order.get_change(line)'>
+                                        <t t-esc='widget.format_currency_no_symbol(order.get_change(line))' />
                                      </t>
                                 </td>
                                 <td class='col-name'> <t t-esc='line.name' /> </td>
         </div>
     </t>
 
+    <t t-name="UnpaidOrdersPopupWidget">
+        <div class="modal-dialog">
+            <div class="popup popup-unpaid-orders">
+                <p class="message">Unpaid Orders</p>
+                <t t-if='widget.pos.db.get_unpaid_orders().length === 0'>
+                    <p class='comment'>
+                        There are no unpaid orders
+                    </p>
+                </t>
+                <t t-if='widget.pos.db.get_unpaid_orders().length > 0'>
+                    <p class='comment traceback'>
+                        <t t-esc='JSON.stringify(widget.pos.db.get_unpaid_orders(),null,2)' />
+                    </p>
+                </t>
+                <div class="footer">
+                    <div class="button confirm">
+                        Ok
+                    </div>
+                </div>
+            </div>
+        </div>
+    </t>
+
     <t t-name="SelectionPopupWidget">
         <div class="modal-dialog">
             <div class="popup popup-selection">
                     <li class="button show_orders">Show All Unsent Orders</li>
                     <li class="button delete_orders">Delete All Unsent Orders</li>
                 </ul>
+                <p class="category">Unpaid Orders</p>
+                <ul>
+                    <li class="button show_unpaid_orders">Show All Unpaid Orders</li>
+                    <li class="button delete_unpaid_orders">Delete All Unpaid Orders</li>
+                </ul>
 
                 <p class="category">Hardware Status</p>
                 <ul>
                             <t t-if="order.get_client()">
                                 <i class='fa fa-user'/>
                             </t>
-                            <t t-esc="(order.get_client() ? order.get_client_name()+' : ':'') + order.get('creationDate').toString('t')"/>
+                            <t t-esc="(order.get_client() ? order.get_client_name()+' : ':'') + order.creation_date.toString('t')"/>
                         </span>
                     </t>
                     <t t-if='order !== widget.pos.get_order()'>
     <t t-name="PosTicket">
         <div class="pos-sale-ticket">
             
-            <div class="pos-center-align"><t t-esc="moment().format('L LT')"/> <t t-esc="order.get('name')"/></div>
+            <div class="pos-center-align"><t t-esc="moment().format('L LT')"/> <t t-esc="order.name"/></div>
             <br />
             <t t-esc="widget.pos.company.name"/><br />
             Phone: <t t-esc="widget.pos.company.phone || ''"/><br />
                 <tr>
                     <td>Subtotal:</td>
                     <td class="pos-right-align">
-                        <t t-esc="widget.format_currency(order.getSubtotal())"/>
+                        <t t-esc="widget.format_currency(order.get_subtotal())"/>
                     </td>
                 </tr>
-                <t t-foreach="order.getTaxDetails()" t-as="taxdetail">
+                <t t-foreach="order.get_tax_details()" t-as="taxdetail">
                     <tr>
                         <td><t t-esc="taxdetail.name" /></td>
                         <td class="pos-right-align">
                 <tr>
                     <td>Discount:</td>
                     <td class="pos-right-align">
-                        <t t-esc="widget.format_currency(order.getDiscountTotal())"/>
+                        <t t-esc="widget.format_currency(order.get_total_discount())"/>
                     </td>
                 </tr>
                 <tr class="emph">
                     <td>Total:</td>
                     <td class="pos-right-align">
-                        <t t-esc="widget.format_currency(order.getTotalTaxIncluded())"/>
+                        <t t-esc="widget.format_currency(order.get_total_with_tax())"/>
                     </td>
                 </tr>
             </table>
             <br />
             <table>
                 <tr><td>Change:</td><td class="pos-right-align">
-                    <t t-esc="widget.format_currency(order.getChange())"/>
+                    <t t-esc="widget.format_currency(order.get_change())"/>
                     </td></tr>
             </table>
             <t t-if="receipt.footer">
index 5eaab36..d68eb59 100644 (file)
@@ -17,11 +17,11 @@ openerp.pos_discount = function(instance){
             var discount = $(QWeb.render('DiscountButton'));
 
             discount.click(function(){
-                var order    = self.pos.get('selectedOrder');
+                var order    = self.pos.get_order();
                 var product  = self.pos.db.get_product_by_id(self.pos.config.discount_product_id[0]);
-                var discount = - self.pos.config.discount_pc/ 100.0 * order.getTotalTaxIncluded();
+                var discount = - self.pos.config.discount_pc/ 100.0 * order.get_total_tax_included();
                 if( discount < 0 ){
-                    order.addProduct(product, { price: discount });
+                    order.add_product(product, { price: discount });
                 }
             });
 
index 4b1c1f3..7c46e29 100644 (file)
@@ -57,21 +57,44 @@ openerp.pos_loyalty = function(instance){
                 domain: function(self){ return [['loyalty_program_id','=',self.loyalty.id]]; },
                 loaded: function(self,rewards){
                     self.loyalty.rewards = rewards; 
+                    self.loyalty.rewards_by_id = {};
+                    for (var i = 0; i < rewards.length;i++) {
+                        self.loyalty.rewards_by_id[rewards[i].id] = rewards[i];
+                    }
                 },
             });
         }
     }
 
+    var _super_orderline = module.Orderline;
+    module.Orderline = module.Orderline.extend({
+        get_reward: function(){
+            return this.pos.loyalty.rewards_by_id[this.reward_id];
+        },
+        set_reward: function(reward){
+            this.reward_id = reward.id;
+        },
+        export_as_JSON: function(){
+            var json = _super_orderline.prototype.export_as_JSON.apply(this,arguments);
+            json.reward_id = this.reward_id;
+            return json;
+        },
+        init_from_JSON: function(json){
+            _super_orderline.prototype.init_from_JSON.apply(this,arguments);
+            this.reward_id = json.reward_id;
+        },
+    });
+
     var _super = module.Order;
     module.Order = module.Order.extend({
 
         /* The total of points won, excluding the points spent on rewards */
         get_won_points: function(){
-            if (!this.pos.loyalty || !this.get('client')) {
+            if (!this.pos.loyalty || !this.get_client()) {
                 return 0;
             }
             
-            var orderLines = this.get('orderLines').models;
+            var orderLines = this.get_orderlines();
             var rounding   = this.pos.loyalty.rounding;
             
             var product_sold = 0;
@@ -84,7 +107,7 @@ openerp.pos_loyalty = function(instance){
                 var rules  = this.pos.loyalty.rules_by_product_id[product.id] || [];
                 var overriden = false;
 
-                if (line.reward) {  // Reward products are ignored
+                if (line.get_reward()) {  // Reward products are ignored
                     continue;
                 }
                 
@@ -114,7 +137,11 @@ openerp.pos_loyalty = function(instance){
                                 break;
                             }
                         }
+                        var _category = category;
                         category = this.pos.db.get_category_by_id(this.pos.db.get_category_parent_id(category.id));
+                        if (_category === category) {
+                            break;
+                        }
                     }
                 }
 
@@ -133,20 +160,21 @@ openerp.pos_loyalty = function(instance){
 
         /* The total number of points spent on rewards */
         get_spent_points: function() {
-            if (!this.pos.loyalty || !this.get('client')) {
+            if (!this.pos.loyalty || !this.get_client()) {
                 return 0;
             } else {
-                var lines    = this.get('orderLines').models;
+                var lines    = this.get_orderlines();
                 var rounding = this.pos.loyalty.rounding;
                 var points   = 0;
 
                 for (var i = 0; i < lines.length; i++) {
                     var line = lines[i];
-                    if (line.reward) {
-                        if (line.reward.type === 'gift') {
-                            points += round_pr(line.get_quantity() * line.reward.point_cost, rounding);
-                        } else if (line.reward.type === 'discount') {
-                            points += round_pr(-line.get_price_with_tax() * line.reward.point_cost, rounding);
+                    var reward = line.get_reward();
+                    if (reward) {
+                        if (reward.type === 'gift') {
+                            points += round_pr(line.get_quantity() * reward.point_cost, rounding);
+                        } else if (reward.type === 'discount') {
+                            points += round_pr(-line.get_price_with_tax() * reward.point_cost, rounding);
                         }
                     }
                 }
@@ -156,7 +184,7 @@ openerp.pos_loyalty = function(instance){
 
         /* The total number of points lost or won after the order is validated */
         get_new_points: function() {
-            if (!this.pos.loyalty || !this.get('client')) {
+            if (!this.pos.loyalty || !this.get_client()) {
                 return 0;
             } else { 
                 return round_pr(this.get_won_points() - this.get_spent_points(), this.pos.loyalty.rounding);
@@ -165,30 +193,30 @@ openerp.pos_loyalty = function(instance){
 
         /* The total number of points that the customer will have after this order is validated */
         get_new_total_points: function() {
-            if (!this.pos.loyalty || !this.get('client')) {
+            if (!this.pos.loyalty || !this.get_client()) {
                 return 0;
             } else { 
-                return round_pr(this.get('client').loyalty_points + this.get_new_points(), this.pos.loyalty.rounding);
+                return round_pr(this.get_client().loyalty_points + this.get_new_points(), this.pos.loyalty.rounding);
             }
         },
 
         /* The number of loyalty points currently owned by the customer */
         get_current_points: function(){
-            return this.get('client') ? this.get('client').loyalty_points : 0;
+            return this.get_client() ? this.get_client().loyalty_points : 0;
         },
 
         /* The total number of points spendable on rewards */
         get_spendable_points: function(){
-            if (!this.pos.loyalty || !this.get('client')) {
+            if (!this.pos.loyalty || !this.get_client()) {
                 return 0;
             } else {
-                return round_pr(this.get('client').loyalty_points - this.get_spent_points(), this.pos.loyalty.rounding);
+                return round_pr(this.get_client().loyalty_points - this.get_spent_points(), this.pos.loyalty.rounding);
             }
         },
 
         /* The list of rewards that the current customer can get */
         get_available_rewards: function(){
-            var client = this.get('client');
+            var client = this.get_client();
             if (!client) {
                 return [];
             } 
@@ -207,7 +235,7 @@ openerp.pos_loyalty = function(instance){
         },
 
         apply_reward: function(reward){
-            var client = this.get('client');
+            var client = this.get_client();
             if (!client) {
                 return;
             } else if (reward.type === 'gift') {
@@ -220,11 +248,11 @@ openerp.pos_loyalty = function(instance){
                     return;
                 }
 
-                var line = this.addProduct(product, { 
+                var line = this.add_product(product, { 
                     price: 0, 
                     quantity: 1, 
                     merge: false, 
-                    extras: { reward: reward },
+                    extras: { reward_id: reward.id },
                 });
 
             } else if (reward.type === 'discount') {
@@ -232,7 +260,7 @@ openerp.pos_loyalty = function(instance){
                 var lrounding = this.pos.loyalty.rounding;
                 var crounding = this.pos.currency.rounding;
                 var spendable = this.get_spendable_points();
-                var order_total = this.getTotalTaxIncluded();
+                var order_total = this.get_total_with_tax();
                 var discount    = round_pr(order_total * reward.discount,crounding);
 
                 if ( round_pr(discount * reward.point_cost,lrounding) > spendable ) { 
@@ -248,17 +276,17 @@ openerp.pos_loyalty = function(instance){
                     return;
                 }
 
-                var line = this.addProduct(product, { 
+                var line = this.add_product(product, { 
                     price: -discount, 
                     quantity: 1, 
                     merge: false,
-                    extras: { reward: reward },
+                    extras: { reward_id: reward.id },
                 });
             }
         },
             
         validate: function(){
-            var client = this.get('client');
+            var client = this.get_client();
             if ( client ) {
                 client.loyalty_points = this.get_new_total_points();
             }
@@ -279,8 +307,8 @@ openerp.pos_loyalty = function(instance){
     module.PosWidget.include({
         loyalty_reward_click: function(){
             var self = this;
-            var order  = this.pos.get('selectedOrder');
-            var client = order.get('client'); 
+            var order  = this.pos.get_order();
+            var client = order.get_client(); 
             if (!client) {
                 this.screen_selector.set_current_screen('clientlist');
                 return;
index 5149173..39534f4 100644 (file)
@@ -15,7 +15,7 @@ function openerp_restaurant_floors(instance,module){
                 self.floors_by_id[floors[i].id] = floors[i];
             }
             // Ignore floorplan features if no floor specified, or feature deactivated
-            self.config.iface_floorplan = self.config.iface_floorplan && self.floors.length;
+            self.config.iface_floorplan = self.config.iface_floorplan && !!self.floors.length;
         },
     });
 
@@ -25,7 +25,9 @@ function openerp_restaurant_floors(instance,module){
         model: 'restaurant.table',
         fields: ['name','width','height','position_h','position_v','shape','floor_id','color'],
         loaded: function(self,tables){
+            self.tables_by_id = {};
             for (var i = 0; i < tables.length; i++) {
+                self.tables_by_id[tables[i].id] = tables[i];
                 var floor = self.floors_by_id[tables[i].floor_id[0]];
                 if (floor) {
                     floor.tables.push(tables[i]);
@@ -318,9 +320,11 @@ function openerp_restaurant_floors(instance,module){
             if (this.editing) { 
                 this.toggle_editing();
             }
+            this.pos_widget.order_selector.show();
         },
         show: function(){
             this._super();
+            this.pos_widget.order_selector.hide();
             for (var i = 0; i < this.table_widgets.length; i++) { 
                 this.table_widgets[i].renderElement();
             }
@@ -592,15 +596,25 @@ function openerp_restaurant_floors(instance,module){
     var _super_order = module.Order.prototype;
     module.Order = module.Order.extend({
         initialize: function(attr) {
-            _super_order.initialize.call(this,attr);
-            this.table = this.pos.table;
+            _super_order.initialize.apply(this,arguments);
+            if (!this.table) {
+                this.table = this.pos.table;
+            }
+            this.save_to_db();
         },
         export_as_JSON: function() {
             var json = _super_order.export_as_JSON.apply(this,arguments);
-            json.table = this.table.name;
-            json.floor = this.table ? this.table.floor.name : false; 
+            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_id  = this.table ? this.table.floor.id : false;
             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;
+        },
     });
 
     // We need to modify the OrderSelector to hide itself when we're on
@@ -609,6 +623,12 @@ function openerp_restaurant_floors(instance,module){
         floor_button_click_handler: function(){
             this.pos.set_table(null);
         },
+        hide: function(){
+            this.$el.addClass('oe_invisible');
+        },
+        show: function(){
+            this.$el.removeClass('oe_invisible');
+        },
         renderElement: function(){
             var self = this;
             this._super();
@@ -656,6 +676,14 @@ function openerp_restaurant_floors(instance,module){
             }
         },
 
+        // if we have tables, we do not load a default order, as the default order will be
+        // set when the user selects a table.
+        set_start_order: function() {
+            if (!this.config.iface_floorplan) {
+                _super_posmodel.set_start_order.apply(this,arguments);
+            }
+        },
+
         // we need to prevent the creation of orders when there is no
         // table selected.
         add_new_order: function() {
@@ -670,11 +698,14 @@ function openerp_restaurant_floors(instance,module){
             }
         },
 
+
         // get the list of unpaid orders (associated to the current table)
         get_order_list: function() {    
             var orders = _super_posmodel.get_order_list.call(this);  
-            if (!this.table || !this.config.iface_floorplan) {
+            if (!this.config.iface_floorplan) {
                 return orders;
+            } else if (!this.table) {
+                return [];
             } else {
                 var t_orders = [];
                 for (var i = 0; i < orders.length; i++) {
index 9030287..8b1f9e9 100644 (file)
@@ -54,26 +54,43 @@ function openerp_restaurant_multiprint(instance,module){
         },
     });
 
+    module.Orderline = module.Orderline.extend({
+        get_line_diff_hash: function(){
+            if (this.get_note()) {
+                return this.get_product().id + '|' + this.get_note();
+            } else {
+                return '' + this.get_product().id;
+            }
+        },
+    });
+
+    var _super_order = module.Order.prototype;
     module.Order = module.Order.extend({
         lineResume: function(){
             var resume = {};
-            this.get('orderLines').each(function(item){
-                var line = item.export_as_JSON();
-                if( typeof resume[line.product_id] === 'undefined'){
-                    resume[line.product_id] = line.qty;
-                }else{
-                    resume[line.product_id] += line.qty;
+
+            this.orderlines.each(function(line){
+                var line_hash = line.get_line_diff_hash();
+                var qty  = Number(line.get_quantity());
+                var note = line.get_note();
+                var product_id = line.get_product().id;
+
+                if (typeof resume[line_hash] === 'undefined') {
+                    resume[line_hash] = { qty: qty, note: note, product_id: product_id };
+                } else {
+                    resume[line_hash].qty += qty;
                 }
             });
             return resume;
         },
         saveChanges: function(){
-            this.old_resume = this.lineResume();
+            this.saved_resume = this.build_line_resume();
+            this.trigger('change',this);
         },
         computeChanges: function(categories){
-            var current = this.lineResume();
-            var old     = this.old_resume || {};
-            var json    = this.export_as_JSON();
+            var current_res = this.build_line_resume();
+            var old_res     = this.saved_resume || {};
+            var json        = this.export_as_JSON();
             var add = [];
             var rem = [];
 
@@ -174,6 +191,15 @@ function openerp_restaurant_multiprint(instance,module){
             }
             return false;
         },
+        export_as_JSON: function(){
+            var json = _super_order.export_as_JSON.apply(this,arguments);
+            json.multiprint_resume = this.saved_resume;
+            return json;
+        },
+        init_from_JSON: function(json){
+            _super_order.init_from_JSON.apply(this,arguments);
+            this.saved_resume = json.multiprint_resume;
+        },
     });
 
     module.PosWidget.include({
diff --git a/addons/pos_restaurant/static/src/js/notes.js b/addons/pos_restaurant/static/src/js/notes.js
new file mode 100644 (file)
index 0000000..1e4c948
--- /dev/null
@@ -0,0 +1,71 @@
+function openerp_restaurant_notes(instance,module){
+    "use strict";
+
+    var QWeb = instance.web.qweb;
+    var _t   = instance.web._t;
+
+    var _super_orderline = module.Orderline.prototype;
+
+    module.Orderline = module.Orderline.extend({
+        initialize: function(attr, options) {
+            _super_orderline.initialize.call(this,attr,options);
+            this.note = this.note || "";
+        },
+        set_note: function(note){
+            this.note = note;
+            this.trigger('change',this);
+        },
+        get_note: function(note){
+            return this.note;
+        },
+        can_be_merged_with: function(orderline) {
+            if (orderline.get_note() !== this.get_note()) {
+                return false;
+            } else {
+                return _super_orderline.can_be_merged_with.call(this,orderline);
+            }
+        },
+        clone: function(){
+            var orderline = _super_orderline.clone.call(this);
+            orderline.note = this.note;
+            return orderline;
+        },
+        export_as_JSON: function(){
+            var json = _super_orderline.export_as_JSON.call(this);
+            json.note = this.note;
+            return json;
+        },
+        init_from_JSON: function(json){
+            _super_orderline.init_from_JSON.apply(this,arguments);
+            this.note = json.note;
+        },
+    });
+
+    module.PosWidget.include({
+        orderline_note_click: function(){
+            var self = this;
+            var line = this.pos.get_order().get_selected_orderline();
+
+            if (line) {
+                this.screen_selector.show_popup('textarea',{
+                    message: _t('Orderline Note'),
+                    value:   line.get_note(),
+                    confirm: function(note) {
+                        line.set_note(note);
+                    },
+                });
+            }
+        },
+        build_widgets: function(){
+            var self = this;
+            this._super();
+
+            if (this.pos.config.iface_orderline_notes) {
+                var button = $(QWeb.render('OrderlineNoteButton'));
+                button.click(function(){ self.orderline_note_click(); });
+                button.appendTo(this.$('.control-buttons'));
+                this.$('.control-buttons').removeClass('oe_hidden');
+            }
+        },
+    });
+}
index e3d6b08..f58f77e 100644 (file)
@@ -11,11 +11,11 @@ function openerp_restaurant_splitbill(instance, module){
         renderElement: function(){
             var self = this;
             this._super();
-            var order = this.pos.get('selectedOrder');
+            var order = this.pos.get_order();
             if(!order){
                 return;
             }
-            var orderlines = order.get('orderLines').models;
+            var orderlines = order.get_orderlines();
             for(var i = 0; i < orderlines.length; i++){
                 var line = orderlines[i];
                 linewidget = $(QWeb.render('SplitOrderline',{ 
@@ -35,7 +35,7 @@ function openerp_restaurant_splitbill(instance, module){
 
         lineselect: function($el,order,neworder,splitlines,line_id){
             var split = splitlines[line_id] || {'quantity': 0, line: null};
-            var line  = order.getOrderline(line_id);
+            var line  = order.get_orderline(line_id);
             
             if( !line.get_unit().groupable ){
                 if( split.quantity !== line.get_quantity()){
@@ -57,11 +57,11 @@ function openerp_restaurant_splitbill(instance, module){
             if( split.quantity ){
                 if ( !split.line ){
                     split.line = line.clone();
-                    neworder.addOrderline(split.line);
+                    neworder.add_orderline(split.line);
                 }
                 split.line.set_quantity(split.quantity);
             }else if( split.line ) {
-                neworder.removeOrderline(split.line);
+                neworder.remove_orderline(split.line);
                 split.line = null;
             }
      
@@ -73,11 +73,11 @@ function openerp_restaurant_splitbill(instance, module){
                 quantity: split.quantity,
                 id: line_id,
             })));
-            this.$('.order-info .subtotal').text(this.format_currency(neworder.getSubtotal()));
+            this.$('.order-info .subtotal').text(this.format_currency(neworder.get_subtotal()));
         },
 
         pay: function(order,neworder,splitlines){
-            var orderlines = order.get('orderLines').models;
+            var orderlines = order.get_orderlines();
             var empty = true;
             var full  = true;
 
@@ -106,10 +106,10 @@ function openerp_restaurant_splitbill(instance, module){
             }else{
                 for(var id in splitlines){
                     var split = splitlines[id];
-                    var line  = order.getOrderline(parseInt(id));
+                    var line  = order.get_orderline(parseInt(id));
                     line.set_quantity(line.get_quantity() - split.quantity);
                     if(Math.abs(line.get_quantity()) < 0.00001){
-                        order.removeOrderline(line);
+                        order.remove_orderline(line);
                     }
                     delete splitlines[id];
                 }
@@ -136,8 +136,8 @@ function openerp_restaurant_splitbill(instance, module){
             this._super();
             this.renderElement();
 
-            var order = this.pos.get('selectedOrder');
-            var neworder = new module.Order({
+            var order = this.pos.get_order();
+            var neworder = new module.Order({},{
                 pos: this.pos,
                 temporary: true,
             });
@@ -170,7 +170,7 @@ function openerp_restaurant_splitbill(instance, module){
                 var splitbill = $(QWeb.render('SplitbillButton'));
 
                 splitbill.click(function(){
-                    if(self.pos.get('selectedOrder').get('orderLines').models.length > 0){
+                    if(self.pos.get_order().get_orderlines().length > 0){
                         self.pos_widget.screen_selector.set_current_screen('splitbill');
                     }
                 });