You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[FIX] pos_loyalty: fix corrupted product specific discount
Steps to reproduce
------------------
- Create a product with price $80
- Create a fixed discount reward for this product with $40
- In PoS config, enable global discount
- In a new PoS order, add the product created in the first step and
observe that we now have 2 orderlines, the product at $80 and the
discount at $40. Total amount remaining to pay is $40
- Add a global discount of 50%
-> At this point, we are expecting to apply the 50% discount on the
remaining $40, and hence, a discount of $20, which changes the order's
total price to $20. We also expect the fixed discount line of $40 to
remain at $40, as it's a fixed price discount.
Indeed, we now see a $20 global discount as an orderline, but the $40
fixed discount has changed its value from $40 to $53.33, and thus, the
total amount has decreased to $6.67 instead of $20 -> A corrupted final
amount!! In some other pricing configs, this final total amount will
even become negative.
Reason
------
After applying the global discount, we recalculate the value of the
discounts to keep everything in sync, so we recompute the discount value
of the fixed $40 discount in `_getRewardLineValuesDiscount`, and since
now the total amount to pay, i.e. `order.get_total_with_tax()` is less
then the value of the product (due to the global discount),
`discountFactor` [1] of the fixed discount increases since
`discountable` decreases. However, at the end when we calculate the new
`unit_price` of this fixed discount, we multiply the `discountFactor` by
the intial product price, i.e. by the price before the global discount,
and hence, the amount of the fixed tax will be higher than expected,
causing this buggy behavior. Below is a math representation of the bad
(current) vs good (new) behavior:
Bad:
discountable = $60 = $80 - $20, where $20 is (total - fixed) * discount,
i.e. (80-40)*0.5
discountFactor = $40 / $60 = 0.666666
price_unit = 0.666666 * $80 = $53.3333 (instead of $40)
Good should be:
discountable = $60 = $80 - $20, where $20 is (total - fixed) * discount,
i.e. (80-40)*0.5
discountFactor = $40 / $60 = 0.666666
price_unit = 0.666666 * $60 = $40
I.e the good behavior should be multiplying the `discountFactor` by the
the min of the remaining total price (after applying the global
discount, so $60), and the initial value of the product (here $80).
The formula has been updated accordingly.
[1]: https://github.com/odoo/odoo/blob/76e2aa6b70d1fb03b8ce2f8e4a7e9c3d9425270f/addons/pos_loyalty/static/src/overrides/models/pos_order.js#L1163
opw-4622428
closesodoo#206752
X-original-commit: 86bd047
Signed-off-by: Adrien Guilliams (adgu) <[email protected]>
Signed-off-by: Hadi El Yakhni (hael) <[email protected]>
0 commit comments