Zen Cart Logo
Forums / General Questions / Buy selection of items for offer price

Buy selection of items for offer price

Views: 1,043

Results 1 to 10 of 10
5 May 2016, 10:00 AM
#1
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Buy selection of items for offer price

Hi,

I am developing a function allowing customers to buy a selection of items for an offer price but I am having trouble when trying to apply it to multiple products with the same offer as the second item seems to be ignored.

Any help or advice would be appreciated.

Please find the code so far:

<?php
class offerprice extends base {
	

  var $offersAllowed ;
  var $offerlimit;

  
  function offerprice() {
  	global $zco_notifier;
    $_SESSION['cart']->attach($this, array('NOTIFIER_CART_SHOW_TOTAL_END'));
    $zco_notifier->attach($this, array('NOTIFIER_COUPON_SUCCESSFULLY_ADDED'));
  }

  
  function update(&$class, $eventID) {
  	global $order;

		$cost_saving = 0;
		$multiple = 0;
		$products = $_SESSION['cart']->get_products();
		
		global $db;
		$sql = "select products_id, products_price, products_offer_price, products_offer_quantity 
            from " . TABLE_PRODUCTS . "
            where products_offer_price > 0
              and products_offer_quantity > 0
              and (products_offer_date_from IS NULL OR DATE(products_offer_date_from) <= DATE(NOW()) )
              and (products_offer_date_to IS NULL OR DATE(products_offer_date_to) >= DATE(NOW()) )";
		$products_list = $db->Execute($sql);
		
		while (!$products_list->EOF) {
			$mysql_id = $products_list->fields['products_id'];
			$mysql_price = $products_list->fields['products_price'];
			$mysql_offer_price = $products_list->fields['products_offer_price'];
			$mysql_offer_quantity = $products_list->fields['products_offer_quantity'];
			
			$this->offerpriceArray[]= array('products_id' => $products_list->fields['products_id'], 
										 'products_price' => $products_list->fields['products_price'],
										 'products_offer_price' => $products_list->fields['products_offer_price'], 
										 'products_offer_quantity' => $products_list->fields['products_offer_quantity']);
			$products_list->MoveNext();
		}
		
			$cost_minimize = 0;		
			$cost_minimize_agg = 0;
			
			$offerItem = $this->offerpriceArray;
			
		for($i=0; $i < sizeof($offerItem); $i++ ) {
				
				if ($_SESSION['cart']->in_cart($offerItem[$i]['products_id']) && $id != $offerItem[$i]['products_id']) {
				  		
					if ((isset($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty']) && $_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= 1)) {
						
						$id = $offerItem[$i]['products_id'];
						$offerItem[$i]['qty'] = $_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'];

						$price = $offerItem[$i]['products_price'];
						$offer_price = $offerItem[$i]['products_offer_price'];
						$quantity = $offerItem[$i]['products_offer_quantity'];
						$numoffers = $quantity;
						$cart_quantity = $_SESSION['cart']->contents[$id]['qty'];
						
						if ($numoffers > 0) {
							
							/* BOF: Check Offer */
							if ($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= $quantity) {
								$_SESSION['offer_id'][$i] = $id;
								
								$offer_multiples = floor($cart_quantity / $quantity);
								$offer_modulus = floor(($cart_quantity % $quantity));
								
								$offered_quantity = $offer_multiples * $offer_modulus;
								
								
								$remaining_quantity = $price * $offer_modulus;
								
								$total_price = $price * $cart_quantity;
								
								$offer_total_price = $offer_price * $offer_multiples;
								$offer_price_final = $offer_total_price + $remaining_quantity;
							
							//$final_price_vat = zen_add_tax($products[$j]['final_price'], zen_get_tax_rate($products[$j]['tax_class_id']));
							//$cost_minimize_agg += $total_price;
							
								
								echo "<p>Offer Multiples: ".$offer_multiples."<br />";
								echo "ID: ".$id."<br />";
								echo "Price: ".$price."<br />";
								echo "Cart Quantity: " .$cart_quantity."<br />";
								echo "Offer Quantity: " .$quantity."<br />";
								echo "Offer Price: ".$offer_price."<br />";
								echo "Total Price: ".$total_price."<br />";
								echo "Modulus: ".$offer_modulus."<br />";
								echo "Offer Total Price: ".$offer_total_price."<br />";
								echo "Offer Price Final: ".$offer_price_final."</p>";
								echo "<p> Cart Session<br />";
								$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
								$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
								echo "Cart Total minus Total Price: ";
								echo $_SESSION['cart']->total -= $total_price_vat;
								echo "<br />Cart Total plus Offer Total Price: ";
								echo $_SESSION['cart']->total += $offer_price_final_vat;
								echo "</p>";
								
								/*
								$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
								$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
								$_SESSION['cart']->total -= $total_price_vat;
								$_SESSION['cart']->total += $offer_price_final_vat;
								*/
							}
							/* EOF: Check Offer */
						}
					}
				}
		////////////////
		}
	}
}

?>
5 May 2016, 3:49 PM
#2
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Re: Buy selection of items for offer price

After taking a brake from this and reviewing my code I have got this going again with the exception of getting the cart quantity to display to show on the items.

This script is based on the Buy One Get One Free plugin here: https://www.zen-cart.com/downloads.php?do=file&id=1221

Please see below:

<?php
/**
 * Observer class used apply a Buy One Get One Free(offer) algorithim to the cart
 *
 */
class offerprice extends base {
	
  /**
   * an array of ids of products that can be offer.
   *
   * @var array
   */
  //var $offersArray = array(); //Under Siege2-Dark Territory & The replacement Killers
  /**
   * Integer number of offers allowed per product
   * 
   * For example if I add 4 items of product 10, that would suggest that I pay for 2 and get the other 2 free.
   * however you may want to restrict the customer to only getting 1 free regardless of the actual quantity
   *
   * @var integer
   */
  var $offersAllowed ;
  var $offerlimit;
  /**
   * constructor method
   * 
   * Attaches our class to the $_SESSION['cart'] class and watches for 1 notifier event.
   */
  function offerprice() {
  	global $zco_notifier;
    $_SESSION['cart']->attach($this, array('NOTIFIER_CART_SHOW_TOTAL_END'));
    $zco_notifier->attach($this, array('NOTIFIER_COUPON_SUCCESSFULLY_ADDED'));
  }
  /**
   * Update Method
   * 
   * Called by observed class when any of our notifiable events occur
   * 
   * This is a bit of a hack, but it works. 
   * First we loop through each product in the offer Array and see if that product is in the cart.
   * Then we calculate the number of free items. As it is buy one get one free, the number of free items
   * is equal to the total quantity of an item/2.
   * Then we have to hack a bit (would be nice if there was a single cart method to return a product's in-cart price)
   * We loop thru the cart until we find the offer item, get its final price, calculate the saving
   * and adjust the cart total accordingly.
   *
   * @param object $class
   * @param string $eventID
   */
  function update(&$class, $eventID) {
  	global $order;
		$cost_saving = 0;
		$multiple = 0;
		$products = $_SESSION['cart']->get_products();
		
		global $db;
		$sql = "select products_id, products_price, products_offer_price, products_offer_quantity 
            from " . TABLE_PRODUCTS . "
            where products_offer_price > 0
              and products_offer_quantity > 0
              and (products_offer_date_from IS NULL OR DATE(products_offer_date_from) <= DATE(NOW()) )
              and (products_offer_date_to IS NULL OR DATE(products_offer_date_to) >= DATE(NOW()) )";
		$products_list = $db->Execute($sql);
		
		while (!$products_list->EOF) {
			$mysql_id = $products_list->fields['products_id'];
			$mysql_price = $products_list->fields['products_price'];
			$mysql_offer_price = $products_list->fields['products_offer_price'];
			$mysql_offer_quantity = $products_list->fields['products_offer_quantity'];
			
			$this->offerpriceArray[]= array('products_id' => $products_list->fields['products_id'], 
										 'products_price' => $products_list->fields['products_price'],
										 'products_offer_price' => $products_list->fields['products_offer_price'], 
										 'products_offer_quantity' => $products_list->fields['products_offer_quantity']);
			$products_list->MoveNext();
		}
		
			$cost_minimize = 0;		
			$cost_minimize_agg = 0;
			
			$offerItem = $this->offerpriceArray;
			
		for($i=0; $i < sizeof($offerItem); $i++ ) {
				$id = $offerItem[$i]['products_id'];
				  //if (($_SESSION['cart']->in_cart($offerItem[$i]['products_id'])) || ($_SESSION['cart']->in_cart($id_for_test_attribute))) {
				  		
						
						
					//if ((isset($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty']) && $_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= 1)) {
						$price = $offerItem[$i]['products_price'];
						$offer_price = $offerItem[$i]['products_offer_price'];		
						$quantity = $offerItem[$i]['products_offer_quantity'];
						$numoffers = $quantity;
						
					  if ($numoffers > 0) {
					
							/* BOF: Check Offer */
							//if ($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= $quantity) {
								
								$offer_multiples = floor($cart_quantity / $quantity);
								$offer_modulus = floor(($cart_quantity % $quantity));
								
								$offered_quantity = $offer_multiples * $offer_modulus;
								
								
								$remaining_quantity = $price * $offer_modulus;
								
								$total_price = $price * $cart_quantity;
								
								$offer_total_price = $offer_price * $offer_multiples;
								$offer_price_final = $offer_total_price + $remaining_quantity;
							//}
							/* EOF: Check Offer */
					  }
					//}
					
					
					
				  //}
			/*if(array_search($id, $_SESSION['offer_id'], false)) {
				//echo "ID: ";
				$id;
				//echo " PRICE MINUS: ";
				$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
				$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
				$_SESSION['cart']->total -= $total_price_vat;
				//echo " PRICE PLUS: ";
				$_SESSION['cart']->total += $offer_price_final_vat;
				//echo " ";
			}
			$_SESSION['offer_id'][$i] = $id;*/
			echo "<p>Offer Multiples: ".$offer_multiples."<br />";
			echo "ID: ".$id."<br />";
			echo "Price: ".$price."<br />";
			echo "Cart Quantity: " .$cart_quantity."<br />";
			echo "Offer Quantity: " .$quantity."<br />";
			echo "Offer Price: ".$offer_price."<br />";
			echo "Total Price: ".$total_price."<br />";
			echo "Modulus: ".$offer_modulus."<br />";
			echo "Offer Total Price: ".$offer_total_price."<br />";
			echo "Offer Price Final: ".$offer_price_final."</p>";
			echo "<p> Cart Session<br />";
			$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
			$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
			echo "Cart Total minus Total Price: ";
			echo $_SESSION['cart']->total -= $total_price_vat;
			echo "<br />Cart Total plus Offer Total Price: ";
			echo $_SESSION['cart']->total += $offer_price_final_vat;
			echo "</p>";
			} /*unset($_SESSION['offer_id']);*/

		////////////////
	}
}
?>
5 May 2016, 4:02 PM
#3
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Re: Buy selection of items for offer price

I have added the following on line 75

'cart_quantity' => $_SESSION['cart']->contents[$products_list->fields['products_id']]['qty']);

And the following on line 94

$cart_quantity = $offerItem[$i]['cart_quantity'];

Still no avail. Why doesn't the cart session look like it is pulling in results?

5 May 2016, 6:47 PM
#4
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Buy selection of items for offer price

From looking at what has been posted, it looks like this code doesn't modify the cart contents and only is retrieving information from it. There's a section that is commented out that would have modified the price it looks like.

6 May 2016, 9:09 AM
#5
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Re: Buy selection of items for offer price

Hi McNumbers, This isn't the issue I am having. The issue I am having is that is doesn't seem to be pulling in the cart quantity via

$_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty']

I have tried modifying it as follows to no avail

$_SESSION['cart']->contents[4533]['qty']

I'm not sure what it is that has broken here or how to fix this.

6 May 2016, 12:18 PM
#6
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Buy selection of items for offer price

Does this product have attributes?

6 May 2016, 12:44 PM
#7
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Re: Buy selection of items for offer price

Yes it does, despite this I believe I have it working now. The issue I have left is caused by duplicate entries. This is my latest code base:

<?php
/**
 * Observer class used apply a Buy One Get One Free(offer) algorithim to the cart
 *
 */
class offerprice extends base {
	
  /**
   * an array of ids of products that can be offer.
   *
   * @var array
   */
  //var $offersArray = array(); //Under Siege2-Dark Territory & The replacement Killers
  /**
   * Integer number of offers allowed per product
   * 
   * For example if I add 4 items of product 10, that would suggest that I pay for 2 and get the other 2 free.
   * however you may want to restrict the customer to only getting 1 free regardless of the actual quantity
   *
   * @var integer
   */
  var $offersAllowed ;
  var $offerlimit;
  /**
   * constructor method
   * 
   * Attaches our class to the $_SESSION['cart'] class and watches for 1 notifier event.
   */
  function offerprice() {
  	global $zco_notifier;
    $_SESSION['cart']->attach($this, array('NOTIFIER_CART_SHOW_TOTAL_END'));
    $zco_notifier->attach($this, array('NOTIFIER_COUPON_SUCCESSFULLY_ADDED'));
  }
  /**
   * Update Method
   * 
   * Called by observed class when any of our notifiable events occur
   * 
   * This is a bit of a hack, but it works. 
   * First we loop through each product in the offer Array and see if that product is in the cart.
   * Then we calculate the number of free items. As it is buy one get one free, the number of free items
   * is equal to the total quantity of an item/2.
   * Then we have to hack a bit (would be nice if there was a single cart method to return a product's in-cart price)
   * We loop thru the cart until we find the offer item, get its final price, calculate the saving
   * and adjust the cart total accordingly.
   *
   * @param object $class
   * @param string $eventID
   */
  function update(&$class, $eventID) {
  	global $order;
		$cost_saving = 0;
		$multiple = 0;
		$products = $_SESSION['cart']->get_products();
		
		global $db;
		$sql = "select products_id, products_price, products_offer_price, products_offer_quantity 
            from " . TABLE_PRODUCTS . "
            where products_offer_price > 0
              and products_offer_quantity > 0
              and (products_offer_date_from IS NULL OR DATE(products_offer_date_from) <= DATE(NOW()) )
              and (products_offer_date_to IS NULL OR DATE(products_offer_date_to) >= DATE(NOW()) )";
		$products_list = $db->Execute($sql);
		
		while (!$products_list->EOF) {
			$mysql_id = $products_list->fields['products_id'];
			$mysql_price = $products_list->fields['products_price'];
			$mysql_offer_price = $products_list->fields['products_offer_price'];
			$mysql_offer_quantity = $products_list->fields['products_offer_quantity'];
			
			$this->offerpriceArray[]= array('products_id' => $products_list->fields['products_id'], 
										 'products_price' => $products_list->fields['products_price'],
										 'products_offer_price' => $products_list->fields['products_offer_price'], 
										 'products_offer_quantity' => $products_list->fields['products_offer_quantity']);
			$products_list->MoveNext();
		}
		
			$cost_minimize = 0;		
			$cost_minimize_agg = 0;
			
			$offerItem = $this->offerpriceArray;
			
		for($i=0; $i < sizeof($offerItem); $i++ ) {
				$id = $offerItem[$i]['products_id'];
				  //if ($_SESSION['cart']->in_cart($offerItem[$i]['products_id'])) {
				  		
						
						
					//if ((isset($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty']) && $_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= 1)) {
						$cart_quantity = $_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'];
						$price = $offerItem[$i]['products_price'];
						$offer_price = $offerItem[$i]['products_offer_price'];		
						$quantity = $offerItem[$i]['products_offer_quantity'];
						$numoffers = $quantity;
						
					  if ($numoffers > 0) {
					
							/* BOF: Check Offer */
							//if ($_SESSION['cart']->contents[$offerItem[$i]['products_id']]['qty'] >= $quantity) {
								$offer_multiples = floor($cart_quantity / $quantity);
								$offer_modulus = floor(($cart_quantity % $quantity));
								
								$offered_quantity = $offer_multiples * $offer_modulus;
								
								
								$remaining_quantity = $price * $offer_modulus;
								
								$total_price = $price * $cart_quantity;
								
								$offer_total_price = $offer_price * $offer_multiples;
								$offer_price_final = $offer_total_price + $remaining_quantity;
							//}
							/* EOF: Check Offer */
					  }
					//}
					
					
					
				  //}
			/*if(array_search($id, $_SESSION['offer_id'], false)) {
				//echo "ID: ";
				$id;
				//echo " PRICE MINUS: ";
				$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
				$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
				$_SESSION['cart']->total -= $total_price_vat;
				//echo " PRICE PLUS: ";
				$_SESSION['cart']->total += $offer_price_final_vat;
				//echo " ";
			}*/
				if (($cart_quantity != '') && ($cart_quantity != null)) {
					$_SESSION['offer_id'][$i] = $id;
					echo "<p>Offer Multiples: ".$offer_multiples."<br />";
					echo "ID: ".$id."<br />";
					echo "Price: ".$price."<br />";
					echo "Cart Quantity: " .$cart_quantity."<br />";
					echo "Offer Quantity: " .$quantity."<br />";
					echo "Offer Price: ".$offer_price."<br />";
					echo "Total Price: ".$total_price."<br />";
					echo "Modulus: ".$offer_modulus."<br />";
					echo "Offer Total Price: ".$offer_total_price."<br />";
					echo "Offer Price Final: ".$offer_price_final."</p>";
					echo "<p> Cart Session<br />";
					$total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
					$offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
					echo "Cart Total minus Total Price: ";
					echo $_SESSION['cart']->total -= $total_price_vat;
					echo "<br />Cart Total plus Offer Total Price: ";
					echo $_SESSION['cart']->total += $offer_price_final_vat;
					echo "</p>";
				}
			} /*unset($_SESSION['offer_id']);*/

		////////////////
	}
}
?>
6 May 2016, 1:06 PM
#8
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Buy selection of items for offer price

I have a sneaking suspicion that it works for product without attributes, but does not for product that do have attributes.

It looks like the right direction was beginning to be taken to address product with attribute, but if you look at the shopping_cart class and at several of the functions that include the $products_id as a parameter, you'll see that the definition for that parameter is as "mixed". Mixed in this regards is made of the products_id as found in the products table, combined with a hash value related to the attributes as generated with the function zen_get_uprid. The resulting "products_id" (mixed value) is something like 1355:a5d1328..... etc. And is anticipated to be different for every variation of attributes applied (a unique string if you will). Therefore when looking for contents[products_id] the products_id must be the mixed value related to the cart entry in question.

To resolve your issue though, in fullness and depending on how you are applying this "special" code, once you have a list of product id's that apply, you'll also want to go through what is in the cart and see if the zen_get_prid($products_id) is the same as in your "special" list if you are going to apply this to a product having any type of attribute, but should also consider the possibility of expanding the functionality to account for application against only product having specific attribute(s) and thus would need to track the attributes associated with your products_list and sequence them the same way the cart sequences them, send them through zen_get_uprid() and then can pull/compare the two products_ids.

11 May 2016, 9:06 AM
#9
cozmoz avatar

cozmoz

New Zenner

Join Date:
Jun 2014
Location:
Suffolk, England
Posts:
23
Plugin Contributions:
0

Re: Buy selection of items for offer price

Hi McNumbers,

Thanks for the reply. I have implemented this in the code and it seems to be working fine but I am still unsure how to stop from applying the code to the same product ID more than once. Please find code snippet below:

if ( zen_get_uprid($id, $_SESSION['cart']->in_cart($id)) ) {
	echo "<br />";
	echo "ID: ";
	echo $id;
	echo "<br />";
	echo " PRICE MINUS: ";
	echo "<br />";
	echo $total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
	echo "<br />";
	echo $offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
	echo "<br />";
	echo $_SESSION['cart']->total -= $total_price_vat;
	echo "<br />";
	echo " PRICE PLUS: ";
	echo "<br />";
	echo $_SESSION['cart']->total += $offer_price_final_vat;
	echo "<br />";
}
11 May 2016, 10:41 AM
#10
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Buy selection of items for offer price

Cozmoz:

Hi McNumbers,

Thanks for the reply. I have implemented this in the code and it seems to be working fine but I am still unsure how to stop from applying the code to the same product ID more than once. Please find code snippet below:

if ( zen_get_uprid($id, $_SESSION['cart']->in_cart($id)) ) {
echo "<br />";
echo "ID: ";
echo $id;
echo "<br />";
echo " PRICE MINUS: ";
echo "<br />";
echo $total_price_vat = zen_add_tax($total_price, zen_get_tax_rate(1));
echo "<br />";
echo $offer_price_final_vat = zen_add_tax($offer_price_final, zen_get_tax_rate(1));
echo "<br />";
echo $_SESSION['cart']->total -= $total_price_vat;
echo "<br />";
echo " PRICE PLUS: ";
echo "<br />";
echo $_SESSION['cart']->total += $offer_price_final_vat;
echo "<br />";
}


I'll get to your above direct question in a moment, but first seems that I need to explain what you have because this code doesn't appear to do what you think you want it to do.

The if statement apparently is setup to display data that pertains to the current iteration. Okay, understandable. Within the if check though there is a combination of functions. First: 
Zen_get_uprid($products_id, $parameters)

This function is designed to provide the mixed products_id that I described above. The first parameter is intended to be the base products_id (large integer number if you will). The second parameter is intended to be an array of attributes. If that parameter is not an array or the $products_id ($id in your code) is already a mixed products_id (containing the colon (:)) then the function returns the first parameter as provided ($id), with no alteration.
Then there is the use of the shopping cart classes function of in_cart. This also expects a mixed products_id if is contains attributes, otherwise an integer would define the products_id. In either case, the function returns true or false. Neither true nor false is an array. Therefore used here in the zen_get_uprid function as the second parameter, the zen_get_uprid function always returns $id. So provided that $id does not evaluate to false (0, null, false, etc), the above code snippet is always run... 

So... again not sure what the intent of the above code is but the if statement could be shortened to: if ($id)

Now to your original question. How to prevent a value from being processed more than once... assuming that a product could contain attributes and you are trying to only display information about the base product and not about each variant of the product (prod1 with attribute1, prod1 with attribute2) then you would want to create an array to track this, either the array key is the products id number and each "product" is added to the array like $itrackdata[zen_get_prid($id_as_mixed_product_id)]=true or you would want to add an item to an array if the current id# is not already in the array:

if(!in_array($id, $itrackdata)){
$itrackdata[]=zen_get_prid($id_as_mixed_product_id);
}


Then that array is used to loop through and provide the desired data such that the products_id is used one time. There are a number of other ways this can be done, but really? If the value $id is still being used as the product_id associated with your "special" code and $id is NOT a mixed products_id (I thought previously it was cast as an integer) then this code completely falls apart for product with attributes. 

If the above main code is still even somewhat the same, then let's step through a little.
First a sql is made to query the products table to obtain a list of products that fit a specific criteria. Okay, so this will provide the integer value of every product meeting the criteria and store that in $products_list->fields['products_id'], then that is stored in $this->offerPriceArray, then that is converted to $offerItem. All the while still talking about an integer products_id. Then $offerItem is assigned to $id... 

Then (at least in the earlier code) the integer $id was being used to look at the contents of the cart. If the integer value (no attributes associated otherwise would be a mixed value) is in the cart then the overall code applies if not in the cart then won't be able to get the data previously sought such as qty for attribute related product...

Lastly, the above provided code snippet in no way is sufficient to identify any issue with happening multiple times. At best can do as have and advise of the misuse of the two functions in the if statement or something specifically happening inside the if statement.