0

We have a Drupal Commerce cart. The pricing can be altered based on discounts that come in from an external database via XML httprequests. It worked -fine- when the XML requests were made when the user hit the 'Add' button. But another developer removed that code and now wants the XML requests to be made on the cart form.

The problem I'm having is that it appears that the cart wants to display -before- my code will trigger and update the line items.

So... is there a way to hook onto a cart form/view so that my update code fires -before- the view is actually rendered? Below is a snippet. What happens is that the default pricing displays and -then- when the user hits the 'Update Cart' button, the code fires and updates the pricing with the discounts from the external database.

function formxml_form_alter($form, $form_state, $form_id){ 
global $user;
if(! $user)
  return;

if($form_id == 'views_form_commerce_cart_form_default')
      $order = commerce_cart_order_load($user->uid);

     // request pricing from external site and store in array 
 $request_string = 'http://mysite/Start?CartID=' . $customer_number . '&Cust=' . $customer_number . '&Cntact=' . $contact_number;
    $result = drupal_http_request($request_string, $options);       

$seq = 1;
foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
    $line_item = $line_item_wrapper->value();
    $my_product_id =  $line_item->commerce_product[LANGUAGE_NONE][0]['product_id'];
    $product = commerce_product_load($my_product_id);
        $my_product_title = rtrim($product->title);
            // update each line item with prices from external db array
            ...
     } 
    // now save order
$form_state['order'] = commerce_order_status_update($order, 'cart', TRUE);
commerce_order_save($form_state['order']);

1 Answer 1

1

The best and cleanest way to achieve what you want is with a product pricing rule and a custom action with what you have above. That way it goes through the normal Commerce hooks. You just create a rule reacting on "Calculate the sell price of a product."

If you only want the rule to fire on cart and checkout pages, you can also create a custom condition that checks your current path (or there might be a module that adds that condition for you.)

So instead of a hook_form_alter, you want to declare a hook_rules_action_info().

8
  • Thanks. Here's the thing: the price of -every- item can change depending on every other item. ie. If the user modifies the qty of item #2, that may change the price of all other items, so I have to call the external db every time the cart is added, deleted or updated. Is there a way I can simply call my PHP function as the -Action- of a Product Pricing Rule? That would be 1000% easier than using all their dropdowns.
    – jchwebdev
    Apr 2, 2013 at 18:45
  • 1
    Yes, you can do anything you want in a custom action. Then you just pass it the order object through rules, and do whatever you want. Perhaps a version of what you have above. Rules also has all sorts of events to react on, like adding an item to the cart, removing from the cart, updating a line item, etc. You can put a custom action on each of these if you want, although Calculating the Sell Price of a Product should meet your needs.
    – jazzdrive3
    Apr 2, 2013 at 20:26
  • 1
    Yes, that's basically what jazzdrive3 suggests above. Write a custom condition / action that implements your code on the pages it ought to operate. If I were you, I'd also implement a local cache so the web service isn't called every time the page refreshes on the checkout form. Give the cached data a reasonable timeout (a couple minutes?) and manually invalidate the cache if something in the cart changes. Apr 2, 2013 at 20:26
  • The problem I'm having is that I can't, for the life of me, figure out how to write the new unit price back to the commerce line item so that it updates the cart. Here is snip of what I have in my Pricing Rule. I know it's being triggered... just not writing to the db. Ideas? foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) { $line_item = $line_item_wrapper->value(); $line_item_wrapper->commerce_unit_price = ($new_price * 100); $line_item_wrapper->commerce_unit_price = $n_total; $line_item = commerce_line_item_save($line_item);
    – jchwebdev
    Apr 2, 2013 at 20:49
  • BTW: The above code is in a rule that is triggered by "Calculating the sell price of a product". Frustrated. Couldn't find a -single- example of this on the web.
    – jchwebdev
    Apr 2, 2013 at 20:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.