Discount on Sale


For marketing reasons it should be possible to grant discounts to base prices
and inform customers about the price reduction on sale.
To have a fine-grained control what to discount or not, the feature is
implemented on line level.
The discount can be seen as a ratio between the unit price and the base price and as a difference discount amount between base price and unit price.
Discount is calculated with these formulas:

                     unit price
a)  discount = 1 -  ------------
                     base price

b)  unit price = base price * (1 - discount )

c)  discount_amount = base price - unit price
                    = base price * discount


base price = 100
unit price = 90
discount = 0.1
discount amount = 10

The discount is represented in percentage and as an amount.
It is possible to set a discount for sale lines without a product.

When calculating the discount from the unit price and vice versa,
rational numbers are resulted, which needs to be rounded.


The feature is implemented in module:

sale_discount depends sale

The sale line gets the new fields discount and base_price.

Field base_price

base_price = fields.numeric(
    'Base Price', digits=…, states={
        'readonly': Eval('product') | Eval('discount')})

The base price is filled at line creation time with 0.0.
Without a given product the base price is editable by the user,
but then it will be no longer editable, if there is a discount.

On change product the base_price is re-evaluated by a method per default
to the actual list_price of the product.
The base price can be influenced by functionalities provided by separate
Besides the product list price, the base price could be filled with a:

  • price from a price list,
  • price from a parent price list (when hierarchy is added),
  • price from a catalog price

Field discount

discount = fields.Function(
    fields.numeric('Discount', digits=…,
    getter='on_change_with_discount', setter='set_discount'))

Because the base price is constant for the same product and constant when
there is a discount, the ratio between unit price and the discount value is
always determined.
It calculates:

* a new discount value by a change of the unit price by formula a)
* a new unit price by a change of the discount value by formula b)

Field discount amount

discount_amount = fields.Function(
    fields.numeric('Discount Amount', digits=…,
    getter='on_change_with_discount', setter='set_discount'))


Yes, but also for purchases. Punctual discounting happens there too.

BTW, these discounts may be fractions, typically to round the discounted unit price.

Example: product list price 465.69
discounted unit price = 442.00
calculated discount = 5.087

I very much like the suggestion to be able to calculate either the discount derived from the discounted unit price as well as the latter applying the discount. This will save much time during entry/validation.

Maybe you are interesting about discount modules that use gross unit price, discount and recalculate unit price:

  • account_invoice_modules
  • sale_discount
  • purchase_discount


Also there are other discount modules:

  • sale_discount_price_list
  • sale_pos_discount
  • account_invoice_3_discount
  • sale_3_discount


Discount is a marketing effect so there is no need to support it on invoice, this will just make the code more complex and cumbersome for supplier invoice and other customer invoice not subject to discount.

For me, it is not that simple. The price to use as base price is not necessary the list price. I had already seen many different cases: the list price, the price from another price list, the price from a parent price list (when hierarchy is added), the price from a catalog price etc.

It should take care of the rounding issue. The computation should be stable.

It should be filled when the line is created, just like the unit price is filled.

For me, this is a too simplistic design. Discount is normally limited in value. Indeed I think this is another feature which involve unit price tolerance. It probably needs to follow the MatchMixin pattern.

I do not think it is the right approach. This should be managed by price list.

I do not see the need to compute such discount. When purchasing, you do not want to follow into the marketing tricks of discount. The only thing that matter is the actual unit price.

This shows that there are no standard method to do discount, so the proposal should find a good generic way which allow to easily implement any kind of method.

Also I think the proposal is missing the most important point. Discount should be seen by the customer so it should be displayed on the sale report.

I believe this is incoherent. The sale (or purchase) order should reflect the reality of the
transaction as should necessarily the invoice too. Especially when these elements are apparent on the ‘official’ documents exchanged.

resteve: thanks, I take a look!

I think we are clear in this point:
On sale you wanted to inform your customer that you give him a discount to
make your offer more attractive in price.

The difference is here:
If you purchase a product for a smaller price than your expected price it could
have many reasons. Maybe your pricelist is not up to date, the supplier made
an error or it is a real discount. Anyway in all cases the difference from
your price expectation would be shown as a discount.
So on purchase the proposed discount implementation provides misleading
information and would need another conception, which is going beyond the scope
of this proposal.
For now you can just collect the effective unit price of any purchase and
you have information about the price in the cost price diagram or stock moves.

Yes, but it can be also done in another way, without influencing the invoice
calculations at all.
When a sale creates an invoice, we can add a default information text per line about
the given discount like “Including 10% black Friday discount”.

1 Like

Added to proposal.

Added to proposal.

Here I am not sure what to do.
The precision of the base price is at least depending on another external module.
The precision of the unit price is depending on user preference.
So we need to represent the discount with enough precision.

On the other hand does it not make much sense to have decimal
places on a percentage.

For the customer the exact calculation is not so important when
we show only the unit price and the discount.
In this example

we can represent the discount to the customer as 5%. The internal
representation could be with 16 digits.

What do you think?

Added to proposal.

Removed all additional features from proposal.

Of course discount should be rounded, probably with 2 digits. But it is not the important part, the important part is when the computation is triggered between the three fields which one need to be updated and how. This process must always have the same result no matter the order in which the form is filled.

I think this should be added in sale module because it will be also needed to implement the tolerance on the unit price.

I do not think it makes sense to fill with 0 when no information is provided.

I think it should never be editable by the user otherwise it will not be usable for tolerance.

I guess I disagree. In fact, perhaps the sort of discount should be distinguished as to
whether it is a percentage or a fixed amount. I believe that would resolve my issues.

To take my example, either 5.087% discount or a fixed discount of 23.69 would do.
In fact, the example I took was exactly that, fixed, but I fit it into OpenERP percentage
style discounts and what seemed to be your proposal basis.

In any event, I still strongly believe minimally a fractional discount is still necessary.

A similar resolve is needed for invoicing based upon advancement where
such advancement is either in percentage terms or fixed (elaboration left to a new topic).

Good point. I guess it should be solved by having two ways to compute discount as percentage or as amount. I guess we could have a selection field on the line to define which one to use and probably the default value should be ‘amount’ as it is the one which is sure to provide always the right value. But as the way discount are done is probably a choice in the company (the way price list are configured), I think the default value should be configurable.

Well, this statement does not really reflect business practice.
Most customers want to see all discounts on the invoice, either on line item level, or on header level (Total per discount category)

We would need as well the option to send just a credit note for the rebates: First an invoice for the full amount, and secondly a credit note for the rebates (mostly needed in central payer scenarios)

This all should be possible and a manageable by add-on modules,
based on this feature, but not in the scoop of this feature.

Sounds interesting to me, but your feature is IMHO a complete different story, which is not scoop of my feature, too.

Just wanted to mention a market requirement in that context…

Why not including both fields as functional ones? As the percentage depends on the discount amount and the unit_price I don’t think it will be hard to compute it.

Because the user will want to decide which version to promote to the customer.
Also percentage may not always result a rational number which can not be defined without rounding issue in decimal.

I think the best option is to store the base_unit_price from product and then let the user decide what needs to be shown on the report. If we have the base_unit_price and the unit_price we can compute all the required information: Discount Amount and Discount Percentage with formulas.

I do not think it is viable to request the user to choose the format on each line.
I think we must find a solution which determine which format to use automatically.

Probably it makes sense to include a configuration value on sale level, with a default value on the sale configuration like we do for the invoice/shipment method.

I do not think a configuration is the right answer because the discount depend on how the price is computed and this computation can be based on different formula per products. Some will have a nice percentage result, others not. That’s why I think this should be done with a smart algorithm which decide which method to use.

Maybe such algorithm could be:

  • compute the percentage
  • if the percentage is a multiple of 5%, then display it
  • otherwise compute and display the amount

The value 5% could be a parameter.