1

I Have a custom module website_decimal_quantity. after installing this module, In the website shop cart, when the user clicks on the + or - button to adjust quantity, It should add or deduct .1 value from it. i find out that a function onclickaddcartjson in the sale.variantmixin is responsible for the button click.i tried to extend the onclickaddcartjson function that present in the website_sale.website_sale. but it does not work. Thanks For the Attention

My code is like :

publicWidget.registry.WebsiteSale.include({
    onClickAddCartJSON: function (ev) {
        ev.preventDefault();
        var $link = $(ev.currentTarget);
        var $input = $link.closest('.input-group').find("input");
        var min = parseFloat($input.data("min") || 0);
        var max = parseFloat($input.data("max") || Infinity);
        var previousQty = parseFloat($input.val() || 0, 10);
        var quantity = ($link.has(".fa-minus").length ? -0.1 : 0.1) + previousQty;
        var newQty = quantity > min ? (quantity < max ? quantity : max) : min;

        if (newQty !== previousQty) {
            $input.val(newQty).trigger('change');
        }
        return false;
    },

        
_changeCartQuantity: function ($input, value, $dom_optional, line_id, productIDs) {
    _.each($dom_optional, function (elem) {
        $(elem).find('.js_quantity').text(value);
        productIDs.push($(elem).find('span[data-product-id]').data('product-id'));
    });
    $input.data('update_change', true);

    this._rpc({
        route: "/shop/cart/update_json",
        params: {
            line_id: line_id,
            product_id: parseInt($input.data('product-id'), 10),
            set_qty: value
        },
    }).then(function (data) {
        $input.data('update_change', false);
        var check_value = parseFloat($input.val());
        if (isNaN(check_value)) {
            check_value = 1;
        }
        if (value !== check_value) {
            $input.trigger('change');
            return;
        }
        if (!data.cart_quantity) {
            return window.location = '/shop/cart';
        }
        wSaleUtils.updateCartNavBar(data);
        $input.val(data.quantity);
        $('.js_quantity[data-line-id='+line_id+']').val(data.quantity).text(data.quantity);

        if (data.warning) {
            var cart_alert = $('.oe_cart').parent().find('#data_warning');
            if (cart_alert.length === 0) {
                $('.oe_cart').prepend('<div class="alert alert-danger alert-dismissable" role="alert" id="data_warning">'+
                        '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button> ' + data.warning + '</div>');
            }
            else {
                cart_alert.html('<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button> ' + data.warning);
            }
            $input.val(data.quantity);
        }
    });
},

_onChangeCartQuantity: function (ev) {
            var $input = $(ev.currentTarget);
            if ($input.data('update_change')) {
                return;
            }
            var value = parseFloat($input.val());
            if (isNaN(value)) {
                value = 1;
            }
            var $dom = $input.closest('tr');
            // var default_price = parseFloat($dom.find('.text-danger > span.oe_currency_value').text());
            var $dom_optional = $dom.nextUntil(':not(.optional_product.info)');
            var line_id = parseInt($input.data('line-id'), 10);
            var productIDs = [parseInt($input.data('product-id'), 10)];
            this._changeCartQuantity($input, value, $dom_optional, line_id, productIDs);
        },
})

The change that I made is in _onclickaddcartjson; change the line

   var quantity = ($link.has(".fa-minus").length ? -0.1 : 0.1) + previousQty;

and in _changeCartQuantity, change the check_value into:

   var check_value = parseFloat($input.val())

And in _onChangeCartQuantity, change the value into:

   var value = parseFloat($input.val()).

Even if I made these changes in source file without my custom module, the quantity increase or decrease by .1. But it automatically turns into an integer value. That means when I click on the + button, the value changes to 1.1, but it immediately changes to 1. Also, if I click on the - button, it will changes to 2.9 from 3, then it changes to 2 as its value. If anybody has an idea about this please share. Thanks for the attention.

  • could you publish your js file please ? – sylvain May 19 '22 at 11:46
  • i published my code as answer by mistake. will u please check the code ? Thanks for the attention – Odoo Beginner May 21 '22 at 03:29
  • When quantity input value is automatically changed back to integer, it might be caused by parseInt($input.val()) in _onChangeCartQuantity in the file: website_sale.js: – sylvain May 22 '22 at 15:11
  • that y i changed the parseInt($input.val()) in to parseFloat($input.val()) . but if i did not change the check_value in changeCartQuantity into float then the function call repeatedly. – Odoo Beginner May 23 '22 at 03:18
  • yes of course: replacing parseInt($input.val()) by parseFloat($input.val()) should be done at that place – sylvain May 23 '22 at 04:17
  • finally am solved my problem. along with the mentioned changes i did some small changes in sale_order.py . then i got my answer. Thanks for your great support – Odoo Beginner May 23 '22 at 11:31
  • In website_sale/models/sale_order.py : You just have to replace int(sum(order.mapped('website_order_line.product_uom_qty'))) BY sum(order.mapped('website_order_line.product_uom_qty')): – sylvain May 23 '22 at 14:27

1 Answers1

0

Yes, it 's possible as the type of the underlying field in model SaleOrderLine is Float. And in website_sale/models/sale_order.py : int(sum(order.mapped('website_order_line.product_uom_qty'))) needs to be reülaced by: sum(order.mapped('website_order_line.product_uom_qty')):

   class SaleOrderLine(models.Model): 
            _name = 'sale.order.line'

      product_uom_qty = fields.Float(string='Quantity', digits='Product Unit of Measure', required=True, default=1.0)

     @api.depends('order_line.product_uom_qty', 'order_line.product_id')
     def _compute_cart_info(self):
        for order in self:
            order.cart_quantity = sum(order.mapped('website_order_line.product_uom_qty'))
            order.only_services = all(l.product_id.type in ('service', 'digital') for l in order.website_order_line)


The underlying python method to add quantity is located in addons module website_sale/models/sale_oder.py :

     def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs):
        """ Add or set product quantity, add_qty can be negative """
        self.ensure_one()
        product_context = dict(self.env.context)
        product_context.setdefault('lang', self.sudo().partner_id.lang)
        SaleOrderLineSudo = self.env['sale.order.line'].sudo().with_context(product_context)
        ...

...which is called by 2 methods in website_sale/controllers/main.py :

   @http.route(['/shop/cart/update'], type='http', auth="public", methods=['GET', 'POST'], website=True, csrf=False)
   def cart_update(self, product_id, add_qty=1, set_qty=0, **kw):

AND

    @http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True, csrf=False)
    def cart_update_json(self, product_id, line_id=None, add_qty=None, set_qty=None, display=True):
        """This route is called when changing quantity from the cart or adding
        a product from the wishlist."""
        """This route is called when adding a product to cart (no options)."""

This controller method cart_update_json is called in sale/.../js/variant_mixin.js by:

     onClickAddCartJSON: function (ev) {
        ev.preventDefault();
        var $link = $(ev.currentTarget);
        var $input = $link.closest('.input-group').find("input");
        var min = parseFloat($input.data("min") || 0);
        var max = parseFloat($input.data("max") || Infinity);
        var previousQty = parseFloat($input.val() || 0, 10);
        var quantity = ($link.has(".fa-minus").length ? -1 : 1) + previousQty;
        var newQty = quantity > min ? (quantity < max ? quantity : max) : min;

        if (newQty !== previousQty) {
            $input.val(newQty).trigger('change');
        }
        return false;
    },

...where: var quantity = ($link.has(".fa-minus").length ? -1 : 1) + previousQty; shows us that is incremented +1 oder -1

That s why you need to override this function in website_sale/.../website_sale.js to integrate:

   var $parent = $(ev.target).closest('.js_product');
   var product_id = this._getProductId($parent);
   if product_id == yourspecificproductid
      var quantity = ($link.has(".fa-minus").length ? -0.1 : 0.1) + 
  previousQty; 
   else
      var quantity = ($link.has(".fa-minus").length ? -1 : 1) + 
  previousQty; 
      

When quantity input value is changed automatically, it might be caused by parseInt($input.val()) in _onChangeCartQuantity in the file: website_sale.js:

        _onChangeCartQuantity: function (ev) {
         var $input = $(ev.currentTarget);
         if ($input.data('update_change')) {
             return;
         }
         var value = parseFloat($input.val() || 0, 10);
         if (isNaN(value)) {
             value = 1;
         }
         var $dom = $input.closest('tr');
         // var default_price = parseFloat($dom.find('.text-danger > span.oe_currency_value').text());
         var $dom_optional = $dom.nextUntil(':not(.optional_product.info)');
         var line_id = parseInt($input.data('line-id'), 10);
        var productIDs = [parseInt($input.data('product-id'), 10)];
        this._changeCartQuantity($input, value, $dom_optional, line_id, productIDs);
    },
sylvain
  • 853
  • 1
  • 7
  • 20