Hi,

Maybe this is dummy question, but I can't find out how to display the coupon field on the cart page.
Any help is appreciated.

Thanks

Laurent

CommentFileSizeAuthor
#94 2872455-phpcs-on-commit.diff1.87 KBmglaman
#90 interdiff-84-90.txt4.88 KBczigor
#90 commerce-2872455-90-coupon_redemption_on_cart.patch19.58 KBczigor
#84 interdiff-74-84.txt4.26 KBczigor
#84 commerce-2872455-84-coupon_redemption_on_cart.patch21.19 KBczigor
#74 2872455-fixed.gif330.15 KBmglaman
#74 2872455-74.patch20.92 KBmglaman
#73 2872455-latest-patch.gif426.42 KBmglaman
#73 2872455-73.patch20.54 KBmglaman
#70 2872455-70.patch19.44 KBlisastreeter
#63 Allow_coupons_to_be_redeemed_on_the_cart_page--2872455--63.patch10.3 KBtrebormc
#59 2872455-59.patch13.6 KBMaico de Jong
#57 2872455-54.patch15.45 KBjeroendegloire
#53 cart-coupon-redemption-right.gif273.4 KBmglaman
#53 2872455-53.patch13.6 KBmglaman
#41 interdiff-2872455-41-38.patch1.57 KBgmem
#41 2872455-41.patch12.56 KBgmem
#38 2872455-38.patch12.55 KBmglaman
#38 interdiff-2872455-38-36.txt7.1 KBmglaman
#36 2872455-36.patch15.93 KBmglaman
#36 interdiff-2872455-36-34.txt4.16 KBmglaman
#34 2872455-34.patch11.77 KBmglaman
#30 cart-coupon-redemption.gif87.75 KBmglaman
#30 interdiff-2872455-27-30.txt2.72 KBmglaman
#30 allow_coupons_to_be-2872455-30.patch11.73 KBmglaman
#27 allow_coupons_to_be-2872455-27.patch11.08 KBsorabh.v6
#27 allow_coupons_to_be-2872455-27-interdiff.txt1.06 KBsorabh.v6
#23 allow_coupons_to_be-2872455-23.patch10.82 KBsorabh.v6
#23 allow_coupons_to_be-2872455-23-interdiff.txt4.11 KBsorabh.v6
#17 allow_coupons_to_be-2872455-17.patch6.53 KBsorabh.v6
#17 allow_coupons_to_be-2872455-17-interdiff.txt1.83 KBsorabh.v6
#15 allow_coupons_to_be-2872455-15.patch6.33 KBsorabh.v6
#15 allow_coupons_to_be-2872455-15-interdiff.txt11.77 KBsorabh.v6
#8 coupon_redemption_from_cart--2872455-8.patch8.04 KBDom.
#7 coupon_redemption_from_cart--2872455-7.patch7.43 KBDom.
#6 cart-after.png15.76 KBDom.
#6 cart-view.png11.35 KBDom.
#6 coupon_redemption_from_cart--2872455-6.patch7.37 KBDom.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Laurent_ created an issue. See original summary.

bojanz’s picture

Title: Displaying the coupon redeem field » Allow coupons to be redeemed on the cart page
Version: 8.x-2.0-beta6 » 8.x-2.x-dev
Category: Support request » Feature request

There is none.

#2792653: Checkout coupon pane implementation tracks the issue for checkout, let's track the cart side here.

mglaman’s picture

It is possible if you review the Promotions test module.

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function commerce_promotion_test_form_views_form_commerce_cart_form_default_alter(&$form, FormStateInterface $form_state, $form_id) {
  // We know that view forms are build on the base ID plus arguments.
  $order_id = substr($form_id, strlen('views_form_commerce_cart_form_default_'));

  $form['coupons'] = [
    '#type' => 'commerce_coupon_redemption_form',
    '#order_id' => $order_id,
    '#title' => t('Promotion code'),
    '#description' => t('Enter your promotion code to redeem a discount.'),
    '#submit_title' => t('Apply'),
    '#remove_title' => t('Remove promotion'),
  ];
}

However there is no exposed block for this.

EDIT: see https://github.com/drupalcommerce/commerce/blob/8.x-2.x/modules/promotio...

Dom.’s picture

Hi !
The solution by @mglaman adds the redemption form by the end of the cart, ie beneath the total and checkout button.
Better UX would be to have the coupon redemption in the views footer, above the "order total" field.

To do so, I am willing to provide a patch with a new global view field. I made on extending AreaPluginBase (just like commerce_order_total). However, in the render() method, something like the following does not render. I do not know why though. I guess I have to gt the correct renderer but can't find one.

$element['form'] = [
  '#type' => 'commerce_coupon_redemption_form',
  '#order_id' => $order->id(),
  '#cardinality' => 1,
  '#element_ajax' => [
    [get_class($this), 'ajaxRefreshSummary'],
  ],
];
return $element;

Do you know about it ?

Dom.’s picture

I managed to do so: I will make it as a patch as soon as possible.

Dom.’s picture

Here is a patch for this issue.

The patch defines a new "Coupon Redemption" field available in views that you can add to your view footer:

The patch includes:
- the definition of the CouponRedemption views area plugin
-- this include a configuration to let you redeem multiple coupon from the cart
-- the field takes it's order in the footer into account
- a change on how the OrderTotal views area plugin is rendered
-- to allow the coupon pane from the view to actually reload in ajax the order total when a coupon is applied
-- to allow the ordering of the footer fields to be considered

Finally, after configuration you have an ajax enabled coupon redemption form within your cart view:

Don't forget to /core/rebuild.php after applying the patch.

Dom.’s picture

Adding a new patch: it may happen that someone remove the "Order total" from cart views footer. The new patch prevent the coupon redemption to fail in that case.

Dom.’s picture

Because both CouponRedemtion and OrderTotal are now views area plugins, the alteration of form adds 'actions' to commerce_order_summary form in the checkout process.
This new patch removes this side effect.

sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
sorabh.v6’s picture

@Dom. Coupon form is appearing on cart footer after setting coupon redemption field in cart-form view. It applies coupon on cart page perfectly. But it making checkout page in loop and I am also not able to apply or remove coupon from order-summary sidebar on checkout page.

When I click on 'Continue to review' button it just refresh the page and don't take me to next checkout step.

Error which I am getting for adding/removing coupon -
Uncaught PHP Exception Symfony\\Component\\HttpKernel\\Exception\\HttpException: "The specified #ajax callback is empty or not callable." at /var/www/d8Contrib/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php line 67, referer: http://d8contrib.dev/checkout/7/order_information

Thanks

sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
Status: Needs review » Needs work
mglaman’s picture

+++ b/modules/promotion/src/Plugin/views/area/CouponRedemption.php
@@ -0,0 +1,133 @@
+          '#element_ajax' => [

Typo

sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6
sorabh.v6’s picture

Hi All,

I am trying to complete this work. But after hours of debugging, I am still not able to find which code is causing the problem. I can apply the coupon on the cart page and it reduces the cart total price. Then I click the checkout button. On order_information checkout step, if I try to add or remove coupon then I get below error -

Symfony\Component\HttpKernel\Exception\HttpException: The specified #ajax callback is empty or not callable. in Drupal\Core\Form\FormAjaxResponseBuilder->buildResponse() (line 67 of /var/www/drupal8.dev/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php).

I also saw the ajax call on browser console and there in response I am getting -

The website encountered an unexpected error. Please try again later.

I tried to move to next checkout step by clicking 'Continue to review' button. It just refreshes the page and does not take me to next step of checkout. If I try to go to next step manually by altering the checkout url, then again it would take me order_information checkout step even if I put the review in the URL instead of order_information.

If you can guide me, then I will be able to complete this patch.

@mglaman What is typo error you mentioned in #12?

Thanks All

sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
Status: Needs work » Needs review
FileSize
11.77 KB
6.33 KB

Patch uploaded for coupon field on cart form. Initial work from #8. Removed changes from commerce_checkout.module and updated changes in OrderTotal.php. Please review.

drugan’s picture

Status: Needs review » Needs work

#15 fixed empty ajax callback issue but introduced another (minor) one. That is when on a cart page you've applied coupon and then removed it, so the ajax replacing stops working on all subsequent attempts to apply/remove a coupon. So, the order summary stays the same what it was after the first ajax action applied, though having right expected value on the background.

sorabh.v6’s picture

Issue mentioned in #16 by @drugan is resolved in the attached patch. Please review.

Thanks All

sorabh.v6’s picture

Status: Needs work » Needs review
drugan’s picture

Status: Needs review » Reviewed & tested by the community

I've tested the #17 and for me it works great. The only thing that would be useful is to add functional test for this change.

sorabh.v6’s picture

@drugan Thanks for reviewing the patch. I was planning to write test, but since its a view area I was not sure if I can write test for it. Therefore, I saw test for OrderTotal view area plugin in the commerce_order module. And there was no test for that view area, so I thought maybe we don't write test for view area.

If we do, please provide any test for view area that I can refer for writing test for CouponRedemption view area.

Thanks

drugan’s picture

@sorabh.v6

Go to the web directory of your site:

cd my-site/web

... and run:

locate -r $PWD".*/FunctionalJavascript/.*\Test.php"

FunctionalJavascript test is exactly what we need for this change.

sorabh.v6’s picture

@drugan Thanks, working on test now.

sorabh.v6’s picture

@drugan New patch contains test for coupon redemption on cart page. Please review.

drugan’s picture

Status: Needs review » Reviewed & tested by the community

Great work!

But, I think it will not hurt a lot if you'd made these changes:

First, I remember from the d.o testing framework docs that it is always better to use explicit values in a test instead of randomly generated ones;


    $coupon = $this->createEntity('commerce_promotion_coupon', [
     // 'code' => $this->getRandomGenerator()->word(8),
      'code' => 'СКИДКА-Ё!@#',
      'status' => TRUE,
    ]);

That way we'd also check how utf-8 value coupons work. Also, it would be useful to apply coupon once more after // Coupon removal. block.

    // Coupon removal.
    $this->getSession()->getPage()->pressButton('Remove coupon');
    $this->waitForAjaxToFinish();
    $this->assertSession()->pageTextNotContains($coupon->getCode());
    $this->assertSession()->fieldExists('Coupon code');
    $this->assertSession()->buttonExists('Apply coupon');

    // Repeat applying the same coupon.
    $this->getSession()->getPage()->fillField('Coupon code', $coupon->getCode());
    $this->getSession()->getPage()->pressButton('Apply coupon');
    $this->waitForAjaxToFinish();
    $this->assertSession()->pageTextContains($coupon->getCode());

Just to be sure that #16 does not appear any more.

gauravjeet’s picture

Patch #17 works as expected. Great work.
I agree with drugan's thought #24

it is always better to use explicit values in a test instead of randomly generated ones
sorabh.v6’s picture

Assigned: Unassigned » sorabh.v6

Thanks @gauravjeet @drugan I will make suggested changes.

Thanks

sorabh.v6’s picture

Assigned: sorabh.v6 » Unassigned
Status: Reviewed & tested by the community » Needs review
FileSize
1.06 KB
11.08 KB

Changes made as per #24. Please review.

@drugan Thanks for the suggestion.

Thanks All

drugan’s picture

Status: Needs review » Reviewed & tested by the community

YESSS!

mglaman’s picture

Assigned: Unassigned » mglaman
Status: Reviewed & tested by the community » Needs work

Looks good. Just one concern about test coverage. I'll also give it a manual test.

+++ b/modules/order/src/Plugin/views/area/OrderTotal.php
@@ -80,11 +80,14 @@ class OrderTotal extends AreaPluginBase {
+          $order_total = $order->get('total_price')->view(['label' => 'hidden', 'type' => 'commerce_order_total_summary']);
+          $order_total['#weight'] = $this->position;
+          $order_total['#prefix'] = '<div data-drupal-selector="order-total">';
+          $order_total['#suffix'] = '</div>';
+          return $order_total;

+++ b/modules/promotion/src/Plugin/views/area/CouponRedemption.php
@@ -0,0 +1,148 @@
+    if (isset($order_total)) {
+      $order_total['#prefix'] = '<div data-drupal-selector="order-total">';
+      $order_total['#suffix'] = '</div>';
+      return new InsertCommand('[data-drupal-selector="order-total"]', $order_total);
+    }

The test is great, but it does not verify that this AJAX refresh command works.

mglaman’s picture

This is great! One problem. CartCouponRedemptionTest.php is a duplicate of CouponRedemptionElementTest.php and doesn't actually test the view plugin.

We need to alter the cart form view to embed the plugin and not rely on commerce_promotion_test to alter it in. I am fine with testing the view area plugin as part of the form element test. So updating CartCouponRedemptionTest to add the view area plugin to the default cart view instead of commerce_promotion_test altering it in. Keep a blank commerce_promotion_test.module instead.

mglaman’s picture

Assigned: Unassigned » mglaman

I'll wrap this up so we can integrate it into the Belgrade theme.

joshmiller’s picture

@mglaman - Any update on this? Either it's sitting in branch finished but unshared or it got lost in the holiday shuffle. No worries, just thought a little prod here might keep it moving.

mglaman’s picture

This feel through the cracks. Bringing it back up.

mglaman’s picture

Status: Needs work » Needs review
FileSize
11.77 KB

Reroll #30.

mglaman’s picture

+++ b/modules/order/src/Plugin/views/area/OrderTotal.php
@@ -79,11 +79,13 @@ class OrderTotal extends AreaPluginBase {
-          $order_total = $order->get('total_price')->view(['label' => 'hidden', 'type' => 'commerce_order_total_summary']);
-          $order_total['#weight'] = $this->position;
-          $order_total['#prefix'] = '<div data-drupal-selector="order-total">';
-          $order_total['#suffix'] = '</div>';
+          $order_total = $order->get('total_price')->view([
+            'label' => 'hidden',
+            'type' => 'commerce_order_total_summary',
+            'weight' => $this->position,

+++ b/modules/order/templates/commerce-order-total-summary.html.twig
@@ -18,7 +18,7 @@
-<div{{ attributes }}>
+<div{{ attributes.setAttribute('data-drupal-selector', 'order-total-summary') }}>

I just realized that this would break if anyone (previously) extended the theme template.

Maybe it is worth using the prefix.

mglaman’s picture

Updates tests of the element to use the views plugin.

Local decided to not run PhantomJS right after I think I fixed last test. Semi-blind patch post.

Status: Needs review » Needs work

The last submitted patch, 36: 2872455-36.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

mglaman’s picture

Status: Needs work » Needs review
FileSize
7.1 KB
12.55 KB

I forgot we had duplicate tests, fixed. Add schema.

Status: Needs review » Needs work

The last submitted patch, 38: 2872455-38.patch, failed testing. View results

mglaman’s picture

Assigned: mglaman » Unassigned

Need to try and figure out the schema issues.

Drupal\Core\Config\Schema\SchemaIncompleteException: Schema errors for views.view.commerce_cart_form with the following errors: views.view.commerce_cart_form:display.default.display_options.footer.commerce_coupon_redemption.allow_multiple missing schema
gmem’s picture

Managed to get tests working locally and the patch applies and functions well in manual testing. Had to change the plugin_id in the test, which seems to have fixed the issue with the schema for allow_multiple not being found.

Status: Needs review » Needs work

The last submitted patch, 41: interdiff-2872455-41-38.patch, failed testing. View results

gmem’s picture

Status: Needs work » Needs review

Interdiff got tested by accident, patch itself passes.

The last submitted patch, 6: coupon_redemption_from_cart--2872455-6.patch, failed testing. View results

The last submitted patch, 7: coupon_redemption_from_cart--2872455-7.patch, failed testing. View results

The last submitted patch, 8: coupon_redemption_from_cart--2872455-8.patch, failed testing. View results

mglaman’s picture

oof! thanks for the catch.

p4trizio’s picture

I have an issue with messages not showing after ajax but only on next page reload. Anybody has the same problem?
EDIT: sorry, this is working perfectly, looking forward for the patch to be committed

p4trizio’s picture

Status: Needs review » Reviewed & tested by the community
mglaman’s picture

Status: Reviewed & tested by the community » Needs work

Forgot to update this earlier. We discussed this internally and decide that we should provide this by default -- why hide such a nice feature.

We would want to work with the default UX then. The full-width message is not great nor the default styling.

Two options I considered

  • Split the area below the order information into two columns, coupon redemption on the left and totals on the right. 50/50 or so.
  • Have the coupon redemption above the order total, constraint its width so the message is not the entire page width
p4trizio’s picture

Hi @mglaman sorry I didn't know that.
You are right it's such a nice feature! About the options you considered I personally like the second, so that the coupon redemption is above the order total: frontend devs will be able to customize the position.

mglaman’s picture

Assigned: Unassigned » mglaman

Works for me, I mind either, just so long as its _something_ better than being thrown on the page.

mglaman’s picture

Assigned: mglaman » Unassigned
Status: Needs work » Needs review
FileSize
13.6 KB
273.4 KB

I forgot we can't add this by default, because then cart is dependent on promotion. Here's some quick CSS.

p4trizio’s picture

@mglaman pretty clean indeed, should we wait for more feedbacks on this to move the state of the issue to reviewed?

mirom’s picture

Is there different behaviour for coupons which can be combined with others? From the gif it seems that you can use only single coupon.

mglaman’s picture

@mglaman pretty clean indeed, should we wait for more feedbacks on this to move the state of the issue to reviewed?

I'd like to get some feedback.

Is there different behaviour for coupons which can be combined with others? From the gif it seems that you can use only single coupon.

You can allow multiple. The default I was testing was with single coupon.

jeroendegloire’s picture

Status: Needs review » Needs work

The last submitted patch, 57: 2872455-54.patch, failed testing. View results

Maico de Jong’s picture

Status: Needs work » Needs review
FileSize
13.6 KB

Rerolling patch #53 for latest dev, which is working fine for me!

@jeroendegloire
Not sure why you've included another patch in this one? Referred issue is also included in latest dev now/

Status: Needs review » Needs work

The last submitted patch, 59: 2872455-59.patch, failed testing. View results

joekers’s picture

Tested the latest patch from #59 and it's still working well.

trebormc’s picture

Patch from #59 working well.

trebormc’s picture

Povilas Uogintas’s picture

Hey,

Somehow latest patch does not work... Ajax refresh fail... There are the errors:

Error: Call to a member function load() on null in Drupal\commerce_promotion\Plugin\views\area\CouponRedemption::ajaxRefreshSummary() (line 141 of /app/web/modules/contrib/commerce/modules/promotion/src/Plugin/views/area/CouponRedemption.php)
#0 /app/web/modules/contrib/commerce/modules/promotion/src/Element/CouponRedemptionForm.php(292): Drupal\commerce_promotion\Plugin\views\area\CouponRedemption::ajaxRefreshSummary(Array, Object(Drupal\Core\Form\FormState))
#1 [internal function]: Drupal\commerce_promotion\Element\CouponRedemptionForm::ajaxRefresh(Array, Object(Drupal\Core\Form\FormState), Object(Symfony\Component\HttpFoundation\Request))
#2 /app/web/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php(69): call_user_func_array(Array, Array)
#3 /app/web/core/lib/Drupal/Core/Form/EventSubscriber/FormAjaxSubscriber.php(109): Drupal\Core\Form\FormAjaxResponseBuilder->buildResponse(Object(Symfony\Component\HttpFoundation\Request), Array, Object(Drupal\Core\Form\FormState), Array)
#4 [internal function]: Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber->onException(Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#5 /app/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#6 /app/vendor/symfony/http-kernel/HttpKernel.php(228): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.exceptio...', Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent))
#7 /app/vendor/symfony/http-kernel/HttpKernel.php(79): Symfony\Component\HttpKernel\HttpKernel->handleException(Object(Drupal\Core\Form\FormAjaxException), Object(Symfony\Component\HttpFoundation\Request), 1)
#8 /app/web/modules/contrib/simple_oauth/src/HttpMiddleware/BasicAuthSwap.php(67): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#9 /app/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#10 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#11 /app/vendor/asm89/stack-cors/src/Asm89/Stack/Cors.php(49): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#12 /app/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Asm89\Stack\Cors->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#13 /app/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#14 /app/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#15 /app/web/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#16 /app/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#17 {main}.

This part is failing:

  /**
   * Ajax callback for refreshing the order summary.
   */
  public static function ajaxRefreshSummary(array $form, FormStateInterface $form_state) {
    $order_id = $form['output'][0]['#rows'][0]->order_id;
    $order = $form['output'][0]['#rows'][0]->_entity->load($order_id);
    $order_total = $order->get('total_price')->view(['label' => 'hidden', 'type' => 'commerce_order_total_summary']);
    if (isset($order_total)) {
      return new InsertCommand('[data-drupal-selector="order-total-summary"]', $order_total);
    }
    return NULL;
  }

Any ideas?

Cheers!

Povilas Uogintas’s picture

I tested and changing that into this:

 /**
   * Ajax callback for refreshing the order summary.
   */
  public static function ajaxRefreshSummary(array $form, FormStateInterface $form_state) {
    $order_id = $form['output'][0]['#rows'][0]["#row"]->order_id;
    $order = $form['output'][0]['#rows'][0]["#row"]->_entity->load($order_id);
    $order_total = $order->get('total_price')->view(['label' => 'hidden', 'type' => 'commerce_order_total_summary']);
    if (isset($order_total)) {
      return new InsertCommand('[data-drupal-selector="order-total-summary"]', $order_total);
    }
    return NULL;
  }

seems to solved the issue.... I might create my own Views Area plugin for now... That way it will be easier to control other potential bugs!

FiNeX’s picture

Hi, the latest patches (#59 and #63 on -dev). Both adds the coupon to the cart but the ajax refresh doesn't work, you have to manually refresh the page to see it. The "remove coupon" button does the same: it removes the coupon but the cart summary is not ajax-refreshed.

After this test I've updated ajaxRefreshSummary() according to #65 but nothing changed.

bojanz’s picture

The patch will need to be rerolled to use the inline form instead of the deprecated commerce_coupon_redemption_form element.

luca_cracco’s picture

Hi! I tried using the inline form but it doesn't work.
The trait "AjaxFormTrait" doesn't work because of the core bug #2897377 and would also require reloading the cart view (for the order summary total component). The trait only reloads the form (i think).

lisastreeter’s picture

@luca_cracco I'm working on rerolling this patch and also having trouble getting it to work with the inline form.:

The specified #ajax callback is empty or not callable.

lisastreeter’s picture

Here is a WIP patch that is not working. It applies to the current dev, though, so it might be helpful to anybody looking at this issue. Coupons can be applied and removed, but the order summary disappears. Also, once you use one of the coupon redemption form buttons, neither the checkout nor the update-order button will work.

I made a variety of unsuccessful attempts to try to attach the ajax callback attached to the coupon redemption form.

mglaman’s picture

So, I did some debugging. The problem is.......... VIEWS! Or so it seems. \Drupal\commerce\AjaxFormTrait works fine. It returns the form entirely. But Views is missing the order total area and it changes the form's action to be /cart?ajax_form=1&_wrapper_format=html, breaking all non-AJAX buttons (ie: remove, update, checkout.)

mglaman’s picture

This broke due to the fact InlineForm replaces the entire form, instead of a subset. Views builds forms in a weird way, and this is causing the havoc.

mglaman’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
20.54 KB
426.42 KB

Here is a patch which is mostly working. There's some extra stuff being inserted.

EDIT: The extra "stuff" is the outer field divs when running Replace on [data-drupal-selector="order-total-summary"]. Each AJAX is nesting more and more.

<div class="field field--name-total-price field--type-commerce-price field--label-hidden field--item">
    <div class="field field--name-total-price field--type-commerce-price field--label-hidden field--item">
        <div data-drupal-selector="order-total-summary">
mglaman’s picture

🙌🎉. Need to see about them tests.

The last submitted patch, 73: 2872455-73.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 74: 2872455-74.patch, failed testing. View results

trebormc’s picture

#74 works fine. Thanks

introfini’s picture

#74 worked with me also. Thanks!

Marko B’s picture

Works on 2.13 commerce, thnx

chrisrockwell’s picture

Works on 2.14

sekoz’s picture

I'm not seeing any changes in the cart page.
Nothing mentioning coupons in the source of the /cart page, I tried with the default bartik theme too.
All hunks of patch 74 applied successfully .

drupal 8.8.1
drupalcommerce 8.x-2.16

then I've got a few extra modules commerce paypal, commerce extended quantity, commerce product tax, commerce stock..
could there be some conflict there? or it just doesn't work for 2.16?

joekers’s picture

@sekoz have you updated the view to include the new Coupon redemption handler in the Footer? If not, comment #4 should help.

sekoz’s picture

@joekers thanks I missed updating the view.
It is now working fine as described by others.

czigor’s picture

Status: Needs work » Needs review
FileSize
21.19 KB
4.26 KB

Removing the commerce_promotion_test module dependency from the test since that made the coupon redemption form appear twice on the cart form view.

Also replaced the waitForAjaxToFinish() calls with their non-deprecated counterparts.

introfini’s picture

I've applied patch #84 to Commerce 2.17 and it's working as expected. Thanks czigor!

3ssom’s picture

Status: Needs review » Reviewed & tested by the community

I've applied the patch #84 also and tested it. works fine!

I'll put this as RTBC.

mglaman’s picture

🙌 I'll commit on Monday. I think it's time.

The last submitted patch, 70: 2872455-70.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

mglaman’s picture

Assigned: Unassigned » mglaman

nits for later. and phpcs from https://www.drupal.org/pift-ci-job/1610564

  1. +++ b/modules/order/templates/commerce-order-total-summary.html.twig
    @@ -19,7 +19,7 @@
    -<div{{ attributes }}>
    +<div>
    

    Can't remember why we removed this. Is it because we now put the classes in a prefix? Some folks might be relying on this.

  2. +++ b/modules/promotion/css/promotion.cart_redemption_form.css
    @@ -0,0 +1,11 @@
    +.field--name-total-price {
    +  clear: both;
    +}
    

    😬this isn't scoped

  3. +++ b/modules/promotion/src/Plugin/views/area/CouponRedemption.php
    @@ -0,0 +1,205 @@
    +  protected $inlineFormManager;  ¶
    

    whitespace

  4. +++ b/modules/promotion/src/Plugin/views/area/CouponRedemption.php
    @@ -0,0 +1,205 @@
    +      if ($order = $this->orderStorage->load($argument->getValue())) {
    

    I think we should unnest this logic and quit early if the order is null

  5. +++ b/modules/promotion/tests/modules/commerce_promotion_test/commerce_promotion_test.module
    @@ -14,12 +14,17 @@ use Drupal\Core\Form\FormStateInterface;
    +  $inline_form_manager = \Drupal::getContainer()->get('plugin.manager.commerce_inline_form');
    +  $inline_form = $inline_form_manager->createInstance('coupon_redemption', [
    +    'order_id' => $order_id,
    +    'max_coupons' => Drupal::request()->query->get('coupon_cardinality'),
    +  ]);
    +
    ...
    +  $form['coupons']  = [
    +    '#parents' => ['coupons'],
    ...
    +  $form['coupons'] = $inline_form->buildInlineForm($form['coupons'], $form_state);
    

    since we're adding this by default, is this used anymore?

czigor’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
19.58 KB
4.88 KB

1. Re-added the attributes.
2. Not sure why but since the patch in #70 we don't attach the css, so let's remove the css file and the library definition too.
3. Fixed.
4. Fixed.
5. Some older tests (e.g. CouponRedemptionElementTest) depend on this so I think we should leave this. Alternatively we could convert the old tests to add the area to the view footer inside the test as CartCouponRedemptionElementTest does though.

mglaman’s picture

Some older tests (e.g. CouponRedemptionElementTest) depend on this so I think we should leave this. Alternatively we could convert the old tests to add the area to the view footer inside the test as CartCouponRedemptionElementTest does though.

Oh yeah! We should keep it then, the idea is to prove this works without the View or the CheckoutPane.

3ssom’s picture

Status: Needs review » Reviewed & tested by the community

I applied patch #90 in a new fresh install with latest release of core and commerce, works as expected :)

RTBC again, hopefully this will get committed soon.

  • mglaman committed 32ce9e3 on 8.x-2.x authored by czigor
    Issue #2872455 by mglaman, sorabh.v6, Dom., czigor, gmem, trebormc,...
mglaman’s picture

Assigned: mglaman » Unassigned
Status: Reviewed & tested by the community » Fixed
FileSize
1.87 KB

Thank you, everyone! This has now landed. 🥳

Fixed some phpcs on commit.

Status: Fixed » Closed (fixed)

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