[MERGE] point_of_sale: various fixes and improvements
bzr revid: chs@openerp.com-20130910125223-5iu0tohmourxcz64 bzr revid: fva@openerp.com-20130911155921-xyqskhjx9r9pgw9c
This commit is contained in:
commit
a590fbaf43
|
@ -3,12 +3,17 @@ import logging
|
||||||
import simplejson
|
import simplejson
|
||||||
import os
|
import os
|
||||||
import openerp
|
import openerp
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
from openerp.addons.web import http
|
from openerp.addons.web import http
|
||||||
from openerp.addons.web.http import request
|
from openerp.addons.web.http import request
|
||||||
from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
|
from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
|
||||||
|
|
||||||
class PointOfSaleController(http.Controller):
|
class PointOfSaleController(http.Controller):
|
||||||
|
def __init__(self):
|
||||||
|
self.scale = 'closed'
|
||||||
|
self.scale_weight = 0.0
|
||||||
|
|
||||||
@http.route('/pos/app', type='http', auth='admin')
|
@http.route('/pos/app', type='http', auth='admin')
|
||||||
def app(self):
|
def app(self):
|
||||||
|
@ -64,6 +69,10 @@ class PointOfSaleController(http.Controller):
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
@http.route('/pos/test_connection', type='json', auth='admin')
|
||||||
|
def test_connection(self):
|
||||||
|
return
|
||||||
|
|
||||||
@http.route('/pos/scan_item_success', type='json', auth='admin')
|
@http.route('/pos/scan_item_success', type='json', auth='admin')
|
||||||
def scan_item_success(self, ean):
|
def scan_item_success(self, ean):
|
||||||
"""
|
"""
|
||||||
|
@ -98,18 +107,38 @@ class PointOfSaleController(http.Controller):
|
||||||
|
|
||||||
@http.route('/pos/weighting_start', type='json', auth='admin')
|
@http.route('/pos/weighting_start', type='json', auth='admin')
|
||||||
def weighting_start(self):
|
def weighting_start(self):
|
||||||
print "weighting_start"
|
if self.scale == 'closed':
|
||||||
|
print "Opening (Fake) Connection to Scale..."
|
||||||
|
self.scale = 'open'
|
||||||
|
self.scale_weight = 0.0
|
||||||
|
time.sleep(0.1)
|
||||||
|
print "... Scale Open."
|
||||||
|
else:
|
||||||
|
print "WARNING: Scale already Connected !!!"
|
||||||
return
|
return
|
||||||
|
|
||||||
@http.route('/pos/weighting_read_kg', type='json', auth='admin')
|
@http.route('/pos/weighting_read_kg', type='json', auth='admin')
|
||||||
def weighting_read_kg(self):
|
def weighting_read_kg(self):
|
||||||
print "weighting_read_kg"
|
if self.scale == 'open':
|
||||||
return 3.14
|
print "Reading Scale..."
|
||||||
|
time.sleep(0.025)
|
||||||
|
self.scale_weight += 0.01
|
||||||
|
print "... Done."
|
||||||
|
return self.scale_weight
|
||||||
|
else:
|
||||||
|
print "WARNING: Reading closed scale !!!"
|
||||||
|
return 0.0
|
||||||
|
|
||||||
@http.route('/pos/weighting_end', type='json', auth='admin')
|
@http.route('/pos/weighting_end', type='json', auth='admin')
|
||||||
def weighting_end(self):
|
def weighting_end(self):
|
||||||
print "weighting_end"
|
if self.scale == 'open':
|
||||||
return
|
print "Closing Connection to Scale ..."
|
||||||
|
self.scale = 'closed'
|
||||||
|
self.scale_weight = 0.0
|
||||||
|
time.sleep(0.1)
|
||||||
|
print "... Scale Closed."
|
||||||
|
else:
|
||||||
|
print "WARNING: Scale already Closed !!!"
|
||||||
|
|
||||||
@http.route('/pos/payment_request', type='json', auth='admin')
|
@http.route('/pos/payment_request', type='json', auth='admin')
|
||||||
def payment_request(self, price):
|
def payment_request(self, price):
|
||||||
|
|
|
@ -175,10 +175,9 @@
|
||||||
background: linear-gradient(#b2b3d7, #7f82ac);
|
background: linear-gradient(#b2b3d7, #7f82ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-of-sale #rightheader button.neworder-button {
|
.point-of-sale #rightheader button.square{
|
||||||
width: 32px;
|
width: 32px;
|
||||||
margin-left:4px;
|
margin-left:4px;
|
||||||
margin-right:4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-of-sale div#order-selector {
|
.point-of-sale div#order-selector {
|
||||||
|
@ -186,12 +185,20 @@
|
||||||
}
|
}
|
||||||
.point-of-sale ol#orders {
|
.point-of-sale ol#orders {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
.point-of-sale li.order-selector-button {
|
.point-of-sale li.order-selector-button {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
.point-of-sale li.selected-order button {
|
.point-of-sale li.selected-order button {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
|
background: #7174A8 !important;
|
||||||
|
color: rgb(236, 237, 255) !important;
|
||||||
|
text-shadow: 0px 1px rgba(0, 0, 0, 0.31);
|
||||||
|
-webkit-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset;
|
||||||
|
-moz-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset;
|
||||||
|
-ms-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset;
|
||||||
|
box-shadow: 0px 1px 2px rgb(63, 66, 139) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* c) The session buttons */
|
/* c) The session buttons */
|
||||||
|
@ -215,7 +222,7 @@
|
||||||
.point-of-sale #rightheader .header-button:last-child{
|
.point-of-sale #rightheader .header-button:last-child{
|
||||||
border-left: 1px solid #3a3a3a;
|
border-left: 1px solid #3a3a3a;
|
||||||
}
|
}
|
||||||
.point-of-sale #rightheader .header-button:hover{
|
.point-of-sale #rightheader .header-button:active{
|
||||||
background: rgba(0,0,0,0.2);
|
background: rgba(0,0,0,0.2);
|
||||||
text-shadow: #000 0px 0px 3px;
|
text-shadow: #000 0px 0px 3px;
|
||||||
color:#EEE;
|
color:#EEE;
|
||||||
|
@ -307,18 +314,10 @@
|
||||||
border-top: 1px solid #efefef;
|
border-top: 1px solid #efefef;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.point-of-sale #paypad button, .point-of-sale #numpad button, .point-of-sale .popup button{
|
.point-of-sale #paypad button:active,
|
||||||
position: relative;
|
.point-of-sale #numpad button:active,
|
||||||
top: 0;
|
.point-of-sale #numpad .selected-mode,
|
||||||
-webkit-transition: top 150ms linear;
|
.point-of-sale .popup button:active{
|
||||||
-moz-transition: top 150ms linear;
|
|
||||||
-ms-transition: top 150ms linear;
|
|
||||||
transition: top 150ms linear;
|
|
||||||
}
|
|
||||||
.point-of-sale #paypad button:active, .point-of-sale #numpad button:active, .point-of-sale .popup button:active{
|
|
||||||
top:3px;
|
|
||||||
}
|
|
||||||
.point-of-sale #paypad button:hover, .point-of-sale #numpad button:hover, .point-of-sale #numpad .selected-mode, .point-of-sale .popup button:hover {
|
|
||||||
border: none;
|
border: none;
|
||||||
color: white;
|
color: white;
|
||||||
background: #7f82ac;
|
background: #7f82ac;
|
||||||
|
@ -518,7 +517,7 @@
|
||||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||||
}
|
}
|
||||||
.point-of-sale .category-simple-button:hover {
|
.point-of-sale .category-simple-button:active{
|
||||||
color: white;
|
color: white;
|
||||||
background: #7f82ac;
|
background: #7f82ac;
|
||||||
border: 1px solid #7f82ac;
|
border: 1px solid #7f82ac;
|
||||||
|
@ -1049,13 +1048,13 @@
|
||||||
-moz-transition: background 250ms ease-in-out;
|
-moz-transition: background 250ms ease-in-out;
|
||||||
transition: background 250ms ease-in-out;
|
transition: background 250ms ease-in-out;
|
||||||
}
|
}
|
||||||
.point-of-sale .order .orderline:hover{
|
.point-of-sale .order .orderline:active{
|
||||||
background: rgba(140,143,183,0.05);
|
background: rgba(140,143,183,0.05);
|
||||||
-webkit-transition: background 50ms ease-in-out;
|
-webkit-transition: background 50ms ease-in-out;
|
||||||
-moz-transition: background 50ms ease-in-out;
|
-moz-transition: background 50ms ease-in-out;
|
||||||
transition: background 50ms ease-in-out;
|
transition: background 50ms ease-in-out;
|
||||||
}
|
}
|
||||||
.point-of-sale .order .orderline.empty:hover{
|
.point-of-sale .order .orderline.empty:active{
|
||||||
background: transparent;
|
background: transparent;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1155,7 @@
|
||||||
.point-of-sale .pos-actionbar .button .icon{
|
.point-of-sale .pos-actionbar .button .icon{
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
.point-of-sale .pos-actionbar .button:hover {
|
.point-of-sale .pos-actionbar .button:active{
|
||||||
color: white;
|
color: white;
|
||||||
background: #7f82ac;
|
background: #7f82ac;
|
||||||
border: 1px solid #7f82ac;
|
border: 1px solid #7f82ac;
|
||||||
|
@ -1173,7 +1172,7 @@
|
||||||
.point-of-sale .pos-actionbar .button.disabled *{
|
.point-of-sale .pos-actionbar .button.disabled *{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.point-of-sale .pos-actionbar .button.disabled:hover{
|
.point-of-sale .pos-actionbar .button.disabled:active{
|
||||||
border: 1px solid #cacaca;
|
border: 1px solid #cacaca;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
@ -1242,7 +1241,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
}
|
}
|
||||||
.point-of-sale .debug-widget .button:hover{
|
.point-of-sale .debug-widget .button:active{
|
||||||
background: rgba(96,21,177,0.45);
|
background: rgba(96,21,177,0.45);
|
||||||
}
|
}
|
||||||
.point-of-sale .debug-widget input{
|
.point-of-sale .debug-widget input{
|
||||||
|
@ -1330,7 +1329,7 @@
|
||||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
||||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
||||||
}
|
}
|
||||||
.point-of-sale .popup .button:hover {
|
.point-of-sale .popup .button:active{
|
||||||
color: white;
|
color: white;
|
||||||
background: #7f82ac;
|
background: #7f82ac;
|
||||||
border: 1px solid #7f82ac;
|
border: 1px solid #7f82ac;
|
||||||
|
@ -1398,7 +1397,7 @@
|
||||||
-moz-transition: all 250ms ease-in-out;
|
-moz-transition: all 250ms ease-in-out;
|
||||||
transition: all 250ms ease-in-out;
|
transition: all 250ms ease-in-out;
|
||||||
}
|
}
|
||||||
.point-of-sale .scrollbar .button:hover{
|
.point-of-sale .scrollbar .button:active{
|
||||||
text-shadow: rgba(255,255,255,0.8) 0px 0px 15px;
|
text-shadow: rgba(255,255,255,0.8) 0px 0px 15px;
|
||||||
}
|
}
|
||||||
.point-of-sale .scrollbar .button.disabled{
|
.point-of-sale .scrollbar .button.disabled{
|
||||||
|
|
|
@ -1,6 +1,81 @@
|
||||||
|
|
||||||
function openerp_pos_devices(instance,module){ //module is instance.point_of_sale
|
function openerp_pos_devices(instance,module){ //module is instance.point_of_sale
|
||||||
|
|
||||||
|
// the JobQueue schedules a sequence of 'jobs'. each job is
|
||||||
|
// a function returning a deferred. the queue waits for each job to finish
|
||||||
|
// before launching the next. Each job can also be scheduled with a delay.
|
||||||
|
// the is used to prevent parallel requests to the proxy.
|
||||||
|
|
||||||
|
module.JobQueue = function(){
|
||||||
|
var queue = [];
|
||||||
|
var running = false;
|
||||||
|
var scheduled_end_time = 0;
|
||||||
|
var end_of_queue = (new $.Deferred()).resolve();
|
||||||
|
var stoprepeat = false;
|
||||||
|
|
||||||
|
var run = function(){
|
||||||
|
if(end_of_queue.state() === 'resolved'){
|
||||||
|
end_of_queue = new $.Deferred();
|
||||||
|
}
|
||||||
|
if(queue.length > 0){
|
||||||
|
running = true;
|
||||||
|
var job = queue[0];
|
||||||
|
if(!job.opts.repeat || stoprepeat){
|
||||||
|
queue.shift();
|
||||||
|
stoprepeat = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the time scheduled for this job
|
||||||
|
scheduled_end_time = (new Date()).getTime() + (job.opts.duration || 0);
|
||||||
|
|
||||||
|
// we run the job and put in def when it finishes
|
||||||
|
var def = job.fun() || (new $.Deferred()).resolve();
|
||||||
|
|
||||||
|
// we don't care if a job fails ...
|
||||||
|
def.always(function(){
|
||||||
|
// we run the next job after the scheduled_end_time, even if it finishes before
|
||||||
|
setTimeout(function(){
|
||||||
|
run();
|
||||||
|
}, Math.max(0, scheduled_end_time - (new Date()).getTime()) );
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
running = false;
|
||||||
|
end_of_queue.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// adds a job to the schedule.
|
||||||
|
// opts : {
|
||||||
|
// duration : the job is guaranteed to finish no quicker than this (milisec)
|
||||||
|
// repeat : if true, the job will be endlessly repeated
|
||||||
|
// important : if true, the scheduled job cannot be canceled by a queue.clear()
|
||||||
|
// }
|
||||||
|
this.schedule = function(fun, opts){
|
||||||
|
queue.push({fun:fun, opts:opts || {}});
|
||||||
|
if(!running){
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all jobs from the schedule (except the ones marked as important)
|
||||||
|
this.clear = function(){
|
||||||
|
queue = _.filter(queue,function(job){job.opts.important === true});
|
||||||
|
};
|
||||||
|
|
||||||
|
// end the repetition of the current job
|
||||||
|
this.stoprepeat = function(){
|
||||||
|
stoprepeat = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// returns a deferred that resolves when all scheduled
|
||||||
|
// jobs have been run.
|
||||||
|
// ( jobs added after the call to this method are considered as well )
|
||||||
|
this.finished = function(){
|
||||||
|
return end_of_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// this object interfaces with the local proxy to communicate to the various hardware devices
|
// this object interfaces with the local proxy to communicate to the various hardware devices
|
||||||
// connected to the Point of Sale. As the communication only goes from the POS to the proxy,
|
// connected to the Point of Sale. As the communication only goes from the POS to the proxy,
|
||||||
// methods are used both to signal an event, and to fetch information.
|
// methods are used both to signal an event, and to fetch information.
|
||||||
|
@ -10,7 +85,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
options = options || {};
|
options = options || {};
|
||||||
url = options.url || 'http://localhost:8069';
|
url = options.url || 'http://localhost:8069';
|
||||||
|
|
||||||
this.weight = 0;
|
|
||||||
this.weighting = false;
|
this.weighting = false;
|
||||||
this.debug_weight = 0;
|
this.debug_weight = 0;
|
||||||
this.use_debug_weight = false;
|
this.use_debug_weight = false;
|
||||||
|
@ -35,18 +109,11 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
this.connection.destroy();
|
this.connection.destroy();
|
||||||
},
|
},
|
||||||
message : function(name,params){
|
message : function(name,params){
|
||||||
var ret = new $.Deferred();
|
|
||||||
var callbacks = this.notifications[name] || [];
|
var callbacks = this.notifications[name] || [];
|
||||||
for(var i = 0; i < callbacks.length; i++){
|
for(var i = 0; i < callbacks.length; i++){
|
||||||
callbacks[i](params);
|
callbacks[i](params);
|
||||||
}
|
}
|
||||||
|
return this.connection.rpc('/pos/' + name, params || {});
|
||||||
this.connection.rpc('/pos/' + name, params || {}).done(function(result) {
|
|
||||||
ret.resolve(result);
|
|
||||||
}).fail(function(error) {
|
|
||||||
ret.reject(error);
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// this allows the client to be notified when a proxy call is made. The notification
|
// this allows the client to be notified when a proxy call is made. The notification
|
||||||
|
@ -82,13 +149,32 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
|
|
||||||
//the client is starting to weight
|
//the client is starting to weight
|
||||||
weighting_start: function(){
|
weighting_start: function(){
|
||||||
|
var ret = new $.Deferred();
|
||||||
if(!this.weighting){
|
if(!this.weighting){
|
||||||
this.weighting = true;
|
this.weighting = true;
|
||||||
if(!this.bypass_proxy){
|
this.message('weighting_start').always(function(){
|
||||||
this.weight = 0;
|
ret.resolve();
|
||||||
return this.message('weighting_start');
|
});
|
||||||
}
|
}else{
|
||||||
|
console.error('Weighting already started!!!');
|
||||||
|
ret.resolve();
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
|
// the client has finished weighting products
|
||||||
|
weighting_end: function(){
|
||||||
|
var ret = new $.Deferred();
|
||||||
|
if(this.weighting){
|
||||||
|
this.weighting = false;
|
||||||
|
this.message('weighting_end').always(function(){
|
||||||
|
ret.resolve();
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
console.error('Weighting already ended !!!');
|
||||||
|
ret.resolve();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
//returns the weight on the scale.
|
//returns the weight on the scale.
|
||||||
|
@ -96,17 +182,14 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
// and a weighting_end()
|
// and a weighting_end()
|
||||||
weighting_read_kg: function(){
|
weighting_read_kg: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var ret = new $.Deferred();
|
||||||
this.message('weighting_read_kg',{})
|
this.message('weighting_read_kg',{})
|
||||||
.done(function(weight){
|
.then(function(weight){
|
||||||
if(self.weighting){
|
ret.resolve(self.use_debug_weight ? self.debug_weight : weight);
|
||||||
if(self.use_debug_weight){
|
}, function(){ //failed to read weight
|
||||||
self.weight = self.debug_weight;
|
ret.resolve(self.use_debug_weight ? self.debug_weight : 0.0);
|
||||||
}else{
|
|
||||||
self.weight = weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
return this.weight;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
// sets a custom weight, ignoring the proxy returned value.
|
// sets a custom weight, ignoring the proxy returned value.
|
||||||
|
@ -121,12 +204,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
this.debug_weight = 0;
|
this.debug_weight = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
// the client has finished weighting products
|
|
||||||
weighting_end: function(){
|
|
||||||
this.weight = 0;
|
|
||||||
this.weighting = false;
|
|
||||||
this.message('weighting_end');
|
|
||||||
},
|
|
||||||
|
|
||||||
// the pos asks the client to pay 'price' units
|
// the pos asks the client to pay 'price' units
|
||||||
payment_request: function(price){
|
payment_request: function(price){
|
||||||
|
|
|
@ -24,6 +24,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||||
|
|
||||||
this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes
|
this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes
|
||||||
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
||||||
|
this.proxy_queue = new module.JobQueue(); // used to prevent parallels communications to the proxy
|
||||||
this.db = new module.PosLS(); // a database used to store the products and categories
|
this.db = new module.PosLS(); // a database used to store the products and categories
|
||||||
this.db.clear('products','categories');
|
this.db.clear('products','categories');
|
||||||
this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode
|
this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode
|
||||||
|
@ -55,7 +56,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||||
'selectedOrder': null,
|
'selectedOrder': null,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.get('orders').bind('remove', function(){ self.on_removed_order(); });
|
this.get('orders').bind('remove', function(order,_unused_,options){
|
||||||
|
self.on_removed_order(order,options.index,options.reason);
|
||||||
|
});
|
||||||
|
|
||||||
// We fetch the backend data on the server asynchronously. this is done only when the pos user interface is launched,
|
// We fetch the backend data on the server asynchronously. this is done only when the pos user interface is launched,
|
||||||
// Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched.
|
// Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched.
|
||||||
|
@ -239,11 +242,14 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||||
|
|
||||||
// this is called when an order is removed from the order collection. It ensures that there is always an existing
|
// this is called when an order is removed from the order collection. It ensures that there is always an existing
|
||||||
// order and a valid selected order
|
// order and a valid selected order
|
||||||
on_removed_order: function(removed_order){
|
on_removed_order: function(removed_order,index,reason){
|
||||||
if( this.get('orders').isEmpty()){
|
if(reason === 'abandon' && this.get('orders').size() > 0){
|
||||||
this.add_new_order();
|
// when we intentionally remove an unfinished order, and there is another existing one
|
||||||
|
this.set({'selectedOrder' : this.get('orders').at(index) || this.get('orders').last()});
|
||||||
}else{
|
}else{
|
||||||
this.set({ selectedOrder: this.get('orders').last() });
|
// when the order was automatically removed after completion,
|
||||||
|
// or when we intentionally delete the only concurrent order
|
||||||
|
this.add_new_order();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -254,6 +260,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||||
this.set('selectedOrder', order);
|
this.set('selectedOrder', order);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//removes the current order
|
||||||
|
delete_current_order: function(){
|
||||||
|
this.get('selectedOrder').destroy({'reason':'abandon'});
|
||||||
|
console.log('coucou!');
|
||||||
|
},
|
||||||
|
|
||||||
// saves the order locally and try to send it to the backend.
|
// saves the order locally and try to send it to the backend.
|
||||||
// it returns a deferred that succeeds after having tried to send the order and all the other pending orders.
|
// it returns a deferred that succeeds after having tried to send the order and all the other pending orders.
|
||||||
push_order: function(order) {
|
push_order: function(order) {
|
||||||
|
|
|
@ -271,19 +271,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
});
|
});
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier';
|
this.cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier';
|
||||||
|
|
||||||
this.pos_widget.set_numpad_visible(this.show_numpad && cashier_mode);
|
this.pos_widget.set_numpad_visible(this.show_numpad && this.cashier_mode);
|
||||||
this.pos_widget.set_leftpane_visible(this.show_leftpane);
|
this.pos_widget.set_leftpane_visible(this.show_leftpane);
|
||||||
this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !cashier_mode);
|
this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !this.cashier_mode);
|
||||||
this.pos_widget.set_cashier_controls_visible(cashier_mode);
|
this.pos_widget.set_cashier_controls_visible(this.cashier_mode);
|
||||||
|
|
||||||
if(cashier_mode && this.pos.iface_self_checkout){
|
if(this.cashier_mode && this.pos.iface_self_checkout){
|
||||||
this.pos_widget.client_button.show();
|
this.pos_widget.client_button.show();
|
||||||
}else{
|
}else{
|
||||||
this.pos_widget.client_button.hide();
|
this.pos_widget.client_button.hide();
|
||||||
}
|
}
|
||||||
if(cashier_mode){
|
if(this.cashier_mode){
|
||||||
this.pos_widget.close_button.show();
|
this.pos_widget.close_button.show();
|
||||||
}else{
|
}else{
|
||||||
this.pos_widget.close_button.hide();
|
this.pos_widget.close_button.hide();
|
||||||
|
@ -441,7 +441,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
module.ErrorInvoiceTransferPopupWidget = module.ErrorPopupWidget.extend({
|
module.ErrorInvoiceTransferPopupWidget = module.ErrorPopupWidget.extend({
|
||||||
template: 'ErrorInvoiceTransferPopupWidget',
|
template: 'ErrorInvoiceTransferPopupWidget',
|
||||||
});
|
});
|
||||||
|
|
||||||
module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
|
module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
|
||||||
template:'ScaleInviteScreenWidget',
|
template:'ScaleInviteScreenWidget',
|
||||||
|
|
||||||
|
@ -451,30 +451,35 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
show: function(){
|
show: function(){
|
||||||
this._super();
|
this._super();
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var queue = this.pos.proxy_queue;
|
||||||
|
|
||||||
self.pos.proxy.weighting_start();
|
queue.schedule(function(){
|
||||||
|
return self.pos.proxy.weighting_start();
|
||||||
this.intervalID = setInterval(function(){
|
},{ unclearable: true });
|
||||||
var weight = self.pos.proxy.weighting_read_kg();
|
|
||||||
if(weight > 0.001){
|
queue.schedule(function(){
|
||||||
clearInterval(this.intervalID);
|
return self.pos.proxy.weighting_read_kg().then(function(weight){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
if(weight > 0.001){
|
||||||
}
|
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||||
},100);
|
}
|
||||||
|
});
|
||||||
|
},{duration: 100, repeat: true});
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: _t('Back'),
|
label: _t('Back'),
|
||||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||||
click: function(){
|
click: function(){
|
||||||
clearInterval(this.intervalID);
|
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
close: function(){
|
close: function(){
|
||||||
this._super();
|
this._super();
|
||||||
clearInterval(this.intervalID);
|
var self = this;
|
||||||
this.pos.proxy.weighting_end();
|
this.pos.proxy_queue.clear();
|
||||||
|
this.pos.proxy_queue.schedule(function(){
|
||||||
|
return self.pos.proxy.weighting_end();
|
||||||
|
},{ unclearable: true });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -486,9 +491,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
|
|
||||||
show: function(){
|
show: function(){
|
||||||
this._super();
|
this._super();
|
||||||
this.renderElement();
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var queue = this.pos.proxy_queue;
|
||||||
|
|
||||||
|
this.set_weight(0);
|
||||||
|
this.renderElement();
|
||||||
|
|
||||||
this.add_action_button({
|
this.add_action_button({
|
||||||
label: _t('Back'),
|
label: _t('Back'),
|
||||||
|
@ -507,14 +514,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.pos.proxy.weighting_start();
|
queue.schedule(function(){
|
||||||
this.intervalID = setInterval(function(){
|
return self.pos.proxy.weighting_start()
|
||||||
var weight = self.pos.proxy.weighting_read_kg();
|
},{ unclearable: true });
|
||||||
if(weight != self.weight){
|
|
||||||
self.weight = weight;
|
queue.schedule(function(){
|
||||||
self.renderElement();
|
return self.pos.proxy.weighting_read_kg().then(function(weight){
|
||||||
}
|
self.set_weight(weight);
|
||||||
},100);
|
});
|
||||||
|
},{duration:50, repeat: true});
|
||||||
|
|
||||||
},
|
},
|
||||||
renderElement: function(){
|
renderElement: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -544,54 +553,24 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
var product = this.get_product();
|
var product = this.get_product();
|
||||||
return (product ? product.get('price') : 0) || 0;
|
return (product ? product.get('price') : 0) || 0;
|
||||||
},
|
},
|
||||||
get_product_weight: function(){
|
set_weight: function(weight){
|
||||||
return this.weight || 0;
|
this.weight = weight;
|
||||||
|
this.$('.js-weight').text(this.get_product_weight_string());
|
||||||
|
},
|
||||||
|
get_product_weight_string: function(){
|
||||||
|
return (this.weight || 0).toFixed(3) + ' Kg';
|
||||||
},
|
},
|
||||||
close: function(){
|
close: function(){
|
||||||
|
var self = this;
|
||||||
this._super();
|
this._super();
|
||||||
clearInterval(this.intervalID);
|
|
||||||
this.pos.proxy.weighting_end();
|
this.pos.proxy_queue.clear();
|
||||||
|
this.pos.proxy_queue.schedule(function(){
|
||||||
|
self.pos.proxy.weighting_end();
|
||||||
|
},{ unclearable: true });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// the JobQueue schedules a sequence of 'jobs'. each job is
|
|
||||||
// a function returning a deferred. the queue waits for each job to finish
|
|
||||||
// before launching the next. Each job can also be scheduled with a delay.
|
|
||||||
// the queue jobqueue is used to prevent parallel requests to the payment terminal.
|
|
||||||
|
|
||||||
module.JobQueue = function(){
|
|
||||||
var queue = [];
|
|
||||||
var running = false;
|
|
||||||
var run = function(){
|
|
||||||
if(queue.length > 0){
|
|
||||||
running = true;
|
|
||||||
var job = queue.shift();
|
|
||||||
setTimeout(function(){
|
|
||||||
var def = job.fun();
|
|
||||||
if(def){
|
|
||||||
def.done(run);
|
|
||||||
}else{
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
},job.delay || 0);
|
|
||||||
}else{
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// adds a job to the schedule.
|
|
||||||
this.schedule = function(fun, delay){
|
|
||||||
queue.push({fun:fun, delay:delay});
|
|
||||||
if(!running){
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove all jobs from the schedule
|
|
||||||
this.clear = function(){
|
|
||||||
queue = [];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module.ClientPaymentScreenWidget = module.ScreenWidget.extend({
|
module.ClientPaymentScreenWidget = module.ScreenWidget.extend({
|
||||||
template:'ClientPaymentScreenWidget',
|
template:'ClientPaymentScreenWidget',
|
||||||
|
@ -740,7 +719,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
module.ProductScreenWidget = module.ScreenWidget.extend({
|
module.ProductScreenWidget = module.ScreenWidget.extend({
|
||||||
template:'ProductScreenWidget',
|
template:'ProductScreenWidget',
|
||||||
|
|
||||||
scale_screen: 'scale_invite',
|
scale_screen: 'scale',
|
||||||
|
client_scale_screen : 'scale_invite',
|
||||||
client_next_screen: 'client_payment',
|
client_next_screen: 'client_payment',
|
||||||
|
|
||||||
show_numpad: true,
|
show_numpad: true,
|
||||||
|
@ -754,7 +734,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
this.product_list_widget = new module.ProductListWidget(this,{
|
this.product_list_widget = new module.ProductListWidget(this,{
|
||||||
click_product_action: function(product){
|
click_product_action: function(product){
|
||||||
if(product.get('to_weight') && self.pos.iface_electronic_scale){
|
if(product.get('to_weight') && self.pos.iface_electronic_scale){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.scale_screen, {product: product});
|
self.pos_widget.screen_selector.set_current_screen( self.cashier_mode ? self.scale_screen : self.client_scale_screen, {product: product});
|
||||||
}else{
|
}else{
|
||||||
self.pos.get('selectedOrder').addProduct(product);
|
self.pos.get('selectedOrder').addProduct(product);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,10 +62,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
start: function() {
|
start: function() {
|
||||||
this.state.bind('change:mode', this.changedMode, this);
|
this.state.bind('change:mode', this.changedMode, this);
|
||||||
this.changedMode();
|
this.changedMode();
|
||||||
this.$el.find('button#numpad-backspace').click(_.bind(this.clickDeleteLastChar, this));
|
this.$el.find('.numpad-backspace').click(_.bind(this.clickDeleteLastChar, this));
|
||||||
this.$el.find('button#numpad-minus').click(_.bind(this.clickSwitchSign, this));
|
this.$el.find('.numpad-minus').click(_.bind(this.clickSwitchSign, this));
|
||||||
this.$el.find('button.number-char').click(_.bind(this.clickAppendNewChar, this));
|
this.$el.find('.number-char').click(_.bind(this.clickAppendNewChar, this));
|
||||||
this.$el.find('button.mode-button').click(_.bind(this.clickChangeMode, this));
|
this.$el.find('.mode-button').click(_.bind(this.clickChangeMode, this));
|
||||||
},
|
},
|
||||||
clickDeleteLastChar: function() {
|
clickDeleteLastChar: function() {
|
||||||
return this.state.deleteLastChar();
|
return this.state.deleteLastChar();
|
||||||
|
@ -189,8 +189,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
}else if( mode === 'price'){
|
}else if( mode === 'price'){
|
||||||
order.getSelectedLine().set_unit_price(val);
|
order.getSelectedLine().set_unit_price(val);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.pos.get('selectedOrder').destroy();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
change_selected_order: function() {
|
change_selected_order: function() {
|
||||||
|
@ -362,28 +360,23 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
this.order = options.order;
|
this.order = options.order;
|
||||||
this.order.bind('destroy',function(){ self.destroy(); });
|
this.order.bind('destroy',function(){ self.destroy(); });
|
||||||
this.order.bind('change', function(){ self.renderElement(); });
|
this.order.bind('change', function(){ self.renderElement(); });
|
||||||
this.pos.bind('change:selectedOrder', _.bind( function(pos) {
|
this.pos.bind('change:selectedOrder', function() {
|
||||||
var selectedOrder;
|
self.renderElement();
|
||||||
selectedOrder = pos.get('selectedOrder');
|
}, this);
|
||||||
if (this.order === selectedOrder) {
|
|
||||||
this.setButtonSelected();
|
|
||||||
}
|
|
||||||
}, this));
|
|
||||||
},
|
},
|
||||||
renderElement:function(){
|
renderElement:function(){
|
||||||
this._super();
|
this._super();
|
||||||
this.$('button.select-order').off('click').click(_.bind(this.selectOrder, this));
|
this.$('button.select-order').off('click').click(_.bind(this.selectOrder, this));
|
||||||
this.$('button.close-order').off('click').click(_.bind(this.closeOrder, this));
|
this.$('button.close-order').off('click').click(_.bind(this.closeOrder, this));
|
||||||
|
if( this.order === this.pos.get('selectedOrder') ){
|
||||||
|
this.$el.addClass('selected-order');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
selectOrder: function(event) {
|
selectOrder: function(event) {
|
||||||
this.pos.set({
|
this.pos.set({
|
||||||
selectedOrder: this.order
|
selectedOrder: this.order
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setButtonSelected: function() {
|
|
||||||
$('.selected-order').removeClass('selected-order');
|
|
||||||
this.$el.addClass('selected-order');
|
|
||||||
},
|
|
||||||
closeOrder: function(event) {
|
closeOrder: function(event) {
|
||||||
this.order.destroy();
|
this.order.destroy();
|
||||||
},
|
},
|
||||||
|
@ -848,17 +841,24 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
this.leftpane_width = '440px';
|
this.leftpane_width = '440px';
|
||||||
this.cashier_controls_visible = true;
|
this.cashier_controls_visible = true;
|
||||||
this.image_cache = new module.ImageCache(); // for faster products image display
|
this.image_cache = new module.ImageCache(); // for faster products image display
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return self.pos.ready.done(function() {
|
return self.pos.ready.done(function() {
|
||||||
|
$('.oe_tooltip').remove(); // remove tooltip from the start session button
|
||||||
|
|
||||||
self.build_currency_template();
|
self.build_currency_template();
|
||||||
self.renderElement();
|
self.renderElement();
|
||||||
|
|
||||||
self.$('.neworder-button').click(function(){
|
self.$('.neworder-button').click(function(){
|
||||||
self.pos.add_new_order();
|
self.pos.add_new_order();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.$('.deleteorder-button').click(function(){
|
||||||
|
self.pos.delete_current_order();
|
||||||
|
});
|
||||||
|
|
||||||
//when a new order is created, add an order button widget
|
//when a new order is created, add an order button widget
|
||||||
self.pos.get('orders').bind('add', function(new_order){
|
self.pos.get('orders').bind('add', function(new_order){
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="rightheader">
|
<div id="rightheader">
|
||||||
<div id="order-selector">
|
<div id="order-selector">
|
||||||
<button class="neworder-button">+</button>
|
<button class="neworder-button square">➕</button>
|
||||||
|
<button class="deleteorder-button square">➖</button>
|
||||||
<ol id="orders"></ol>
|
<ol id="orders"></ol>
|
||||||
</div>
|
</div>
|
||||||
<!-- here goes header buttons -->
|
<!-- here goes header buttons -->
|
||||||
|
@ -93,10 +94,10 @@
|
||||||
<button class="input-button number-char">9</button>
|
<button class="input-button number-char">9</button>
|
||||||
<button class="mode-button" data-mode='price'>Price</button>
|
<button class="mode-button" data-mode='price'>Price</button>
|
||||||
<br />
|
<br />
|
||||||
<button class="input-button" id="numpad-minus" >+/-</button>
|
<button class="input-button numpad-minus" >+/-</button>
|
||||||
<button class="input-button number-char">0</button>
|
<button class="input-button number-char">0</button>
|
||||||
<button class="input-button number-char">.</button>
|
<button class="input-button number-char">.</button>
|
||||||
<button class="input-button" id="numpad-backspace">
|
<button class="input-button numpad-backspace">
|
||||||
<img src="/point_of_sale/static/src/img/backspace.png" width="24" height="21" />
|
<img src="/point_of_sale/static/src/img/backspace.png" width="24" height="21" />
|
||||||
</button>
|
</button>
|
||||||
<br />
|
<br />
|
||||||
|
@ -191,8 +192,9 @@
|
||||||
<div class="display">
|
<div class="display">
|
||||||
<span class="weight">
|
<span class="weight">
|
||||||
<p>
|
<p>
|
||||||
<t t-esc="widget.get_product_weight().toFixed(3)" />
|
<span class='js-weight'>
|
||||||
Kg
|
<t t-esc="widget.get_product_weight_string()" />
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</span>
|
</span>
|
||||||
<span class="product-name">
|
<span class="product-name">
|
||||||
|
|
|
@ -451,7 +451,7 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin,
|
||||||
// TODO: reorder results to match ids list
|
// TODO: reorder results to match ids list
|
||||||
return this._model.call('read',
|
return this._model.call('read',
|
||||||
[ids, fields || false],
|
[ids, fields || false],
|
||||||
{context: this._model.context(options.context)});
|
{context: this.get_context(options.context)});
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Read a slice of the records represented by this DataSet, based on its
|
* Read a slice of the records represented by this DataSet, based on its
|
||||||
|
|
|
@ -166,13 +166,13 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
|
||||||
var is_loaded = 0,
|
var is_loaded = 0,
|
||||||
$this = $(this),
|
$this = $(this),
|
||||||
record_id = $this.data('id'),
|
record_id = $this.data('id'),
|
||||||
parent_id = $this.data('parent-id'),
|
row_parent_id = $this.data('row-parent-id'),
|
||||||
record = self.records[record_id],
|
record = self.records[record_id],
|
||||||
children_ids = record[self.children_field];
|
children_ids = record[self.children_field];
|
||||||
|
|
||||||
_(children_ids).each(function(childid) {
|
_(children_ids).each(function(childid) {
|
||||||
if (self.$el.find('[id=treerow_' + childid + '][data-parent-id='+ record_id +']').length ) {
|
if (self.$el.find('[id=treerow_' + childid + '][data-row-parent-id='+ record_id +']').length ) {
|
||||||
if (self.$el.find('[id=treerow_' + childid + '][data-parent-id='+ record_id +']').is(':hidden')) {
|
if (self.$el.find('[id=treerow_' + childid + '][data-row-parent-id='+ record_id +']').is(':hidden')) {
|
||||||
is_loaded = -1;
|
is_loaded = -1;
|
||||||
} else {
|
} else {
|
||||||
is_loaded++;
|
is_loaded++;
|
||||||
|
@ -196,7 +196,6 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
|
||||||
_(records).each(function (record) {
|
_(records).each(function (record) {
|
||||||
self.records[record.id] = record;
|
self.records[record.id] = record;
|
||||||
});
|
});
|
||||||
|
|
||||||
var $curr_node = self.$el.find('#treerow_' + id);
|
var $curr_node = self.$el.find('#treerow_' + id);
|
||||||
var children_rows = QWeb.render('TreeView.rows', {
|
var children_rows = QWeb.render('TreeView.rows', {
|
||||||
'records': records,
|
'records': records,
|
||||||
|
@ -206,7 +205,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
|
||||||
'level': $curr_node.data('level') || 0,
|
'level': $curr_node.data('level') || 0,
|
||||||
'render': instance.web.format_value,
|
'render': instance.web.format_value,
|
||||||
'color_for': self.color_for,
|
'color_for': self.color_for,
|
||||||
'parent_id': id
|
'row_parent_id': id
|
||||||
});
|
});
|
||||||
if ($curr_node.length) {
|
if ($curr_node.length) {
|
||||||
$curr_node.addClass('oe_open');
|
$curr_node.addClass('oe_open');
|
||||||
|
@ -250,7 +249,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
|
||||||
showcontent: function (curnode,record_id, show) {
|
showcontent: function (curnode,record_id, show) {
|
||||||
curnode.parent('tr').toggleClass('oe_open', show);
|
curnode.parent('tr').toggleClass('oe_open', show);
|
||||||
_(this.records[record_id][this.children_field]).each(function (child_id) {
|
_(this.records[record_id][this.children_field]).each(function (child_id) {
|
||||||
var $child_row = this.$el.find('[id=treerow_' + child_id + '][data-parent-id='+ curnode.data('id') +']');
|
var $child_row = this.$el.find('[id=treerow_' + child_id + '][data-row-parent-id='+ curnode.data('id') +']');
|
||||||
if ($child_row.hasClass('oe_open')) {
|
if ($child_row.hasClass('oe_open')) {
|
||||||
$child_row.toggleClass('oe_open',show);
|
$child_row.toggleClass('oe_open',show);
|
||||||
this.showcontent($child_row, child_id, false);
|
this.showcontent($child_row, child_id, false);
|
||||||
|
|
|
@ -685,7 +685,7 @@
|
||||||
t-foreach="records" t-as="record"
|
t-foreach="records" t-as="record"
|
||||||
t-att-id="'treerow_' + record.id"
|
t-att-id="'treerow_' + record.id"
|
||||||
t-att-data-id="record.id" t-att-data-level="level + 1"
|
t-att-data-id="record.id" t-att-data-level="level + 1"
|
||||||
t-att-data-parent-id="parent_id">
|
t-att-data-row-parent-id="row_parent_id">
|
||||||
<t t-set="children" t-value="record[children_field]"/>
|
<t t-set="children" t-value="record[children_field]"/>
|
||||||
<t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
|
<t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
|
||||||
<t t-set="rank" t-value="'oe-treeview-first'"/>
|
<t t-set="rank" t-value="'oe-treeview-first'"/>
|
||||||
|
|
Loading…
Reference in New Issue