[WIP] point_of_sale: much progress on the indexeddb backend
bzr revid: fva@openerp.com-20120809172113-ex3o5vyt4ckv4au6
This commit is contained in:
parent
dc8f543d17
commit
03b79a9832
|
@ -146,6 +146,8 @@ function openerp_pos_db(instance, module){
|
|||
productStore.createIndex('category','category', {unique:false});
|
||||
|
||||
var imageStore = this.db.createObjectStore('images', {keyPath: 'id'});
|
||||
|
||||
var categoryStore = this.db.createObjectStore('categories', {keypath:'name'});
|
||||
},
|
||||
|
||||
_add_data: function(store, data){
|
||||
|
@ -286,6 +288,9 @@ function openerp_pos_db(instance, module){
|
|||
}
|
||||
}
|
||||
},
|
||||
/* the callback function will be called with all products as parameter, by increasing id.
|
||||
* if the callback returns 'break' the iteration will stop
|
||||
*/
|
||||
for_all_products: function(callback){
|
||||
var transaction = this.db.transaction('products');
|
||||
var objectStore = transaction.objectStore('products');
|
||||
|
@ -299,6 +304,29 @@ function openerp_pos_db(instance, module){
|
|||
}
|
||||
};
|
||||
},
|
||||
/* the callback function will be called with all products as parameter by increasing id.
|
||||
* if the callback returns 'break', the iteration will stop
|
||||
* if the callback returns a product object, it will be inserted in the db, possibly
|
||||
* overwriting an existing product. The intended usage is for the callback to return a
|
||||
* modified version version of the product with the same id. Anything else and you're on your own.
|
||||
*/
|
||||
modify_all_products: function(callback){
|
||||
var transaction = this.db.transaction('products','readwrite');
|
||||
var objectStore = transaction.objectStore('products');
|
||||
objectStore.openCursor().onsuccess = function(event){
|
||||
var cursor = event.target.result;
|
||||
if(cursor){
|
||||
var ret = callback(cursor.value);
|
||||
if(ret === undefined || ret === null){
|
||||
cursor.continue();
|
||||
}else if(ret === 'break'){
|
||||
return;
|
||||
}else{
|
||||
objectStore.put(ret);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
window.PosDB = module.PosDB;
|
||||
|
||||
|
@ -310,7 +338,74 @@ function openerp_pos_db(instance, module){
|
|||
this.name = options.name || this.name;
|
||||
this.limit = options.limit || this.limit;
|
||||
this.products = this.name + '_products';
|
||||
this.images = this.name + '_images';
|
||||
this.categories = this.name + '_categories';
|
||||
|
||||
this.category_by_id = {};
|
||||
this.root_category_id = 0;
|
||||
this.category_products = {};
|
||||
this.category_ancestors = {};
|
||||
this.category_childs = {};
|
||||
this.category_parent = {};
|
||||
},
|
||||
get_category_by_id: function(categ_id){
|
||||
if(categ_id instanceof Array){
|
||||
var list = [];
|
||||
for(var i = 0, len = categ_id.length; i < len; i++){
|
||||
var cat = this.category_by_id[categ_id[i]];
|
||||
if(cat){
|
||||
list.push(cat);
|
||||
}else{
|
||||
console.error("get_category_by_id: no category has id:",categ_id[i]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}else{
|
||||
return this.category_by_id[categ_id];
|
||||
}
|
||||
},
|
||||
get_category_childs_ids: function(categ_id){
|
||||
return this.category_childs[categ_id] || [];
|
||||
},
|
||||
get_category_ancestors_ids: function(categ_id){
|
||||
return this.category_ancestors[categ_id] || [];
|
||||
},
|
||||
get_category_parent_id: function(categ_id){
|
||||
return this.category_parent[categ_id] || this.root_category_id;
|
||||
},
|
||||
add_categories: function(categories){
|
||||
var self = this;
|
||||
if(!this.category_by_id[this.root_category_id]){
|
||||
this.category_by_id[this.root_category_id] = {
|
||||
id : this.root_category_id,
|
||||
name : 'Root',
|
||||
};
|
||||
}
|
||||
for(var i=0, len = categories.length; i < len; i++){
|
||||
console.log('putting category : ',categories[i].id, categories[i].name);
|
||||
this.category_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
for(var i=0, len = categories.length; i < len; i++){
|
||||
var cat = categories[i];
|
||||
var parent_id = cat.parent_id[0] || this.root_category_id;
|
||||
console.log('category parent',cat.id, parent_id);
|
||||
this.category_parent[cat.id] = cat.parent_id[0];
|
||||
if(!this.category_childs[parent_id]){
|
||||
this.category_childs[parent_id] = [];
|
||||
}
|
||||
this.category_childs[parent_id].push(cat.id);
|
||||
}
|
||||
function make_ancestors(cat_id, ancestors){
|
||||
self.category_ancestors[cat_id] = ancestors;
|
||||
|
||||
ancestors = ancestors.slice(0);
|
||||
ancestors.push(cat_id);
|
||||
|
||||
var childs = self.category_childs[cat_id] || [];
|
||||
for(var i=0, len = childs.length; i < len; i++){
|
||||
make_ancestors(childs[i], ancestors);
|
||||
}
|
||||
}
|
||||
make_ancestors(this.root_category_id, []);
|
||||
},
|
||||
_get_products: function(){
|
||||
var products = localStorage[this.products];
|
||||
|
@ -323,39 +418,51 @@ function openerp_pos_db(instance, module){
|
|||
_set_products: function(products){
|
||||
localStorage[this.products] = JSON.stringify(products);
|
||||
},
|
||||
_get_images: function(){
|
||||
var images = localStorage[this.images];
|
||||
if(images){
|
||||
return JSON.parse(images) || {};
|
||||
_get_categories: function(){
|
||||
var categories = localStorage[this.categories];
|
||||
if(categories){
|
||||
return JSON.parse(categories) || {};
|
||||
}else{
|
||||
return {};
|
||||
}
|
||||
},
|
||||
_set_images: function(images){
|
||||
localStorage[this.images] = JSON.stringify(images);
|
||||
_set_categories: function(categories){
|
||||
localStorage[this.categories] = JSON.stringify(categories);
|
||||
},
|
||||
add_product: function(products){
|
||||
var stored_images = this._get_images();
|
||||
var stored_products = this._get_products();
|
||||
var stored_categories = this._get_categories();
|
||||
|
||||
if(!products instanceof Array){
|
||||
products = [products];
|
||||
}
|
||||
for(var i = 0, len = products.length; i < len; i++){
|
||||
var product = products[i];
|
||||
if(product.product_image_small){
|
||||
product = _.clone(product);
|
||||
stored_images[product.id] = product.product_image_small;
|
||||
delete product['product_image_small'];
|
||||
var categ_id = product.pos_categ_id[0];
|
||||
if(!stored_categories[categ_id]){
|
||||
stored_categories[categ_id] = [];
|
||||
}
|
||||
stored_categories[categ_id].push(product.id);
|
||||
var ancestors = this.get_category_ancestors_ids(categ_id) || [];
|
||||
console.log('ancestors:',ancestors);
|
||||
|
||||
for(var j = 0; j < ancestors.length; j++){
|
||||
if(! stored_categories[ancestors[j]]){
|
||||
stored_categories[ancestors[j]] = [];
|
||||
}
|
||||
stored_categories[ancestors[j]].push(product.id);
|
||||
}
|
||||
stored_products[product.id] = product;
|
||||
}
|
||||
this._set_images(stored_images);
|
||||
this._set_products(stored_products);
|
||||
this._set_categories(stored_categories);
|
||||
},
|
||||
clear: function(done_callback){
|
||||
localStorage.removeItem(this.products);
|
||||
localStorage.removeItem(this.images);
|
||||
localStorage.removeItem(this.categories);
|
||||
if(done_callback){
|
||||
done_callback();
|
||||
}
|
||||
},
|
||||
_count_props : function(obj){
|
||||
if(obj.__count__){
|
||||
|
@ -373,9 +480,6 @@ function openerp_pos_db(instance, module){
|
|||
get_product_count: function(result_callback){
|
||||
result_callback(this._count_props(this._get_products()));
|
||||
},
|
||||
get_image_count: function(result_callback){
|
||||
result_callback(this._count_props(this._get_images()));
|
||||
},
|
||||
get_product_by_id: function(id, result_callback){
|
||||
var products = this._get_products();
|
||||
result_callback( products[id] );
|
||||
|
@ -400,66 +504,55 @@ function openerp_pos_db(instance, module){
|
|||
}
|
||||
result_callback(undefined);
|
||||
},
|
||||
get_product_by_category: function(category, result_callback){
|
||||
var products = this._get_products();
|
||||
get_product_by_category: function(category_id, result_callback){
|
||||
var stored_categories = this._get_categories();
|
||||
var stored_products = this._get_products();
|
||||
var product_ids = stored_categories[category_id];
|
||||
var list = [];
|
||||
for(var i in products){
|
||||
if( products[i] && products[i].category === category){
|
||||
list.push(products[i]);
|
||||
}
|
||||
for(var i = 0, len = product_ids.length; i < len; i++){
|
||||
list.push(stored_products[product_ids[i]]);
|
||||
}
|
||||
result_callback(list);
|
||||
},
|
||||
get_product_image: function(product, result_callback){
|
||||
var images = this._get_images();
|
||||
result_callback(images[product.id]);
|
||||
},
|
||||
search_product: function(fields, query, result_callback){
|
||||
var products = this._get_products();
|
||||
var list = [];
|
||||
if(typeof query !== 'string'){
|
||||
if(query.toString){
|
||||
query = query.toString();
|
||||
}else{
|
||||
throw new Error('search_product: the query must be a string or must be convertible to string');
|
||||
search_product_in_category: function(category_id, fields, query, result_callback){
|
||||
var self = this;
|
||||
this.get_product_by_category(category_id, function(products){
|
||||
var list = [];
|
||||
|
||||
query = query.toString().toLowerCase();
|
||||
|
||||
if(!(fields instanceof Array)){
|
||||
fields = [fields];
|
||||
}
|
||||
}
|
||||
|
||||
query = query.toLowerCase();
|
||||
|
||||
if(!(fields instanceof Array)){
|
||||
fields = [fields];
|
||||
}
|
||||
for(var i in products){
|
||||
for(var j = 0, jlen = fields.length; j < jlen; j++){
|
||||
var field = products[i][fields[j]];
|
||||
if(field === null || field === undefined){
|
||||
continue;
|
||||
}
|
||||
if(typeof field !== 'string'){
|
||||
if(field.toString){
|
||||
field = field.toString();
|
||||
}else{
|
||||
for(var i in products){
|
||||
for(var j = 0, jlen = fields.length; j < jlen; j++){
|
||||
var field = products[i][fields[j]];
|
||||
if(field === null || field === undefined){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(field.toLowerCase().indexOf(query) != -1){
|
||||
list.push(products[i]);
|
||||
break;
|
||||
if(typeof field !== 'string'){
|
||||
if(field.toString){
|
||||
field = field.toString();
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(field.toLowerCase().indexOf(query) != -1){
|
||||
list.push(products[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result_callback(list);
|
||||
result_callback(list);
|
||||
});
|
||||
},
|
||||
for_all_products: function(callback){
|
||||
var products = this._get_products();
|
||||
for(var i in products){
|
||||
var ret = callback(products[i]);
|
||||
if(ret === 'break'){
|
||||
break;
|
||||
}
|
||||
}
|
||||
add_order: function(order,done_callback){
|
||||
},
|
||||
remove_order: function(order_id, done_callback){
|
||||
},
|
||||
get_orders: function(result_callback){
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
window.PosLS = module.PosLS;
|
||||
|
|
|
@ -277,41 +277,37 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
this.action_callback[action] = undefined;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// returns the checksum of the ean, or -1 if the ean has not the correct length, ean must be a string
|
||||
ean_checksum: function(ean){
|
||||
var code = ean.split('');
|
||||
if(code.length !== 13){
|
||||
return -1;
|
||||
}
|
||||
var oddsum = 0, evensum = 0, total = 0;
|
||||
code = code.reverse().splice(1);
|
||||
for(var i = 0; i < code.length; i++){
|
||||
if(i % 2 == 0){
|
||||
oddsum += Number(code[i]);
|
||||
}else{
|
||||
evensum += Number(code[i]);
|
||||
}
|
||||
}
|
||||
total = oddsum * 3 + evensum;
|
||||
return Number((10 - total % 10) % 10);
|
||||
},
|
||||
// returns true if the ean is a valid EAN codebar number by checking the control digit.
|
||||
// ean must be a string
|
||||
check_ean: function(ean){
|
||||
var code = ean.split('');
|
||||
for(var i = 0; i < code.length; i++){
|
||||
code[i] = Number(code[i]);
|
||||
return ean_checksum(ean) === Number(ean[ean.length-1]);
|
||||
},
|
||||
// returns a valid zero padded ean13 from an ean prefix. the ean prefix must be a string.
|
||||
sanitize_ean:function(ean){
|
||||
ean = ean.substr(0,13);
|
||||
|
||||
for(var n = 0, count = (13 - ean.length); n < count; n++){
|
||||
ean = ean + '0';
|
||||
}
|
||||
var st1 = code.slice();
|
||||
var st2 = st1.slice(0,st1.length-1).reverse();
|
||||
// some EAN13 barcodes have a length of 12, as they start by 0
|
||||
while (st2.length < 12) {
|
||||
st2.push(0);
|
||||
}
|
||||
var countSt3 = 1;
|
||||
var st3 = 0;
|
||||
$.each(st2, function() {
|
||||
if (countSt3%2 === 1) {
|
||||
st3 += this;
|
||||
}
|
||||
countSt3 ++;
|
||||
});
|
||||
st3 *= 3;
|
||||
var st4 = 0;
|
||||
var countSt4 = 1;
|
||||
$.each(st2, function() {
|
||||
if (countSt4%2 === 0) {
|
||||
st4 += this;
|
||||
}
|
||||
countSt4 ++;
|
||||
});
|
||||
var st5 = st3 + st4;
|
||||
var cd = (10 - (st5%10)) % 10;
|
||||
return code[code.length-1] === cd;
|
||||
return ean.substr(0,12) + this.ean_checksum(ean);
|
||||
},
|
||||
|
||||
// attempts to interpret an ean (string encoding an ean)
|
||||
|
@ -334,6 +330,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
type:'unknown', //
|
||||
prefix:'',
|
||||
ean:ean,
|
||||
base_ean: ean,
|
||||
id:'',
|
||||
value: 0,
|
||||
unit: 'none',
|
||||
|
@ -355,18 +352,22 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
parse_result.type = 'error';
|
||||
} else if( match_prefix(this.price_prefix_set,'price')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = 'euro';
|
||||
} else if( match_prefix(this.weight_prefix_set,'weight')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.value = Number(ean.substring(7,12))/1000.0;
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.unit = 'Kg';
|
||||
} else if( match_prefix(this.client_prefix_set,'client')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.unit = 'Kg';
|
||||
} else if( match_prefix(this.cashier_prefix_set,'cashier')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
} else if( match_prefix(this.discount_prefix_set,'discount')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = '%';
|
||||
} else {
|
||||
|
|
|
@ -64,17 +64,16 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
initialize: function(session, attributes) {
|
||||
Backbone.Model.prototype.initialize.call(this, attributes);
|
||||
var self = this;
|
||||
this.session = session;
|
||||
this.dao = new module.LocalStorageDAO(); // used to store the order's data on the Hard Drive
|
||||
this.ready = $.Deferred(); // used to notify the GUI that the PosModel has loaded all resources
|
||||
this.flush_mutex = new $.Mutex(); // used to make sure the orders are sent to the server once at time
|
||||
//this.build_tree = _.bind(this.build_tree, this); // ???
|
||||
this.session = session;
|
||||
this.categories = {};
|
||||
this.root_category = null;
|
||||
this.weightable_categories = []; // a flat list of all categories that directly contain weightable products
|
||||
|
||||
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.db = new module.PosLS(); // a database used to store the products and product images
|
||||
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
||||
this.db = new module.PosLS(); // a database used to store the products and categories
|
||||
|
||||
window.db = this.db;
|
||||
|
||||
// pos settings
|
||||
this.use_scale = false;
|
||||
|
@ -267,30 +266,14 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
return session_data_def;
|
||||
});
|
||||
|
||||
// associate the products with their categories
|
||||
var prod_process_def = $.when(cat_def, session_def)
|
||||
.pipe(function(){
|
||||
var product_list = self.get('product_list');
|
||||
var categories = self.get('categories');
|
||||
var cat_by_id = {};
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
cat_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
//set the parent in the category
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
categories[i].parent_category = cat_by_id[categories[i].parent_id[0]];
|
||||
}
|
||||
for(var i = 0; i < product_list.length; i++){
|
||||
product_list[i].pos_category = cat_by_id[product_list[i].pos_categ_id[0]];
|
||||
}
|
||||
});
|
||||
|
||||
// when all the data has loaded, we compute some stuff, and declare the Pos ready to be used.
|
||||
$.when(pack_def, cat_def, user_def, users_def, uom_def, session_def, tax_def, prod_process_def, user_def, this.flush())
|
||||
$.when(pack_def, cat_def, user_def, users_def, uom_def, session_def, tax_def, user_def, this.flush())
|
||||
.then(function(){
|
||||
self.build_categories();
|
||||
self.db.clear();
|
||||
self.db.add_categories(self.get('categories'));
|
||||
self.db.add_product(self.get('product_list'));
|
||||
self.set({'cashRegisters' : new module.CashRegisterCollection(self.get('bank_statements'))});
|
||||
//self.log_loaded_data(); //Uncomment if you want to log the data to the console for easier debugging
|
||||
self.log_loaded_data(); //Uncomment if you want to log the data to the console for easier debugging
|
||||
self.ready.resolve();
|
||||
},function(){
|
||||
//we failed to load some backend data, or the backend was badly configured.
|
||||
|
@ -325,7 +308,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// order and a valid selected order
|
||||
on_removed_order: function(removed_order){
|
||||
if( this.get('orders').isEmpty()){
|
||||
this.add_and_select_order(new module.Order({ pos: this }));
|
||||
this.add_new_order();
|
||||
}
|
||||
if( this.get('selectedOrder') === removed_order){
|
||||
this.set({ selectedOrder: this.get('orders').last() });
|
||||
|
@ -340,13 +323,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
});
|
||||
},
|
||||
|
||||
add_and_select_order: function(newOrder) {
|
||||
(this.get('orders')).add(newOrder);
|
||||
return this.set({
|
||||
selectedOrder: newOrder
|
||||
});
|
||||
//creates a new empty order and sets it as the current order
|
||||
add_new_order: function(){
|
||||
var order = new module.Order({pos:this});
|
||||
this.get('orders').add(order);
|
||||
this.set('selectedOrder', order);
|
||||
},
|
||||
|
||||
|
||||
// attemps to send all pending orders ( stored in the DAO ) to the server.
|
||||
// it will do it one by one, and remove the successfully sent ones from the DAO once
|
||||
// it has been confirmed that they have been received.
|
||||
|
@ -390,119 +373,25 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
});
|
||||
},
|
||||
|
||||
// this adds several properties to the categories in order to make it easier to diplay them
|
||||
// fields added include the list of product relevant to each category, list of child categories,
|
||||
// list of ancestors, etc.
|
||||
build_categories : function(){
|
||||
var categories = this.get('categories');
|
||||
var products = this.get('product_list');
|
||||
|
||||
//append the content of array2 into array1
|
||||
function append(array1, array2){
|
||||
for(var i = 0, len = array2.length; i < len; i++){
|
||||
array1.push(array2[i]);
|
||||
scan_product: function(parsed_ean){
|
||||
var self = this;
|
||||
var def = new $.Deferred();
|
||||
this.db.get_product_by_ean13(parsed_ean.base_ean, function(product){
|
||||
var selectedOrder = this.get('selectedOrder');
|
||||
if(!product){
|
||||
def.reject('product-not-found: '+parsed_ean.base_ean);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function appendSet(set1, set2){
|
||||
for(key in set2){
|
||||
set1[key] = set2[key];
|
||||
if(parsed_ean.type === 'price'){
|
||||
selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value});
|
||||
}else if(parsed_ean.type === 'weight'){
|
||||
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false});
|
||||
}else{
|
||||
selectedOrder.addProduct(new module.Product(product));
|
||||
}
|
||||
}
|
||||
|
||||
var categories_by_id = {};
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
categories_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
this.categories_by_id = categories_by_id;
|
||||
|
||||
var root_category = {
|
||||
name : 'Root',
|
||||
id : 0,
|
||||
parent : null,
|
||||
childrens : [],
|
||||
};
|
||||
|
||||
// add parent and childrens field to categories, find root_categories
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
var cat = categories[i];
|
||||
|
||||
cat.parent = categories_by_id[cat.parent_id[0]];
|
||||
if(!cat.parent){
|
||||
root_category.childrens.push(cat);
|
||||
cat.parent = root_category;
|
||||
}
|
||||
|
||||
cat.childrens = [];
|
||||
for(var j = 0; j < cat.child_id.length; j++){
|
||||
cat.childrens.push(categories_by_id[ cat.child_id[j] ]);
|
||||
}
|
||||
}
|
||||
|
||||
categories.push(root_category);
|
||||
|
||||
// set some default fields for next steps
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
var cat = categories[i];
|
||||
|
||||
cat.product_list = []; //list of all products in the category
|
||||
cat.product_set = {}; // [product.id] === true if product is in category
|
||||
cat.weightable_product_list = [];
|
||||
cat.weightable_product_set = {};
|
||||
cat.weightable = false; //true if directly contains weightable products
|
||||
}
|
||||
|
||||
this.root_category = root_category;
|
||||
|
||||
//we add the products to the categories.
|
||||
for(var i = 0, len = products.length; i < len; i++){
|
||||
var product = products[i];
|
||||
var cat = categories_by_id[product.pos_categ_id[0]];
|
||||
if(cat){
|
||||
cat.product_list.push(product);
|
||||
cat.product_set[product.id] = true;
|
||||
if(product.to_weight){
|
||||
cat.weightable_product_list.push(product);
|
||||
cat.weightable_product_set[product.id] = true;
|
||||
cat.weightable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we build a flat list of all categories that directly contains weightable products
|
||||
this.weightable_categories = [];
|
||||
for(var i = 0, len = categories.length; i < len; i++){
|
||||
var cat = categories[i];
|
||||
if(cat.weightable){
|
||||
this.weightable_categories.push(cat);
|
||||
}
|
||||
}
|
||||
|
||||
// add ancestor field to categories, contains the list of parents of parents, from root to parent
|
||||
function make_ancestors(cat, ancestors){
|
||||
cat.ancestors = ancestors.slice(0);
|
||||
ancestors.push(cat);
|
||||
|
||||
for(var i = 0; i < cat.childrens.length; i++){
|
||||
make_ancestors(cat.childrens[i], ancestors.slice(0));
|
||||
}
|
||||
}
|
||||
|
||||
//add the products of the subcategories to the parent categories
|
||||
function make_products(cat){
|
||||
for(var i = 0; i < cat.childrens.length; i++){
|
||||
make_products(cat.childrens[i]);
|
||||
|
||||
append(cat.product_list, cat.childrens[i].product_list);
|
||||
append(cat.weightable_product_list, cat.childrens[i].weightable_product_list);
|
||||
|
||||
appendSet(cat.product_set, cat.childrens[i].product_set);
|
||||
appendSet(cat.weightable_product_set, cat.childrens[i].weightable_product_set);
|
||||
}
|
||||
}
|
||||
|
||||
make_ancestors(root_category,[]);
|
||||
make_products(root_category);
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -159,17 +159,20 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
// it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if
|
||||
// there's an error.
|
||||
barcode_product_action: function(ean){
|
||||
if(this.pos_widget.scan_product(ean)){
|
||||
this.pos.proxy.scan_item_success(ean);
|
||||
if(this.barcode_product_screen){
|
||||
this.pos_widget.screen_selector.set_current_screen(this.barcode_product_screen);
|
||||
}
|
||||
}else{
|
||||
this.pos.proxy.scan_item_error_unrecognized(ean);
|
||||
if(this.barcode_product_error_popup && this.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
|
||||
this.pos_widget.screen_selector.show_popup(this.barcode_product_error_popup);
|
||||
}
|
||||
}
|
||||
var self = this;
|
||||
this.pos_widget.scan_product(ean)
|
||||
.done(function(){
|
||||
self.pos.proxy.scan_item_success(ean);
|
||||
if(self.barcode_product_screen){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
|
||||
}
|
||||
})
|
||||
.fail(function(){
|
||||
self.pos.proxy.scan_item_error_unrecognized(ean);
|
||||
if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
|
||||
self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// what happens when a cashier id barcode is scanned.
|
||||
|
|
|
@ -396,29 +396,21 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
// changes the category. if undefined, sets to root category
|
||||
set_category : function(category){
|
||||
var db = this.pos.db;
|
||||
if(!category){
|
||||
this.category = this.pos.root_category;
|
||||
this.category = db.get_category_by_id(db.root_category_id);
|
||||
}else{
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
this.breadcrumb = [];
|
||||
for(var i = 1; i < this.category.ancestors.length; i++){
|
||||
this.breadcrumb.push(this.category.ancestors[i]);
|
||||
var ancestors_ids = db.get_category_ancestors_ids(this.category.id);
|
||||
for(var i = 1; i < ancestors_ids.length; i++){
|
||||
this.breadcrumb.push(db.get_category_by_id(ancestors_ids[i]));
|
||||
}
|
||||
if(this.category !== this.pos.root_category){
|
||||
if(this.category.id !== db.root_category_id){
|
||||
this.breadcrumb.push(this.category);
|
||||
}
|
||||
if(this.product_type === 'weightable'){
|
||||
this.subcategories = [];
|
||||
for(var i = 0; i < this.category.childrens.length; i++){
|
||||
if(this.category.childrens[i].weightable_product_list.length > 0){
|
||||
this.subcategories.push( this.category.childrens[i]);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.subcategories = this.category.childrens || [];
|
||||
}
|
||||
this.subcategories = db.get_category_by_id(db.get_category_childs_ids(this.category.id));
|
||||
},
|
||||
|
||||
renderElement: function(){
|
||||
|
@ -443,7 +435,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
$(button).appendTo(this.$('.category-list')).click(function(event){
|
||||
var id = category.id;
|
||||
var cat = self.pos.categories_by_id[id];
|
||||
var cat = self.pos.db.get_category_by_id(id);
|
||||
self.set_category(cat);
|
||||
self.renderElement();
|
||||
self.search_and_categories(cat);
|
||||
|
@ -452,7 +444,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
// breadcrumb click actions
|
||||
this.$(".oe-pos-categories-list a").click(function(event){
|
||||
var id = $(event.target).data("category-id");
|
||||
var category = self.pos.categories_by_id[id];
|
||||
var category = self.pos.db.get_category_by_id(id);
|
||||
self.set_category(category);
|
||||
self.renderElement();
|
||||
self.search_and_categories(category);
|
||||
|
@ -475,50 +467,39 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
// filters the products, and sets up the search callbacks
|
||||
search_and_categories: function(category){
|
||||
var self = this;
|
||||
|
||||
var all_products = this.pos.get('product_list');
|
||||
var all_packages = this.pos.get('product.packaging');
|
||||
|
||||
// find all products belonging to the current category
|
||||
var products = [];
|
||||
if(this.product_type === 'weightable'){
|
||||
products = all_products.filter( function(product){
|
||||
return self.category.weightable_product_set[product.id];
|
||||
});
|
||||
}else{
|
||||
products = all_products.filter( function(product){
|
||||
return self.category.product_set[product.id];
|
||||
});
|
||||
}
|
||||
this.pos.db.get_product_by_category(this.category.id, function(products){
|
||||
// product lists watch for reset events on 'products' to re-render.
|
||||
// FIXME that means all productlist widget re-render... even the hidden ones !
|
||||
self.pos.get('products').reset(products);
|
||||
});
|
||||
|
||||
// product lists watch for reset events on 'products' to re-render.
|
||||
// FIXME that means all productlist widget re-render... even the hidden ones !
|
||||
this.pos.get('products').reset(products);
|
||||
|
||||
// find all the products whose name match the query in the searchbox
|
||||
// filter the products according to the search string
|
||||
this.$('.searchbox input').keyup(function(){
|
||||
var results, search_str;
|
||||
search_str = $(this).val().toLowerCase();
|
||||
if(search_str){
|
||||
results = products.filter( function(p){
|
||||
return p.name.toLowerCase().indexOf(search_str) != -1 ||
|
||||
(p.ean13 && p.ean13.indexOf(search_str) != -1);
|
||||
query = $(this).val().toLowerCase();
|
||||
if(query){
|
||||
self.pos.db.search_product_in_category(self.category.id, ['name','ean13'], query, function(products){
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.search-clear').fadeIn();
|
||||
});
|
||||
self.$element.find('.search-clear').fadeIn();
|
||||
}else{
|
||||
results = products;
|
||||
self.$element.find('.search-clear').fadeOut();
|
||||
self.pos.db.get_product_by_category(self.category.id, function(products){
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.search-clear').fadeOut();
|
||||
});
|
||||
}
|
||||
self.pos.get('products').reset(results);
|
||||
});
|
||||
this.$('.searchbox input').click(function(){
|
||||
});
|
||||
|
||||
this.$('.searchbox input').click(function(){}); //Why ???
|
||||
|
||||
//reset the search when clicking on reset
|
||||
this.$('.search-clear').click(function(){
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.searchbox input').val('').focus();
|
||||
self.$('.search-clear').fadeOut();
|
||||
self.pos.db.get_product_by_category(self.category.id, function(products){
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.searchbox input').val('').focus();
|
||||
self.$('.search-clear').fadeOut();
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -693,7 +674,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.build_currency_template();
|
||||
self.renderElement();
|
||||
|
||||
self.$('.neworder-button').click(_.bind(self.create_new_order, self));
|
||||
self.$('.neworder-button').click(function(){
|
||||
self.pos.add_new_order();
|
||||
});
|
||||
|
||||
//when a new order is created, add an order button widget
|
||||
self.pos.get('orders').bind('add', function(new_order){
|
||||
|
@ -721,7 +704,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.screen_selector.show_popup('error', 'Sorry, we could not find any PoS Configuration for this session');
|
||||
}
|
||||
|
||||
self.$('.loader').animate({opacity:0},3000,'swing',function(){self.$('.loader').hide();});
|
||||
self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();});
|
||||
self.$('.loader img').hide();
|
||||
|
||||
if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
|
||||
|
@ -851,51 +834,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
},
|
||||
|
||||
//FIXME this method is probably not at the right place ...
|
||||
scan_product: function(parsed_ean){
|
||||
var selectedOrder = this.pos.get('selectedOrder');
|
||||
var scannedProductModel = this.get_product_by_ean(parsed_ean);
|
||||
if (!scannedProductModel){
|
||||
return false;
|
||||
} else {
|
||||
if(parsed_ean.type === 'price'){
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel), { price:parsed_ean.value});
|
||||
}else if(parsed_ean.type === 'weight'){
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel), { quantity:parsed_ean.value, merge:false});
|
||||
}else{
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
get_product_by_ean: function(parsed_ean) {
|
||||
var allProducts = this.pos.get('product_list');
|
||||
var allPackages = this.pos.get('product.packaging');
|
||||
var scannedProductModel = undefined;
|
||||
|
||||
if (parsed_ean.type === 'price' || parsed_ean.type === 'weight') {
|
||||
var itemCode = parsed_ean.id;
|
||||
var scannedPackaging = _.detect(allPackages, function(pack) {
|
||||
return pack.ean && pack.ean.substring(0,7) === itemCode;
|
||||
});
|
||||
if (scannedPackaging) {
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];});
|
||||
}else{
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 && (pc.ean13.substring(0,7) === parsed_ean.id);});
|
||||
}
|
||||
} else if(parsed_ean.type === 'unit'){
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === parsed_ean.ean;}); //TODO DOES NOT SCALE
|
||||
}
|
||||
return scannedProductModel;
|
||||
},
|
||||
// creates a new order, and add it to the list of orders.
|
||||
create_new_order: function() {
|
||||
var new_order;
|
||||
new_order = new module.Order({ pos: this.pos });
|
||||
this.pos.get('orders').add(new_order);
|
||||
this.pos.set({ selectedOrder: new_order });
|
||||
},
|
||||
changed_pending_operations: function () {
|
||||
var self = this;
|
||||
this.synch_notification.on_change_nbr_pending(self.pos.get('nbr_pending_operations').length);
|
||||
|
|
Loading…
Reference in New Issue