Odoo Help


How to manage tax exemption for exportation when taxes are included in price?

Bernard Wilmus
on 8/29/14, 7:26 AM 1,438 views

All my price lists are tax included (the option Tax Included in Price is checked in my taxes declaration). A partner has a fiscal position outside Europe and the tax substitution is automatically applied in quotation.

The problem is that the quotation uses the price included tax and then applies an export tax of 0% instead of withdrawing the tax. This method is working perfectly if the price doesn't include tax, but not in the case of included tax price.


Ingo Devooght
On 6/17/15, 3:26 AM

Same problem here I got with Odoo 8.0.;

Our company also has tax included in the product prices. This is easier, because we calculate with integer as discounts. It is much easier to calculate for our customer to give a discount of 1 Euro than  0,8403 Euros. :-)

I'm wondering a bit, that there is no out of the box solution, because this is an major issue which affects ALL european companies with inverse/reverse price calculation.

I think there are 3 approaches to solve this problem:

1. Change the unit price with excluded tax:

I don't like this approach so much, because than it is hard to read our bulk prices for consumers (like 1 Euro discount or 2 Euro discount each product). Because of different taxes it is easy to make an user error because of enter wrong price discounts.

2. Using special pricelists for relevant fiscal positions:

This would be for companies with VAT-ID outside of your country and customers outside of the EU (Switzerland for example). So the pricelist could be adapted to the fiscal position. What I don't like here is the mix of tax types (included vs. excluded taxes). Also there will be redudant pricelists which just differ on another base price.

3. Inherit the compute_all method in account.py:

In Accounting/Taxes/Taxes the Tax Free setting needs to get the correct taxes from the base product with python code (reverse):


Now the right tax is calculated in the tax setting. The correct unit price could be calculated.

Later on, when the unit price is calculated we must delete the taxes again:

		class account_tax_code(osv.osv):

def compute_all(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, force_excluded=False):
totalin = totalex = round(price_unit * quantity, precision)
tin = []
tex = []
for tax in taxes:
if not tax.price_include or force_excluded:
tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner, precision=tax_compute_precision)
for r in tin:
totalex -= r.get('amount', 0.0)
                      ->      if r['NEW_OPTION_TO_EXCLUDE_TAX']:
                                            r['amount']=0          <-
totlex_qty = 0.0

This seem to work. But unfortunately I am afraid for getting side effects because I am not a specialist for accounting, so I hope that the journals are still correct after this modification. ;-)

--- UPDATE ---

I think I found a solution. I inherited the sale_order_line class and add a switch in the taxes configuration. It seems to work! Now all customers who don't pay taxes will get the unit_price with excluded taxes.

 class account_tax_code(osv.osv):
    _columns = {
        'exclude_taxes':fields.boolean('Unit_Price = Unit_Price - Taxes', help="Calcuate new unit_price for customers who don't calculate taxes. Only for inverse price calculation!"),
 <record id="account.tax_exclude_taxes" model="ir.ui.view">
            <field name="name">account.tax.form</field>
            <field name="model">account.tax</field>
            <field name="inherit_id" ref="account.view_tax_form" />
            <field name="arch" type="xml">
                <field name="child_depend" position="after">
                    <field name="exclude_taxes" />
 class sale_order_line(osv.osv):
    _inherit = 'sale.order.line'
    def product_id_change_with_wh(self, cr, uid, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, warehouse_id=False, context=None):
        context = context or {}
        result =  super(sale_order_line, self).product_id_change_with_wh( cr, uid, ids, pricelist, product, qty,
            uom, qty_uos, uos, name, partner_id,
            lang, update_tax, date_order, packaging, fiscal_position, flag, warehouse_id=warehouse_id, context=context)
values=result['value'] if values.has_key('price_unit_orig') is False: if values.has_key('tax_id'): if fiscal_position != None: fisc=self.pool['account.tax'].browse(cr, uid, values['tax_id']) if fisc.exclude_taxes: result['value']['price_unit_orig']=result['value']['price_unit'] product=self.pool['product.product'].browse(cr, uid, product) result['value']['price_unit']=(result['value']['price_unit']/(1+product.product_tmpl_id.taxes_id.amount))  return result

Bernard Wilmus
On 9/1/14, 3:59 AM

EXPORT-0 is automatically replaced by the fiscal position rule. A 0% tax is applied to the price that includes tax, the invoice shows a total amount of 0€ of taxes but the total includes the taxes. The only way to get rid of that is to modidify the unit price of the prtoduct by removing taxes manually on each line.

I am using the 7th version of Odoo.

This question has already been raised by Shaun on the 5/5/2013 without any real answer:


Mind And Go
On 8/30/14, 6:31 AM

Hy bernard,

Good question we have here.

You said that the price is tax included and the EXPORT-0 is used, do you mean that EXPORT-0 is automatically replaced by the fiscal position or is it replaced by hand?


About This Community

This platform is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.


Odoo Training Center

Access to our E-learning platform and experience all Odoo Apps through learning videos, exercises and Quizz.

Test it now

Question tools

5 follower(s)


Asked: 8/29/14, 7:26 AM
Seen: 1438 times
Last updated: 6/19/15, 8:01 AM