I'd like to run the shipping rate's calculate_quote() method on clicking "Checkout" in the cart, so the default (perhaps only) shipping rate is calculated and applied to the order at that stage.

In my circumstance, the shipping rates are calculated based on the contents of the basket, and are fixed in that the shopper can't select different options. So the rate can always be calculated just from the cart contents, and the shipping needs to be re-calculated when the cart contents are changed.

Current problem:

1) User selects items to buy, they go to Checkout. No shipping price is shown, OK.
2) User continues to "Review order" page. Shipping is calculated, and price is shown. OK.
3) User returns to basket, and changes the items in the basket. OK.
4) User returns to Checkout page. Shipping price line item is still as calculated back in step 2, and is not updated to take new basket contents into account. ERROR!!
5) User continues to "Review order" page. Shipping is now calculated, and correct price is shown. OK.

Would it be possible to change the calculation trigger from the current "Submit Checkout form" to be activated by a Rule? Then the moment that shipping costs are calculated could be changed as needed.

Comments

mariomc’s picture

I'm subscribing to this.

The best solution seems to be via a rule that behaves similarly to "Commerce Tax - calculate taxes for the line item".

rszrama’s picture

I think we may need to consider the following solution:

  1. As background information, an order's pricing ought to be fluid until the second it stops being a cart order (either on redirection to the payment gateway or checkout completion). This means prices of everything should be recalculated when the shopping cart refreshes. This is how product pricing works now.
  2. Accordingly, shipping should be re-applied on refresh. This doesn't mean API requests need to be sent off or Rules evaluated every time an order is loaded, but it does mean we should have some way to cache quoted services and invalidate them when the contents of an order change. When this happens, we can recalculate shipping based on the customer's prior (or default) shipping service selection.
  3. Additionally, the checkout form ought to be showing the price of individual services when it is built. I don't like (and customers don't like) having to proceed to the next page to evaluate shipping pricing. When you're comparing services from the same carrier, you need to know costs.
fonant’s picture

Agree with rszrama, although for my purposes there isn't any need to refresh the first checkout page as I only have one shipping method. If we can find a way to calculate shipping as a rule that can be evaluated when the checkout page is displayed, that would be excellent.

I think perhaps the most flexible method would be to turn "Calculate shipping" into an action that any rule can fire?

And perhaps add a "Shipping method changed" event too?

Commerce seems to be using Rules a great deal, and doing so certainly gives plenty of flexibility :)

rszrama’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Status: Active » Needs review

I'm fixing this in the 2.x branch by implementing a default Rule that deletes shipping when an order's status is updated from non-"Shopping cart" to "Shopping cart." This will capture any time products are added to the cart / the cart form is submitted / the customer cancels out of checkout. When they come back to checkout, shipping will be recalculated and reapplied to the order on form submission. There is no automatic re-calculation baked into the default rule, but it should be a trivial action to implement if that's what you prefer.

adpo’s picture

There is no automatic re-calculation baked into the default rule, but it should be a trivial action to implement if that's what you prefer.

It sounds like a good idea.
PS> If we could use universal module called Extra Fee, it will be great,

paul.linney’s picture

Can someone provide more info on how to achieve the auto re-calc on view of the cart page - using Shipping 2.x? As with Fonant, I have only one shipping method without any options.

I have tried triggering the 'Add a rate for a shipping service to an order' action rule on the existing 'Delete shipping line items on shopping cart updates' rule, after it has deleted the shipping line items and tried a new rule to call the same action after Adding/Removing an item from the cart.

My Rules knowledge may be lacking for this, but any help would be appreciated.

muschpusch’s picture

This isn't the nicest way to do it but i'm short on time and it could easily be used write an rules action

function MYMODULE_commerce_shipping_service_rate_options_alter(&$options, $order) {                                                                                                                           
  commerce_shipping_delete_shipping_line_items($order);
  //commerce_shipping_collect_rates($order); 
  // you need this but it's getting overwritten by your rules
  $price = array('amount'=>750, 'currency_code' => 'EUR', 'data'=>'');

  $line_item = commerce_shipping_service_rate_calculate('MACHINE_NAME_OF_SERVICE', $price,5);                                                                                                                                

  commerce_shipping_add_shipping_line_item($line_item, $order);                                                                                                                             
 // dsm($order);
  //dsm($line_item);

}

[edit]some cleanup [/edit]

FiNeX’s picture

Why not moving the "Shipping service" pane on the checkout page ( /admin/commerce/config/checkout/form ) ?

muschpusch’s picture

Sorry don't use the hook above use:


function MYMODULE_commerce_checkout_router($order, $checkout_page) {                           

        if ($checkout_page['page_id'] == 'checkout') {  
              //etc 

@Finex: that wouldn't work on a one page checkout

agoradesign’s picture

Thank you very much muschpusch, you're definitely my personal hero of the day. I was trying to solve this problem the whole afternoon, until I found your post here with only a few simple lines of code :))

rszrama’s picture

Status: Needs review » Fixed

If I'm not mistaken, the code to calculate shipping on the initial pageload was committed a long time ago. Based on #4, it looks like I was leaving the door open to recalculate a shipping rate instead of deleting all shipping line items on cart refresh like we do now. To do this, you'd simply edit the default rule that deletes shipping line items and replace that action with the one added in #1452322: Rule to Auto-add shipping service. It does look like there's some follow-up work to do in that issue, but this should be sufficient to close this issue out.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

GuyPaddock’s picture