Sunday, August 30, 2015

Drupal Commerce: Update Totals When Quantity Is Changed

This is just an example on how to implement ajax on the drupal commerce line items form. For this to work on your project, you'll need to make some significant changes, but this should at least give you a good start.


Create a Custom Module

I'm assuming you already have a custom module, so I won't get into it. The module name I am using in this example is "custom_module". Just replace "custom_module" with your module name.

Implement hook_form_alter

First you need to modify the "commerce_order_ui_order_form," which is easily done using hook_form_alter.


function custom_page_form_alter(&$form, &$form_state, $form_id) {
 if ($form_id == 'commerce_order_ui_order_form') {
  $form['#prefix'] = '
'; $form['#suffix'] = '
'; // default totals $order_total = 0.00; $product_total = 0.00; $shipping_total = 0.00; // Create the totals box $form['order_totals'] = array( '#weight' => -11, '#type' => 'fieldset', '#title' => 'Order Totals', ); if (count($form['commerce_line_items'][LANGUAGE_NONE]['line_items'] > 0)) { foreach ($form['commerce_line_items'][LANGUAGE_NONE]['line_items'] as $key => $row) { $line_item = $row['line_item']['#value']; if ($line_item->type == 'product') { $quantity = 1; $sku = $line_item->line_item_label; if (isset($form_state['input'][$sku.'_quantity'])) { $quantity = $form_state['input'][$sku.'_quantity']; // update quantity textfield with new value $row['quantity']['#value'] = $quantity; } $price = ($line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount']*$quantity); // Update line item total column $row['commerce_total']['#markup'] = commerce_currency_format($price, 'USD'); $product_total += $price; // Add submit callback (just rebuilds the form) $row['quantity']['#submit'][] = 'custom_page_quantity_submit'; // Add our ajax callback (just returns the updated form and replaces the old one) $row['quantity']['#ajax'] = array( 'callback' => 'custom_page_quantity_ajax_submit', 'method' => 'replace', 'event' => 'keyup', 'wrapper' => 'create-order-form', ); $row['quantity']['#name'] = $sku . '_quantity'; // Override this specific line item form with our updated one. $form['commerce_line_items'][LANGUAGE_NONE]['line_items'][$key] = $row; } else { // do something with the shipping line item dpm($row); $shipping_total = $line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount']; } } $order_total = $product_total + $shipping_total; // Product Total $form['order_totals']['product_total'] = array( '#prefix' => '
', '#suffix' => '
', '#markup' => 'Product Total: ' . commerce_currency_format($product_total, 'USD'), ); // Shipping Total $form['order_totals']['shipping_total'] = array( '#prefix' => '
', '#suffix' => '
', '#markup' => 'Shipping Total: ' . commerce_currency_format($shipping_total, 'USD'), ); // Order Total $form['order_totals']['order_total'] = array( '#prefix' => '
', '#suffix' => '
', '#markup' => 'Order Total: ' . commerce_currency_format($order_total, 'USD'), ); } } }

function custom_module_quantity_submit

function custom_module_quantity_submit($form, &$form_state) {
 $form_state['rebuild'] = TRUE;
}

This function only does one thing, rebuild the form. Without this one line of code, our ajax callback won't work.

function custom_module_quantity_ajax_submit

function custom_module_quantity_ajax_submit($form, &$form_state) {
 return $form;
}

This function also only does one thing, returns the form that we modified in hook_form_alter.

Improvements



The shipping cost is static. It needs to recalculate when the line items are updated. The only way to do that is to save the order and line items as they are modified, and then call a couple function from the commerce shipping module. I'm going to make an update on how to do that shortly.

No comments:

Post a Comment