1 function openerp_pos_db(instance, module){
3 /* PosLS is a LocalStorage based implementation of the point of sale database,
4 it performs better for few products, but does not scale beyond 500 products.
6 module.PosLS = instance.web.Class.extend({
7 name: 'openerp_pos_ls', //the prefix of the localstorage data
8 limit: 100, // the maximum number of results returned by a search
9 init: function(options){
10 options = options || {};
11 this.name = options.name || this.name;
12 this.limit = options.limit || this.limit;
14 //cache the data in memory to avoid roundtrips to the localstorage
17 this.category_by_id = {};
18 this.root_category_id = 0;
19 this.category_products = {};
20 this.category_ancestors = {};
21 this.category_childs = {};
22 this.category_parent = {};
24 /* returns the category object from its id */
25 get_category_by_id: function(categ_id){
26 if(categ_id instanceof Array){
28 for(var i = 0, len = categ_id.length; i < len; i++){
29 var cat = this.category_by_id[categ_id[i]];
33 console.error("get_category_by_id: no category has id:",categ_id[i]);
38 return this.category_by_id[categ_id];
41 /* returns a list of the category's child categories ids, or an empty list
42 * if a category has no childs */
43 get_category_childs_ids: function(categ_id){
44 return this.category_childs[categ_id] || [];
46 /* returns a list of all ancestors (parent, grand-parent, etc) categories ids
47 * starting from the root category to the direct parent */
48 get_category_ancestors_ids: function(categ_id){
49 return this.category_ancestors[categ_id] || [];
51 /* returns the parent category's id of a category, or the root_category_id if no parent.
52 * the root category is parent of itself. */
53 get_category_parent_id: function(categ_id){
54 return this.category_parent[categ_id] || this.root_category_id;
56 /* adds categories definitions to the database. categories is a list of categories objects as
57 * returned by the openerp server. Categories must be inserted before the products or the
58 * product/ categories association may (will) not work properly */
59 add_categories: function(categories){
61 if(!this.category_by_id[this.root_category_id]){
62 this.category_by_id[this.root_category_id] = {
63 id : this.root_category_id,
67 for(var i=0, len = categories.length; i < len; i++){
68 this.category_by_id[categories[i].id] = categories[i];
70 for(var i=0, len = categories.length; i < len; i++){
71 var cat = categories[i];
72 var parent_id = cat.parent_id[0] || this.root_category_id;
73 this.category_parent[cat.id] = cat.parent_id[0];
74 if(!this.category_childs[parent_id]){
75 this.category_childs[parent_id] = [];
77 this.category_childs[parent_id].push(cat.id);
79 function make_ancestors(cat_id, ancestors){
80 self.category_ancestors[cat_id] = ancestors;
82 ancestors = ancestors.slice(0);
83 ancestors.push(cat_id);
85 var childs = self.category_childs[cat_id] || [];
86 for(var i=0, len = childs.length; i < len; i++){
87 make_ancestors(childs[i], ancestors);
90 make_ancestors(this.root_category_id, []);
92 /* loads a record store from the database. returns default if nothing is found */
93 load: function(store,deft){
94 if(this.cache[store] !== undefined){
95 return this.cache[store];
97 var data = localStorage[this.name + '_' + store];
98 if(data !== undefined){
99 data = JSON.parse(data);
100 this.cache[store] = data;
106 /* saves a record store to the database */
107 save: function(store,data){
108 localStorage[this.name + '_' + store] = JSON.stringify(data);
109 this.cache[store] = data;
111 add_products: function(products){
112 var stored_products = this.load('products',{});
113 var stored_categories = this.load('categories',{});
115 if(!products instanceof Array){
116 products = [products];
118 for(var i = 0, len = products.length; i < len; i++){
119 var product = products[i];
120 var categ_id = product.pos_categ_id[0];
121 if(!stored_categories[categ_id]){
122 stored_categories[categ_id] = [];
124 stored_categories[categ_id].push(product.id);
125 var ancestors = this.get_category_ancestors_ids(categ_id) || [];
127 for(var j = 0; j < ancestors.length; j++){
128 if(! stored_categories[ancestors[j]]){
129 stored_categories[ancestors[j]] = [];
131 stored_categories[ancestors[j]].push(product.id);
133 stored_products[product.id] = product;
135 this.save('products',stored_products);
136 this.save('categories',stored_categories);
138 /* removes all the data from the database. TODO : being able to selectively remove data */
140 localStorage.removeItem(this.name + '_products');
141 localStorage.removeItem(this.name + '_categories');
143 /* this internal methods returns the count of properties in an object. */
144 _count_props : function(obj){
146 for(var prop in obj){
147 if(obj.hasOwnProperty(prop)){
153 get_product_by_id: function(id){
154 return this.load('products',{})[id];
156 get_product_by_ean13: function(ean13){
157 var products = this.load('products',{});
158 for(var i in products){
159 if( products[i] && products[i].ean13 === ean13){
165 get_product_by_category: function(category_id){
166 var stored_categories = this.load('categories',{});
167 var stored_products = this.load('products',{});
168 var product_ids = stored_categories[category_id];
170 for(var i = 0, len = Math.min(product_ids.length,this.limit); i < len; i++){
171 list.push(stored_products[product_ids[i]]);
175 /* returns as a parameter of the result_callback function a list of products with :
176 * - a category that is or is a child of category_id,
177 * - a field in fields that contains a value that contains the query
178 * If a search is started before the previous has returned, the previous search may be cancelled
179 * (and the corresponding result_callback never called)
181 search_product_in_category: function(category_id, fields, query){
183 var stored_categories = this.load('categories',{});
184 var stored_products = this.load('products',{});
185 var product_ids = stored_categories[category_id];
189 query = query.toString().toLowerCase();
191 if(!(fields instanceof Array)){
194 for(var i = 0, len = product_ids.length; i < len && count < this.limit; i++){
195 var product = stored_products[product_ids[i]];
196 for(var j = 0, jlen = fields.length; j < jlen; j++){
197 var field = product[fields[j]];
198 if(field === null || field === undefined){
201 field = field.toString().toLowerCase();
202 if(field.indexOf(query) != -1){
211 add_order: function(order){
212 var last_id = this.load('last_order_id',0);
213 var orders = this.load('orders',[]);
214 orders.push({id: last_id + 1, data: order});
215 this.save('last_order_id',last_id+1);
216 this.save('orders',orders);
218 remove_order: function(order_id){
219 var orders = this.load('orders',[]);
220 orders = _.filter(orders, function(order){
221 return order.id !== order_id;
223 this.save('orders',orders);
225 get_orders: function(){
226 return this.load('orders',[]);
230 module.LocalStorageDAO = instance.web.Class.extend({
231 add_operation: function(operation) {
233 return $.async_when().pipe(function() {
234 var tmp = self._get('oe_pos_operations', []);
235 var last_id = self._get('oe_pos_operations_sequence', 1);
236 tmp.push({'id': last_id, 'data': operation});
237 self._set('oe_pos_operations', tmp);
238 self._set('oe_pos_operations_sequence', last_id + 1);
241 remove_operation: function(id) {
243 return $.async_when().pipe(function() {
244 var tmp = self._get('oe_pos_operations', []);
245 tmp = _.filter(tmp, function(el) {
248 self._set('oe_pos_operations', tmp);
251 get_operations: function() {
253 return $.async_when().pipe(function() {
254 return self._get('oe_pos_operations', []);
257 _get: function(key, default_) {
258 var txt = localStorage['oe_pos_dao_'+key];
261 return JSON.parse(txt);
263 _set: function(key, value) {
264 localStorage['oe_pos_dao_'+key] = JSON.stringify(value);
266 reset_stored_data: function(){
267 for(key in localStorage){
268 if(key.indexOf('oe_pos_dao_') === 0){
269 delete localStorage[key];
277 window.PosLS = module.PosLS;