Jump to content

Quantity does not change after purchase


Recommended Posts

I noticed something funny with an order I received yesterday and wanted to check it out.  They paid with PayPal though I don't know if that makes a difference. PayPal transaction went thru smoothly.

I made a test purchase of just one and when I look at the product after (frontend) the quantity has not changed.  It has in admin - but not storefront.  I have to manually go to admin and clear the cache for the correct quantity to show storefront.  Thanks for any and all help.

 

My product page is heavily modified.  This is the code and how it looks

 

 

 

<h4 class="prodprice" style="border-top:1px dotted #C0C0C0;">

               {if $PRODUCT.ctrl_sale}

               <span class="old_price" id="fbp"{if !$CTRL_HIDE_PRICES} data-price="{$PRODUCT.full_base_price}"{/if}>{$PRODUCT.price}</span>

               <span class="sale_price" id="ptp"{if !$CTRL_HIDE_PRICES} data-price="{$PRODUCT.price_to_pay}"{/if}>{$PRODUCT.sale_price}</span>

               {else}

               <span class="ptp" {if !$CTRL_HIDE_PRICES} data-price="{$PRODUCT.price_to_pay}"{/if}>{$PRODUCT.price}</span>

               {/if}

            </h4>  

            <div class="small-2 medium-2 columns">

      <input type="text" name="quantity" value="1" maxlength="3" class="quantity required text-center" >

      <input type="hidden" name="add" value="{$PRODUCT.product_id}">

   </div>

   <div class="small-1 medium-1 columns">

     &nbsp;   </div>

 

   <div  class="small-9 medium-9 columns">

    <!--  <link itemprop="availability" href="http://schema.org/InStock" /> -->

      <button type="submit" value="Add to Basket" class="button buyprod">Add to Basket</button>

   </div>

   {/if}

</div>

{else}

   {if $CTRL_HIDE_PRICES}

<p class="buy_button"><strong>{$LANG.catalogue.login_to_view}</strong></p>

   {else if $CTRL_OUT_OF_STOCK}

  <!-- <link itemprop="availability" href="http://schema.org/OutOfStock" /> -->

   <div class="medium13  pad-top ">Not available for purchase thru this store </div>

 

   {/if}

{/if}

</div>

 {if $PRODUCT.stock_level}

  <div class="row collapse">

  <div class="small-12 medium-11 large-11 columns">

  <div class="large14 bold pad-top ">{$PRODUCT.stock_level}&nbsp;&nbsp;Available thru this Store</div>  

  </div>

  

  <div class="row collapse">

  <div class="small-12 medium-12 large-12 columns">

  <div class="small12">Place quantity to purchase in the box - up to the available limit</div>  

  </div>

 </div> </div>

  {/if}

product-qty500.png

Link to comment
Share on other sites

We would need to check the code that queries the database for the stock levels. That would be in the catalogue class, function getProductStock().

In that function, there is:

        // Fall back to traditional stock check if there are no results for the combination or it is not used
        if (is_numeric($product_id) && ($products = $GLOBALS['db']->select('CubeCart_inventory', array('stock_level'), array('product_id' => (int)$product_id), false, 1, false, false)) !== false) {

The DB->select() call should have false as the seventh argument. This tells the database code to not use the cache when asking for the stock levels.

(Just above that is a call to query for stock levels in the Options Matrix table, but I think this product does not have options.)

There is another conversation on the forums where a fresh stock level is coming from the database, yet is not being properly reflected on the displayed page. We have yet to find where the problem lies.

Link to comment
Share on other sites

No I don't use options.  Could this have anything to do with the minimum maximum quantity to purchase added in 6.4.3?  So are you saying for now until a solution is found I just need to keep on top of clearing my cache?  How will I know a solution is found.  Did my code look ok to you.

Link to comment
Share on other sites

It is not the View Product template code we need to see.

We need to verify the core code, the catalogue class, function getProductStock(). See above.

I will look at the Min/Max Quantity feature to see if it could affect the value determined to be the stock level.

 

Link to comment
Share on other sites

(On CC644) I recorded a diagnostic tracer on the View Product page, and noted the stock level shown. Then I manually changed the stock level directly in the database.

I recorded another tracer, and noted that the stock level had changed to the new level.

Do you have any plugins or code snippets that might affect the stock levels of products?

Link to comment
Share on other sites

No plugins or code snippets that directly affect stock levels.  Did you look at my code above and see if my modifications could have caused it.  I might have done something wrong.  The stock level does change in admin - just not the store front unless I clear the cache

Link to comment
Share on other sites

Please make this small edit:

In /classes/catalogue.class.php, near line 461, frind:

$product['stock_level'] = ($GLOBALS['config']->get('config', 'stock_level')=='1') ? $product['stock_level'] : false;
$product['unsuppressed_stock_level'] = $product['stock_level'];
$GLOBALS['smarty']->assign('PRODUCT', $product);

Change to:

$product['stock_level'] = ($GLOBALS['config']->get('config', 'stock_level')=='1') ? $product['stock_level'] : false;
$product['unsuppressed_stock_level'] = $product['stock_level']; trigger_error('Logging the product stock level for '.$product['product_code'].' as '.$product['stock_level'], E_USER_NOTICE);
$GLOBALS['smarty']->assign('PRODUCT', $product);

By adding this trigger_error() statement, we can get an independent indication of the stock level before the stock level value being passed to the template.

You will see the notice in admin, Error Log, System Error Log tab.

Link to comment
Share on other sites

Take a note of the stock level from admin, Products, "SCO-2000".

On the storefront, view that product. Take note of the stock level shown there.

Do the stock levels agree?

If so, change the stock level in admin. Do NOT clear the cache.

On the storefront, go back to the homepage, then re-visit that product's page.

Did the stock level change?

If the stock levels did not agree, or the stock level displayed did not change after changing it in admin, then look in admin, Error Log, System Error Log for the report of what the stock level should be shown as.

Link to comment
Share on other sites

The stock levels agreed at first.   Changed the stock level in admin to 2 without clearing the cache and the stock level showed 2 in admin but the original 3 on the product page. No errors in the admin error logs.  cPanel error log shows 173 lines

Link to comment
Share on other sites

Posted (edited)

By the by - I didn't upgrade to 6.4.4. just applied the security patch.

ok got debug enabled.  Got 135 errors in admin error log including:

[<strong>Notice</strong>] /home/claudias/public_html/classes/catalogue.class.php:462 - Logging the product stock level for SCO-2000 as 2
https://www.claudiasbargains.com/baby-powder-scented-fragrance-oil.html

Got this in red:

Hack: 1626478097.53770 --- Duration: 21389 µs [ERROR - NOT CACHED]
INSERT INTO `CubeCart_system_error_log` (`message`,`url`,`backtrace`,`time`) VALUES ('[<strong>Notice</strong>] /home/claudias/public_html/classes/catalogue.class.php:462 - Logging the product stock level for SCO-2000 as 3','https://www.claudiasbargains.com/baby-powder-scented-fragrance-oil.html','trigger_error() (catalogue.class.php:462)\ndisplayProduct() (cubecart.class.php:2898)\n_product() (cubecart.class.php:462)\nloadPage() (controller.index.inc.php:90)\ninclude() (index.php:20)\n','1626478097');

 

in cpanel lines 297-301 at bottom:

[16-Jul-2021 19:33:15 America/Louisville] PHP Notice:  Undefined variable: find_prev_next_prod_id in /home/claudias/public_html/modules/plugins/PrevNext/hooks/class.catalogue.productassign.php on line 26
[16-Jul-2021 19:33:15 America/Louisville] PHP Notice:  Trying to access array offset on value of type null in /home/claudias/public_html/modules/plugins/PrevNext/hooks/class.catalogue.productassign.php on line 26
[16-Jul-2021 19:33:15 America/Louisville] PHP Notice:  Undefined variable: find_prev_next_prod_id in /home/claudias/public_html/modules/plugins/PrevNext/hooks/class.catalogue.productassign.php on line 27
[16-Jul-2021 19:33:15 America/Louisville] PHP Notice:  Trying to access array offset on value of type null in /home/claudias/public_html/modules/plugins/PrevNext/hooks/class.catalogue.productassign.php on line 27
[16-Jul-2021 19:33:15 America/Louisville] PHP Notice:  Logging the product stock level for TLS-5500 as 1 in /home/claudias/public_html/classes/catalogue.class.php on line 462

Iine 229

[16-Jul-2021 19:25:02 America/Louisville] PHP Notice:  Logging the product stock level for SCO-2000 as 2 in /home/claudias/public_html/classes/catalogue.class.php on line 462

Line 267

[16-Jul-2021 19:27:37 America/Louisville] PHP Notice:  Logging the product stock level for SCO-2000 as 3 in /home/claudias/public_html/classes/catalogue.class.php on line 462

 

 
     
     
     
     
     
     
     
Edited by Claudia M
Link to comment
Share on other sites

So from line 229, you viewed the SCO-2000 page at 19:25, then adjusted the stock level, then viewed the SCO-2000 page at 19:27.

I assume you increased the stock level from 2 to 3?

If so, all this looks good. (Actually, the SQL query that inserts the entry into the CubeCart_system_error_log database table, the timestamp of 1626478097 suggests the time this happened was at 2:2:37GMT -- though adjusting for timezone differences keeps the minutes and seconds the same, but minutes are different by about 25 minutes. I can't explain that.)

However, the problem we are trying to solve would say that the stock level displayed was at 2 and stayed at 2 even though the value reported by these log entries suggest the value did change.

Link to comment
Share on other sites

I see this as the problem we are trying to solve would say that the stock level displayed was at 2 and stayed at 2 even though the value reported by these log entries suggest the value did change.

This points the finger directly at a rendered template page is getting cached. Or the hosting provider has implemented some sort of web server page caching. (I ran into that with Hiawatha Web Server.) But that is highly improbable.

With CC643, you are able to change the skin for yourself. For you, choose to use the standard Foundation and make the same tests.

On the Demo site, I changed the stock level from 153 to 150, did not clear the cache, and yet the View Product page did have the changed stock level.

Edited by bsmither
Link to comment
Share on other sites

I keep a copy of all the files I edit along with two copies of the current Foundation skin one for edits, one orginal for no edits.  Just for the heck of it I uploaded my class/catalogue.class file from my edited file (Not from the foundation skin). I then ran the stock level test again and it worked!! Tomorrow I'm going to compare the files and see what the heck the difference was!!!

Link to comment
Share on other sites

These are the only changes between the original 6.4.3 classes.catalogue.class.php file and my file. The stock level works using my changes. I thought you had mentioned others having this problem. Do you see anything in the original code that may cause the problem?

 

6.4.3  Line 71

{

        $pre_release = $GLOBALS['db']->select('CubeCart_inventory', 'MIN(`live_from`) AS `next_time`', '`live_from` > UNIX_TIMESTAMP()', false, 1, false, false);

        if(!is_null($pre_release[0]['next_time'])) {

            $this->_where_live_from = ' AND `live_from` < UNIX_TIMESTAMP() ';

        }

    }

 

MINE

{

        if($pre_release = $GLOBALS['db']->select('CubeCart_inventory', 'MIN(`live_from`) AS `next_time`', '`live_from` > UNIX_TIMESTAMP()', false, 1, false, false)) {

            $this->_where_live_from = ' AND `live_from` < UNIX_TIMESTAMP() ';

        }

    }

 

6.4.3  Line 406

}

                    $skin_data = GUI::getInstance()->getSkinData();

                    foreach ($reviews as $review) {

 

MINE

 }

                    foreach ($reviews as $review) {

 

6.4.3  Line 415

$review['gravatar'] = md5(strtolower(trim($review['email'])));

                            if($skin_data['info']['gravatar_ajax']) {

                                $review['gravatar_exists'] = true;

                            } else {

                                $gravatar_url = 'gravatar.com';

                                $gravatar_path = '/avatar/'.$review['gravatar'].'?d=404&r=g';

                                $review['gravatar_src'] = 'https://'.$gravatar_url.$gravatar_path;

                               

                                $request = new Request($gravatar_url, $gravatar_path, 443, true, false, 3, true);

                                $request->skiplog(true);

                                $request->setMethod('get');

                                $request->cache(true);

                                $request->customOption(CURLOPT_NOBODY, true);

                                $request->setSSL();

                                ob_start();

                                $request->send();

                                $result = ob_get_contents();

                                ob_end_clean();

                                $review['gravatar_exists'] = $result ? true : false;

                            }

                        } else {

                            $review['gravatar_exists'] = false;

 

MINE

 $review['gravatar'] = md5(strtolower(trim($review['email'])));

                            $review['gravatar_src'] = 'https://www.gravatar.com/avatar/'.$review['gravatar'].'?d=404&r=g';

                            $headers = get_headers($review['gravatar_src']);

                            $review['gravatar_exists'] = strstr($headers[0], '200') ? true : false;

                        } else {

                            $review['gravatar_exists'] = false;

 

6.4.3  Line 415

 $GLOBALS['gui']->addBreadcrumb($product['name'], currentPage());

            }

 

            // Output to main GUI

 

MINE

$GLOBALS['gui']->addBreadcrumb($product['name'], currentPage());

            }

// Start SemperFi Modification

                                    if($GLOBALS['config']->get('config','sfws_related_products_status_product_pages') == 1){

                                                if($GLOBALS['config']->get('config','sfws_related_products_amount_product_pages')){

                                                            $rp_limit = $GLOBALS['config']->get('config','sfws_related_products_amount_product_pages');

                                                } else {

                                                            $rp_limit = 3;

                                                }

                                                if(($GLOBALS['config']->get('config','sfws_related_products_status_hide_oos_options') == 3 && $GLOBALS['config']->get('config', 'hide_out_of_stock')) || $GLOBALS['config']->get('config','sfws_related_products_status_hide_oos_options') == 1) { // Always hidden or CubeCart says to hide

                                                            $stock_where_manual = " AND ((I.use_stock_level = '0') OR (I.use_stock_level = '1' AND I.stock_level > 0))";

                                                }

                                                $seed = mt_rand(1, 10000);

                                                $related_products_type = '';

                                                $get_related_products_manual_query = "SELECT R.related_product_id, I.* FROM ".$GLOBALS['config']->get('config','dbprefix')."CubeCart_related_products AS R INNER JOIN ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_inventory AS I ON R.related_product_id = I.product_id WHERE R.main_product_id = ".$product['product_id']." AND I.status = 1 AND I.available != 0 ".$stock_where_manual." ORDER BY RAND(".$seed.") LIMIT ".$rp_limit;

                                                $related_products_manual = $GLOBALS['db']->query($get_related_products_manual_query);

                                                if ($related_products_manual){

                                                            $related_products = $related_products_manual;

                                                            $related_products_type = 'Manual';

                                                } else {

                                                            if($GLOBALS['config']->get('config','sfws_related_products_status_product_pages_random') == 1){

                                                                        if(($GLOBALS['config']->get('config','sfws_related_products_status_hide_oos_options') == 3 && $GLOBALS['config']->get('config', 'hide_out_of_stock')) || $GLOBALS['config']->get('config','sfws_related_products_status_hide_oos_options') == 1) { // Always hidden or CubeCart says to hide

                                                                                    $stock_where_auto = " AND ((use_stock_level = '0') OR (use_stock_level = '1' AND stock_level > 0))";

                                                                        }

     $get_related_products_auto_query = "SELECT * FROM ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_inventory WHERE product_id != ".$product['product_id']." AND cat_id = ".$product['cat_id']." AND status = 1 AND available != 0 ".$stock_where_auto." ORDER BY RAND(".$seed.") LIMIT ".$rp_limit;                                                                   

     $related_products_auto = $GLOBALS['db']->query($get_related_products_auto_query);

                                                                        if ($related_products_auto){

                                                                                    $related_products = $related_products_auto;

                                                                                    $related_products_type = 'Auto';

                                                                        }

                                                            }

                                                }

                                                if ($related_products) {

                                                            foreach ($related_products as $related_product) {

                                                                        if($related_products_type == "Manual"){

                                                                                    $related_product['related_product_id'] = $related_product['related_product_id'];

                                                                        } else {

                                                                                    $related_product['related_product_id'] = $related_product['product_id'];

                                                                        }

                                                                        $category_data = $GLOBALS['catalogue']->getCategoryStatusByProductID($related_product['related_product_id']);

                                                                        $category_status = false;

                                                                        if (is_array($category_data)) {

                                                                                    foreach ($category_data as $trash => $data) {

                                                                                                if ($data['status'] == 1) {

                                                                                                            $category_status = true;

                                                                                                }

                                                                                    }

                                                                        }

                                                                        if (!$category_status) {

                                                                                    continue;

                                                                        }

                                                                        $GLOBALS['language']->translateProduct($related_product);

                                                                        $related_product['image'] = $GLOBALS['gui']->getProductImage($related_product['product_id'], 'small');

                                                                        $related_product['ctrl_sale'] = (!$GLOBALS['tax']->salePrice($related_product['price'], $related_product['sale_price']) || !$GLOBALS['config']->get('config', 'catalogue_sale_mode')) ? false : true;

                                                                        $GLOBALS['catalogue']->getProductPrice($related_product);

                                                                        $related_product_sale = $GLOBALS['tax']->salePrice($related_product['price'], $related_product['sale_price']);

                                                                        $related_product['price_unformatted'] = $related_product['price'];

                                                                        $related_product['sale_price_unformatted'] = ($related_product_sale) ? $related_product['sale_price'] : null;

                                                                        $related_product['price'] = $GLOBALS['tax']->priceFormat($related_product['price']);

                                                                        $related_product['sale_price'] = ($related_product_sale) ? $GLOBALS['tax']->priceFormat($related_product['sale_price']) : null;

                                                                        $related_product['ctrl_stock'] = (!$related_product['use_stock_level'] || $GLOBALS['config']->get('config', 'basket_out_of_stock_purchase') || ($related_product['use_stock_level'] && $GLOBALS['catalogue']->getProductStock($related_product['product_id'], null, true))) ? true : false;

                                                                        $related_product['url'] = $GLOBALS['seo']->buildURL('prod', $related_product['product_id'], '&amp;');

                                                                        $varsRelatedProducts[] = $related_product;

                                                            }

                                                            $GLOBALS['smarty']->assign('RELATED_PRODUCTS_TYPE', $related_products_type);

                                                            $GLOBALS['smarty']->assign('RELATED_PRODUCTS', $varsRelatedProducts);

                                                }

                                    }

                                    // End SemperFi Modification

 

            // Output to main GUI

 

6.4.3  Line 755

 public function getCategoryProducts($category_id, $page = 1, $per_page = 10, $hidden = false)

    {

        if (strtolower($page) == 'all') {

            $per_page = false;

            $page  = false;

        }

 

        $where2 = $this->outOfStockWhere(false, 'INV', true);

 

        if (($result = $GLOBALS['db']->query('SELECT I.product_id FROM `'.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_category_index` as I,  `'.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_inventory` as INV WHERE I.cat_id = '.$category_id.' AND I.product_id = INV.product_id AND INV.status = 1'.$where2)) !== false) {

            $this->_category_count = $GLOBALS['db']->numrows();

 

MINE

public function getCategoryProducts($category_id, $page = 1, $per_page = 10, $hidden = false)

    {

        if (strtolower($page) == 'all') {

            $per_page = false;

            $page  = false;

        }

 // START My do not show product on Cat Page if Sold   

$where = " AND INV.available = '1'";

        $where2 = $this->outOfStockWhere(false, 'INV', true);

        if (($result = $GLOBALS['db']->query('SELECT I.product_id FROM `'.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_category_index` as I,  `'.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_inventory` as INV WHERE I.cat_id = '.$category_id.' AND I.product_id = INV.product_id AND INV.status = 1'.$where.$where2)) !== false) {

          // END My do not show product on Cat Page if Sold

            $this->_category_count = $GLOBALS['db']->numrows();

 

6.4.3 Line 1059

$where = $this->outOfStockWhere(array('product_id' => $product_id, 'status' => 1));

 

        if (is_array($order) && isset($order['price']) && $GLOBALS['config']->get('config', 'catalogue_sale_mode')) {

            $query = 'SELECT *, IF(`sale_price`> 0 AND `sale_price` < `price`,`sale_price`,`price`) AS `price_sort` FROM '.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_inventory WHERE '.$where.' ORDER BY `price_sort` '.$order['price'];

            if (!empty($page) && is_numeric($page)) {

                $query = $query.' LIMIT '.$per_page.' OFFSET '.(int)($page-1)*$per_page;

            }

            $result = $GLOBALS['db']->query($query);

        } else {

 

MINE

$where = $this->outOfStockWhere(array('product_id' => $product_id, 'status' => 1));

 

        if (is_array($order) && isset($order['price']) && $GLOBALS['config']->get('config', 'catalogue_sale_mode')) {

            if (!empty($page) && is_numeric($page)) {

                $query = 'SELECT *, IF(`sale_price` > 0, `sale_price`, `price`) AS price_sort FROM '.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_inventory WHERE '.$where.' ORDER BY `price_sort` '.$order['price'].' LIMIT '.$per_page.' OFFSET '.(int)($page-1)*$per_page;

            } else {

                $query = 'SELECT *, IF(`sale_price` > 0, `sale_price`, `price`) AS price_sort FROM '.$GLOBALS['config']->get('config', 'dbprefix').'CubeCart_inventory WHERE '.$where.' ORDER BY `price_sort` '.$order['price'];

            }

            $result = $GLOBALS['db']->query($query);

        } else {

 

6.4.3 Line 1843

foreach($manufacturers as $manufacturer) {

                    $ids[] = $manufacturer['id'];

                }

                $manufacturers = implode(',',$ids);

                $where[] = "AND `I`.`manufacturer` IN($manufacturers)";

            }

 

MINE

  foreach($manufacturers as $manufacturer) {

                    $ids[] = $manufacturer['id'];

                }

                $manufacturers = implode(',',$ids);

                $where[] = "OR `I`.`manufacturer` IN($manufacturers)";

            }

Link to comment
Share on other sites

I cannot duplicate the problem.

As an experiment, in /includes/global.inc.php, add this line at the bottom (just above the very last line):

$glob['safe_mode'] = true;

This will inhibit all plugins and code snippets. (But not any custom coding.)

Make the test. Did the displayed stock level change?

Undo the change made above to restore normal operation.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...