I have ajax enabled checkout panes. When I implement coupon code checkout pane at review screen, its preventing me to complete checkout by always showing "Please enter a code." error message. As the field is not required so technically it can be left blank although I have already applied a code code then also it shows the same error message.

When debugging into code in /includes/commerce_coupon.checkout_pane.inc, I am sure its showing because control is going in else condition.

if (isset($form_state['triggering_element']) && $form_state['triggering_element']['#name'] == 'coupon_add') {
    $code = $form_state['input']['commerce_coupon']['coupon_code'];
    if (!empty($code)) {
      $coupon = commerce_coupon_redeem_coupon_code($code, $order, $error);

      if ($coupon) {
        // Clear the field value so that the coupon code does not get
        // resubmitted causing an error when user uses main "Continue to next
        // step" submit.
        $pane_form['coupon_code']['#value'] = '';

        // Reload the order so it is not out of date.
        $order = commerce_order_load($order->order_id);

        // Recalculate discounts.
        commerce_cart_order_refresh($order);
      }
    }
    else {      
      $error = t('Please enter a code.');
    }

If I click on 'Continue to next step' it should not go into this condition. Is this because of AJAX? Can you share some patch to fix it?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rajeevgole created an issue. See original summary.

rajeevgole’s picture

rajeevgole’s picture

FileSize
37.7 KB
bpirkle’s picture

I know this is an older issue, but we're seeing the same thing on one of our clients, but not another. Some data points that we've noticed so far:

For the client that does not exhibit the problem, function _form_button_was_clicked (form.inc, line 2209 in Drupal 7.58) recognizes and sets the submit button as the triggering element. However, in client with the problem, the triggering element does not get set. This is because $form_state['input'] does not have the name of the triggering button.

The client with the problem therefore falls back to form.inc line 1973, which sets the triggering element to be the first submit button on the form (in this case, the Add Coupon button). It is worth mentioning that the Add Coupon button is also the first submit button on the form in the client without the problem. But it is okay there, because that client's $form_state['input'] values correctly caused Forms API to detect the triggering button. Here's the relevant code in form.inc:

    if (!$form_state['programmed'] && !isset($form_state['triggering_element']) && !empty($form_state['buttons'])) {
      $form_state['triggering_element'] = $form_state['buttons'][0];
    }

Basically, Forms API is having to do a last-chance fallback to guess the triggering element, by blindly choosing the first button. In this case, that turns out to be the wrong thing, thereby confusing commerce_coupon.

For the client without the problem, files in my call stack the point _form_button_was_clicked look like:
index.php
menu.inc
commerce_checkout_pages.inc
form.inc

For the client with the problem, it looks like
index.php
menu.inc
ajax.inc
form.inc

Notice that the client with the problem includes ajax.inc, which the other client does not.

The two clients use different base themes (Zurb for the client with the problem, Omega for the one without). If I switch to Bartik or Garland on the client with the problem, the problem goes away. That doesn't necessarily mean it is a Zurb bug - it may be something we're doing elsewhere in our codebase that trips us up when Zurb is active but not the other themes.

If we come up with a solution, I'll post it here.

bpirkle’s picture

We learned more.

In our case, the issue was related to commerce_avatax address validation. Near the top of contrib/commerce_avatax/js/address_validate.js is this line:

{code:java}
$('button.checkout-continue').unbind('click').click(function(event) {
{code}

Commere Avatax takes over the Continue button click. There's related code in commerce_avatax_validate_shipping_address_ajax_callback:

{code:java}
$commands[] = array(
'command' => 'afterAddressValidation',
'validation_result' => isset($form_state['address_validation_result']) ? $form_state['address_validation_result'] : FALSE,
'errors' => NULL,
);
{code}

This led me to 70 of commerce_avatax's address_validate.js:

{code:java}
$('form.commerce_checkout_form').submit();
{code}

When the form is submitted that way, we get the triggering element issues that end up making commerce_coupon unhappy.

Commerce Avatax probably isn't the only module that uses this pattern, so presumably the problem could appear in various other module combinations. I'm also not sure why the issue went away with a different theme, maybe there's a clue there on an actual solution.

In our case, we simply moved the Coupon pane to the second page of checkout, after address validation is done, to work around the issue. I wish I could provide an actual solution, but we stopped there. Hopefully the above will help someone else either solve it, or at least know how to work around it.

Deg’s picture

Our particular scenario might be fixed in 7.x-5.x-dev and newer versions of commerce_avatax, as reported in https://www.drupal.org/project/commerce_avatax/issues/2871701, but we were unable to confirm that at this time. YMMV.