I am trying to implement flat pricing for Craft (ie. different fixed prices for products, based on the currency). I have it working thanks to this post (Craft Commerce: Hard code different product prices based on currency?), but where I am having problems is with applying sales.

The site I am working on has different prices for different currencies. These are fixed prices that are not based on Craft’s built-in exchange rates for different currencies. For example, a product in Currency A has a price of $100, which is stored in the Commerce’s default price field. However, the price for that product in Currency B has a price of $1000 - and that is stored in a custom text field for that product.

When a person orders a product in Currency B, I intervene on the LineItems::EVENT_POPULATE_LINE_ITEM event and manually set the price to Currency B’s price (from the custom text field on that product). This works except for when there are sales for that product.

If there is a sale which applies a 10% discount to the product, then Currency A’s price would be $90 (reduced by $10). However, when someone ordering with Currency B buys that product (which is $1000), that price gets reduced by only $10 (instead of $100). So it appears Commerce is calculating the discount based on Currency A’s price of $100 and applying that to whatever is the line item’s price.

I’ve written a method to calculate Currency B’s final sale price based on the discounts applied to Currency A.

However, it seems the sale’s discount is applied again after the populate line item event so even if I use my method to apply and calculate the correct Currency B sale price, Craft still applies the $10 sales discount again.

Is there a way for me to tell Craft not to apply the sale discount and let me do it manually if a product is being ordered in Currency B?

  • This is something we'd like information on as well. We've used Commerce 1 and 2 on ecommerce sites where pricing was set by currency/country (not by a rate from a base currency) and are not certain how we'd handle sale pricing for prices set in custom fields. As an aside, I've been developing ecommerce sites for 25 years and have yet to have a client who prices their products the way Commerce has this set up... it really needs to support flat pricing and/or multiple stores, etc.
    – Mike
    Commented Jan 3, 2020 at 18:07

2 Answers 2


Setting the saleAmount in addition to setting the price prevents Craft from applying the sale amount later.


In your LineItems::EVENT_POPULATE_LINE_ITEM event function, you can do something like this to change the sale amount:

Event::on(LineItems::class, LineItems::EVENT_POPULATE_LINE_ITEM, function(LineItemEvent $e) {
        $orderId = $e->lineItem->orderId;
        if ($e->lineItem->getOrder()->getPaymentCurrency() !== 'GBP') {
            $price = $e->lineItem->getPurchasable()->getFieldValues()['priceIn'.ucfirst(strtolower($e->lineItem->getOrder()->getPaymentCurrency()))];
            if ($e->lineItem->onSale) {
                $percentageProduct = $e->lineItem->getPurchasable()->getSales()[0]->applyAmount;
                $e->lineItem->saleAmount = $price * ($percentageProduct);
        } else {
            $price = $e->lineItem->price;

        $cart = $e->lineItem->getOrder();
        $e->lineItem->price = $price;
        $e->lineItem->note  = $e->lineItem->getOrder()->getPaymentCurrency();

You might need a different logic depending on the kind of sales you do, % or amount etc, but the above works for me using %.

  • The EVENT_POPULATE_LINE_ITEM event is where I am setting Country B's price for that item. But if sales are applied to that item from within CraftCommerce's control panel, that price is then adjusted using Country A's sales price which results in an incorrect price for Country B. Your solution doesn't address the problem.
    – Sheldon
    Commented Jan 9, 2020 at 4:17
  • It does address it exactly I think? Line 3 I'm pulling the sales %, then I apply it to the currency B price (defined in line 1), and that's my sale amount for currency B. I've edited my answer to add the whole content of my event if that helps make it clearer. In my code, GBP is my main currency.
    – Seb
    Commented Jan 9, 2020 at 20:43
  • Just chipping in here but as I understand Craft re-applies the sale amount (calculated from Currency A) on currency B still (however currency B is calculated). That's the issue... trying to stop Craft from changing that price in the cart, no?
    – Mike
    Commented Jan 11, 2020 at 0:33
  • I don't think there is a way to "stop" this behaviour, but you can control it using something like the code above. If you don't want any sale at all, then it's even simpler, just set the $e->lineItem->saleAmount to 0
    – Seb
    Commented Jan 14, 2020 at 19:57

Your Answer

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

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