## Requirements
We need multiple benefits per basket line for our implementation. Two offers we want to combine are:
1. a usually time-based offer like "If Germany wins, next day 15% off all products"
2. a custom offer where every user gets a 50% discount up to 150 Euros per year paid by his employer
On our site it is so common that people buy only quantity 1 of one product that we will skip the UI
part of the basket functionality. Both offers should apply to the same product. For example if a
product costs 100 Euros and Germany won yesterday (which it did!) the first offer is active and the
price is 85 Euros. Then the other offer applies and the user gets a discount of 50% on the remaining
price. The end price is then 42,50 Euros.
## Current situation in Oscar
To implement offers oscar has the concept of conditions and benefits. An example condition is "buy
two products from category A". An example benefit is "get 50% off a product from category B".
Oscar takes care to consume the products mentioned in the condition and in the benefit so that
1. the same two products from category A don't allow a discount for a second product from category B
2. the two products from category A can't be discounted
3. the same product from category B that was discounted cannot be discounted again
4. the product from category B cannot be used as a condition for another benefit
It does so by using `Line._affected_quantity` to track what quantity of the line was used in
conditions (`Line.consume()`) or benefits (`Line.discount()`). Both methods use the same counter.
When testing a condition oscar looks in the basket whether there are lines that weren't used in
another condition or discounted by a benefit by comparing `Line.quantity` and
`Line._affected_quantity`.
### Shortcomings
* Mixing the tracking of condition-consumed and benefit-consumed items leads to problems such as
* `CountCondition` and `CoverageCondition` consume lines inconsistently. `CountCondition` discards
lines with a zero price, `CoverageCondition` does not.
## The plan
In order to fix the shortcomings of the current implementation and also realize the new requirements
I intend to
1. (Refactoring) Separately track which line items were used in which condition and which were used
in which benefit. Details on semantics below.
1. Use an extra data structure instead of basket lines to track that (anticipating
2. Don't use lines that were used in a condition or in a benefit to satisfy another condition.
3. Don't use lines that were used in a condition or in a benefit for another benefit.
4. `CountCondition`: mark random N items from the range
5. `CoverageCondition`: mark a quantity of one for random N items from the range
6. `ValueCondition`: mark random items from the range in increments of quantity one until the
condition value has been reached or surpassed
7. Benefits mark all items that have received a discount
8. Remove tracking infrastructure from `Line`.
2. (Feature) Support multiple benefits per line
1. Add a field `conflicts_with_other_benefits` (better naming ideas very welcome!) to Benefit with
default True.
2. When looking for lines a benefit can be applied to make sure that for every line there is at
most one benefit with `conflicts_with_other_benefits == True`.
3. (Feature) Apply offers in order of desecending `ConditionalOffer.priority`.