Home > Mobile >  Problem with ajax price update when changing options
Problem with ajax price update when changing options

Time:08-13

I got a problem on a Prestashop website (1.7.7.8) , with updating price when changing options. In some particular cases, an error occured and the price is not displayed.

You can see the bug here : https://bacom.lebonweb.fr/accueil/32-bache.html

This append in a specific scenario, when we have several options ; and not all are availables for all others options (not sure to be clear..). In this case :

  • the type "Roll up" has only 1 dimension available (200cm and 85cm).
  • the type "Bache" has others dimensions available, but not the same as the type ROLL UP

So to see the bug, you can follow those steps :

1/ go to https://bacom.lebonweb.fr/accueil/32-bache.html

2/ by default TYPE is rollup. Change the type select, choosing "Bache"

3/ the selects Hauteur and Largeur are well updated, with the available values for BACHE type (different from the ROLLUP type values). But the price disapears, and the error is "Can not retrieve the id_product_attribute" (debug mode is on)

If you reload the page, the bug disapear.

Some tests confirms the problem comes from the theme ; with classic default theme the same scenario works fine (http://www.lebonweb.fr/dev/bacom-test/femmes/2-42-brown-bear-printed-sweater.html)

I've tried, file by file (tpl and js) , to replace custom theme code with default theme code. But impossible to solve this error....

I'm probably missing something with ajax & JS. I've noticed this warning on console : "jQuery(window).on('load'...) called after load event occurred"...

But after 2 days of searching, reading, and testings, still unable to find a solution. Would you have advice or suggestion on where I should investigate more ?

Thanks a lot


EDIT : To explain diferently (and shortlier ^^) the problem with combinations I'm encountering :

EXEMPLE : We got 3 combinations of a t-shirt :

T shirt - RED - Size : 1

T-shirt - RED - Size 2

T-shirt - BLACK - Size 1

Changing one option may automatically change another option value :

step 1 : choose options : color : RED / Size 2

step 2 : change option color to BLACK = Size change automatically to 1

In my case, it seems that the default combination datas (the one loaded automatically in this exemple scenario) is not sent to the ajax request that gets the price datas. Wheras in other place in the page, those default datas are well get.

Maybe something like the ajax call to get price is called BEFORE another call that calculate the default combination according to option changes...?

Hope this other presentation of my problem will help :)

Thanks !

CodePudding user response:

this took some debugging, I don't know how much this might be helpful to you but thought I would try anyway....

the js is making a call to

https://bacom.lebonweb.fr/index.php?controller=product&token=7dc88db1baee0ecae0e917cf624997d0&id_product=32&id_customization=0&group[20]=112&group[22]=124&group[21]=113&group[11]=52&qty=1'

with the following form data:

controller  product
token   7dc88db1baee0ecae0e917cf624997d0
id_product  32
id_customization    0
group[20]   112
group[22]   124
group[21]   113
group[11]   52
qty 1

and the following body data

quickview   0
ajax    1
action  refresh
quantity_wanted 1

this api is then throwing the following error:

Can not retrieve the id_product_attribute
at line 6582 in file classes/Product.php
6577.                 );
6578.             }
6579.         }
6580. 
6581.         if (empty($idProductAttribute)) {
6582.             throw new PrestaShopObjectNotFoundException('Can not retrieve the id_product_attribute');
6583.         }
6584. 
6585.         return $idProductAttribute;
6586.     }

The call is coming from

function ajaxProductCombinationChange(productId, attributes) {
        $.ajax({
            type: 'POST',
            url: prestashopFacebookAjaxController,
            data: {
                action: 'CustomizeProduct',
                ajax: true,
                id_product: productId,
                attribute_ids: attributes,
            }
        });
    }

So I wonder is this a php error rather than a jquery one as even when I refresh the page in edge, chrome or firefox I always get the error?

I hope this helps

CodePudding user response:

so i dug into this a bit more, this is a rather long detail so please bare with me, the php stack trace is :

Can not retrieve the id_product_attribute
at line 6582 in file classes/Product.php

6577.                 );
6578.             }
6579.         }
6580. 
6581.         if (empty($idProductAttribute)) {
6582.             throw new PrestaShopObjectNotFoundException('Can not retrieve the id_product_attribute');
6583.         }
6584. 
6585.         return $idProductAttribute;
6586.     }
6587. 
    ProductCore::getIdProductAttributeByIdAttributes - [line 6594 - classes/Product.php] - [3 Arguments]

    6589.      * @deprecated 1.7.3.1
    6590.      * @see Product::getIdProductAttributeByIdAttributes()
    6591.      */
    6592.     public static function getIdProductAttributesByIdAttributes($id_product, $id_attributes, $find_best = false)
    6593.     {
    6594.         return self::getIdProductAttributeByIdAttributes($id_product, $id_attributes, $find_best);
    6595.     }
    6596. 
    6597.     /**
    6598.      * Get the combination url anchor of the product.
    6599.      *
    ProductCore::getIdProductAttributesByIdAttributes - [line 1391 - modules/ttproductcountdown/ttproductcountdown.php] - [2 Arguments]

    1386.             $groups = Tools::getValue('group');
    1387. 
    1388.             if (!empty($groups) && method_exists('Product', 'getIdProductAttributesByIdAttributes')) {
    1389.                 $id_product_attribute = (int) Product::getIdProductAttributesByIdAttributes(
    1390.                     $id_product,
    1391.                     $groups
    1392.                 );
    1393.             }
    1394.         }
    1395.         if ($id_product_attribute === null) {
    1396.             $id_product_attribute = Tools::getValue('id_product_attribute');
    TTProductCountdown->hookPSPC - [line 1439 - modules/ttproductcountdown/ttproductcountdown.php] - [1 Arguments]

    1434.             ($this->product_position == 'displayProductPriceBlock'
    1435.             || $this->product_list_position == 'over_img'
    1436.             || $this->product_list_position == 'displayProductPriceBlock')
    1437.         ) {
    1438.             $params['hook'] = 'displayProductPriceBlock';
    1439.             return $this->hookPSPC($params);
    1440.         }
    1441.     }
    1442. 
    1443.     public function hookDisplayProductButtons($params)
    1444.     {

the call is still/now coming from:

emit("updateProduct", {
                eventType: "updatedProductCombination",
                event: e,
                resp: {},
                reason: {
                    productUrl: o.default.urls.pages.product || ""
                }
            }

there seams to be a function in core.js

 "updatedProductQuantity" === t && (h = 750),
                u = setTimeout(function() {
                    "" !== f && (s = r.default.ajax({
                        url: n   (-1 === n.indexOf("?") ? "?" : "&")   f   p,
                        method: "POST",
                        data: {
                            quickview: (0,
                            r.default)(".modal.quickview.in").length,
                            ajax: 1,
                            action: "refresh",
                            quantity_wanted: "updatedProductCombination" === t ? c.attr("min") : c.val()
                        },
                        dataType: "json",
                        beforeSend: function() {
                            null !== s && s.abort()
                        },
                        error: function(e, t, n) {
                            "abort" !== t && 0 === (0,
                            r.default)("section#main > .ajax-error").length && l()
                        },
                        success: function(e, n, i) {
                            var a = (0,
                            r.default)("<div>").append(e.product_cover_thumbnails);
                            (0,
                            r.default)(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").html() !== a.find(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").html() && (0,
                            r.default)(".quickview .images-container, .page-product:not(.modal-open) .row .images-container, .page-product:not(.modal-open) .product-container .images-container").replaceWith(e.product_cover_thumbnails),
                            (0,
                            r.default)(".quickview .product-prices, .page-product:not(.modal-open) .row .product-prices, .page-product:not(.modal-open) .product-container .product-prices").first().replaceWith(e.product_prices),
                            (0,
                            r.default)(".quickview .product-customization, .page-product:not(.modal-open) .row .product-customization, .page-product:not(.modal-open) .product-container .product-customization").first().replaceWith(e.product_customization),
                            (0,
                            r.default)(".quickview .product-variants, .page-product:not(.modal-open) .row .product-variants, .page-product:not(.modal-open) .product-container .product-variants").first().replaceWith(e.product_variants),
                            (0,
                            r.default)(".quickview .product-discounts, .page-product:not(.modal-open) .row .product-discounts, .page-product:not(.modal-open) .product-container .product-discounts").first().replaceWith(e.product_discounts),
                            (0,
                            r.default)(".quickview .product-additional-info, .page-product:not(.modal-open) .row .product-additional-info, .page-product:not(.modal-open) .product-container .product-additional-info").first().replaceWith(e.product_additional_info),
                            (0,
                            r.default)(".quickview #product-details, #product-details").replaceWith(e.product_details),
                            (0,
                            r.default)(".quickview .product-flags, .page-product:not(.modal-open) .row .product-flags, .page-product:not(.modal-open) .product-container .product-flags").first().replaceWith(e.product_flags),
                            function(e) {

this line is where that error message is coming from:

 r.default)(".quickview .product-prices, .page-product:not(.modal-open) .row .product-prices, .page-product:not(.modal-open) .product-container .product-prices").first().replaceWith(e.product_prices)

it is injecting the following htlm :

'\n\x3C!-- begin _partials/notifications.tpl -->\n\n<aside id="notifications">\n  <div >\n    \n          \n        <article  role="alert" data-alert="warning">\n          <ul>\n                          <li>Can not retrieve the id_product_attribute</li>\n                      </ul>\n        </article>\n      \n    \n    \n      </div>\n</aside>\n\n\x3C!-- end _partials/notifications.tpl -->\n'

if i reply the same ajax call though postman or fiddler i can re-create the error, the

 <script src="https://bacom.lebonweb.fr/themes/core.js"></script>

witch as you say is a theme script I assume this is something that is added by the site host your using or some sort of plug in ?

when I compare it to the theme that works (http://www.lebonweb.fr/dev/bacom-test/femmes/2-42-brown-bear-printed-sweater.html)

the request is totally different :

http://www.lebonweb.fr/dev/bacom-test/index.php?controller=product&token=e75591940fae6ed3e01a3adbbbac3d6c&id_product=2&id_customization=0&group[1]=2&group[2]=10&qty=1

moreover the core.js file is totally different, for a start its minimized ...so you could try copying the core.js file from the theme that works to the theme that dose not and see what happens, in theory if it's just a theme script the core functionality should still work, failing that contact the site provider or raise an issue worth the theme provider (assuming that have github or some equivalent) and ask why their theme script is failing as theme script shouldn't act differently that's kinda the point of them, better still do away with the theme and use your own, a very good and widely used theme is https://getbootstrap.com/docs/5.0/getting-started/introduction/ it is easy to use and offers very good customisable styling and functionality

I hope this helps

  • Related