WooCommerce doesn't have an object to represent a discount of an order. Coupons are available as an object, but they are very specific and not applicable to the use-cases you would use a discount object for.
The context for this is that on yoast.com we currently have 5 ways that a discount can occur:
A single product is on sale. A sale price is essentially always a discount. For subscription purposes, you always want to know the original price. This is probably why WooCommerce has three different meta fields to keep track of:
a. The current price.
b. The sale price.
c. The original price.
A coupon code.
All products on the whole site are discounted by a specific percentual amount.
A customer buys a certain amount of the same plugin which results in a certain amount of percentual discount.
A customer buys a bundle which gives them the right to a certain percentual discount.
These are all implemented in a custom way. The first two is implemented by WooCommerce itself. 3 is implemented by our own custom code. 4. is implemented by the WooCommerce bulk discount add-on. 5. is implemented using WooCommerce product bundles.
This means that this code conflicts in unique ways and they all have to have code to make sure they play nice with each other. I am proposing a discount object that will streamline all of this. With that object in place the order of these can be handled in a clear way and conflicts will be less painful.
This is also important for reporting. Currently the bulk discount is sometimes seen as a sale which really throws off our reporting.
I have thought about how the code could look like and I think it would make sense to have an interface for this. All the different plugins could implement this interface to add a another way to have a discount. The interface should have a method to get the price after the discount. The method could be named apply
.
This also means that you then can have an aggregate discount that combines all the discounts that apply to an order/line item.
I don't have the capacity to write this code, but I will be available to do code reviews.
master
branch of WooCommerce on Github (this is not the same version as on WordPress.org!)@atimmer Hi Anton
A single product is on sale. A sale price is essentially always a discount.
In most cases yes, but not always. e.g. when changing the price vs RRP. I've certainly never seen a store where sale prices have been reflected in the cart like real coupon based discounts...
All products on the whole site are discounted by a specific percentual amount.
A customer buys a certain amount of the same plugin which results in a certain amount of percentual discount.
A customer buys a bundle which gives them the right to a certain percentual discount.
These seems to be the same thing in terms of what they are/what they do. They take a product price, run some calculations, and adjust the product price before the cart does it's own calculations.
This means that this code conflicts in unique ways and they all have to have code to make sure they play nice with each other. I am proposing a discount object that will streamline all of this. With that object in place the order of these can be handled in a clear way and conflicts will be less painful.
It won't be possible for core to handle these types of calculations for plugins - they will all have their own logic and ways discounts need to occur.
I also don't think coupon based discounts should be mixed with the product price modification type discounts those plugins implement. Coupons should really apply last. And unlike the examples you have where they discount the line items and show discounts per line (even though technically coupons discount the line items) they are presented as discounts on the cart as a whole.
For the types of discount you're proposing, I'm assuming they currently work something as follows:
You're correct there is no way in core to track or store these types of discounts.
I'm not sure how _"Currently the bulk discount is sometimes seen as a sale which really throws off our reporting."_ would happen without reviewing plugin code. As long as the prices are modified correctly, line totals + order totals will always be correct for reports. Perhaps there is some usage of woocommerce_get_discounted_price
going on which affect line item costs and apply after coupons..
I don't have the capacity to write this code, but I will be available to do code reviews.
I don't think we'll be able to prioritise this one either as there doesn't appear to be much demand. Plugins can do what they need under the current system. Whilst a refactor could be an improvement, there is also a potential to break the current system.
For this reason I'm going to mark this as wontfix
for now. If we decide to work on something which needs this (product discounts extension? @avivapinchas @bor0) that would be an ideal use case to build something new in core to support it, but without that use case it probably doesn't make sense for us to guess what's needed as that could make things worse :)
If plugin developers using the current system wanted to join forces and agree/contribute a unified system for core they can all benefit from that would be good. Like you, we'd be happy to code review any proposals :) Could raise this in dev chat to see if folks are interested?
Thanks cc @claudiulodro
This seems to be in line with some of the conflicts we've had for Account Funds/Store Credit.
cc @laurendavissmith @madeincosmos
How does one code bulk discounts with current system?
If one touches woocommerce_calculate_totals
and woocommerce_calculated_total
then things seem to be ok, up to the point when an admin clicks "Recalculate Totals" in wp-admin, when wc_save_order_items()
breaks any custom applied discount.
Another way (that I haven't yet tried) seems to be the woocommerce_get_discounted_price
filter, but the big fat "this is legacy" note there makes me a bit reluctant to use it.
P.S. Someone has tagged this as "good first issue"? ROFL.
Most helpful comment
@atimmer Hi Anton
In most cases yes, but not always. e.g. when changing the price vs RRP. I've certainly never seen a store where sale prices have been reflected in the cart like real coupon based discounts...
These seems to be the same thing in terms of what they are/what they do. They take a product price, run some calculations, and adjust the product price before the cart does it's own calculations.
It won't be possible for core to handle these types of calculations for plugins - they will all have their own logic and ways discounts need to occur.
I also don't think coupon based discounts should be mixed with the product price modification type discounts those plugins implement. Coupons should really apply last. And unlike the examples you have where they discount the line items and show discounts per line (even though technically coupons discount the line items) they are presented as discounts on the cart as a whole.
For the types of discount you're proposing, I'm assuming they currently work something as follows:
You're correct there is no way in core to track or store these types of discounts.
I'm not sure how _"Currently the bulk discount is sometimes seen as a sale which really throws off our reporting."_ would happen without reviewing plugin code. As long as the prices are modified correctly, line totals + order totals will always be correct for reports. Perhaps there is some usage of
woocommerce_get_discounted_price
going on which affect line item costs and apply after coupons..I don't think we'll be able to prioritise this one either as there doesn't appear to be much demand. Plugins can do what they need under the current system. Whilst a refactor could be an improvement, there is also a potential to break the current system.
For this reason I'm going to mark this as
wontfix
for now. If we decide to work on something which needs this (product discounts extension? @avivapinchas @bor0) that would be an ideal use case to build something new in core to support it, but without that use case it probably doesn't make sense for us to guess what's needed as that could make things worse :)If plugin developers using the current system wanted to join forces and agree/contribute a unified system for core they can all benefit from that would be good. Like you, we'd be happy to code review any proposals :) Could raise this in dev chat to see if folks are interested?
Thanks cc @claudiulodro