Commit a42c27f99e0061b7c4f recently fixed some bugs on sale_coupon.
This commit add some tests to be sure theses bugs are fixed and won't appear
again.
This closes#1744
Some use cases were wrong, this commit attempt to fix those.
Here is the most important ones:
1. Discount was offered on free product 'value' aswell
Cart: 4 iPad Mini + one free offered + 10% discount
| qty | unit value | line total |
----------------------------------------------------
iPad Mini | 4 | 320 | 1280 |
- 10% discount| 1 | 128 | 128 |
= 1152
- free product| 1 | 320 | 320 |
= 832
Should be
| qty | unit value | line total |
----------------------------------------------------
iPad Mini | 4 | 320 | 1280 |
- free product| 1 | 320 | 320 |
= 960
- 10% discount| 1 | 96 | 96 |
= 864
The error result is $32 which is the 10% discount applied on the free iPad.
2. Decreasing product quantity below the minimum threshold to be elligible for
the promotion doesn't remove the product
- (With a promotion offering a free iPad when you buy 3 (fourth is free))
- Create a quotation with 3 iPads Mini, save and update promotions, you don't
have a free one, which is 'correct'
- Edit, change the quantity to 4 iPads, save, update promotions, you have a
free iPad (reduced from total), still correct
- Edit, change the quantity back to 3 ipad, update ptomotions, you still have
a free iPad even if you only bought 3 of them (the way it is designed, the
free iPad should only appears when you order your fourth).
The error result in a 'loss' of $320 since at the end we are offering a free
iPad and the user only pays 2 instead of 3.
3. Free product will be considered as regular product when updating quantity
of regular product afterward
This error is kind of exponential: the more you play with the flow explained
bellow, the more incorrect it becomes.
Buy 100 iPads, get 25 free iPads.
Then set quantity (on regular iPad) to 50, it will recalculate the amount of
free iPad thinking the 25 previous free iPads are regular iPad.
(50 + 25) = 75 regular iPads = 18 free iPads (25 previous free iPads were
wrongly used for the calculation but they are simply gone at this point).
Cart is now 50 regular iPads and 18 free one, total: $10240 (50×320 - 18×320).
It should be 12 free iPads, not 18, so $12160 (50×320 − 12×320)
The error result in a loss of $1920: ~ 20% of the total amount of the order.
This error will also appear the other way around if you add quantity instead of
removing some.
Playing with this error multiple times, you can arrive to a negative total
(more free than paid products), 0 total or very low total ($320 for 100 iPads).
4. Free product are wrongly calculated, user get too many of them
- Create a quotation with 10 iPads, you get 3 free iPads instead of 2
- Indeed, your first 4 iPads should give you a free one
- Your next 4 iPads should give you a second one (you got 8)
- The last 2 (to reach 10) are not enough to give you a third free iPad
The error result in a loss of $320 out of a total of 2560$ which is ~ 15%
5. Paid/regular products related to a promotion won't be taken into account
when checking if you have the minimum amount threshold to apply the promotion
Promotion: 3 Computer Case(25$) = 1 Free Little Server (40.000$), auto applied
-Have a cart with 3 'Computer Case' and 2 'Little Server'
-One little server of the 2 is free (because you have 3 computer cases)
-You so pay 3x25 + 1x40000 which is 40075$
-Create a promo code that will give you 10% discount if you bought over $2000
-You won't get the reduction even if you bought over $40.000 because the
little server you pay is considered as the product of the reward product
even if you dont have it free. It doesn't check how many regular product
should be substracted according to the number of free product you have
6. Wrong product is checked for the required quantity to apply the promotion
Promotion: 3 iPads Mini ($320) = 1 free Bose Mini Bluetooth Speaker ($247)
- Add 8 iPads Mini and a Bose Mini Bluetooth Speaker to your cart
- The system should give you a free Bose Mini Bluetooth Speaker since you
only have one regular Bose
- But the system is giving you 2 free Bose Mini Bluetooth Speaker
Cart is: 8 iPad ($2560), 1 Bose ($247), 2 free Bose (-$496)
The system think that it should give you 2 free Bose because you are eligible
to, since you have 8 iPad, but it doesn't check that you have enough regular
Bose.
The error result in a loss of $247 out of a total of $2311
7. Auto applying promotion are not applied if there is already a promotion code
Promotion:
- Free iPad Mini if you buy 3 (so the fourth become free), auto applied
- 10% discount with code '10pc'
- Add 4 iPads Mini, you got a free one
- Set quantity back to 1 iPad, free one is gone
- Add code 10pc, you got a 10% reduction line
- Set quantity to 4 iPads again, you dont have the free iPad since there is
already a promo code
This could make sense but it is not coherent since the 2 promotions would be
applied if they were both on auto apply mode.
Note:
- If both promotions are on auto apply, you will get both
- If 10% discount becomes auto applied and iPad promotion now has a code
(reverse situation) it will work
8. Discount is only applied on untaxed amount, not on tax
Discount will ONLY be calculated on the untaxed amount and then reduced from
the sale order/cart total.
The taxes would be unchanged and charged like the product was full price.
Let's illustrate with a $100 product, a 15% tax and a 20% discount:
1. Tax included:
$100 : Product with 15% included taxes
$86.96 : Untaxed product
$13.04 : Taxes
After aplying 20% discount, result should be:
$80 : Product with 15% included taxes
$69.57 : Untaxed product
$10.43 : Taxes
Instead we have:
$82.61 : Product with 15% included taxes
$69.57 : Untaxed product
$13.04 : Taxes
There is a difference of $2.61 which is the result of the taxes not being
discounted: 13.04-10.43 = 2.61
2. Tax excluded:
$115 : Product with 15% excluded taxes
$100 : Untaxed product
$15 : Taxes
After aplying 20% discount, result should be:
$92 : Product with 15% included taxes
$80 : Untaxed product
$12 : Taxes
Instead we have:
$95 : Product with 15% included taxes
$80 : Untaxed product
$15 : Taxes
There is a difference of $3 which is the result of the taxes not being
discounted: 15-12 = 3
9. Taxes of the free shipping reward would be considered as paid value when
checking if required threshold is met.
------------------------------------------
Not really a bug, more an improvement:
1. The way it was designed, the rule_minimum_amount would check if your order
amount was over the required threshold to be eligible for the reward.
'Problem' is that it your order has already a discount (eg: 10%), it would
check if the price without discount is above the required amount.
I don't think it is coherent, let's illustrate:
- First pomotion (auto applied): 1 iPad Mini for free if you buy over $2000
- Second promotion (auto applied): 50% on order
If an user is buying for $2000, he is actually paying $1000 thanks to the 50%
discount.
Should we give him the free iPad?
The current implementation is giving it, which is not convenient IMHO.
Now, we use the amount the user really pay to check if he is elligible.
2. Since new promotions have the same sequence by default, they will be sorted
and applied by their creation order. This will result in inconsistent behavior:
- Promotion 1 : 10% discount
- Promotion 2 : free shipping
- Both promotion are auto applied and need a minimum of $872.73 tax excluded
Let's illustrate with a $873 order:
If the promotions were created in the order above, you won't get both rewards
since the 10% discount will be applied first and will lower the SO total.
The order will then fall below the $872.73 required amount and won't be
eligible for the free shipping.
But if you created the free shipping promotion before the discount one, you
will be eligible for both since the free shipping will be applied first and
won't change the SO total.
To keep the same behavior independently of the promotion creation order, we now
sort by reward_type ('discount' > 'free_shipping' > 'product' to apply
discounts first.
This is better IMHO, since you want to give promotions with a minimum threshold
ONLY if the user really pays that amount. It wouldn't be the case if the total
is checked before the discount is applied.
Instead of after
If "Lock Confirmed Orders" option is checked, a sale order with a coupon can not
be confirmed as the lines are recomputed after the change of state
Fixes odoo/odoo#22333
Closes#1823
Before this commit, if minimum product quantity was set to 0 on a coupon
program, it would then throw:
- On backend, when updating promotions
- On frontend (shop), user won't access his cart (error 500)
Now, we prevent quantity from being lower than 1
Step to reproduce:
- Create a coupon automatically applied, set quantity to 0, set reward to
'Free Product' and set free product to iPad Mini
- Go to /shop and add a iPad Mini to your cart, it will throw an error 500
instead of redirecting to your cart
- Go to backend, click on 'Update Promotions' on a quotation, it will show an
error popup
When you create a coupon, before this commit, all account move line was rewrite with the currency (useless OP).
Now the creation for a db of 15k lines tkaes 2 secondes instead of 10 minutes.
Note: The following bugs were also impacting the e-commerce.
This commit fixes some bugs related to promotion program offering free product:
- Create a promotion program that offers an ipad if you buy 3 of them, so the
fourth is free (reduced in total)
1. Buying 4, getting a free one, removing one, free one remains
- Create a quotation with 3 ipad, save and update promotions, you don't have
a free one, which is 'correct'
- Edit, change the qty to 4 ipad, save, update promotions, you have a free
ipad (reduced from total), still correct
- Edit, change the qty back to 3 ipad, update ptomotions, you still have a
free ipad even if you only bought 3 of them (the way it is designed, the
free ipad should only appears when you order your fourth).
2. Exponential bug: buy a lot of ipad, get a lot of free ipad then set the qty
to a lower amount, you will have a lot more free ipad than you should.
It can even lead to a negative amount (more free ipad than you paid ipad, but
in that case you won't be able to confirm the sale).
- Create a quotation with 100 ipad, you get 31 free ipad (which is incorrect,
see bug 3)
- Edit and change the qty back to 10 ipad and save
- Update promotions, you will have 10 ipad to pay and 10 free ipad resulting
in a null total.
3. Buy X ipad, get Y+Z free instead of Y (lets illustrate with 10)
- Create a quotation with 10 ipad, you get 3 free ipad instead of 2
- Indeed, your first 4 ipad should give you a free one
- Your next 4 ipad should give you a second one (you got 8)
- The last 2 (to reach 10) are not enough to give you a third free ipad
This is because free products are reward lines in the SO (is_reward_line) but
not linked to an applied_coupon_ids
Now, these reward lines will be considered as such and the coupon computing
will return correct results
This closes#1643
Before this commit:
Coupon error on cart would always show "Invalid or Expired coupon code"
instead of a more accurate error (eg: already applied, can't use 2 code..).
Plus it would still show the error on page refresh because of the error being
stored in URL param.
Now:
It will show the exact error and since the error is not stored in URL, it won't
be still displayed on page refresh.
This closes#1601
If a promotion program has a start date without a end date, or a end
date without a start date, there was an error of comparing string to
boolean
opw-775236
Purpose
=======
Click on Generate Coupon gives traceback
Steps to reproduce issue :
>> install coupon.
>> total number of customers are more than 40.
>> debugger mode off.
>> now click on generate the coupon.
Specification
=============
Before the new char domain widget, we were forced to couple the domain Char field with a many2many computed field to display the partners.
Now it's not useful, and this is leading to a traceback if the records count is greater than 40.
Now that we're closer to switching to P3 for good, these helpers have
outlived their usefulness, and mostly add noise.
All remaining dict.iter*() or dict.view*() must be converted to the
normal keys(), values() or items() calls.
Whenever the result is likely to be used for more than the scope of a
loop, or when the dict needs to be modified during iteration, the calls
must be wrapped in a ``list()``, to protect the new P3 semantics.
Those cases are very exceptional.
Also removed some dead code or improved the API to remove unnecessary
conversions.
Purpose
=======
You install CRM but you don't see CRM icon (except in English, as long as sales is not installed) -> confusing
The dashboard with salesteam is not obvious & not useful for simple users: what are those channel boxes about? why don't I see all my activities?, etc.
Specifications
==============
Split CRM & Sales + land in business views straight away
Default Entry Views
~~~~~~~~~~~~~~~~~~~
- New default view for CRM: Pipeline kanban
- New default view for Sales: Quotation list
Dashboards
~~~~~~~~~~
- Move sales teams dashboard to Reporting: Sales Channels.
- Remove the upper part of the sales team dashboard
Menuitems Structure
~~~~~~~~~~~~~~~~~~~
- CRM menu
Pipeline:
- Leads (optional)
- Pipeline (default menu, default filter "My Pipeline")
- Next Activities -> to remove (now there is an icon in top bar for next activities)
- Quotations (If sale_management installed)
Customers
Phone Calls (if voip, if not yet removed because there is a BE task to use next activities instead)
Leads Management:
- Scoring Rules
- Leads Assignation
- Team Assignation
Reporting:
- Leads
- Scoring page views
- Opp. Assignement
- Patnerships
- Pipeline
- Activities
- Phonecalls
- Sales Channels
Configuration:
- Settings
- Sales Channels
- Activity Types
- Leads & Opportunities:
- Lead Tags
- Lost Reasons
- Resellers
- Partner Level
- Partner Activations
- Sales menu:
Orders:
- Quotations
- Orders
- Customers
Invoicing:
- Orders to Invoice
- Orders to Upsell
Catalog:
- Products
- Promotion Programs
- Coupon Programs
Reporting:
- Sales
- Sales Channels
- All channels sales orders
Configuration:
- Settings
- Sales Channels
- Sales Orders:
- Quotation templates
- Payment acquirers
- Delivery Methods
Settings
~~~~~~~~
- Split settings form
- Remove recommended apps section
- Remove Timesheets section
- Remove Inventory Management and move shipping connectors to Shipping section
- Remove Integrations section
- Move Docsaway option to "Quotations & Orders", right after proforma
- Autocomplete and asterix: move to CRM section
- Restructure and rename sections this way:
- Product Catalog
- Pricing
- Quotations & Orders
- Shipping
- Invoicing
- eBay (if installed)
- Remove all the "Save this page and come back here" when checking a box that installs a new module
- restructure a bit the CRM settings, with 3 sections:
Pipeline
- Leads
Contacts
- Phone Validation
- Customer Autocomplete
Integrations
- Google Calendar / Synchronize your calendar with Google Calendar (copy from general settings but don't show message "Save this page and come back here...".
- Asterisk (VOIP)
The default invoicing policy should always be by ordered quantity.
Otherwise, if the user changes the default invoicing policy to
"delivered quantity", coupon won't be applied to the invoice.
opw-749632
Purpose
=======
Currently we are updating the coupon rewards on the fly when creating/modifying/deleting a sales order line.
To avoid multiple searches on res_partners and product to know whether the customer/product is valid on the sale coupon program, we store the applicable customers and products on the program according to the domain defined on it.
This brings 2 issues:
- The customers/products stored on the program are not updated (Was the original spec)
- The checks are numerous and maybe overkill for the given results
Specification
=============
- Don't recompute the reward lines on SO modifications. Add a button to compute the line by hand and make an automatic compute on the SO validation or on the page shop/payment.
- When recomputing the reward lines, make a search on the res_partners and products instead. Now that the action is not triggered so often we can afford to make a search.
- Don't use the fields rule_partners_domain and rule_products_domain. This should be removed in master.
- The field is_public_included is useless now. And we decided to make the coupon available for all the partners if they fit the domain on the program.
Purpose
=======
People doesn't understand that the reward line product is the product that will be used in the discount line, not the product the be rewarded
If they set another product before the program is created, the product they set will be renamed, which is wrong.
Specification
=============
- Don't display the field before it's set
- Make the field readonly on the program form view