3

I am inspecting my cart when the user visits /commerce/cart and if the cart contains a specific product, I want to alert the user that they can redeem a credit for "x" item. If the users chooses to use the credit, I would like to assign the qualifying product a discount.

...
if ($lineItems) {
    foreach ($lineItems as $lineItem) {
        foreach ($lineItem->purchasable->product->foo as $bar) {

            ...
            // qualifying product found - return json to javascript
            ...
        }
...

$discount = new commerce_DiscountModel();
...
??
// apply discount to cart/update ui via javascript to reflect discount

I'm able get all the way up to creating a new discount. I assume I start by creating a new discount model and populate it with the price of the product I am wanting to discount? I'm not really sure where to start - thank you for any suggestions!

EDIT

First off, thank you, Jeremy for your help. I (think) I am slowly starting to understand. I don't understand how or why the handler is or isn't getting called.

Here is my updated main plugin file:

MyPlugin.php

public function init()
{
    error_log(__FUNCTION__); // this is logged

    craft()->on('commerce_discounts.onBeforeMatchLineItem',
        [
            craft()->myPlugin, 
            'onBeforeMatchLineItemHandler'
        ]
    );
    ...
}

Then my service file looks like this:

MyPluginService.php

class MyPluginService extends BaseApplicationComponent
{
    public function onBeforeMatchLineItemHandler($event)
    {
        // this method never gets executed

        $cart = craft()->commerce_cart->getCart();
        $lineItem = $event->params['lineItem'];
        $discount = $event->params['discount'];

        error_log('line item: ' . $lineItem);
        error_log('discount: ' . $discount);
    }

    ...
}

If I change the name of the handler to "myPluginz" or something that doesn't exist, it throws an error, so I know I have the right syntax at least.

The handler was actually called once, but now it never gets executed. The product I have in my cart is promotable, and is not excluded from any sale. So it seems I am matching the criteria needed.

I also tried this straight from the docs.

public function init()
{
    error_log(__FUNCTION__); // this is logged
    craft()->on('commerce_discounts.onBeforeMatchLineItem', function ($event) {
        error_log(print_r($event, true)); // this is not executed

    });
}

I don't understand what I've done wrong to cause the event not to fire.

EDIT 2

Well, I think I have finally managed to get out of my own way. I'll update this thread as I progress through.

2

I would turn this on it's head slightly (assuming you can express the discount itself, i.e. what it does specifically to the discount item, using normal Commerce discount rules).

If you can, then you can basically make the application of the discount conditional based on what's in the cart.

Here's some sketch code - obviously you might need to change the logic etc

public function onBeforeMatchLineItemHandler($event){

$lineItem = $event->params['lineItem'];
$discount = $event->params['discount'];

$cart = craft()->commerce_cart->getCart();

$idOfItemToPossiblyDiscount = whatever;
$idOfParentItem = whatever;
$idOfDiscount = whatever;

/First check which discount we're thinking about applying
if($discount->id == $idOfDiscount){

    $shouldDiscount = false;
    if ($lineItem->purchasable instanceof Commerce_VariantModel){
        //First check if this is the item that might get discounted
        if($lineItem->purchasable->id) == $idOfItemToPossiblyDiscount)){
            //Ok, so we have that item in the cart now loop through $cart to see if the 'parent' item is in the cart
            foreach ($cart->lineItems as $item){
                if ($item->purchasable->$id) == $idOfParentItem){
                    //do nothing, but finish here - Commerce will carry on and apply the discount as long as
                    //we dont set event->performAction = false;
                    $shouldDiscount = true;
                    break;
                }
            }

        }

    }

    if(!$shouldDiscount){
        $event->performAction = false;
    }

}

Obviously at the template end of things you can loop through what's in the cart and do similar logic to show messages etc - e.g. if parent item is in, and not the discount item, present the offer, etc....

  • Thank you, Jeremy - I have updated my question with things I have tried. I swear the handler fired once. I saved my project and when I came back the event is no longer firing. – Damon Jun 5 '16 at 1:30
  • Well, I think I might have (finally) started to get out of my own way. I'll update my post for others as I go. Thank you again for your help! – Damon Jun 5 '16 at 1:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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