[FIX] account,sale: fix tax excl -> tax incl price include

Create a 15% tax [TaxA] *not* included in price
Create a 15% tax [TaxB] included in price
Create a fiscal position mapping TaxA to TaxB
Create a customer and assign this fiscal position
Create a product :
Price = 100€
Tax = TaxA
Create a SO with this customer and this product

We have this situation

| Price Unit | Tax | Subtotal |
|------------|-----|----------|
|     115    | TaxB|   100    |

While it should be

| Price Unit | Tax | Subtotal |
|------------|-----|----------|
|     100    | TaxB| 86.96    |

after tax mapping, as it was before
https://github.com/odoo/odoo/commit/625486a8382fde9033b73e2a4b4e7713cf4131c1

opw-2811596

closes odoo/odoo#89361

X-original-commit: 1a5b2b44c63afb302a2d6fc1e841e4ef3af46df5
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Grazioso Andrea (agr) <agr@odoo.com>
This commit is contained in:
Andrea Grazioso (agr-odoo)
2022-04-22 10:58:57 +02:00
parent 51dadebd45
commit 8ba7908880
2 changed files with 115 additions and 25 deletions
+12 -12
View File
@@ -129,20 +129,20 @@ class ProductProduct(models.Model):
# Apply fiscal position.
if product_taxes and fiscal_position:
product_taxes_after_fp = fiscal_position.map_tax(product_taxes)
flattened_taxes_after_fp = product_taxes_after_fp._origin.flatten_taxes_hierarchy()
flattened_taxes_before_fp = product_taxes._origin.flatten_taxes_hierarchy()
taxes_before_included = any(tax.price_include for tax in flattened_taxes_before_fp)
if set(product_taxes.ids) != set(product_taxes_after_fp.ids):
flattened_taxes_before_fp = product_taxes._origin.flatten_taxes_hierarchy()
if any(tax.price_include for tax in flattened_taxes_before_fp):
taxes_res = flattened_taxes_before_fp.compute_all(
product_price_unit,
quantity=1.0,
currency=currency,
product=product,
is_refund=is_refund_document,
)
product_price_unit = taxes_res['total_excluded']
if set(product_taxes.ids) != set(product_taxes_after_fp.ids) and taxes_before_included:
taxes_res = flattened_taxes_before_fp.compute_all(
product_price_unit,
quantity=1.0,
currency=currency,
product=product,
is_refund=is_refund_document,
)
product_price_unit = taxes_res['total_excluded']
flattened_taxes_after_fp = product_taxes_after_fp._origin.flatten_taxes_hierarchy()
if any(tax.price_include for tax in flattened_taxes_after_fp):
taxes_res = flattened_taxes_after_fp.compute_all(
product_price_unit,
+103 -13
View File
@@ -172,49 +172,139 @@ class TestSaleOrder(TestSaleCommon):
'name': "George"
})
tax_include_src = self.env['account.tax'].create({
'name': "Include tax",
'name': "Include 21%",
'amount': 21.00,
'amount_type': 'percent',
'price_include': True,
})
tax_include_dst = self.env['account.tax'].create({
'name': "Exclude tax",
'name': "Include 6%",
'amount': 6.00,
'amount_type': 'percent',
'price_include': True,
})
product_tmpl = self.env['product.template'].create({
tax_exclude_src = self.env['account.tax'].create({
'name': "Exclude 15%",
'amount': 15.00,
'amount_type': 'percent',
'price_include': False,
})
tax_exclude_dst = self.env['account.tax'].create({
'name': "Exclude 21%",
'amount': 21.00,
'amount_type': 'percent',
'price_include': False,
})
product_tmpl_a = self.env['product.template'].create({
'name': "Voiture",
'list_price': 121,
'taxes_id': [(6, 0, [tax_include_src.id])]
})
product_product = product_tmpl.product_variant_id
product_tmpl_b = self.env['product.template'].create({
'name': "Voiture",
'list_price': 100,
'taxes_id': [(6, 0, [tax_exclude_src.id])]
})
fpos = self.env['account.fiscal.position'].create({
'name': "fiscal position",
fpos_incl_incl = self.env['account.fiscal.position'].create({
'name': "incl -> incl",
'sequence': 1
})
self.env['account.fiscal.position.tax'].create({
'position_id' :fpos.id,
'position_id' :fpos_incl_incl.id,
'tax_src_id': tax_include_src.id,
'tax_dest_id': tax_include_dst.id
})
fpos_excl_incl = self.env['account.fiscal.position'].create({
'name': "excl -> incl",
'sequence': 2,
})
self.env['account.fiscal.position.tax'].create({
'position_id' :fpos_excl_incl.id,
'tax_src_id': tax_exclude_src.id,
'tax_dest_id': tax_include_dst.id
})
fpos_incl_excl = self.env['account.fiscal.position'].create({
'name': "incl -> excl",
'sequence': 3,
})
self.env['account.fiscal.position.tax'].create({
'position_id' :fpos_incl_excl.id,
'tax_src_id': tax_include_src.id,
'tax_dest_id': tax_exclude_dst.id
})
fpos_excl_excl = self.env['account.fiscal.position'].create({
'name': "excl -> excp",
'sequence': 4,
})
self.env['account.fiscal.position.tax'].create({
'position_id' :fpos_excl_excl.id,
'tax_src_id': tax_exclude_src.id,
'tax_dest_id': tax_exclude_dst.id
})
# Create the SO with one SO line and apply a pricelist and fiscal position on it
# Then check if price unit and price subtotal matches the expected values
# Test Mapping included to included
order_form = Form(self.env['sale.order'].with_context(tracking_disable=True))
order_form.partner_id = partner
order_form.pricelist_id = pricelist
order_form.fiscal_position_id = fpos
order_form.fiscal_position_id = fpos_incl_incl
with order_form.order_line.new() as line:
line.name = product_product.name
line.product_id = product_product
line.name = product_tmpl_a.product_variant_id.name
line.product_id = product_tmpl_a.product_variant_id
line.product_uom_qty = 1.0
line.product_uom = uom
sale_order = order_form.save()
self.assertRecordValues(sale_order.order_line, [{'price_unit': 106, 'price_subtotal': 100}])
# Check the unit price of SO line
self.assertRecordValues(sale_order.order_line, [{'price_unit': 106}])
# Test Mapping excluded to included
order_form = Form(self.env['sale.order'].with_context(tracking_disable=True))
order_form.partner_id = partner
order_form.pricelist_id = pricelist
order_form.fiscal_position_id = fpos_excl_incl
with order_form.order_line.new() as line:
line.name = product_tmpl_b.product_variant_id.name
line.product_id = product_tmpl_b.product_variant_id
line.product_uom_qty = 1.0
line.product_uom = uom
sale_order = order_form.save()
self.assertRecordValues(sale_order.order_line, [{'price_unit': 100, 'price_subtotal': 94.34}])
# Test Mapping included to excluded
order_form = Form(self.env['sale.order'].with_context(tracking_disable=True))
order_form.partner_id = partner
order_form.pricelist_id = pricelist
order_form.fiscal_position_id = fpos_incl_excl
with order_form.order_line.new() as line:
line.name = product_tmpl_a.product_variant_id.name
line.product_id = product_tmpl_a.product_variant_id
line.product_uom_qty = 1.0
line.product_uom = uom
sale_order = order_form.save()
self.assertRecordValues(sale_order.order_line, [{'price_unit': 100, 'price_subtotal': 100}])
# Test Mapping excluded to excluded
order_form = Form(self.env['sale.order'].with_context(tracking_disable=True))
order_form.partner_id = partner
order_form.pricelist_id = pricelist
order_form.fiscal_position_id = fpos_excl_excl
with order_form.order_line.new() as line:
line.name = product_tmpl_b.product_variant_id.name
line.product_id = product_tmpl_b.product_variant_id
line.product_uom_qty = 1.0
line.product_uom = uom
sale_order = order_form.save()
self.assertRecordValues(sale_order.order_line, [{'price_unit': 100, 'price_subtotal': 100}])
def test_pricelist_application(self):
""" Test different prices are correctly applied based on dates """