6

Customers will be purposed an optional insurance in the shopping cart, calculated as a percentage of Cart Total. I added this feature as an editable field in a footer view of the shopping cart, and I'm trying to setup ajax callback to update the cart.

EDIT (@people who already read the question) : I solved the initial bugs, so this is a clean update. You can jump to item 7 if you don't want to read the full implementation...

What I've done so far :

  1. Created an insurance taxonomy, each term is an insurance option with a % decimal fields (in order to allow insurance options changes at any time).
  2. Added this taxonomy to the order fields with a term reference field "Insurance" .
  3. Created a very simple view block called cart_field_assurances with that Insurance field, with editable format.
  4. Installed Cart View Override, cloned shoppping cart form and set that clone as shopping cart
  5. Created a views-view--commerce-cart-form-assurances.tpl.php template with :

    print $rows;
    print views_embed_view('cart_field_assurances', 'block');
    
  6. Moved insurance view before #edit-actions div with Jquery

    var insurance = $('.view-id-cart_field_assurances').detach();
    insurance.prependTo('#edit-actions');
    
  7. Removed action buttons, added ajax to the field, declared insurance price component

    function vts_insurance_form_views_form_cart_field_assurances_block_alter(&$form, &$form_state, $form_id) {
      $ajax = array(
        'callback' => 'vts_insurance_cart_refresh', 
        'progress' => array('type' => 'throbber', 'message' => ''),
      );
      $form['field_order_assurances'][0]['field_order_assurances']['und']['#ajax'] = $ajax;
      //Hide buttons
      $form['field_order_assurances'][0]['actions']['submit']['#attributes']['class'] = array('hidden');
      $form['actions']['#attributes']['class'] = array('hidden'); 
    }
    
    //ajax callback
    function vts_insurance_cart_refresh(&$form, &$form_state) {
      //Load the order
      $view = $form_state['build_info']['args'][0];
      $order_id = $view->result[0]->order_id;
      $order =  commerce_order_load($order_id);         
      //set new value
      $order->field_order_assurances['und'][0]['tid'] = $form_state['values']['field_order_assurances'][0]['field_order_assurances']['und'][0]['tid'];
      commerce_order_save($order);
    }
    
    //insurance price component
    function vts_insurance_commerce_price_component_type_info() {
      return array(
        'insurance' => array(
          'title' => t('Insurances'), 
          'display_title' => t('Insurances'), 
          'weight' => -10,
        ), 
      );
    }
    
  8. Set up a rule : Before saving a commerce order, calculate the insurance amount and add it to total as an Insurances price component

To illustrate, this is the shopping cart form, with the optional insurance field below

Drupal Commerce optional insurance

The question

How to refresh the display of "Cart Commerce Order total" shopping form view (and its price components of course) in vts_insurance_cart_refresh ajax callback ?

6
  • Which cart module are you using Kojo?
    – Darvanen
    Sep 15, 2014 at 0:03
  • commerce_order_save(my_order); looks like a syntax error $my_order vs my_order is missing a $ You should post your actual code if you want people to help debug it. Sep 15, 2014 at 10:45
  • @Darvanen, I use Commerce native commerce_cart.module plus Commerce Cart Ajax.
    – Kojo
    Sep 15, 2014 at 13:02
  • @DavidThomas, indeed, there was a typo in the question, tks. So I updated it with the full code. But at the moment the pbs begin even without this custom code, so it seems there's a pb when you add a footer to the shopping cart view ...
    – Kojo
    Sep 15, 2014 at 13:12
  • @kojo, ok without going into too much detail, you'd be better to use the commerce api, create a checkout pane with hook_commerce_checkout_pane_info and a price component with hook_commerce_price_component_type_info Sep 15, 2014 at 22:37

2 Answers 2

1

To implement an optional insurance field in the shopping cart : first, follow question steps 1 to 6.

For a nice ajax replacement, create a very simple Order total view with a Global: Custom text field (which we'll hide with a css class, just to have the minimum :one field) and put Commerce Order: Order total field in footer.

Then alter the form and setup the ajax callback :

function vts_insurance_form_views_form_cart_field_assurances_block_alter(&$form, &$form_state, $form_id) {
  //add ajax to our field
  $form['field_order_assurances'][0]['field_order_assurances']['und']['#ajax'] = array(
    'callback' => 'vts_insurance_cart_refresh', 
    'progress' => array('type' => 'throbber', 'message' => ''),
  );
  //unset unused buttons
  unset($form['field_order_assurances'][0]['actions']['submit']);
  unset($form['actions']);
}

function vts_insurance_cart_refresh(&$form, &$form_state) {  
  $order = commerce_cart_order_load($GLOBALS['user']->uid);

  //set the order insurance field value & save it
  $order->field_order_assurances['und'][0]['tid'] = $form_state['values']['field_order_assurances'][0]['field_order_assurances']['und'][0]['tid'];
  commerce_order_save($order);
  commerce_cart_order_refresh($order);

  //Display a message to customer
  $term = taxonomy_term_load($order->field_order_assurances['und'][0]['tid']);
  dsm(t('Insurance : you selected ').$term->name);
  $commands[] = ajax_command_replace('.messages.status', theme('status_messages'));

  //Refresh the cart total display
  $cart_total = commerce_embed_view('shopping_cart_total', 'block', array($order->order_id));
  $commands[] = ajax_command_replace('.view-shopping-cart-total', $cart_total);

  return array('#type' => 'ajax', '#commands' => $commands);
}

In the module js file, play with your DOM elements to display them as wished

(function ($) {

  $(document).ready(function(){
    //A wrapper for the first shopping cart total refresh                   
    $('.commerce-order-handler-area-order-total').wrap('<div class="view-shopping-cart-total"></div>');
    //Move the editable field above buttons
    var assurances = $('.view-id-cart_field_assurances').detach();
    $('.view-shopping-cart-total').before(assurances);
    //A wrapper for ajax messages
    var insurance_message = $("<div class='messages status insurance'></div>");
    insurance_message.appendTo(assurances).hide();
  });

})(jQuery);

A rule setting up a Fee price component, depending on the insurance field percentage value.

{ "rules_calcul_des_assurances" : {
    "LABEL" : "Calcul des assurances",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "TAGS" : [ "Commerce Cart" ],
    "REQUIRES" : [ "commerce", "rules", "commerce_fees" ],
    "ON" : { "commerce_fees_order" : [] },
    "IF" : [
      { "entity_exists" : {
          "type" : "commerce_order",
          "property" : "order_id",
          "value" : [ "commerce-order:order-id" ]
        }
      },
      { "entity_has_field" : { "entity" : [ "commerce-order" ], "field" : "field_order_assurances" } }
    ],
    "DO" : [
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "commerce-order:commerce-order-total:amount-decimal" ],
            "op" : "*",
            "input_2" : [ "commerce-order:field-order-assurances:field-pourcentage" ]
          },
          "PROVIDE" : { "result" : { "assurance_cout" : "Co\u00fbt de l\u0027assurance" } }
        }
      },
      { "commerce_fees_apply" : {
          "entity" : [ "commerce-order" ],
          "fee" : "assurances",
          "amount" : [ "assurance-cout" ],
          "currency_code" : "EUR"
        }
      }
    ]
  }
}

With such implementation, it is possible to add any kind of field in the shopping cart footer, allowing customers to choose options that will change the order total adding a price component, with Ajax feature. Nice.

0

As I see you should add some line item to your cart. I would go with a product line item. So now if you have a product called insurance you need to assign the price of total shopping cart * 0.17 to your insurance product

I would try to put all the heavy lifting to rules module. Specially because of the fact rules can / will decide the prices including / exluding taxes. You can change tax depending on your taxonomy term selection if you choose so. And you could add pricing % to taxonomy fields.

Or another and maybe even better way could be https://www.drupal.org/project/commerce_fees

1
  • Thank you. Where would you put the editable field then to allow customer to choose insurance ? Could you develop your product line item solution with more details, a short step by step ? Because at the moment I'm afraid I don't really understand it. Be sure I've been searching a lot and I even tried Fees...
    – Kojo
    Sep 15, 2014 at 13:19

Your Answer

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

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