[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:
@@ -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,
|
||||
|
||||
@@ -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 """
|
||||
|
||||
Reference in New Issue
Block a user