user21218060
user21218060

Reputation: 17

Problem with editing order in Shopware admin panel when custom discount is added

I wrote custom cart discount according to the documentation https://developer.shopware.com/docs/guides/plugins/plugins/checkout/cart/add-cart-discounts Everything works fine, discount is recalculated when customer add or remove products from his cart but when I want to edit this order in admin panel I receive error:

Uncaught PHP Exception Shopware\Core\Checkout\Cart\Exception\LineItemNotStackableException: "Line item with identifier "CHEAPEST_ITEM_CART_DISCOUNT" is not stackable and the quantity cannot be changed." at /var/www/shop/vendor/shopware/core/Checkout/Cart/LineItem/LineItem.php line 233 {"exception":"[object] (Shopware\Core\Checkout\Cart\Exception LineItemNotStackableException(code: 0): Line item with identifier "CHEAPEST_ITEM_CART_DISCOUNT" is not stackable and the quantity cannot be changed. at /var/www/shop/vendor/shopware/core/Checkout/Cart/LineItem/LineItem.php:233)"} []

I "solved" this by add in code this checking:

if($behavior->hasPermission(self::SKIP_PROMOTION)){
        $items = $original->getLineItems()->filterType(self::LINE_ITEM_TYPE);
        foreach ($items as $item) {
            $toCalculate->add($item);
        }
        return;
    }

Now, if I edit order in admin panel, error doesn't show up but discount is not calculated again and switch "Disable automatic promotions" doesn't work.

Is there any solution to recalculate custom discount in order in edit action? When I add new order in admin panel everything works fine, problem is only on edit. Documentation doesn't say anything about this.

Upvotes: 0

Views: 353

Answers (1)

dneustadt
dneustadt

Reputation: 13161

Find if the discount was already added to the cart by the referencing the identifier. If it was, simply remove the old instance from the cart before adding the recalculated discount.

if ($original->has($discountLineItem->getId())) {
    $original->get($discountLineItem->getId())->setRemovable(true);
    $original->remove($discountLineItem->getId());

    return;
}

// $discountLineItem->getType() should equal LineItem::DISCOUNT_LINE_ITEM
$toCalculate->add($discountLineItem);

In addition you'll have to make sure your processor is executed after Shopware's own PromotionProcessor or otherwise it will try to re-add the discount you previously added manually.

<service id="MyPlugin\Cart\CustomPromotionProcessor">
    <!-- ... inject after default discount cart processor (3700) -->
    <tag name="shopware.cart.processor" priority="3600"/>
</service>

I created an example plugin that includes all the changes from the guide necessary for the recalculation. Tested on the current release candidate for 6.5 but should also work in latest version of 6.4.

That example is based on having a discount in form of a percentage of the cart value. If the discount is supposed to be a varying absolute value the procedure is slightly different. I created a branch in the aforementioned repository with an example for that as well.

Upvotes: 1

Related Questions