diff --git a/addons/account/models/product.py b/addons/account/models/product.py index 459d193cd0e..8a9897478b5 100644 --- a/addons/account/models/product.py +++ b/addons/account/models/product.py @@ -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, diff --git a/addons/sale/tests/test_sale_pricelist.py b/addons/sale/tests/test_sale_pricelist.py index 39dc268ff93..fa810e4b34e 100644 --- a/addons/sale/tests/test_sale_pricelist.py +++ b/addons/sale/tests/test_sale_pricelist.py @@ -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 """