~pexego/openobject-addons/6.1-pexego-sale_commission

« back to all changes in this revision

Viewing changes to django_pos/pos/static/js/pos.js

  • Committer: Santi Argueso (Pexego)
  • Date: 2013-02-06 17:03:36 UTC
  • mfrom: (10.1.6 pexego-addons_6.1)
  • Revision ID: santiago@pexego.es-20130206170336-ml430s6p9jknun0j
[MERGE]

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
    
3
3
    db.point_of_sale = {};
4
4
 
 
5
    var __extends = function(child, parent) {
 
6
        var __hasProp = Object.prototype.hasOwnProperty;
 
7
        for (var key in parent) {
 
8
            if (__hasProp.call(parent, key))
 
9
                child[key] = parent[key];
 
10
        }
 
11
        function ctor() {
 
12
            this.constructor = child;
 
13
        }
 
14
 
 
15
        ctor.prototype = parent.prototype;
 
16
        child.prototype = new ctor;
 
17
        child.__super__ = parent.prototype;
 
18
        return child;
 
19
    };
 
20
 
5
21
    var QWeb = db.web.qweb;
6
22
    var qweb_template = function(template) {
7
23
        return function(ctx) {
69
85
                }, this));
70
86
            }, this));
71
87
            $.when(this.fetch('pos.category', ['name', 'parent_id', 'child_id']),
72
 
                this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small', 'ean13', 'id'], [['pos_categ_id', '!=', false]]),
73
 
                this.fetch('product.packaging', ['product_id', 'ean']),
 
88
                this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small'], [['pos_categ_id', '!=', 'false']]),
74
89
                this.fetch('account.bank.statement', ['account_id', 'currency', 'journal_id', 'state', 'name'],
75
90
                    [['state', '=', 'open'], ['user_id', '=', this.session.uid]]),
76
91
                this.fetch('account.journal', ['auto_cash', 'check_dtls', 'currency', 'name', 'type']),
208
223
     Models
209
224
     ---
210
225
     */
211
 
 
212
 
    var CashRegister = Backbone.Model.extend({
213
 
    });
214
 
 
215
 
    var CashRegisterCollection = Backbone.Collection.extend({
216
 
        model: CashRegister,
217
 
    });
218
 
 
219
 
    var Product = Backbone.Model.extend({
220
 
    });
221
 
 
222
 
    var ProductCollection = Backbone.Collection.extend({
223
 
        model: Product,
224
 
    });
225
 
 
226
 
    var Category = Backbone.Model.extend({
227
 
    });
228
 
 
229
 
    var CategoryCollection = Backbone.Collection.extend({
230
 
        model: Category,
231
 
    });
232
 
 
 
226
    var CashRegister = (function() {
 
227
        __extends(CashRegister, Backbone.Model);
 
228
        function CashRegister() {
 
229
            CashRegister.__super__.constructor.apply(this, arguments);
 
230
        }
 
231
 
 
232
        return CashRegister;
 
233
    })();
 
234
    var CashRegisterCollection = (function() {
 
235
        __extends(CashRegisterCollection, Backbone.Collection);
 
236
        function CashRegisterCollection() {
 
237
            CashRegisterCollection.__super__.constructor.apply(this, arguments);
 
238
        }
 
239
 
 
240
        CashRegisterCollection.prototype.model = CashRegister;
 
241
        return CashRegisterCollection;
 
242
    })();
 
243
    var Product = (function() {
 
244
        __extends(Product, Backbone.Model);
 
245
        function Product() {
 
246
            Product.__super__.constructor.apply(this, arguments);
 
247
        }
 
248
 
 
249
        return Product;
 
250
    })();
 
251
    var ProductCollection = (function() {
 
252
        __extends(ProductCollection, Backbone.Collection);
 
253
        function ProductCollection() {
 
254
            ProductCollection.__super__.constructor.apply(this, arguments);
 
255
        }
 
256
 
 
257
        ProductCollection.prototype.model = Product;
 
258
        return ProductCollection;
 
259
    })();
 
260
    var Category = (function() {
 
261
        __extends(Category, Backbone.Model);
 
262
        function Category() {
 
263
            Category.__super__.constructor.apply(this, arguments);
 
264
        }
 
265
 
 
266
        return Category;
 
267
    })();
 
268
    var CategoryCollection = (function() {
 
269
        __extends(CategoryCollection, Backbone.Collection);
 
270
        function CategoryCollection() {
 
271
            CategoryCollection.__super__.constructor.apply(this, arguments);
 
272
        }
 
273
 
 
274
        CategoryCollection.prototype.model = Category;
 
275
        return CategoryCollection;
 
276
    })();
233
277
    /*
234
278
     Each Order contains zero or more Orderlines (i.e. the content of the "shopping cart".)
235
279
     There should only ever be one Orderline per distinct product in an Order.
307
351
            };
308
352
        },
309
353
        exportAsJSON: function() {
310
 
            return {
 
354
            var result;
 
355
            result = {
311
356
                qty: this.get('quantity'),
312
357
                price_unit: this.get('list_price'),
313
358
                discount: this.get('discount'),
314
359
                product_id: this.get('id')
315
360
            };
 
361
            return result;
316
362
        },
317
363
    });
318
 
 
319
364
    var OrderlineCollection = Backbone.Collection.extend({
320
365
        model: Orderline,
321
366
    });
 
367
    /*
 
368
     Every PaymentLine has all the attributes of the corresponding CashRegister.
 
369
     */
 
370
    var Paymentline = (function() {
 
371
        __extends(Paymentline, Backbone.Model);
 
372
        function Paymentline() {
 
373
            Paymentline.__super__.constructor.apply(this, arguments);
 
374
        }
322
375
 
323
 
    // Every PaymentLine has all the attributes of the corresponding CashRegister.
324
 
    var Paymentline = Backbone.Model.extend({
325
 
        defaults: { 
326
 
            amount: 0,
327
 
        },
328
 
        initialize: function(attributes) {
329
 
            Backbone.Model.prototype.initialize.apply(this, arguments);
330
 
        },
331
 
        getAmount: function(){
 
376
        Paymentline.prototype.defaults = {
 
377
            amount: 0
 
378
        };
 
379
        Paymentline.prototype.getAmount = function() {
332
380
            return this.get('amount');
333
 
        },
334
 
        exportAsJSON: function(){
335
 
            return {
 
381
        };
 
382
        Paymentline.prototype.exportAsJSON = function() {
 
383
            var result;
 
384
            result = {
336
385
                name: db.web.datetime_to_str(new Date()),
337
386
                statement_id: this.get('id'),
338
387
                account_id: (this.get('account_id'))[0],
339
388
                journal_id: (this.get('journal_id'))[0],
340
389
                amount: this.getAmount()
341
390
            };
342
 
        },
343
 
    });
344
 
 
345
 
    var PaymentlineCollection = Backbone.Collection.extend({
346
 
        model: Paymentline,
347
 
    });
348
 
    
349
 
    var Order = Backbone.Model.extend({
350
 
        defaults:{
 
391
            return result;
 
392
        };
 
393
        return Paymentline;
 
394
    })();
 
395
    var PaymentlineCollection = (function() {
 
396
        __extends(PaymentlineCollection, Backbone.Collection);
 
397
        function PaymentlineCollection() {
 
398
            PaymentlineCollection.__super__.constructor.apply(this, arguments);
 
399
        }
 
400
 
 
401
        PaymentlineCollection.prototype.model = Paymentline;
 
402
        return PaymentlineCollection;
 
403
    })();
 
404
    var Order = (function() {
 
405
        __extends(Order, Backbone.Model);
 
406
        function Order() {
 
407
            Order.__super__.constructor.apply(this, arguments);
 
408
        }
 
409
 
 
410
        Order.prototype.defaults = {
351
411
            validated: false,
352
412
            step: 'products',
353
 
        },
354
 
        initialize: function(attributes){
355
 
            Backbone.Model.prototype.initialize.apply(this, arguments);
356
 
            this.set({
357
 
                creationDate:   new Date,
358
 
                orderLines:     new OrderlineCollection,
359
 
                paymentLines:   new PaymentlineCollection,
360
 
                name:           "Order " + this.generateUniqueId(),
 
413
        };
 
414
        Order.prototype.initialize = function() {
 
415
            this.set({creationDate: new Date});
 
416
            this.set({
 
417
                orderLines: new OrderlineCollection
 
418
            });
 
419
            this.set({
 
420
                paymentLines: new PaymentlineCollection
361
421
            });
362
422
            this.bind('change:validated', this.validatedChanged);
363
 
            return this;
364
 
        },
365
 
        events: {
 
423
            return this.set({
 
424
                name: "Order " + this.generateUniqueId()
 
425
            });
 
426
        };
 
427
        Order.prototype.events = {
366
428
            'change:validated': 'validatedChanged'
367
 
        },
368
 
        validatedChanged: function() {
 
429
        };
 
430
        Order.prototype.validatedChanged = function() {
369
431
            if (this.get("validated") && !this.previous("validated")) {
370
432
                this.set({'step': 'receipt'});
371
433
            }
372
 
        },
373
 
        generateUniqueId: function() {
 
434
        }
 
435
        Order.prototype.generateUniqueId = function() {
374
436
            return new Date().getTime();
375
 
        },
376
 
        addProduct: function(product) {
 
437
        };
 
438
        Order.prototype.addProduct = function(product) {
377
439
            var existing;
378
440
            existing = (this.get('orderLines')).get(product.id);
379
441
            if (existing != null) {
385
447
                    this.get('orderLines').remove(line);
386
448
                }, this);
387
449
            }
388
 
        },
389
 
        addPaymentLine: function(cashRegister) {
 
450
        };
 
451
        Order.prototype.addPaymentLine = function(cashRegister) {
390
452
            var newPaymentline;
391
453
            newPaymentline = new Paymentline(cashRegister);
392
454
            /* TODO: Should be 0 for cash-like accounts */
394
456
                amount: this.getDueLeft()
395
457
            });
396
458
            return (this.get('paymentLines')).add(newPaymentline);
397
 
        },
398
 
        getName: function() {
 
459
        };
 
460
        Order.prototype.getName = function() {
399
461
            return this.get('name');
400
 
        },
401
 
        getTotal: function() {
 
462
        };
 
463
        Order.prototype.getTotal = function() {
402
464
            return (this.get('orderLines')).reduce((function(sum, orderLine) {
403
465
                return sum + orderLine.getPriceWithTax();
404
466
            }), 0);
405
 
        },
406
 
        getTotalTaxExcluded: function() {
 
467
        };
 
468
        Order.prototype.getTotalTaxExcluded = function() {
407
469
            return (this.get('orderLines')).reduce((function(sum, orderLine) {
408
470
                return sum + orderLine.getPriceWithoutTax();
409
471
            }), 0);
410
 
        },
411
 
        getTax: function() {
 
472
        };
 
473
        Order.prototype.getTax = function() {
412
474
            return (this.get('orderLines')).reduce((function(sum, orderLine) {
413
475
                return sum + orderLine.getTax();
414
476
            }), 0);
415
 
        },
416
 
        getPaidTotal: function() {
 
477
        };
 
478
        Order.prototype.getPaidTotal = function() {
417
479
            return (this.get('paymentLines')).reduce((function(sum, paymentLine) {
418
480
                return sum + paymentLine.getAmount();
419
481
            }), 0);
420
 
        },
421
 
        getChange: function() {
 
482
        };
 
483
        Order.prototype.getChange = function() {
422
484
            return this.getPaidTotal() - this.getTotal();
423
 
        },
424
 
        getDueLeft: function() {
 
485
        };
 
486
        Order.prototype.getDueLeft = function() {
425
487
            return this.getTotal() - this.getPaidTotal();
426
 
        },
427
 
        exportAsJSON: function() {
428
 
            var orderLines, paymentLines;
 
488
        };
 
489
        Order.prototype.exportAsJSON = function() {
 
490
            var orderLines, paymentLines, result;
429
491
            orderLines = [];
430
492
            (this.get('orderLines')).each(_.bind( function(item) {
431
493
                return orderLines.push([0, 0, item.exportAsJSON()]);
434
496
            (this.get('paymentLines')).each(_.bind( function(item) {
435
497
                return paymentLines.push([0, 0, item.exportAsJSON()]);
436
498
            }, this));
437
 
            return {
 
499
            result = {
438
500
                name: this.getName(),
439
501
                amount_paid: this.getPaidTotal(),
440
502
                amount_total: this.getTotal(),
443
505
                lines: orderLines,
444
506
                statement_ids: paymentLines
445
507
            };
446
 
        },
447
 
    });
448
 
 
449
 
    var OrderCollection = Backbone.Collection.extend({
450
 
        model: Order,
451
 
    });
452
 
 
453
 
    var Shop = Backbone.Model.extend({
454
 
        initialize: function() {
 
508
            return result;
 
509
        };
 
510
        return Order;
 
511
    })();
 
512
    var OrderCollection = (function() {
 
513
        __extends(OrderCollection, Backbone.Collection);
 
514
        function OrderCollection() {
 
515
            OrderCollection.__super__.constructor.apply(this, arguments);
 
516
        }
 
517
 
 
518
        OrderCollection.prototype.model = Order;
 
519
        return OrderCollection;
 
520
    })();
 
521
    var Shop = (function() {
 
522
        __extends(Shop, Backbone.Model);
 
523
        function Shop() {
 
524
            Shop.__super__.constructor.apply(this, arguments);
 
525
        }
 
526
 
 
527
        Shop.prototype.initialize = function() {
455
528
            this.set({
456
529
                orders: new OrderCollection(),
457
530
                products: new ProductCollection()
469
542
                    });
470
543
                }
471
544
            }, this));
472
 
        },
473
 
        addAndSelectOrder: function(newOrder) {
 
545
        };
 
546
        Shop.prototype.addAndSelectOrder = function(newOrder) {
474
547
            (this.get('orders')).add(newOrder);
475
548
            return this.set({
476
549
                selectedOrder: newOrder
477
550
            });
478
 
        },
479
 
    });
480
 
 
 
551
        };
 
552
        return Shop;
 
553
    })();
481
554
    /*
482
555
     The numpad handles both the choice of the property currently being modified
483
556
     (quantity, price or discount) and the edition of the corresponding numeric value.
544
617
            }
545
618
        },
546
619
    });
547
 
 
548
620
    /*
549
621
     ---
550
622
     Views
702
774
        },
703
775
        on_selected: function() {},
704
776
    });
705
 
 
706
777
    var OrderWidget = db.web.OldWidget.extend({
707
778
        init: function(parent, options) {
708
779
            this._super(parent);
784
855
            $('#total').html(total.toFixed(2)).hide().fadeIn();
785
856
        },
786
857
    });
787
 
 
788
858
    /*
789
859
     "Products" step.
790
860
     */
791
861
    var CategoryWidget = db.web.OldWidget.extend({
792
862
        start: function() {
793
863
            this.$element.find(".oe-pos-categories-list a").click(_.bind(this.changeCategory, this));
794
 
            $("#products-screen-ol").css("top",$("#products-screen-categories").height()+"px");
795
864
        },
796
865
        template_fct: qweb_template('pos-category-template'),
797
866
        render_element: function() {
824
893
        },
825
894
        on_change_category: function(id) {},
826
895
    });
827
 
 
828
896
    var ProductWidget = db.web.OldWidget.extend({
829
897
        tag_name:'li',
830
898
        template_fct: qweb_template('pos-product-template'),
847
915
            return this;
848
916
        },
849
917
    });
850
 
 
851
918
    var ProductListWidget = db.web.OldWidget.extend({
852
919
        init: function(parent, options) {
853
920
            this._super(parent);
999
1066
                this.currentPaymentLines.last().set({amount: val});
1000
1067
        },
1001
1068
    });
1002
 
 
1003
1069
    var ReceiptWidget = db.web.OldWidget.extend({
1004
1070
        init: function(parent, options) {
1005
1071
            this._super(parent);
1042
1108
            $('.pos-receipt-container', this.$element).html(qweb_template('pos-ticket')({widget:this}));
1043
1109
        },
1044
1110
    });
1045
 
 
1046
1111
    var OrderButtonWidget = db.web.OldWidget.extend({
1047
1112
        tag_name: 'li',
1048
1113
        template_fct: qweb_template('pos-order-selector-button-template'),
1082
1147
            this.$element.addClass('order-selector-button');
1083
1148
        }
1084
1149
    });
1085
 
 
1086
1150
    var ShopWidget = db.web.OldWidget.extend({
1087
1151
        init: function(parent, options) {
1088
1152
            this._super(parent);
1163
1227
                }
1164
1228
        },
1165
1229
    });
1166
 
 
1167
1230
    var App = (function() {
1168
 
 
1169
1231
        function App($element) {
1170
1232
            this.initialize($element);
1171
1233
        }
1181
1243
            this.categoryView.on_change_category.add_last(_.bind(this.category, this));
1182
1244
            this.category();
1183
1245
        };
1184
 
 
1185
1246
        App.prototype.category = function(id) {
1186
 
            var c, products, self = this;
1187
 
 
1188
 
            id = !id ? 0 : id; 
1189
 
 
 
1247
            var c, products;
 
1248
            if (id == null) {
 
1249
                id = 0;
 
1250
            }
1190
1251
            c = pos.categories[id];
1191
1252
            this.categoryView.ancestors = c.ancestors;
1192
1253
            this.categoryView.children = c.children;
1193
1254
            this.categoryView.render_element();
1194
1255
            this.categoryView.start();
1195
 
            allProducts = pos.store.get('product.product');
1196
 
            allPackages = pos.store.get('product.packaging');
1197
1256
            products = pos.store.get('product.product').filter( function(p) {
1198
1257
                var _ref;
1199
1258
                return _ref = p.pos_categ_id[0], _.indexOf(c.subtree, _ref) >= 0;
1200
1259
            });
1201
1260
            (this.shop.get('products')).reset(products);
1202
 
 
1203
 
 
1204
 
            //returns true if the code is a valid EAN codebar number by checking the control digit.
1205
 
            var checkEan = function(code) {
1206
 
                var st1 = code.slice();
1207
 
                var st2 = st1.slice(0,st1.length-1).reverse();
1208
 
                // some EAN13 barcodes have a length of 12, as they start by 0
1209
 
                while (st2.length < 12) {
1210
 
                    st2.push(0);
1211
 
                }
1212
 
                var countSt3 = 1;
1213
 
                var st3 = 0;
1214
 
                $.each(st2, function() {
1215
 
                    if (countSt3%2 === 1) {
1216
 
                        st3 +=  this;
1217
 
                    }
1218
 
                    countSt3 ++;
1219
 
                });
1220
 
                st3 *= 3;
1221
 
                var st4 = 0;
1222
 
                var countSt4 = 1;
1223
 
                $.each(st2, function() {
1224
 
                    if (countSt4%2 === 0) {
1225
 
                        st4 += this;
1226
 
                    }
1227
 
                    countSt4 ++;
1228
 
                });
1229
 
                var st5 = st3 + st4;
1230
 
                var cd = (10 - (st5%10)) % 10;
1231
 
                return code[code.length-1] === cd;
1232
 
            }
1233
 
 
1234
 
            var codeNumbers = [];
1235
 
 
1236
 
            // returns a product that has a packaging with an EAN matching to provided ean string. 
1237
 
            // returns undefined if no such product is found.
1238
 
            var getProductByEAN = function(ean) {
1239
 
                var prefix = ean.substring(0,2);
1240
 
                var scannedProductModel = undefined;
1241
 
                if (prefix in {'02':'', '22':'', '24':'', '26':'', '28':''}) {
1242
 
                    // PRICE barcode
1243
 
                    var itemCode = ean.substring(0,7);
1244
 
                    var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === itemCode;});
1245
 
                    if (scannedPackaging !== undefined) {
1246
 
                        scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];});
1247
 
                        scannedProductModel.list_price = Number(ean.substring(7,12))/100;
1248
 
                    }
1249
 
                } else if (prefix in {'21':'','23':'','27':'','29':'','25':''}) {
1250
 
                    // WEIGHT barcode
1251
 
                    var weight = Number(barcode.substring(7,12))/1000;
1252
 
                    var itemCode = ean.substring(0,7);
1253
 
                    var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === itemCode;});
1254
 
                    if (scannedPackaging !== undefined) {
1255
 
                        scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];});
1256
 
                        scannedProductModel.list_price *= weight;
1257
 
                        scannedProductModel.name += ' - ' + weight + ' Kg.';
1258
 
                    }
1259
 
                } else {
1260
 
                    // UNIT barcode
1261
 
                    scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === ean;});   //TODO DOES NOT SCALE
1262
 
                }
1263
 
                return scannedProductModel;
1264
 
            }
1265
 
 
1266
 
            // The barcode readers acts as a keyboard, we catch all keyup events and try to find a 
1267
 
            // barcode sequence in the typed keys, then act accordingly.
1268
 
            $('body').delegate('','keyup', function (e){
1269
 
 
1270
 
                //We only care about numbers
1271
 
                if (!isNaN(Number(String.fromCharCode(e.keyCode)))) {
1272
 
 
1273
 
                    // The barcode reader sends keystrokes with a specific interval.
1274
 
                    // We look if the typed keys fit in the interval. 
1275
 
                    if (codeNumbers.length==0) {
1276
 
                        timeStamp = new Date().getTime();
1277
 
                    } else {
1278
 
                        if (lastTimeStamp + 30 < new Date().getTime()) {
1279
 
                            // not a barcode reader
1280
 
                            codeNumbers = [];
1281
 
                            timeStamp = new Date().getTime();
1282
 
                        }
1283
 
                    }
1284
 
                    codeNumbers.push(e.keyCode - 48);
1285
 
                    lastTimeStamp = new Date().getTime();
1286
 
                    if (codeNumbers.length == 13) {
1287
 
                        // a barcode reader
1288
 
                        if (!checkEan(codeNumbers)) {
1289
 
                            // barcode read error, raise warning
1290
 
                            $(QWeb.render('pos-scan-warning')).dialog({
1291
 
                                resizable: false,
1292
 
                                height:220,
1293
 
                                modal: true,
1294
 
                                title: "Warning",
1295
 
                                buttons: {
1296
 
                                    "OK": function() {
1297
 
                                        $( this ).dialog( "close" );
1298
 
                                        return;
1299
 
                                    },
1300
 
                                }
1301
 
                            });
1302
 
                        }
1303
 
                        var selectedOrder = self.shop.get('selectedOrder');
1304
 
                        var scannedProductModel = getProductByEAN(codeNumbers.join(''));
1305
 
                        if (scannedProductModel === undefined) {
1306
 
                            // product not recognized, raise warning
1307
 
                            $(QWeb.render('pos-scan-warning')).dialog({
1308
 
                                resizable: false,
1309
 
                                height:220,
1310
 
                                modal: true,
1311
 
                                title: "Warning",
1312
 
                                buttons: {
1313
 
                                    "OK": function() {
1314
 
                                        $( this ).dialog( "close" );
1315
 
                                        return;
1316
 
                                    },
1317
 
                                }
1318
 
                            });
1319
 
                        } else {
1320
 
                            selectedOrder.addProduct(new Product(scannedProductModel));
1321
 
                        }
1322
 
 
1323
 
                        codeNumbers = [];
1324
 
                    }
1325
 
                } else {
1326
 
                    // NaN
1327
 
                    codeNumbers = [];
1328
 
                }
1329
 
            });
1330
 
 
 
1261
            var self = this;
1331
1262
            $('.searchbox input').keyup(function() {
1332
1263
                var m, s;
1333
1264
                s = $(this).val().toLowerCase();
1343
1274
                return (self.shop.get('products')).reset(m);
1344
1275
            });
1345
1276
            return $('.search-clear').click( function() {
1346
 
                (self.shop.get('products')).reset(products);
 
1277
                (this.shop.get('products')).reset(products);
1347
1278
                $('.searchbox input').val('').focus();
1348
1279
                return $('.search-clear').fadeOut();
1349
1280
            });
1443
1374
            }, this));
1444
1375
        },
1445
1376
        close: function() {
1446
 
            // remove barcode reader event listener
1447
 
            $('body').undelegate('', 'keyup')
1448
 
 
1449
1377
            return new db.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_close_statement']], ['res_id']).pipe(
1450
1378
                    _.bind(function(res) {
1451
1379
                return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {