I am working on a one page checkout and I'm trying to get the cart review pane updated with a shipping price while user selects a shipping option.
I have attached #ajax information to the shipping options, to update the cart review form when a shipping option is saved.
Modifying the commerce shipping ajax callback on checkout
if($form_id == 'commerce_checkout_form_checkout') {
$form['commerce_shipping']['shipping_service']['#ajax']['callback'] = 'mshop_shipping_pane_service_details_refresh';
}
Ajax callback
function mshop_shipping_pane_service_details_refresh($form, $form_state) {
// Update shipping form
$commands[] = ajax_command_replace('#' . $form['commerce_shipping']['service_details']['#id'], render($form['commerce_shipping']['service_details']));
// Update checkout cart review
list($view_id, $display_id) = explode('|', variable_get('commerce_cart_contents_pane_view', 'commerce_cart_summary|default'));
$commands[] = ajax_command_replace('.view-mshop-cart-shopping-cart-summary', commerce_embed_view($view_id, $display_id, array(arg(1))));
return array('#type' => 'ajax', '#commands' => $commands);
}
The issue : The AJAX is working, the updated cart review view is updated, but the shipping option is not applied.
My guess is that, as the form is only updated and not submitted, the order is not saved. So as the cart review's view is based on the order, and the shipping option is not saved yet in the order, it does not display the right shipping information in the cart review.
Any workaround?
EDIT:
Thanks to milkovsky comment I have been able to save the order with the shipping rate applied to the order. Then the cart review view displays correctly with the updated cart rate applied.
/**
* Ajax callback: Returns the shipping details form elements that match the
* currently selected shipping service.
*/
function mshop_shipping_pane_service_details_refresh($form, &$form_state, $checkout_pane, $order) {
// Get order from form
list($order, $checkout_pane) = $form_state['build_info']['args'];
// Load up to date order
$order = commerce_order_load($order->order_id);
// Get selected
$service_name = $form['commerce_shipping']['shipping_service']['#default_value'];
commerce_shipping_service_rate_order($service_name, $order);
// Delete any existing shipping line items from the order.
commerce_shipping_delete_shipping_line_items($order, TRUE);
// Extract the unit price from the calculated rate.
$rate_line_item = $order->shipping_rates[$service_name];
$rate_line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $rate_line_item);
$unit_price = $rate_line_item_wrapper->commerce_unit_price->value();
// Create a new shipping line item with the calculated rate from the form.
$line_item = commerce_shipping_line_item_new($service_name, $unit_price, $order->order_id, $rate_line_item->data, $rate_line_item->type);
// Save and add the line item to the order.
$new_line_item = commerce_shipping_add_shipping_line_item($line_item, $order, TRUE);
commerce_order_save($order);
// Update shipping form
$commands[] = ajax_command_replace('#' . $form['commerce_shipping']['service_details']['#id'], render($form['commerce_shipping']['service_details']));
// Update checkout cart review
list($view_id, $display_id) = explode('|', variable_get('commerce_cart_contents_pane_view', 'commerce_cart_summary|default'));
$commands[] = ajax_command_replace('.view-mshop-cart-shopping-cart-summary', commerce_embed_view($view_id, $display_id, array($order->order_id)));
$commands[] = ajax_command_after('.main form', theme('status_messages'));
// $commands[] = ajax_command_after('.'.$form['#attributes']['class'][1].':eq(0)',theme('status_messages'));
return array('#type' => 'ajax', '#commands' => $commands);
}
$form['commerce_shipping']['shipping_service']['#ajax']['callback'] = ...
if($form_id == 'commerce_checkout_form_checkout') { $form['commerce_shipping']['shipping_service']['#ajax']['callback'] = 'mshop_shipping_pane_service_details_refresh'; }
implementinghook_form_alter
or some special commerce hook?