From 9663670948158867b9b5ab37eb94ea74358e481c Mon Sep 17 00:00:00 2001 From: Adil Houmadi Date: Sun, 12 Jul 2015 14:27:37 +0200 Subject: [PATCH] =?UTF-8?q?[ADD]=20:=20When=20we=20mouseover=20the=20price?= =?UTF-8?q?=20tag,=20a=20tooltip=20is=20shown=20to=20indicate=20the=20comp?= =?UTF-8?q?utation=20depending=20on=20the=20quantity=20like=20this=20outpu?= =?UTF-8?q?t=20:=201x=20->=20100=20=E2=82=AC=203x=20->=2070=20=E2=82=AC=20?= =?UTF-8?q?5x=20->=2050=20=E2=82=AC=20[IMP]=20:=20update=20readme=20to=20i?= =?UTF-8?q?ndicate=20the=20new=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pos_pricelist/README.rst | 11 ++- pos_pricelist/static/src/css/style.css | 102 ++++++++++++++++++++++++- pos_pricelist/static/src/js/db.js | 13 ++++ pos_pricelist/static/src/js/models.js | 85 ++++++++++++++------- pos_pricelist/static/src/js/widgets.js | 4 + 5 files changed, 185 insertions(+), 30 deletions(-) diff --git a/pos_pricelist/README.rst b/pos_pricelist/README.rst index e0681825..8f353a3b 100644 --- a/pos_pricelist/README.rst +++ b/pos_pricelist/README.rst @@ -35,9 +35,16 @@ The POS will recognize it and will compute the price according to the rule defin 2. (-2) : Rule based on supplierinfo 3. (default) : Any price type which is set on the product form +3. An new option is introduced in the POS config to let the user show price with taxes in product widget. +the UI is updated when we change the customer in order to adapt the prices. +The computation take in account the pricelist and the fiscal position of the customer + +4. When we mouseover the price tag, a tooltip is shown to indicate the computation depending on the quantity like this output : +1x -> 100 € +3x -> 70 € +5x -> 50 € + Missing features ---------------- * As you may know, product template is not fully implemented in the POS, so I decided to drop it from this module. -* When there are more than one price depending on the quantity, only the price - for first interval is shown. diff --git a/pos_pricelist/static/src/css/style.css b/pos_pricelist/static/src/css/style.css index 5a652bb9..37902d8b 100644 --- a/pos_pricelist/static/src/css/style.css +++ b/pos_pricelist/static/src/css/style.css @@ -43,4 +43,104 @@ background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-radius: 5px 5px 0 0; -} \ No newline at end of file +} + +/* ToolTip */ +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-size: 12px; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + right: 5px; + bottom: 0; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} diff --git a/pos_pricelist/static/src/js/db.js b/pos_pricelist/static/src/js/db.js index 12458860..fea397f4 100644 --- a/pos_pricelist/static/src/js/db.js +++ b/pos_pricelist/static/src/js/db.js @@ -174,6 +174,19 @@ function pos_pricelist_db(instance, module) { = prices['priceWithTax'] } } + }, + find_product_rules: function (product) { + var len = this.pricelist_item_sorted.length; + var rules = []; + for (var i = 0; i < len; i++) { + var rule = this.pricelist_item_sorted[i]; + if ((rule.product_id && rule.product_id[0] == product.id) || + (rule.categ_id && product.categ_id + && rule.categ_id[0] == product.categ_id[0])) { + rules.push(rule); + } + } + return rules; } }) } diff --git a/pos_pricelist/static/src/js/models.js b/pos_pricelist/static/src/js/models.js index 1b33036c..8d0b8a73 100644 --- a/pos_pricelist/static/src/js/models.js +++ b/pos_pricelist/static/src/js/models.js @@ -189,7 +189,7 @@ function pos_pricelist_models(instance, module) { var taxdetail = {}; var product_taxes = this.get_applicable_taxes_for_orderline(); var all_taxes = _(this.compute_all(product_taxes, base)).flatten(); - _(all_taxes).each(function(tax) { + _(all_taxes).each(function (tax) { if (tax.price_include) { totalNoTax -= tax.amount; } else { @@ -259,13 +259,13 @@ function pos_pricelist_models(instance, module) { /** * @returns {Array} */ - get_applicable_taxes_for_orderline: function() { + get_applicable_taxes_for_orderline: function () { // find applicable taxes for this product and this customer var fiscal_position_taxes = []; var product_taxes = []; var product = this.get_product(); var partner = this.order ? this.order.get_client() : null; - var taxes = this.pos.taxes; + var taxes = this.pos.taxes; if (partner && partner.property_account_position) { fiscal_position_taxes = this.pos.db.find_taxes_by_fiscal_position_id( @@ -516,35 +516,66 @@ function pos_pricelist_models(instance, module) { for (var i = 0, len = product_list_ui.length; i < len; i++) { var product_ui = product_list_ui[i]; var product_id = $(product_ui).data('product-id'); - // price which computed via pricelist var product = $.extend({}, db.get_product_by_id(product_id)); - var price = this.compute_price_all(db, product, partner, 1); - if (price !== false && price !== 0.0) { - if (this.pos.config.display_price_with_taxes) { - // create a fake order in order to get price - // for this customer - var order = new module.Order({pos: this.pos}); - order.set_client(partner); - var orderline = new openerp.point_of_sale.Orderline({}, - { - pos: this.pos, - order: order, - product: product, - price: price - } - ); - // reset the sequence - this.pos.pos_session.sequence_number--; - var prices = orderline.get_all_prices(); - price = prices['priceWithTax']; + var rules = db.find_product_rules(product); + var quantities = []; + quantities.push(1); + for (var j = 0; j < rules.length; j++) { + quantities.push(rules[j].min_quantity); + } + quantities = quantities.sort(); + var prices_displayed = ''; + for (var k = 0; k < quantities.length; k++) { + var qty = quantities[k]; + var price = this.compute_price_all( + db, product, partner, qty + ); + if (price !== false && price !== 0.0) { + if (this.pos.config.display_price_with_taxes) { + var prices = this.simulate_price( + product, partner, price, qty + ); + price = prices['priceWithTax'] + } + price = round_di(parseFloat(price) + || 0, this.pos.dp['Product Price']); + price = this.pos_widget.format_currency(price); + if (k == 0) { + $(product_ui).find('.price-tag').html(price); + } + prices_displayed += qty + + 'x → ' + price + '
'; } - price = round_di(parseFloat(price) - || 0, this.pos.dp['Product Price']); - price = this.pos_widget.format_currency(price); - $(product_ui).find('.price-tag').html(price); + } + if (prices_displayed != '') { + $(product_ui).find('.price-tag').attr( + 'data-original-title', prices_displayed + ); + $(product_ui).find('.price-tag').attr( + 'data-toggle', 'tooltip' + ); + $(product_ui).find('.price-tag').tooltip( + {delay: {show: 50, hide: 100}} + ); } } }, + simulate_price: function (product, partner, price, qty) { + // create a fake order in order to get price + // for this customer + var order = new module.Order({pos: this.pos}); + order.set_client(partner); + var orderline = new openerp.point_of_sale.Orderline + ({}, { + pos: this.pos, order: order, + product: product, price: price + }); + orderline.set_quantity(qty); + // reset the sequence + this.pos.pos_session.sequence_number--; + var prices = orderline.get_all_prices(); + return prices; + }, /** * * @param partner diff --git a/pos_pricelist/static/src/js/widgets.js b/pos_pricelist/static/src/js/widgets.js index 5a04e7ea..b1812b1c 100644 --- a/pos_pricelist/static/src/js/widgets.js +++ b/pos_pricelist/static/src/js/widgets.js @@ -52,6 +52,10 @@ function pos_pricelist_widgets(instance, module) { this.display_price_with_taxes = posmodel.config.display_price_with_taxes } + }, + renderElement: function () { + this._super(); + this.pos.pricelist_engine.update_products_ui(null); } }); }