[IMP] point_of_sale: new category system

bzr revid: fva@openerp.com-20120529163944-crk8dblg7t6b2ove
This commit is contained in:
Frédéric van der Essen 2012-05-29 18:39:44 +02:00
parent 33c4a6177e
commit a81a9177f1
5 changed files with 111 additions and 238 deletions

View File

@ -31,9 +31,9 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
},
message : function(name,params,callback){
var success_callback = function(result){ console.log('PROXY SUCCESS:'+name+': ',result); }
var error_callback = function(result){ console.log('PROXY ERROR:'+name+': ',result); }
console.log('PROXY: '+name);
var success_callback = function(result){}; //console.log('PROXY SUCCESS:'+name+': ',result); }
var error_callback = function(result){}; // console.log('PROXY ERROR:'+name+': ',result); }
//console.log('PROXY: '+name);
this.connection.rpc('/pos/'+name, params || {}, callback || success_callback, error_callback);
},

View File

@ -61,7 +61,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
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.build_tree = _.bind(this.build_tree, this); // ???
this.session = session;
this.categories = {};
this.root_category = null;
@ -212,7 +212,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
// when all the data has loaded, we compute some stuff, and declare the Pos ready to be used.
$.when(cat_def, prod_def, session_def, tax_def, prod_process_def, this.get_app_data(), this.flush())
.then(function(){
self.build_tree();
//self.build_tree();
self.build_categories();
self.set({'cashRegisters' : new module.CashRegisterCollection(self.get('bank_statements'))});
console.log('cashRegisters:',self.get('cashRegisters'));
@ -335,6 +335,10 @@ 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');
@ -356,6 +360,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
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',
@ -390,9 +395,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
cat.product_set = {}; // [product.id] === true if product is in category
cat.weightable_product_list = [];
cat.weightable_product_set = {};
cat.regular_product_list = []; //not weightable
cat.regular_product_set = {};
cat.progeny = [];
}
this.root_category = root_category;
@ -409,9 +411,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
if(product.weightable){
cat.weightable_product_list.push(product);
cat.weightable_product_set[product.id] = true;
}else{
cat.regular_product_list.push(product);
cat.regular_product_set[product.id] = true;
}
}
}
@ -426,15 +425,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
}
}
// add progeny field to categories, contains all subcategories of a category
function make_progeny(cat){
for(var i = 0; i < cat.childrens.length; i++){
make_progeny(cat.childrens[i]);
cat.progeny.push(cat.childrens[i]);
append(cat.progeny,cat.childrens[i].progeny);
}
}
//add the products of the subcategories to the parent categories
function make_products(cat){
for(var i = 0; i < cat.childrens.length; i++){
@ -442,83 +432,15 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
append(cat.product_list, cat.childrens[i].product_list);
append(cat.weightable_product_list, cat.childrens[i].weightable_product_list);
append(cat.regular_product_list, cat.childrens[i].regular_product_list);
appendSet(cat.product_set, cat.childrens[i].product_set);
appendSet(cat.weightable_product_set, cat.childrens[i].weightable_product_set);
appendSet(cat.regular_product_set, cat.childrens[i].regular_product_set);
}
}
make_ancestors(root_category,[]);
make_progeny(root_category);
make_products(root_category);
},
build_tree: function() {
var c, id, _i, _len, _ref, _ref2;
_ref = this.get('categories');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
c = _ref[_i];
this.categories[c.id] = {
id: c.id,
name: c.name,
children: c.child_id,
parent: c.parent_id[0],
ancestors: [c.id],
subtree: [c.id]
};
}
_ref2 = this.categories;
for (id in _ref2) {
c = _ref2[id];
this.current_category = c;
this.build_ancestors(c.parent);
this.build_subtree(c);
}
this.categories[0] = {
ancestors: [],
children: (function() {
var _j, _len2, _ref3, _results;
_ref3 = this.get('categories');
_results = [];
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
c = _ref3[_j];
if (!(c.parent_id[0] != null)) {
_results.push(c.id);
}
}
return _results;
}).call(this),
subtree: (function() {
var _j, _len2, _ref3, _results;
_ref3 = this.get('categories');
_results = [];
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
c = _ref3[_j];
_results.push(c.id);
}
return _results;
}).call(this)
};
},
build_ancestors: function(parent) {
if (parent != null) {
this.current_category.ancestors.unshift(parent);
return this.build_ancestors(this.categories[parent].parent);
}
},
build_subtree: function(category) {
var c, _i, _len, _ref, _results;
_ref = category.children;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
c = _ref[_i];
this.current_category.subtree.push(c);
_results.push(this.build_subtree(this.categories[c]));
}
return _results;
}
});
module.CashRegister = Backbone.Model.extend({

View File

@ -307,8 +307,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
this.product_list_widget = new module.ProductListWidget(this,{
only_weightable: true,
weight: this.pos.proxy.weighting_read_kg(),
show_scale: true,
});
this.product_list_widget.replace($('.placeholder-ProductListWidget'));
},
@ -322,7 +321,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.pos_widget.action_bar.set_total_visible(true);
this.pos_widget.action_bar.set_help_visible(true,function(){self.pos_widget.screen_selector.show_popup('help');});
this.pos_widget.action_bar.set_logout_visible(false);
this.pos_widget.onscreen_keyboard.connect();
//this.pos_widget.onscreen_keyboard.connect();
this.product_categories_widget.reset_category();
@ -357,7 +356,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.pos_widget.set_cashier_controls_visible(true);
this.pos_widget.action_bar.set_total_visible(true);
this.pos_widget.action_bar.set_help_visible(false);
this.pos_widget.onscreen_keyboard.connect();
//this.pos_widget.onscreen_keyboard.connect();
this.product_categories_widget.reset_category();
this.pos_widget.order_widget.set_numpad_state(this.pos_widget.numpad.state);
this.pos_widget.action_bar.add_new_button(
@ -564,7 +565,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
module.SearchProductScreenWidget = module.ScreenWidget.extend({
template:'SearchProductScreenWidget',
start: function(){
this.product_categories_widget = new module.ProductCategoriesWidget2(this,{});
this.product_categories_widget = new module.ProductCategoriesWidget(this,{});
this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
this.product_list_widget = new module.ProductListWidget(this,{});
@ -583,7 +584,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
self.pos_widget.screen_selector.set_user_mode('client');
});
this.product_categories_widget.reset_category();
this.pos_widget.onscreen_keyboard.connect();
//this.pos_widget.onscreen_keyboard.connect();
this.pos_widget.order_widget.set_numpad_state(this.pos_widget.numpad.state);
this.pos_widget.action_bar.add_new_button(

View File

@ -396,143 +396,131 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
});
module.ProductCategoriesWidget = module.PosBaseWidget.extend({
template: 'ProductCategoriesWidget',
init: function(parent, options){
this._super(parent,options);
this.on_change_category.add_last(_.bind(this.search_and_categories, this));
this.search_and_categories();
},
start: function() {
this.search_and_categories();
},
template:'ProductCategoriesWidget',
renderElement: function() {
var self = this;
var c;
this.$element.empty();
this.$element.html(QWeb.render(this.template, {
breadcrumb: (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = self.ancestors.length; _i < _len; _i++) {
c = self.ancestors[_i];
_results.push(self.pos.categories[c]);
}
return _results;
})(),
categories: (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = self.children.length; _i < _len; _i++) {
c = self.children[_i];
_results.push(self.pos.categories[c]);
}
return _results;
})()
}));
this.$element.find(".oe-pos-categories-list a").click(_.bind(this.change_category, this));
},
reset_category: function(){
this.on_change_category(0);
},
change_category: function(a) {
var id = $(a.target).data("category-id");
this.on_change_category(id);
},
search_and_categories: function(id){
var self = this,
c,
product_list,
allProducts,
allPackages;
id = id || 0;
c = this.pos.categories[id];
this.ancestors = c.ancestors;
this.children = c.children;
this.renderElement();
allProducts = this.pos.get('product_list');
allPackages = this.pos.get('product.packaging');
product_list = this.pos.get('product_list').filter( function(p){
var _ref = p.pos_categ_id[0];
return _.indexOf(c.subtree, _ref) >= 0;
});
this.pos.get('products').reset(product_list);
this.$element.find('.searchbox input').keyup(function(){
var results, search_str;
search_str = $(this).val().toLowerCase();
if(search_str){
results = product_list.filter( function(p){
return p.name.toLowerCase().indexOf(search_str) != -1;
});
self.$element.find('.search-clear').fadeIn();
}else{
results = product_list;
self.$element.find('.search-clear').fadeOut();
}
self.pos.get('products').reset(results);
});
this.$element.find('.search-clear').click(function(){
self.pos.get('products').reset(product_list);
self.$element.find('.searchbox input').val('').focus();
self.$element.find('.search-clear').fadeOut();
});
},
on_change_category: function(id) {},
});
module.ProductCategoriesWidget2 = module.PosBaseWidget.extend({
template: 'ProductCategoriesWidget2',
init: function(parent, options){
this._super(parent,options);
this.onlyWeightable = false;
this.onlyWeightable = options.onlyWeightable || false;
this.category = this.pos.root_category;
this.breadcrumb = [];
this.subcategories = [];
this.set_category();
},
start: function(){
this.search_and_categories();
},
// changes the category. if undefined, sets to root category
set_category : function(category){
if(!category){
this.category = this.pos.root_category;
}else{
this.category = category;
}
this.breadcrumb = [];
for(var i = 1; i < this.category.ancestors.length; i++){
this.breadcrumb.push(this.category.ancestor[i]);
this.breadcrumb.push(this.category.ancestors[i]);
}
if(this.category !== this.pos.root_category){
this.breadcrumb.push(this.category);
}
if(this.onlyWeightable){
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 = this.category.childrens || [];
},
renderElement: function(){
var self = this;
this._super();
this.$element.empty();
this.$element.find(".oe-pos-categories-list a").click(function(event){
var id = $(event.target).data("category-id");
var category = self.pos.categories_by_id[id];
self.set_category(category);
self.renderElement();
self.search_and_categories(category);
});
},
// resets the current category to the root category
reset_category: function(){
this.set_category();
this.renderElement();
this.search_and_categories();
},
on_change_category: function(id){},
search_and_categories: function(id){},
change_category: function(a){
// 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.onlyWeightable){
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];
});
}
// 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
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);
});
self.$element.find('.search-clear').fadeIn();
}else{
results = products;
self.$element.find('.search-clear').fadeOut();
}
self.pos.get('products').reset(results);
});
this.$('.searchbox input').click(function(){
});
//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();
});
},
});
module.ProductListWidget = module.ScreenWidget.extend({
template:'ProductListWidget',
init: function(parent, options) {
var self = this;
this._super(parent,options);
console.log('ProductListWidget:',this);
this.model = options.model;
this.pos.get('products').bind('reset', this.renderElement, this);
this.product_list = [];
this.weight = options.weight;
this.only_weightable = options.only_weightable || false;
this.weight = options.weight || 0;
this.show_scale = options.show_scale || false;
this.next_screen = options.next_screen || false;
this.pos.get('products').bind('reset', function(){
self.renderElement();
});
},
set_weight: function(weight){
for(var i = 0; i < this.product_list.length; i++){
@ -550,10 +538,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.product_list = [];
this.pos.get('products')
.chain()
.filter(function(product){
// if only weightable, only keeps those with a to_weight category, keep all otherwise
return !self.only_weightable || (product.get('pos_category') && product.get('pos_category').to_weight);
})
.map(function(product) {
var product = new module.ProductWidget(self, {
model: product,
@ -604,6 +588,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
connect : function(){
var self = this;
$(this.input_selector).focus(function(){self.show();});
},
@ -913,10 +898,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.order_widget = new module.OrderWidget(this, {});
this.order_widget.replace($('#placeholder-OrderWidget'));
this.onscreen_keyboard = new module.OnscreenKeyboardWidget(this, {
/*this.onscreen_keyboard = new module.OnscreenKeyboardWidget(this, {
'keyboard_model': 'simple'
});
this.onscreen_keyboard.appendTo($(".point-of-sale #content"));
this.onscreen_keyboard.appendTo($(".point-of-sale #content")); */
// -------- Screen Selector ---------

View File

@ -125,41 +125,6 @@
</t>
<t t-name="ProductCategoriesWidget">
<header>
<ol class="breadcrumb">
<li class="oe-pos-categories-list">
<a href="javascript:void(0)">
<img src="/point_of_sale/static/src/img/home.png" class="homeimg" />
</a>
</li>
<t t-foreach="breadcrumb" t-as="category">
<li class="oe-pos-categories-list">
<img src="/point_of_sale/static/src/img/bc-arrow.png" class="bc-arrow" />
<a href="javascript:void(0)" t-att-data-category-id="category.id">
<t t-esc="category.name"/>
</a>
</li>
</t>
</ol>
<div class="searchbox">
<input placeholder="Search Products" />
<img class="search-clear" src="/point_of_sale/static/src/img/search_reset.gif" />
</div>
</header>
<div id="categories">
<ol>
<t t-foreach="categories" t-as="category">
<li class="oe-pos-categories-list">
<a href="javascript:void(0)" t-att-data-category-id="category.id" class="button">
<t t-esc="category.name"/>
</a>
</li>
</t>
</ol>
</div>
</t>
<t t-name="ProductCategoriesWidget2">
<header>
<ol class="breadcrumb">
<li class="oe-pos-categories-list">