Geting the cart total.

Posts: 23
Joined: 05/25/2008

A newbie here. I'm using the "Custom Price Calculation" module which lets each product have a small snippet of PHP to calculate custum prices or other minor task.

I', setting up a store and I have products I give away, the amount you get depends on your cart total, I have tried several things, this is the latest attempt, but I keep coming up with 0 products allowed, I'm thinking my code that calculates the cart's amount is defective, here is a copy;

$cart_items = uc_cart_get_contents();
$car_total = 0;
if (!empty($cart_items)) {
foreach ($cart_items as $c_item) {
$cart_total += ($c_item->price) * $c_item->qty;
}
}
$cart_credits = round($cart_total / 3);
if ($item->qty > $cart_credits) {
$item->qty = $cart_credits;
}
$item->price = $item->price;

Any tips is appreciated.

Thanks
Cecil
k5nwa

--

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

Posts: 1314
Joined: 08/14/2007
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.

Yeah, where are you getting $item->qty from? I'm not sure what else is around your code... looks like you didn't paste the complete snippet here. I think we'd need to know what the formula "should" be for calculating # of credits based on qty. From glancing at the code it looks like for every 3 products you can give one away? Is that right?

Here's what your code currently says:

- Get the total of the cart item costs.
- Divide that total by 3 (and round it).
- The number of credits = this new value.
- If $item->qty(?) is greater than the number of credits,
-- then $item->qty equals the number of credits.

Then you say $item->price = $item->price... which ... well, that's redundant.

I think the issue lies in the fact that you are calling $item->qty outside of the foreach loop for the cart contents. And in that case it will be $c_item->qty because that's how you are looping through your cart contents array.

I'd suggest fixing that, and double-checking your logic on the method of assigning cart credits.

Is this something that can be accomplished using the Discounts module instead?

--

"Pain don't hurt." - Dalton

Mike Nelson's RiffTrax! www.rifftrax.com

Posts: 23
Joined: 05/25/2008

The line with $item->price = $item->price can be ignored, the module allows a snippet of PHP to be inserted in a window that gets executed when you add or update an item in the cart. You have to have something and they automatically put that in there so there is some PHP to run, it's not needed if I have other code.

$item->qty is the quantity of item I'm adding or updating to the cart(the freebie), it should not be in the loop, the loop is for the purpose of going through all the items in the cart and adding them up but it doesn't appear to do so. I looked up how a foreach loop works and there wasn't much there to make it clear. Either the variable "$cart_items" does not contain a copy of the cart or the foreach loop is wrong.

In the following code here is how I understand it;

$cart_items = uc_cart_get_contents();
The statement above creates a variable "$cart_items" that contains a copy of the carts content, multiple entries of the content of my present cart.

$cart_total = 0;

If the cart is empty don't bother, and the $ total of the cart has been set to $0 all is fine, no freebies.

if (!empty($cart_items)) {

Go through each item in the cart and add the number of parts times the cost to my cart total figure.
Now I'm assuming that the foreach statement on each loop through it takes a different item in the copy of my cart "$cart_items" and assigns it to "$c_items" so I can figure that data to figure out the total cost of the item.

foreach ($cart_items as $c_item) {
$cart_total += ($c_item->price) * $c_item->qty;

In the example I am allowing 1 free item for every $3 in the cart, that is pretty straightforward.
}

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

--

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

Posts: 23
Joined: 05/25/2008

I have narrowed it down some and this is the problem but I don't know the solution yet.

In the following code snippet the following happens;

$cart_items = uc_cart_get_contents(); // supposed to get all 10 cart items and copy them to $cart_items
$c_count = count($cart_items); // supposed to return 10 but returns 3 instead.

Lets say I have 10 items in my cart for $100
I then add a free item.
In the cart the item shows up in the 4th position (no rhyme or reason where it puts items, they go all over the place)
The function count shows that there are 3 items in the cart, it though the new entry(possibly unfinished) is the end of the cart.

I think there is a bug in uc_cart_get_contents() it seems to stop transferring when it runs into a product that may not be completely in the cart, it doesn't see that there are more cart entries past product # 3.

The problem is how to fix it. Temporarily is there a way to determine the order in which items go in the cart?

Something in the product definition? It's not item entry order, I tried the part description, the SKU # and neither had any effect where in the cart a product gets placed. I the new items were entered at the end of the cart this would not be a problem.

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

--

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

Posts: 304
Joined: 11/19/2007
Bug FinderGetting busy with the Ubercode.

Cecil, the problem is with the timing of hook_cart_item(). While the cart is being rebuilt in uc_cart_get_contents() it is invoking hook_cart_item() for each item in the cart. Calling uc_cart_get_contents() from within hook_cart_item() is only going to return the items rebuilt in the cart thus far.

So if the 4th item in your cart of 11 is the one with a custom price calculation, then when it calls uc_cart_get_contents() it is only going to see the 3 items before it plus itself.

Not sure of a good solution though...

Posts: 23
Joined: 05/25/2008

Newbie here so please excuse my ignorance.

I hope there is a solution I was wondering is there a function that will work that returns the $ total of the cart? That is what I'm trying to do. The problem you mention looks hard to fix, I'm in the middle of updating the cart and calling functions about what is in the cart.

As a temporary fix I wonder also if it's possible to use Workflow-NG and trigger a function to execute after the cart has been updated so the function is not being called while the cart is being updated. It might also need to call the code to refresh the page.

Workflow-NG is really a handy tool, my entire shipping structure is controlled by it, I use a whole bunch of Flat rates to figure out the best shipping cost possible. I also use it to control inventory, no deductions of inventory until the order is paid. I hope it will be there when Ubercart gets updated to use Drupal 6

Thanks

--

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.

Posts: 304
Joined: 11/19/2007
Bug FinderGetting busy with the Ubercode.

Here is a quick and sad looking way that you might be able to get this to work (i make no promises), basically copying out the uc_cart_get_contents function into your custom price field. So if you have an item where you'd like to give away 1 for free if the total of the other cart items is over $50, you could put something like this in your custom price field. As I said before though, this module really isn't meant to do this sort of thing...

<?php
static $promotion_used;
$result = db_query("SELECT c.*, n.title, n.vid FROM {node} n INNER JOIN {uc_cart_products} c ON n.nid = c.nid WHERE c.cart_id = '%s'", uc_cart_get_id());
$cart_price = 0;
while (
$cart_item = db_fetch_object($result)) {
 
$cart_product = node_load($cart_item->nid);
 
$cart_item->cost = $cart_product->cost;
 
$cart_item->price = $cart_product->sell_price;
 
$cart_item->weight = $cart_product->weight;
 
$cart_item->data = unserialize($cart_item->data);
 
$cart_item->module = $cart_item->data['module'];
 
$cart_item->options = array();
 
$cart_item->model = $product->model;
  foreach (
module_implements('cart_item') as $module) {
    if(
$module != 'uc_custom_price') {
     
$func = $module .'_cart_item';
     
$func('load', $cart_item);
    }
  }
 
$cart_price += $cart_item->price * $cart_item->qty;
}
$cart_price -= $item->price * $item->qty;
if (
$cart_price > 50 && !$promotion_used) {
 
$item->price = 0;
 
$item->qty = 1;
 
$promotion_used = 1;
}
?>

This has limitations. A user would be able to purchase as many of this free product as they want at the normal price, but as soon as they qualify for the free product they would only be able to get their free one and could not purchase additional. The only way I could think of around this is adding an attribute to the product with 2 options(Promotional Free, Purchase Regularly) or something like that. Then check for that attribute when deciding whether or not to give the product away for free.

Posts: 23
Joined: 05/25/2008

Thanks for the tip, and sorry for not getting back sooner, I been sick lately and everything has been suffered because of it. I'll look at it soon.

I discussed this issue with my son and he thinks also that it should be done differently. Put a everyday price on it, mention that a discount of x dollars will take place for every dollar in the cart and proceed on. At checkout time put a small modification on the discount module to look at the cart then at that point calculate what discount they are entitle to.

My son pushed the idea because;

1. I should allow them to buy any quantity they want at regular price, so it's an extra source of revenue.
2. Everyone loves a discount.

Thanks

--

Cecil
k5nwa
Blessed are the cracked, for they shall let the light in.