From c8b486a7381012c223fbdb296db90770db8ab5d0 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Wed, 10 Dec 2014 00:22:36 +0100 Subject: [PATCH 01/27] [ADD] 'pos_product_template' --- pos_product_template/__init__.py | 21 + pos_product_template/__openerp__.py | 67 +++ pos_product_template/demo/product_product.yml | 36 ++ pos_product_template/demo/res_groups.yml | 25 + pos_product_template/static/src/css/ppt.css | 166 +++++ pos_product_template/static/src/img/icon.png | Bin 0 -> 4290 bytes pos_product_template/static/src/js/ppt.js | 565 ++++++++++++++++++ pos_product_template/static/src/xml/ppt.xml | 130 ++++ pos_product_template/view/view.xml | 37 ++ 9 files changed, 1047 insertions(+) create mode 100644 pos_product_template/__init__.py create mode 100644 pos_product_template/__openerp__.py create mode 100644 pos_product_template/demo/product_product.yml create mode 100644 pos_product_template/demo/res_groups.yml create mode 100644 pos_product_template/static/src/css/ppt.css create mode 100644 pos_product_template/static/src/img/icon.png create mode 100644 pos_product_template/static/src/js/ppt.js create mode 100644 pos_product_template/static/src/xml/ppt.xml create mode 100644 pos_product_template/view/view.xml diff --git a/pos_product_template/__init__.py b/pos_product_template/__init__.py new file mode 100644 index 00000000..6624b810 --- /dev/null +++ b/pos_product_template/__init__.py @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Point Of Sale - Product Template module for Odoo +# Copyright (C) 2014-Today Akretion (http://www.akretion.com) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/pos_product_template/__openerp__.py b/pos_product_template/__openerp__.py new file mode 100644 index 00000000..b35eaf1b --- /dev/null +++ b/pos_product_template/__openerp__.py @@ -0,0 +1,67 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Point Of Sale - Product Template module for Odoo +# Copyright (C) 2014-Today Akretion (http://www.akretion.com) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + 'name': 'Point Of Sale - Product Template', + 'summary': 'Manage Product Template in Front End Point Of Sale', + 'version': '0.1', + 'category': 'Point Of Sale', + 'description': """ +Manage Product Template in Front End Point Of Sale +================================================== + +Functionality: +-------------- + * + +Possible improvements and fix: +------------------------------ + * Display product template name in ProductList; + * Display attributes; + * Improve Template display; + +NON Covered features: +--------------------- + * + +Copyright, Authors and Licence: +------------------------------- + * Copyright: 2014-Today, Akretion; + * Author: + * Sylvain LE GAL (https://twitter.com/legalsylvain); + * Licence: AGPL-3 (http://www.gnu.org/licenses/);""", + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'license': 'AGPL-3', + 'depends': [ + 'point_of_sale', + ], + 'data': [ + 'view/view.xml', + ], + 'qweb': [ + 'static/src/xml/ppt.xml', + ], + 'demo': [ + 'demo/product_product.yml', + 'demo/res_groups.yml', + ], +} diff --git a/pos_product_template/demo/product_product.yml b/pos_product_template/demo/product_product.yml new file mode 100644 index 00000000..3c2e97b8 --- /dev/null +++ b/pos_product_template/demo/product_product.yml @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Point Of Sale - Product Template module for Odoo +# Copyright (C) 2014-Today Akretion (http://www.akretion.com) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +- !record {model: product.product, id: product.product_product_4}: + available_in_pos: True + +- !record {model: product.product, id: product.product_product_4b}: + available_in_pos: True + +- !record {model: product.product, id: product.product_product_4c}: + available_in_pos: True + +- !record {model: product.product, id: product.product_product_11}: + available_in_pos: True + +- !record {model: product.product, id: product.product_product_11b}: + available_in_pos: True diff --git a/pos_product_template/demo/res_groups.yml b/pos_product_template/demo/res_groups.yml new file mode 100644 index 00000000..972797a8 --- /dev/null +++ b/pos_product_template/demo/res_groups.yml @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Point Of Sale - Product Template module for Odoo +# Copyright (C) 2014-Today Akretion (http://www.akretion.com) +# @author Sylvain LE GAL (https://twitter.com/legalsylvain) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +- !record {model: res.groups, id: base.group_no_one}: + users: + - base.user_root diff --git a/pos_product_template/static/src/css/ppt.css b/pos_product_template/static/src/css/ppt.css new file mode 100644 index 00000000..fcea88dd --- /dev/null +++ b/pos_product_template/static/src/css/ppt.css @@ -0,0 +1,166 @@ +/****************************************************************************** + Point Of Sale - Product Template module for Odoo + Copyright (C) 2014-Today Akretion (http://www.akretion.com) + @author Sylvain LE GAL (https://twitter.com/legalsylvain) + + Some part of code from Odoo Project, + Copyright (C) 2004-Today Odoo SA. (). + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +******************************************************************************/ + +/* ********* Variant Selector PopUp ************************************** */ +.pos .modal-dialog .popup-select-variant{ + margin-left:0; + margin-top:0; + left:5%; + width: 90%; + top:5%; + height:85%; +} + +.pos .modal-dialog .popup-select-variant .variant-title{ + height: 8%; +} + +.pos .modal-dialog .popup-select-variant .variant-title #variant-popup-cancel{ + margin: -10px 3px 3px 3px; +} + +.pos .modal-dialog .popup-select-variant .container-attribute-list{ + width:100%; + height:30%; /*FIXME */ + overflow: hidden; + overflow-y: auto; + border-bottom: 1px dashed #444; + -webkit-overflow-scrolling: touch; +} + +.pos .modal-dialog .popup-select-variant .container-variant-list{ + width:100%; + height:60%; /*FIXME */ + overflow: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} + +.pos .variant-list { + padding: 10px; + text-align: left; + -webkit-transform: translate3d(0,0,0); +} + +/* ********* Attribut Display ******************************************** */ +.pos .attribute { + position:relative; + width: 100%; + height:50px; + vertical-align: top; + display: inline-block; +} + +.pos .attribute .attribute-name{ + float: left; + width: 20%; +} + +.pos .attribute .value-list-container{ + width:78%; + float: left; +} +.pos .attribute .selected{ + background-color: white; +} + +.pos .attribute .attribute-value { + float: left; + width: 150px; +} + +/* ********* Variant Display ********************************************* */ +/* This part is a copy past from Odoo Project, with some values changed */ +.pos .variant { + position:relative; + vertical-align: top; + display: inline-block; + line-height: 100px; + font-size: 11px; + margin: 5px !important; + width: 240px; + height:60px; + background:#fff; + border: 1px solid #e2e2e2; + border-radius: 3px; + border-bottom-width: 3px; + overflow: hidden; + cursor: pointer; +} + +.pos .variant .variant-header { + position: relative; + width: 240px; + height: 30px; + background: white; + text-align: center; +} + +.pos .variant .price-tag { + position: absolute; + top: 2px; + right: 2px; + vertical-align: top; + color: white; + line-height: 13px; + background: #7f82ac; + padding: 2px 5px; + border-radius: 2px; +} + +.pos .variant .variant-name { + font-weight: normal; + position: absolute; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + bottom:0; + top:auto; + line-height: 14px; + width:100%; + overflow: hidden; + text-overflow: ellipsis; + background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + /* troublesome in latest webkit + background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + */ + /*background:#FFF;*/ + padding: 3px; + padding-top:15px; +} + +/*.pos .variant-list-scroller{*/ +/* -webkit-box-sizing: border-box;*/ +/* -moz-box-sizing: border-box;*/ +/* -ms-box-sizing: border-box;*/ +/* box-sizing: border-box;*/ +/* width:50%;*/ +/* height:50%;*/ +/* overflow: hidden;*/ +/* overflow-y: auto;*/ +/* -webkit-overflow-scrolling: touch;*/ +/* -webkit-transform: translate3d(0,0,0);*/ + +/*}*/ diff --git a/pos_product_template/static/src/img/icon.png b/pos_product_template/static/src/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4e54d92ab092f28d564edf3e8a8da4f9a5f3aee6 GIT binary patch literal 4290 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 literal 0 HcmV?d00001 diff --git a/pos_product_template/static/src/js/ppt.js b/pos_product_template/static/src/js/ppt.js new file mode 100644 index 00000000..5780c86b --- /dev/null +++ b/pos_product_template/static/src/js/ppt.js @@ -0,0 +1,565 @@ +/****************************************************************************** + Point Of Sale - Product Template module for Odoo + Copyright (C) 2014-Today Akretion (http://www.akretion.com) + @author Sylvain LE GAL (https://twitter.com/legalsylvain) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +******************************************************************************/ + +openerp.pos_product_template = function (instance) { + module = instance.point_of_sale; + var QWeb = instance.web.qweb; + var _t = instance.web._t; + +/* ******************************************************** +Overload: point_of_sale.ProductListWidget + +- The overload will: + - display only product template; + - Add an extra behaviour on click on a template, if template has many + variant, displaying an extra scren to select the variant; +*********************************************************** */ + module.ProductListWidget = module.ProductListWidget.extend({ + + init: function(parent, options) { + this._super(parent,options); + var self = this; + // OVERWRITE 'click_product_handler' function to do + // a different behaviour if template with one or many variants + // are selected. + this.click_product_handler = function(event){ + var product = self.pos.db.get_product_by_id(this.dataset['productId']); + + if (product.product_variant_count == 1) { + // Normal behaviour, The template has only one variant + options.click_product_action(product); + } + else{ + // Display for selection all the variants of a template + self.pos.pos_widget.screen_selector.show_popup('select-variant-popup', product.product_tmpl_id); + } + }; + }, + + /* ************************************************ + Overload: 'set_product_list' + + 'set_product_list' is a function called before displaying Products. + (at the beginning, after a category selection, after a research, etc. + we just splice all products that are not the 'primary variant' + */ + set_product_list: function(product_list){ + for (var i = product_list.length - 1; i >= 0; i--){ + if (!product_list[i].is_primary_variant){ + product_list.splice(i, 1); + } + } + this._super(product_list); + }, + }); + + var _render_product_ = module.ProductListWidget.prototype.render_product; + module.ProductListWidget.prototype.render_product = function(product){ + self = this; + + if (product.product_variant_count == 1){ + // Normal Display + return _render_product_.call(this, product); + } + else{ + var cached = this.product_cache.get_node(product.id); + if(!cached){ + var image_url = this.get_product_image_url(product); + var product_html = QWeb.render('Template',{ + widget: this, + product: product, + image_url: this.get_product_image_url(product), + }); + var product_node = document.createElement('div'); + product_node.innerHTML = product_html; + product_node = product_node.childNodes[1]; + this.product_cache.cache_node(product.id,product_node); + return product_node; + } + return cached; + } + }; + + +/* ******************************************************** +Overload: point_of_sale.PosWidget + +- Add a new PopUp 'SelectVariantPopupWidget'; +*********************************************************** */ + module.PosWidget = module.PosWidget.extend({ + + /* Overload Section */ + build_widgets: function(){ + this._super(); + this.select_variant_popup = new module.SelectVariantPopupWidget(this, {}); + this.select_variant_popup.appendTo($(this.$el)); + this.screen_selector.popup_set['select-variant-popup'] = this.select_variant_popup; + // Hide the popup because all pop up are displayed at the + // beginning by default + this.select_variant_popup.hide(); + }, + }); + +/* ******************************************************** +Define : pos_product_template.SelectVariantPopupWidget + +- This widget that display a pop up to select a variant of a Template; +*********************************************************** */ + module.SelectVariantPopupWidget = module.PopUpWidget.extend({ + template:'SelectVariantPopupWidget', + + init: function(parent, options) { + this._super(parent,options); + this.template_name = ''; + }, + + start: function(){ + var self = this; + // Define Variant Widget + this.variant_list_widget = new module.VariantListWidget(this,{}); + this.variant_list_widget.replace(this.$('.placeholder-VariantListWidget')); + + // Define Attribute Widget + this.attribute_list_widget = new module.AttributeListWidget(this,{}); + this.attribute_list_widget.replace(this.$('.placeholder-AttributeListWidget')); + + // Add behaviour on Cancel Button + this.$('#variant-popup-cancel').off('click').click(function(){ + self.hide(); + }); + }, + + show: function(product_tmpl_id){ + var self = this; + var template = this.pos.db.template_by_id[product_tmpl_id]; + + // Display Name of Template + this.template_name = template.name; + this.$('#variant-title-name').html(template.name); + + // Render Variants + var variant_ids = this.pos.db.template_by_id[product_tmpl_id].product_variant_ids; + var variant_list = []; + for (var i = 0, len = variant_ids.length; i < len; i++) { + variant_list.push(this.pos.db.get_product_by_id(variant_ids[i])); + } + this.variant_list_widget.filters = {} + this.variant_list_widget.set_variant_list(variant_list); + + // Render Attributes + var attribute_ids = this.pos.db.attribute_by_template_id(template.id); + var attribute_list = []; + for (var i = 0, len = attribute_ids.length; i < len; i++) { + attribute_list.push(this.pos.db.get_product_attribute_by_id(attribute_ids[i])); + } + this.attribute_list_widget.set_attribute_list(attribute_list, template); + this._super(); + }, + }); + +/* ******************************************************** +Define: pos_product_template.VariantListWidget + +- This widget will display a list of Variants; +- This widget has some part of code that come from point_of_sale.ProductListWidget; +*********************************************************** */ + module.VariantListWidget = module.PosBaseWidget.extend({ + template:'VariantListWidget', + + init: function(parent, options) { + var self = this; + this._super(parent, options); + this.variant_list = []; + this.filter_variant_list = []; + this.filters = {}; + this.click_variant_handler = function(event){ + var variant = self.pos.db.get_product_by_id(this.dataset['variantId']); + if(variant.to_weight && self.pos.config.iface_electronic_scale){ + self.__parentedParent.hide(); + self.pos_widget.screen_selector.set_current_screen('scale',{product: variant}); + }else{ + self.__parentedParent.hide(); + self.pos.get('selectedOrder').addProduct(variant); + } + }; + }, + + replace: function($target){ + this.renderElement(); + var target = $target[0]; + target.parentNode.replaceChild(this.el,target); + }, + + set_filter: function(attribute_id, value_id){ + this.filters[attribute_id] = value_id; + this.filter_variant(); + }, + + reset_filter: function(attribute_id){ + if (attribute_id in this.filters){ + delete this.filters[attribute_id]; + } + this.filter_variant(); + }, + + filter_variant: function(){ + value_list = [] + for (var item in this.filters){ + value_list.push(parseInt(this.filters[item])); + } + this.filter_variant_list = []; + for (index in this.variant_list){ + variant = this.variant_list[index]; + found = true; + for (var i = 0; i < value_list.length; i++){ + found = found && (variant.attribute_value_ids.indexOf(value_list[i]) != -1); + } + if (found){ + this.filter_variant_list.push(variant); + } + } + this.renderElement(); + }, + + set_variant_list: function(variant_list){ + this.variant_list = variant_list; + this.filter_variant_list = variant_list; + this.renderElement(); + }, + + render_variant: function(variant){ + var variant_html = QWeb.render('VariantWidget', { + widget: this, + variant: variant, + }); + var variant_node = document.createElement('div'); + variant_node.innerHTML = variant_html; + variant_node = variant_node.childNodes[1]; + return variant_node; + }, + + renderElement: function() { + var self = this; + var el_html = openerp.qweb.render(this.template, {widget: this}); + var el_node = document.createElement('div'); + el_node.innerHTML = el_html; + el_node = el_node.childNodes[1]; + if(this.el && this.el.parentNode){ + this.el.parentNode.replaceChild(el_node,this.el); + } + this.el = el_node; + var list_container = el_node.querySelector('.variant-list'); + for(var i = 0, len = this.filter_variant_list.length; i < len; i++){ + var variant_node = this.render_variant(this.filter_variant_list[i]); + variant_node.addEventListener('click',this.click_variant_handler); + list_container.appendChild(variant_node); + } + }, + + }); + +/* ******************************************************** +Define: pos_product_template.AttributeListWidget + + - This widget will display a list of Attribute; +*********************************************************** */ + module.AttributeListWidget = module.PosBaseWidget.extend({ + template:'AttributeListWidget', + + init: function(parent, options) { + var self = this; + this.attribute_list = []; + this.product_template = null; + this.click_set_attribute_handler = function(event){ + /*TODO: Refactor this function with elegant DOM manipulation */ + // remove selected item + parent = this.parentElement.parentElement.parentElement; + parent.children[0].classList.remove('selected'); + for (var i = 0 ; i < parent.children[1].children[0].children.length; i ++){ + elem = parent.children[1].children[0].children[i]; + elem.children[0].classList.remove('selected'); + } + // add selected item + this.children[0].classList.add('selected'); + self.__parentedParent.variant_list_widget.set_filter(this.dataset['attributeId'], this.dataset['attributeValueId']); + }; + this.click_reset_attribute_handler = function(event){ + /*TODO: Refactor this function with elegant DOM manipulation */ + // remove selected item + parent = this.parentElement; + parent.children[0].classList.remove('selected'); + for (var i = 0 ; i < parent.children[1].children[0].children.length; i ++){ + elem = parent.children[1].children[0].children[i]; + elem.children[0].classList.remove('selected'); + } + // add selected item + this.classList.add('selected'); + self.__parentedParent.variant_list_widget.reset_filter(this.dataset['attributeId']); + }; + this._super(parent, options); + }, + + replace: function($target){ + this.renderElement(); + var target = $target[0]; + target.parentNode.replaceChild(this.el,target); + }, + + set_attribute_list: function(attribute_list, product_template){ + this.attribute_list = attribute_list; + this.product_template = product_template; + this.renderElement(); + }, + + render_attribute: function(attribute){ + var attribute_html = QWeb.render('AttributeWidget',{ + widget: this, + attribute: attribute, + }); + var attribute_node = document.createElement('div'); + attribute_node.innerHTML = attribute_html; + attribute_node = attribute_node.childNodes[1]; + + var list_container = attribute_node.querySelector('.value-list'); + for(var i = 0, len = attribute.value_ids.length; i < len; i++){ + var value = this.pos.db.get_product_attribute_value_by_id(attribute.value_ids[i]); + var value_node = this.render_value(attribute, value); + value_node.addEventListener('click', this.click_set_attribute_handler); + list_container.appendChild(value_node); + }; + return attribute_node; + }, + + render_value: function(attribute, value){ + product_list = this.pos.db.get_product_by_ids(this.product_template.product_variant_ids); + subproduct_list = this.pos.db.get_product_by_value_and_products(value.id, product_list); + variant_qty = subproduct_list.length; + var value_html = QWeb.render('AttributeValueWidget',{ + widget: this, + value: value, + variant_qty: variant_qty, + }); + var value_node = document.createElement('div'); + value_node.innerHTML = value_html; + value_node = value_node.childNodes[1]; + return value_node; + }, + + + renderElement: function() { + var self = this; + var el_html = openerp.qweb.render(this.template, {widget: this}); + var el_node = document.createElement('div'); + el_node.innerHTML = el_html; + el_node = el_node.childNodes[1]; + if(this.el && this.el.parentNode){ + this.el.parentNode.replaceChild(el_node,this.el); + } + this.el = el_node; + + var list_container = el_node.querySelector('.attribute-list'); + for(var i = 0, len = this.attribute_list.length; i < len; i++){ + var attribute_node = this.render_attribute(this.attribute_list[i]); + attribute_node.querySelector('.attribute-name').addEventListener('click', this.click_reset_attribute_handler); +// attribute_node.addEventListener('click', this.click_reset_attribute_handler); + list_container.appendChild(attribute_node); + }; + }, + + }); + + +/* ******************************************************** +Overload: point_of_sale.PosDB + +- Add to local storage Product Templates Data. +- Link Product Variants to Product Templates. +- Add an extra field 'is_primary_variant' on product object. the product + will be display on product list, only if it is the primary variant; + Otherwise, the product will be displayed only on Template Screen. +- Add an extra field 'product_variant_count' on product object that + indicates the number of variant of the template of the product. +*********************************************************** */ + module.PosDB = module.PosDB.extend({ + init: function(options){ + this.template_by_id = {}; + this.product_attribute_by_id = {}; + this.product_attribute_value_by_id = {}; + this._super(options); + }, + + get_product_by_value_and_products: function(value_id, products){ + var list = []; + for (var i = 0, len = products.length; i < len; i++) { + if (products[i].attribute_value_ids.indexOf(value_id) != -1){ + list.push(products[i]); + } + } + return list; + }, + + get_product_attribute_by_id: function(attribute_id){ + return this.product_attribute_by_id[attribute_id]; + }, + + get_product_attribute_value_by_id: function(attribute_value_id){ + return this.product_attribute_value_by_id[attribute_value_id]; + }, + + get_product_by_ids: function(product_ids){ + var list = []; + for (var i = 0, len = product_ids.length; i < len; i++) { + list.push(this.product_by_id[product_ids[i]]); + } + return list; + }, + + + attribute_by_template_id: function(template_id){ + template = this.template_by_id[template_id]; + return this.attribute_by_attribute_value_ids(template.attribute_value_ids); + }, + + attribute_by_attribute_value_ids: function(value_ids){ + attribute_ids = []; + for (var i = 0; i < value_ids.length; i++){ + var value = this.product_attribute_value_by_id[value_ids[i]]; + if (attribute_ids.indexOf(value.attribute_id[0])==-1){ + attribute_ids.push(value.attribute_id[0]); + } + } + return attribute_ids; + }, + + add_templates: function(templates){ + for(var i=0 ; i < templates.length; i++){ + var attribute_value_ids = []; + // store Templates + this.template_by_id[templates[i].id] = templates[i]; + + // Update Product information + for (var j = 0; j + + + + + + + + + + + + + + + + + + + + + + diff --git a/pos_product_template/view/view.xml b/pos_product_template/view/view.xml new file mode 100644 index 00000000..169b3db8 --- /dev/null +++ b/pos_product_template/view/view.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 54d6065986612ddbe1e3faf205ee247980c133f8 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 18 Dec 2014 13:10:18 +0100 Subject: [PATCH 02/27] [IMP] better display of attributes values; [FIX] overflow bug; --- pos_product_template/static/src/css/ppt.css | 46 +++++++++++++++++++-- pos_product_template/static/src/xml/ppt.xml | 13 ++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/pos_product_template/static/src/css/ppt.css b/pos_product_template/static/src/css/ppt.css index fcea88dd..638e52c2 100644 --- a/pos_product_template/static/src/css/ppt.css +++ b/pos_product_template/static/src/css/ppt.css @@ -40,7 +40,7 @@ .pos .modal-dialog .popup-select-variant .container-attribute-list{ width:100%; - height:30%; /*FIXME */ + height:40%; overflow: hidden; overflow-y: auto; border-bottom: 1px dashed #444; @@ -49,9 +49,10 @@ .pos .modal-dialog .popup-select-variant .container-variant-list{ width:100%; - height:60%; /*FIXME */ + height:50%; overflow: hidden; overflow-y: auto; + -webkit-overflow-scrolling: touch; } @@ -65,20 +66,22 @@ .pos .attribute { position:relative; width: 100%; - height:50px; vertical-align: top; display: inline-block; } .pos .attribute .attribute-name{ float: left; + font-size: 13px; width: 20%; + overflow:hidden; } .pos .attribute .value-list-container{ width:78%; float: left; } + .pos .attribute .selected{ background-color: white; } @@ -86,7 +89,44 @@ .pos .attribute .attribute-value { float: left; width: 150px; + padding-left: 15px; +} + +.pos .attribute .attribute-value .button{ + width: 100%; +} + +.pos .attribute .attribute-value .attribute-value-header{ + width: 100%; + height: 15px; + text-align: right; + } +.pos .attribute .attribute-value .attribute-value-name{ + width: 100%; + height: 25px; + line-height:25px; + overflow: hidden; + font-size: 10px; + text-align: left; + font-weight: normal; + padding: 2px; +} + +.pos .attribute .attribute-value .variant-quantity{ + position: relative; + top: 2px; + right: 0px; + vertical-align: top; + color: #FFF; + line-height: 13px; + background: none repeat scroll 0% 0% #7F82AC; + padding: 2px 5px; + border-radius: 2px; + font-size: 9px; + margin-right:3px; +} + /* ********* Variant Display ********************************************* */ /* This part is a copy past from Odoo Project, with some values changed */ diff --git a/pos_product_template/static/src/xml/ppt.xml b/pos_product_template/static/src/xml/ppt.xml index 2c217fc6..03a2ad7e 100644 --- a/pos_product_template/static/src/xml/ppt.xml +++ b/pos_product_template/static/src/xml/ppt.xml @@ -27,7 +27,7 @@