Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

[Contribution] QTpro - Quantity Tracking Professional


zonetown

Recommended Posts

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/estrella/public_html/includes/functions/database.php on line 103

 

You need to double check your changes to checkout_process - something must have gotten dropped in your install. One of the two lines:

 

                  if (tep_db_num_rows($attributes_stock_query) > 0) {

or

       if (tep_db_num_rows($stock_query) > 0) {

 

isn't getting its query set. I'll bet its the second one and that you'll find this line:

            $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");

 

out of place. Its easy to lose track of the closing braces in that closing up of the nested IF where its placed.

Link to comment
Share on other sites

Hi Ralph,

 

Thanks for helping. But I don't quite understand. Can help?

 

I believe you're talking abt the bolded part? But I'm not quite sure how to do the checking. any help appreciated. thanks! :)

 

<?php
/*
 $Id: checkout_process.php,v 1.128 2003/05/28 18:00:29 hpdl Exp $

 osCommerce, Open Source E-Commerce Solutions
 http://www.oscommerce.com

 Copyright (c) 2003 osCommerce

 Released under the GNU General Public License
*/

 include('includes/application_top.php');

// if the customer is not logged on, redirect them to the login page
 if (!tep_session_is_registered('customer_id')) {
   $navigation->set_snapshot(array('mode' => 'SSL', 'page' => FILENAME_CHECKOUT_PAYMENT));
   tep_redirect(tep_href_link(FILENAME_LOGIN, '', 'SSL'));
 }
 
 if (!tep_session_is_registered('sendto')) {
   tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL'));
 }

 if ( (tep_not_null(MODULE_PAYMENT_INSTALLED)) && (!tep_session_is_registered('payment')) ) {
   tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL'));
}

// avoid hack attempts during the checkout procedure by checking the internal cartID
 if (isset($cart->cartID) && tep_session_is_registered('cartID')) {
   if ($cart->cartID != $cartID) {
     tep_redirect(tep_href_link(FILENAME_CHECKOUT_SHIPPING, '', 'SSL'));
   }
 }

 include(DIR_WS_LANGUAGES . $language . '/' . FILENAME_CHECKOUT_PROCESS);

// load selected payment module
 require(DIR_WS_CLASSES . 'payment.php');
if ($credit_covers) $payment=''; //ICW added for CREDIT CLASS
 $payment_modules = new payment($payment);

// load the selected shipping module
 require(DIR_WS_CLASSES . 'shipping.php');
 $shipping_modules = new shipping($shipping);

 require(DIR_WS_CLASSES . 'order.php');
 $order = new order;

// load the before_process function from the payment modules
 $payment_modules->before_process();

 require(DIR_WS_CLASSES . 'order_total.php');
 $order_total_modules = new order_total;

 $order_totals = $order_total_modules->process();

 $sql_data_array = array('customers_id' => $customer_id,
                         'customers_name' => $order->customer['firstname'] . ' ' . $order->customer['lastname'],
                         'customers_company' => $order->customer['company'],
                         'customers_street_address' => $order->customer['street_address'],
                         'customers_suburb' => $order->customer['suburb'],
                         'customers_city' => $order->customer['city'],
                         'customers_postcode' => $order->customer['postcode'], 
                         'customers_state' => $order->customer['state'], 
                         'customers_country' => $order->customer['country']['title'], 
                         'customers_telephone' => $order->customer['telephone'], 
                         'customers_email_address' => $order->customer['email_address'],
                         'customers_address_format_id' => $order->customer['format_id'], 
                         'delivery_name' => $order->delivery['firstname'] . ' ' . $order->delivery['lastname'], 
                         'delivery_company' => $order->delivery['company'],
                         'delivery_street_address' => $order->delivery['street_address'], 
                         'delivery_suburb' => $order->delivery['suburb'], 
                         'delivery_city' => $order->delivery['city'], 
                         'delivery_postcode' => $order->delivery['postcode'], 
                         'delivery_state' => $order->delivery['state'], 
                         'delivery_country' => $order->delivery['country']['title'], 
                         'delivery_address_format_id' => $order->delivery['format_id'], 
                         'billing_name' => $order->billing['firstname'] . ' ' . $order->billing['lastname'], 
                         'billing_company' => $order->billing['company'],
                         'billing_street_address' => $order->billing['street_address'], 
                         'billing_suburb' => $order->billing['suburb'], 
                         'billing_city' => $order->billing['city'], 
                         'billing_postcode' => $order->billing['postcode'], 
                         'billing_state' => $order->billing['state'], 
                         'billing_country' => $order->billing['country']['title'], 
                         'billing_address_format_id' => $order->billing['format_id'], 
                         'payment_method' => $order->info['payment_method'], 
                         'cc_type' => $order->info['cc_type'], 
                         'cc_owner' => $order->info['cc_owner'], 
                         'cc_number' => $order->info['cc_number'], 
                         'cc_expires' => $order->info['cc_expires'], 
                         'date_purchased' => 'now()', 
                         'orders_status' => $order->info['order_status'], 
                         'currency' => $order->info['currency'], 
                         'currency_value' => $order->info['currency_value']);
 tep_db_perform(TABLE_ORDERS, $sql_data_array);
 $insert_id = tep_db_insert_id();
 for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {
   $sql_data_array = array('orders_id' => $insert_id,
                           'title' => $order_totals[$i]['title'],
                           'text' => $order_totals[$i]['text'],
                           'value' => $order_totals[$i]['value'], 
                           'class' => $order_totals[$i]['code'], 
                           'sort_order' => $order_totals[$i]['sort_order']);
   tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
 }

 $customer_notification = (SEND_EMAILS == 'true') ? '1' : '0';
 $sql_data_array = array('orders_id' => $insert_id, 
                         'orders_status_id' => $order->info['order_status'], 
                         'date_added' => 'now()', 
                         'customer_notified' => $customer_notification,
                         'comments' => $order->info['comments']);
 tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);

// initialized for the email confirmation
 $products_ordered = '';
 $subtotal = 0;
 $total_tax = 0;

 for ($i=0, $n=sizeof($order->products); $i<$n; $i++) {
// Stock Update - Joao Correia
   if (STOCK_LIMITED == 'true') {
     if (DOWNLOAD_ENABLED == 'true') {
       $stock_query_raw = "SELECT products_quantity, pad.products_attributes_filename 
                           FROM " . TABLE_PRODUCTS . " p
                           LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                            ON p.products_id=pa.products_id
                           LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                            ON pa.products_attributes_id=pad.products_attributes_id
                           WHERE p.products_id = '" . tep_get_prid($order->products[$i]['id']) . "'";
// Will work with only one option for downloadable products
// otherwise, we have to build the query dynamically with a loop
       $products_attributes = $order->products[$i]['attributes'];
       if (is_array($products_attributes)) {
         $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'";
       }
        } else {
           if (is_array($products_attributes)) {
               $allspecial = true;
               $products_stock_attributes_array = array();
               For($k = 0, $n3 = sizeof($products_attributes); $k < $n3; $k++) {
                   if ($products_attributes[$k]['special'] == 0) {
                       $products_stock_attributes_array[] = $products_attributes[$k]['option_id'] . "-" . $products_attributes[$k]['value_id'];
                       $allspecial = false;
                   }
               } 
               if (!$allspecial) {
                 asort($products_stock_attributes_array, SORT_NUMERIC);
                 reset($products_stock_attributes_array);
                 $products_stock_attributes = implode(",", $products_stock_attributes_array);
                 $attributes_stock_query = tep_db_query("select products_stock_quantity from " . TABLE_PRODUCTS_STOCK . " where products_stock_attributes = '$products_stock_attributes' AND products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
              [B]   if (tep_db_num_rows($attributes_stock_query) > 0) {
                     $attributes_stock_values = tep_db_fetch_array($attributes_stock_query);
                     $attributes_stock_left = $attributes_stock_values['products_stock_quantity'] - $order->products[$i]['qty'];
                     if ($attributes_stock_left < 1) {
                         tep_db_query("update " . TABLE_PRODUCTS_STOCK . " set products_stock_quantity = '0' where products_stock_attributes = '$products_stock_attributes' AND products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
                         $actual_stock_bought = $attributes_stock_values['products_stock_quantity'];
                     } else {
                         tep_db_query("update " . TABLE_PRODUCTS_STOCK . " set products_stock_quantity = '" . $attributes_stock_left . "' where products_stock_attributes = '$products_stock_attributes' AND products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
                         $actual_stock_bought = $order->products[$i]['qty'];
                     } 
                 } else {
                     $actual_stock_bought = 0;
                 }
              }  else {
                $actual_stock_bought = $order->products[$i]['qty'];
              }
           } else {
               $actual_stock_bought = $order->products[$i]['qty'];
           } 
           $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
       } 
       if (tep_db_num_rows($stock_query) > 0) {
           $stock_values = tep_db_fetch_array($stock_query);
           // do not decrement quantities if products_attributes_filename exists[/B]            if ((DOWNLOAD_ENABLED != 'true') || (!$stock_values['products_attributes_filename'])) {
               $stock_left = $stock_values['products_quantity'] - $actual_stock_bought;
           } else {
               $stock_left = $stock_values['products_quantity'];
           } 
           tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $stock_left . "' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
           if (($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false')) {
               tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
           } 
       } 
   } 
   // Update products_ordered (for bestsellers list)
   tep_db_query("update " . TABLE_PRODUCTS . " set products_ordered = products_ordered + " . sprintf('%d', $order->products[$i]['qty']) . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");

   $sql_data_array = array('orders_id' => $insert_id, 
                           'products_id' => tep_get_prid($order->products[$i]['id']), 
                           'products_model' => $order->products[$i]['model'], 
                           'products_name' => $order->products[$i]['name'], 
                           'products_price' => $order->products[$i]['price'], 
                           'final_price' => $order->products[$i]['final_price'], 
                           'products_tax' => $order->products[$i]['tax'], 
                           'products_quantity' => $order->products[$i]['qty']);
   tep_db_perform(TABLE_ORDERS_PRODUCTS, $sql_data_array);
   $order_products_id = tep_db_insert_id();
$order_total_modules->update_credit_account($i);//ICW ADDED FOR CREDIT CLASS SYSTEM

//------insert customer choosen option to order--------
   $attributes_exist = '0';
   $products_ordered_attributes = '';
   if (isset($order->products[$i]['attributes'])) {
     $attributes_exist = '1';
     for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
       if (DOWNLOAD_ENABLED == 'true') {
         $attributes_query = "select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pad.products_attributes_maxdays, pad.products_attributes_maxcount , pad.products_attributes_filename 
                              from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa 
                              left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                               on pa.products_attributes_id=pad.products_attributes_id
                              where pa.products_id = '" . $order->products[$i]['id'] . "' 
                               and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' 
                               and pa.options_id = popt.products_options_id 
                               and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' 
                               and pa.options_values_id = poval.products_options_values_id 
                               and popt.language_id = '" . $languages_id . "' 
                               and poval.language_id = '" . $languages_id . "'";
         $attributes = tep_db_query($attributes_query);
       } else {
         $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'");
       }
       $attributes_values = tep_db_fetch_array($attributes);

       $sql_data_array = array('orders_id' => $insert_id, 
                               'orders_products_id' => $order_products_id, 
                               'products_options' => $attributes_values['products_options_name'],
                               'products_options_values' => $attributes_values['products_options_values_name'], 
                               'options_values_price' => $attributes_values['options_values_price'], 
                               'price_prefix' => $attributes_values['price_prefix']);
       tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array);

       if ((DOWNLOAD_ENABLED == 'true') && isset($attributes_values['products_attributes_filename']) && tep_not_null($attributes_values['products_attributes_filename'])) {
         $sql_data_array = array('orders_id' => $insert_id, 
                                 'orders_products_id' => $order_products_id, 
                                 'orders_products_filename' => $attributes_values['products_attributes_filename'], 
                                 'download_maxdays' => $attributes_values['products_attributes_maxdays'], 
                                 'download_count' => $attributes_values['products_attributes_maxcount']);
         tep_db_perform(TABLE_ORDERS_PRODUCTS_DOWNLOAD, $sql_data_array);
       }
       $products_ordered_attributes .= "\n\t" . $attributes_values['products_options_name'] . ' ' . $attributes_values['products_options_values_name'];
     }
   }
//------insert customer choosen option eof ----
   $total_weight += ($order->products[$i]['qty'] * $order->products[$i]['weight']);
   $total_tax += tep_calculate_tax($total_products_price, $products_tax) * $order->products[$i]['qty'];
   $total_cost += $total_products_price;

   //TotalB2B start
   $products_ordered .= $order->products[$i]['qty'] . ' x ' . $order->products[$i]['name'] . ' (' . $order->products[$i]['model'] . ') = ' . $currencies->display_price_nodiscount($order->products[$i]['final_price'], $order->products[$i]['tax'], $order->products[$i]['qty']) . $products_ordered_attributes . "\n";
   //TotalB2B end

 }
$order_total_modules->apply_credit();//ICW ADDED FOR CREDIT CLASS SYSTEM

// lets start with the email confirmation
 $email_order = STORE_NAME . "\n" . 
                EMAIL_SEPARATOR . "\n" . 
                EMAIL_TEXT_ORDER_NUMBER . ' ' . $insert_id . "\n" .
                EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $insert_id, 'SSL', false) . "\n" .
                EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n";
 if ($order->info['comments']) {
   $email_order .= tep_db_output($order->info['comments']) . "\n\n";
 }
 $email_order .= EMAIL_TEXT_PRODUCTS . "\n" . 
                 EMAIL_SEPARATOR . "\n" . 
                 $products_ordered . 
                 EMAIL_SEPARATOR . "\n";

 for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {
   $email_order .= strip_tags($order_totals[$i]['title']) . ' ' . strip_tags($order_totals[$i]['text']) . "\n";
 }

 if ($order->content_type != 'virtual') {
   $email_order .= "\n" . EMAIL_TEXT_DELIVERY_ADDRESS . "\n" . 
                   EMAIL_SEPARATOR . "\n" .
                   tep_address_label($customer_id, $sendto, 0, '', "\n") . "\n";
 }

 $email_order .= "\n" . EMAIL_TEXT_BILLING_ADDRESS . "\n" .
                 EMAIL_SEPARATOR . "\n" .
                 tep_address_label($customer_id, $billto, 0, '', "\n") . "\n\n";
 if (is_object($$payment)) {
   $email_order .= EMAIL_TEXT_PAYMENT_METHOD . "\n" . 
                   EMAIL_SEPARATOR . "\n";
   $payment_class = $$payment;
   $email_order .= $payment_class->title . "\n\n";
   if ($payment_class->email_footer) { 
     $email_order .= $payment_class->email_footer . "\n\n";
   }
 }
 tep_mail($order->customer['firstname'] . ' ' . $order->customer['lastname'], $order->customer['email_address'], EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);

// send emails to other people
 if (SEND_EXTRA_ORDER_EMAILS_TO != '') {
   tep_mail('', SEND_EXTRA_ORDER_EMAILS_TO, EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 }
 
 // Include OSC-AFFILIATE 
 require(DIR_WS_INCLUDES . 'affiliate_checkout_process.php');

// load the after_process function from the payment modules
 $payment_modules->after_process();

 $cart->reset(true);
 
 //added for Points module  
 $sqlquery = tep_db_query('SELECT value from '. TABLE_ORDERS_TOTAL . ' where orders_id = ' . $insert_id . ' and class = \'ot_total\' ');
 
 $order_value = tep_db_fetch_array($sqlquery);
 
 $confquery = tep_db_query('select configuration_value from '. TABLE_CONFIGURATION . ' where configuration_key = "POINTS_PER_DOLLAR_PURCHASE" ');
 
 $confvalue = tep_db_fetch_array($confquery);
 $points_per_dollar = $confvalue['configuration_value'];
 $points_awarded = $order_value['value'] * $points_per_dollar;
     
   $sql_data_array = array('unique_id' => '',
                           'customer_id' => $customer_id,
                           'orders_id' => $insert_id,
                           'points_pending' => $points_awarded,
                           'date_added' => 'now()', 
                           'status' => 1);
                           
   tep_db_perform('customer_points_pending', $sql_data_array);


// unregister session variables used during checkout
 tep_session_unregister('sendto');
 tep_session_unregister('billto');
 tep_session_unregister('shipping');
 tep_session_unregister('payment');
 tep_session_unregister('comments');
if(tep_session_is_registered('credit_covers')) tep_session_unregister('credit_covers');
 $order_total_modules->clear_posts();//ICW ADDED FOR CREDIT CLASS SYSTEM

 tep_redirect(tep_href_link(FILENAME_CHECKOUT_SUCCESS, '', 'SSL'));

 require(DIR_WS_INCLUDES . 'application_bottom.php');
?>

Edited by estrellashopping
Link to comment
Share on other sites

Hi Ralph,

 

Thanks for helping. But I don't quite understand. Can help?

 

I believe you're talking abt the bolded part? But I'm not quite sure how to do the checking. any help appreciated. thanks! :)

 

To do the checking you need to compare the QT Pro code with what you are running and make sure it matches. You can do this by eye, but its easiest with a compare program. Particularly when you are trying to merge multiple contributions like it seems you are. When you're doing this you need to compare QT Pro against the base osCommerce code and also your other contribution against the osCommerce base. Then make sure you have the code from both of them in the right places. Kdiff3 is a great free program to do this.

 

If you do this you'll find the line

 $products_attributes = $order->products[$i]['attributes'];

is out of place and the line:

            $stock_query = tep_db_query($stock_query_raw);

is missing.

Link to comment
Share on other sites

Hi guys,

 

I'm very interested in QTPro - can't understand why OSCommerce supports options and not a different stock pr. option (most options has seperate stock obviously :) - but great QTPro is there.

 

I'm also using Product_options_type (selectlist,radio etc. option types) and static options.

I've merged in QTPro like this:

       
       $products_options_query = tep_db_query("select pov.products_options_values_id, pov.products_options_values_name, pa.options_values_price, pa.price_prefix, pa.options_id, pa.options_values_id from " . TABLE_PRODUCTS_ATTRIBUTES . " pa, " . TABLE_PRODUCTS_OPTIONS_VALUES . " pov where pa.products_id = '" . (int)$HTTP_GET_VARS['products_id'] . "' and pa.options_id = '" . (int)$products_options_name['products_options_id'] . "' and pa.options_values_id = pov.products_options_values_id and pov.language_id = '" . (int)$languages_id . "'");
       echo '<table border="0" cellspacing="0" cellpadding="2"> ';
       while ($products_options = tep_db_fetch_array($products_options_query)) {
//START get attribute stock values/show out of stock QTPro
       if (!$products_options_name['special']) {
         $attribute_stock_query = tep_db_query("select products_stock_quantity from " . TABLE_PRODUCTS_STOCK . " where products_id = '" . (int)$HTTP_GET_VARS['products_id'] . "' AND products_stock_attributes REGEXP '(^|,)" . (int)$products_options['options_id'] . "-" . (int)$products_options['options_values_id']. "(,|$)' AND products_stock_quantity > 0");
         $attrstock=tep_db_num_rows($attribute_stock_query);                  }
             // END get attribute stock values/show out of stock
                                       $static_attribute = false;
                                       if($products_options_name['products_options_is_static'] == '0'){
           if ($attrstock == 0)
                 $products_options_array[] = array('id' => $products_options['products_options_values_id'], 'text' => " Out Of Stock - ".$products_options['products_options_values_name']);
           else
...(same as it was before).

 

Only problem is, that I'm testing this on the matrox G200 MMS item from default shop (see here: http://www.ebutikdemo.minebutik.dk/product...4&products_id=1 ) and I've set the stock to be like this:

Value 4 mb 1

Value 8 mb 0

Premium 4 mb 0

Premium 8 mb 4

 

ie. Premium 8mb should be in stock and premium 4mb should not - but on the product page, when I switch to premium it does not work - as 4mb is set to be in stock.

The problem it would seem is that the Memory table, is not updated when I switch value to premium. Would it be best to "merge all selectlist options" - or is there some javascript one can use to "update" the table?

Link to comment
Share on other sites

I've set the stock to be like this:

  Value    4 mb    1 

  Value    8 mb    0 

  Premium    4 mb    0 

  Premium    8 mb    4

 

ie. Premium 8mb should be in stock and premium 4mb should not - but on the product page, when I switch to premium it does not work - as 4mb is set to be in stock.

The problem it would seem is that the Memory table, is not updated when I switch value to premium. Would it be best to "merge all selectlist options" - or is there some javascript one can use to "update" the table?

It is working as designed. There are some prior posts on this. I've got an update in final testing right now that will add the functionality you are looking for. I'll probably be done testing and post it next week sometime.

Link to comment
Share on other sites

I am using an older version of QTPRO as the newer ones do not work on my site, and yes I am using MS2.2. For some reason the newer versions just don't function properly, and I can get what I need out of the older ones. My concern is that although the code appears to be OK on the shopping cart page, it never displays the product attributes there or in any step of checkout. Here is the QTPRO code from my checkout_shipping.php page. Would someone be so kind as to tell me if it appears to be OK, or why it may not be working?

 

Thanks

 

<?php
   $info_box_contents = array();
   $info_box_contents[0][] = array('align' => 'center',
                                   'params' => 'class="main"',
                                   'text' => '<font color="#FFFFFF"><b>' . TABLE_HEADING_REMOVE . '</b></font>');

   $info_box_contents[0][] = array('align' => 'center',
      	 'params' => 'class="main"',
                                   'text' => '<font color="#FFFFFF"><b>' . TABLE_HEADING_PRODUCTS . '</b></font>');

   $info_box_contents[0][] = array('align' => 'center',
                                   'params' => 'class="main"',
                                   'text' => '<font color="#FFFFFF"><b>' . TABLE_HEADING_QUANTITY . '</b></font>');

   $info_box_contents[0][] = array('align' => 'right',
                                   'params' => 'class="main"',
                                   'text' => '<font color="#FFFFFF"><b>' . TABLE_HEADING_TOTAL . ' </b></font>');

       $any_out_of_stock = 0;
   $products = $cart->get_products();
   for ($i=0, $n=sizeof($products); $i<$n; $i++) {
// Push all attributes information in an array
     if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
       while (list($option, $value) = each($products[$i]['attributes'])) {
         echo tep_draw_hidden_field('id[' . $products[$i]['id'] . '][' . $option . ']', $value);
         $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix
                                     from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                     where pa.products_id = '" . $products[$i]['id'] . "'
                                      and pa.options_id = '" . $option . "'
                                      and pa.options_id = popt.products_options_id
                                      and pa.options_values_id = '" . $value . "'
                                      and pa.options_values_id = poval.products_options_values_id
                                      and popt.language_id = '" . $languages_id . "'
                                      and poval.language_id = '" . $languages_id . "'");
         $attributes_values = tep_db_fetch_array($attributes);

         $products[$i][$option]['products_options_name'] = $attributes_values['products_options_name'];
         $products[$i][$option]['options_values_id'] = $value;
         $products[$i][$option]['products_options_values_name'] = $attributes_values['products_options_values_name'];
         $products[$i][$option]['options_values_price'] = $attributes_values['options_values_price'];
         $products[$i][$option]['price_prefix'] = $attributes_values['price_prefix'];
       }
     }
   }

   for ($i=0, $n=sizeof($products); $i<$n; $i++) {
     if (($i/2) == floor($i/2)) {
       $info_box_contents[] = array('params' => 'class="productListing-even"');
     } else {
       $info_box_contents[] = array('params' => 'class="productListing-odd"');
     }

     $cur_row = sizeof($info_box_contents) - 1;

     $info_box_contents[$cur_row][] = array('align' => 'center',
                                            'params' => 'class="productListing-data" valign="middle"',
                                            'text' => tep_draw_checkbox_field('cart_delete[]', $products[$i]['id']));

     $products_name = '<table border="0" cellspacing="0" cellpadding="4" bgcolor="#FFFFFF">' .
                      '  <tr>' .
                      '    <td class="productListing-data" align="center" valign="middle"><a href="' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id']) . '">' . tep_image(DIR_WS_IMAGES . $products[$i]['image'], $products[$i]['name'], SMALL_IMAGE_WIDTH, SMALL_IMAGE_HEIGHT) . '</a></td>' .
                      '    <td class="productListing-data" align="ceneter" valign="middle"><a href="' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id']) . '"><b>' . $products[$i]['name'] . '</b></a>';

     if (STOCK_CHECK == 'true') {
       $stock_check = tep_check_stock($products[$i]['id'], $products[$i]['quantity']);
       if (tep_not_null($stock_check)) {
         $any_out_of_stock = 1;

         $products_name .= $stock_check;
       }
     }

     if (isset($products[$i]['attributes']) && is_array($products[$i]['attributes'])) {
       reset($products[$i]['attributes']);
       while (list($option, $value) = each($products[$i]['attributes'])) {
         $products_name .= '<br><small><i> - ' . $products[$i][$option]['products_options_name'] . ' ' . $products[$i][$option]['products_options_values_name'] . '</i></small>';
       }
     }

     $products_name .= '  </td>' .
                       '  </tr>' .
                       '</table>';

     $info_box_contents[$cur_row][] = array('align' => 'center', 
             'params' => 'class="productListing-data"',
                                            'text' => $products_name);

     $info_box_contents[$cur_row][] = array('align' => 'center',
                                            'params' => 'class="productListing-data" valign="middle"',
                                            'text' => tep_draw_input_field('cart_quantity[]', $products[$i]['quantity'], 'size="5" maxchars="5"') . tep_draw_hidden_field('products_id[]', $products[$i]['id']));

     $info_box_contents[$cur_row][] = array('align' => 'center',
                                            'params' => 'class="productListing-data" valign="middle"',
                                            'text' => '<b>' . $currencies->display_price($products[$i]['final_price'], tep_get_tax_rate($products[$i]['tax_class_id']), $products[$i]['quantity']) . ' </b></td></tr><tr><td bgcolor="#FFFFFF" colspan="4"><hr width="100%" size="1" noshade color="#FF6600"></td></tr>');
   }

   new productListingBox($info_box_contents);
?>

Link to comment
Share on other sites

I am using an older version of QTPRO as the newer ones do not work on my site, and yes I am using MS2.2. For some reason the newer versions just don't function properly, and I can get what I need out of the older ones. My concern is that although the code appears to be OK on the shopping cart page, it never displays the product attributes there or in any step of checkout. Here is the QTPRO code from my checkout_shipping.php page. Would someone be so kind as to tell me if it appears to be OK, or why it may not be working?

 

Thanks

 

This code looks more like shopping_cart.tpl.php from a store with the BTS contribution installed. It has none of the QT Pro changes made to it. But that wouldn't cause the problem you are describing.

 

The specific problem you are describing is more likely caused by a problem with product_info.php or application_top.php. It doesn't sound like the attributes are getting added to the cart. That could be due to changing the names of the attribute dropdowns in product_info.php or changing them to radiosets or checkboxes. application_top.php is expecting the attributes to be dropdowns with a specific naming convention. Or you could have changes to application_top.php that mangled the code that adds to the cart so that it misses the attributes.

Link to comment
Share on other sites

The new version I have been working on is complete, tested, packaged and ready to go. :) Because I included a manual with screenshots and a backup of my test database it is a big zip file - over the 300K limit for automatic postings to the contributions. So its pending manual approval. I don't know how long that takes. If it takes too long or gets rejected I'll post it in pieces.

 

Here's what's in the new version:

 

New plugin architecture for product attribute display

 

Four plugins for product attribute display, most with additional options:

 

- Multiple dropdowns with out of stock messaging and cart add prevention,

- Sequenced dropdowns showing the customer attribute selections one at a time so that only an in stock combination can be selected

- single dropdown with attribute combinations instead of separate attribute dropdowns

- single radioset - same as single dropdown but a radioset

 

One of these plugins will likely give you a solution to the out of stock attribute combination problem that you will like.

 

The "special" flag for product options has been renamed to "Track Stock" to better reflect its use.

 

On product information page, attributes that stock is tracked for are displayed before attributes that stock is not tracked for.

 

Delete order with restock now restocks product attributes (for orders created with Version 4 installed only)

 

Attribute stock will now go negative if oversold to be consistent with how osCommerce handles product stock

 

stock.php now compatible with register_globals off (if you are applying this to a register globals off version of osCommerce)

 

attribute stock check added to checkout_confirmation

 

Low stock attribute report fixes:

-Language file for English added so titles display

-Multiple attributes per product now work

-Non-stock attributes are ignored

-Product hyperlinks now work

 

Cleanup of products_stock table

 

Moved admin folder under catalog folder to match base osCommerce folder structure

 

A real manual

 

Test data and thorough test script

 

 

I hope you find it useful. Let me know if you find any problems.

Link to comment
Share on other sites

:thumbsup:  Sounds like it's what we're waiting for!! Hopefully we can get it soon!!!

Well, it still hasn't shown up. I'll wait a bit longer before I ping Harald. In the mean time I've posted the new version at:

QT Pro Version 4.0

 

Its 600K+ most of which is the screenshots. I tried to shrink them as much as I could and keep them readable but they still are pretty big. If anyone knows some good mojo to shrink them let me know.

 

I'll leave the file there until I get it posted on the osCommerce contributions site.

Link to comment
Share on other sites

Well, it still hasn't shown up.  I'll wait a bit longer before I ping Harald.  In the mean time I've posted the new version at:

QT Pro Version 4.0

 

Its 600K+ most of which is the screenshots.  I tried to shrink them as much as I could and keep them readable but they still are pretty big.  If anyone knows some good mojo to shrink them let me know.

 

I'll leave the file there until I get it posted on the osCommerce contributions site.

 

Thanks to Tom Thumb for a simple tip (save as gif instead of jpg) that allowed me to shrink the images dramatically - over 300K! Working for big companies I've always had a creative department who handled the images and I only had to worry about the code. At home I am almost always working with digital photos or scans where jpg is better so I didn't know screenshots were best saved as gifs.

 

The net is the file size is now under 300K and is posted to the contributions. Pleae grab it from there. I'll remove the version with the bloated images from my web site.

Link to comment
Share on other sites

Hi - I just dl'ed qtpro4 - GREAT options.

 

I am however VERY sorry that you yourself has no use for Option Types and static options and attributes copier contributions (because I do very much - and if you used them - you'd probably had included products_info.php etc. files in a Option types,static options version ;)

 

if anyone who has the need for these with qtpro4 and manage to get it working - or perhaps want to work on it with me I would be very happy to hear from you. I'm not "into" OSC code enough to believe in myself enough to take the merging of qtpro4 with Option types and static options upon myself, just yet :)

 

This would be sooo much easier if OSC was templates - so one could worry about the data manipulation first - and then handle the layout logic seperately :) I believe that's part of MS3 plans. It would be much easier to merge contributions if OSC was templated properly. (and BTS does not make it easier - because almost no contributions are written for it - so you have to convert them all to BTS - and THEN merge them). if OSC MS3 is templateable - every contribution will be easily mergeable to that... Enough mumbling :)

Link to comment
Share on other sites

I am however VERY sorry that you yourself has no use for Option Types and static options and attributes copier contributions (because I do very much - and if you used them - you'd probably had included products_info.php etc. files in a Option types,static options version ;)

Actually, that's why I went to the plug-in architecture. So that plug-ins for all kinds of things including other contribution merged versions could be supplied without overlaying the QT Pro base code. I've still got a few things to work out to make it really flexible for adding other contributions.

 

Its not that I have no use for these (well, at least I have a use for Attribute Sorter/Copier) its just a matter of time. I will be applying QT Pro to a loaded osCommerce version vs. merging in a bunch of other contributions myself. So, I chose to get this version out to the world while I move on to that project and some business startup activities for a while.

 

I will be posting my list of possible enhancements for discussion and additions in a few weeks. One of my questions will be around merging other attribute related contributions into QT Pro and how useful that will be with the level of other modifications people have made to their stores.

Link to comment
Share on other sites

Actually, that's why I went to the plug-in architecture.  So that  plug-ins for all kinds of things including other contribution merged versions could be supplied without overlaying the QT Pro base code.  I've still got a few things to work out to make it really flexible for adding other contributions.

 

Its not that I have no use for these (well, at least I have a use for Attribute Sorter/Copier) its just a matter of time.  I will be applying QT Pro to a loaded osCommerce version vs. merging in a bunch of other contributions myself.  So, I chose to get this version out to the world while I move on to that project and some business startup activities for a while.

 

I will be posting my list of possible enhancements for discussion and additions in a few weeks.  One of my questions will be around merging other attribute related contributions into QT Pro and how useful that will be with the level of other modifications people have made to their stores.

Link to comment
Share on other sites

Merging this "QT Pro" contribution along with the "Attribute Sets" would be a perfect combination usable by all. I believe "Atrribute Sets 4" (which hasn't been released yet) will contain an attribute sorter.

 

If you want to make it even more comprehensive, mix those 2 contributions with "Option Types" (for text input) and "Options as Images". Mixing these 4 would give you the ultimate attribute options manager.

Link to comment
Share on other sites

I tend to agree with hobbyhen - although I would think static options should be added too. The nice things about all these attribute/option addons is that they are something the site-admin can choose to use or not. so they are only an extra option - not something he's forced to use. I am rather fond of freedom of choice - and if we can give qtpro users the freedom to easily choose to use some of all the other option/attribute options - then that's definetely worth doing.

 

In regards to the comments on other people having modded their own product_info.php etc. I'll say that if all the great attribute/option type features mentioned by hobbyhen and me is included - I can see no other mods (most if not any) can have added - other than design changes - which no matter what, will be simpler to merge in again - than merging X contributions with qtpro :)

 

Just my 5 cent..

Link to comment
Share on other sites

I am using the new QTPro (many thanks to ralphday) and I have a question...

 

When an orde ris placed for a certain jacket, size X-Large, the order goes through just fine and everything seems to work, but when I go to admin it still shows the same quantity amount for that attribute (X-Large). I am testing QTPro making orders with PayPal or the standard Credit Card module. Are there stipulations or procedures that can stand in the way of the stock staying updated dynamically?

 

Thanks,

Aaron

Link to comment
Share on other sites

I am using the new QTPro (many thanks to ralphday) and I have a question...

 

When an orde ris placed for a certain jacket, size X-Large, the order goes through just fine and everything seems to work, but when I go to admin it still shows the same quantity amount for that attribute (X-Large). I am testing QTPro making orders with PayPal or the standard Credit Card module. Are there stipulations or procedures that can stand in the way of the stock staying updated dynamically?

 

Thanks,

Aaron

First the basics. Are these configuration settings right:

 

Check stock level = true

Subtract stock = true

Enable download = false

 

Any mods to checkout_process.php besides QT Pro?

Link to comment
Share on other sites

Hi guys,

 

Just found this mod - that divides the "Product attributes" page into 3 pages (instead of the product attributes page being divided into three parts on same page) - seems really good - and with all those options type, static attributes etc. It isn't a bad idea :)

http://www.oscommerce.com/community/contri...ll/search,links

 

(an idea for inclusion in qtpro perhaps - so The One product options/attributes contrib could be created - qt pro is almost there :)

Link to comment
Share on other sites

I have been beating my head on a few things and wondered if anyone has the same problems...

 

1) When the customer pays via PayPal (either one, IPN 2.9 or Harold's new Paypal module) the product option's stock is not affected but the overall quantity for the base product is.

 

2) When a product has a quantity of 0 and none of the options have stock above 0, this error message appears on the product_info.phppage:

 

Warning: Invalid argument supplied for foreach() in /home/username/public_html/store/includes/classes/pad_base.php on line 430

 

Your help is greatly appreciated. Thanks.

 

-AARON

Link to comment
Share on other sites

I have been beating my head on a few things and wondered if anyone has the same problems...

 

1) When the customer pays via PayPal (either one, IPN 2.9 or Harold's new Paypal module) the product option's stock is not affected but the overall quantity for the base product is.

 

2) When a product has a quantity of 0 and none of the options have stock above 0, this error message appears on the product_info.phppage:

 

Warning: Invalid argument supplied for foreach() in /home/username/public_html/store/includes/classes/pad_base.php on line 430

 

Your help is greatly appreciated. Thanks.

 

-AARON

1) IIRC, Paypal IPN replicates a bunch of the osCommerce code so you'll have to make sure changes are applied in the Paypal IPN versions of the code as well. Not sure what Harold's new Paypal is and if it is similar.

 

2) Good catch. That's a boundary condition I missed in my test scripts. Add this code to the beginning of function _draw_js_stock_array in pad_base

      if (!((isset($combinations)) && (is_array($combinations)) && (sizeof($combinations) > 0))){
       return '{}';
     }

Link to comment
Share on other sites

Thanks! Just to verify, is this what the new function code should look like?

 

function _draw_js_stock_array($combinations) {

if (!((isset($combinations)) && (is_array($combinations)) && (sizeof($combinations) > 0))){
? ? ? ?return '{}';
? ? ?}

     $out='';  
     foreach ($combinations[0]['comb'] as $oid=>$ovid) {
       $out.='{'.$ovid.':';
       $opts[]=$oid;
     }
     $out.='1';
     
     for ($combindex=1; $combindex<sizeof($combinations); $combindex++) {
       $comb=$combinations[$combindex]['comb'];
       for ($i=0; $i<sizeof($opts)-1; $i++) {
         if ($comb[$opts[$i]]!=$combinations[$combindex-1]['comb'][$opts[$i]]) break;
       }
       $out.=str_repeat('}',sizeof($opts)-1-$i).',';
       if ($i<sizeof($opts)-1) {
         for ($j=$i; $j<sizeof($opts)-1; $j++)
           $out.=$comb[$opts[$j]].':{';
       }
       $out.=$comb[$opts[sizeof($opts)-1]].':1';
     }
     $out.=str_repeat('}',sizeof($opts));
     
     return $out;
   }

 }

Edited by royalfunk
Link to comment
Share on other sites

"MANUAL

 

Appendix: Creating a Product Attribute Display Plugin

 

To create, install and activate a new Product Attribute Display plugin:

 

1. Choose the plugin that is closest to your desired functionality to extend...."

 

I Don?t understand theses six steps at all..

 

Is here someone who Could give me detailed instructions how to do this??

 

I Have Done everything else to install this contribution.

Link to comment
Share on other sites

"MANUAL

 

Appendix: Creating a Product  Attribute Display Plugin

 

To create, install and activate a new Product Attribute Display plugin:

 

1. Choose the plugin that is closest to your desired functionality to extend...."

 

I Don?t understand theses six steps at all..

 

Is here someone who Could give me detailed instructions how to do this??

 

I Have Done everything else to install this contribution.

Creating a plugin isn't a required install step. You only need to do this if you don't like one of the four plugins provided or want to build a separate plug-in with code merged from another contribution.

 

The manual is assuming you are familiar with classes in PHP and how one class gets extended by another. But I'm not a tech writer and realize I can make a lot of assumptions when I try to write technical directions so it still may not be clear. PM me or post with more detail on what you are trying to do and I'll see if I can help clarify things for you.

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.

×
×
  • Create New...