[FIX] account: Negative fixed taxes on 100% discount
Issue - Install 'Accounting' module - Create a new 'Tax' X with a fixed price (e.g.: O.O57 $) - Create a new 'Customer Invoice' - Add a product P and set unit price to 0 $ - Set tax X to product P Total tax amount : - 0.06 $ . Solution The sign must be forced to a negative sign in case the balance is on credit to avoid negatif taxes amount. enterprise PR : https://github.com/odoo/enterprise/pull/15035 opw-2378978 closes odoo/odoo#62758 X-original-commit: 684855529e8aaafa0cb90f958d19c563d6e2a897 Related: odoo/enterprise#15105 Signed-off-by: Laurent Smet <smetl@users.noreply.github.com> Signed-off-by: bon-odoo <nboulif@users.noreply.github.com>
This commit is contained in:
@@ -529,6 +529,17 @@ class AccountMove(models.Model):
|
||||
'tax_tag_ids': [(6, 0, tax_vals['tag_ids'])],
|
||||
}
|
||||
|
||||
def _get_tax_force_sign(self):
|
||||
""" The sign must be forced to a negative sign in case the balance is on credit
|
||||
to avoid negatif taxes amount.
|
||||
Example - Customer Invoice :
|
||||
Fixed Tax | unit price | discount | amount_tax | amount_total |
|
||||
-------------------------------------------------------------------------
|
||||
0.67 | 115 | 100% | - 0.67 | 0
|
||||
-------------------------------------------------------------------------"""
|
||||
self.ensure_one()
|
||||
return -1 if self.move_type in ('out_invoice', 'in_refund', 'out_receipt') else 1
|
||||
|
||||
def _recompute_tax_lines(self, recompute_tax_base_amount=False):
|
||||
''' Compute the dynamic tax lines of the journal entry.
|
||||
|
||||
@@ -570,7 +581,7 @@ class AccountMove(models.Model):
|
||||
is_refund = (tax_type == 'sale' and base_line.debit) or (tax_type == 'purchase' and base_line.credit)
|
||||
price_unit_wo_discount = base_line.balance
|
||||
|
||||
balance_taxes_res = base_line.tax_ids._origin.compute_all(
|
||||
balance_taxes_res = base_line.tax_ids._origin.with_context(force_sign=move._get_tax_force_sign()).compute_all(
|
||||
price_unit_wo_discount,
|
||||
currency=base_line.currency_id,
|
||||
quantity=quantity,
|
||||
@@ -3213,7 +3224,8 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
# Compute 'price_total'.
|
||||
if taxes:
|
||||
taxes_res = taxes._origin.compute_all(line_discount_price_unit,
|
||||
force_sign = -1 if move_type in ('out_invoice', 'in_refund', 'out_receipt') else 1
|
||||
taxes_res = taxes._origin.with_context(force_sign=force_sign).compute_all(line_discount_price_unit,
|
||||
quantity=quantity, currency=currency, product=product, partner=partner, is_refund=move_type in ('out_refund', 'in_refund'))
|
||||
res['price_subtotal'] = taxes_res['total_excluded']
|
||||
res['price_total'] = taxes_res['total_included']
|
||||
@@ -3325,7 +3337,7 @@ class AccountMoveLine(models.Model):
|
||||
# 220 | 10% incl, 5% | | 200 | 230
|
||||
# 20 | | 10% incl | 20 | 20
|
||||
# 10 | | 5% | 10 | 10
|
||||
taxes_res = taxes._origin.compute_all(amount_currency, currency=currency, handle_price_include=False)
|
||||
taxes_res = taxes._origin.with_context(force_sign=self.move_id._get_tax_force_sign()).compute_all(amount_currency, currency=currency, handle_price_include=False)
|
||||
for tax_res in taxes_res['taxes']:
|
||||
tax = self.env['account.tax'].browse(tax_res['id'])
|
||||
if tax.price_include:
|
||||
|
||||
@@ -439,9 +439,12 @@ class AccountTax(models.Model):
|
||||
# For the computation of move lines, we could have a negative base value.
|
||||
# In this case, compute all with positive values and negate them at the end.
|
||||
sign = 1
|
||||
if currency.is_zero(base):
|
||||
sign = self._context.get('force_sign', 1)
|
||||
elif base < 0:
|
||||
sign = -1
|
||||
if base < 0:
|
||||
base = -base
|
||||
sign = -1
|
||||
|
||||
# Store the totals to reach when using price_include taxes (only the last price included in row)
|
||||
total_included_checkpoints = {}
|
||||
|
||||
@@ -68,7 +68,7 @@ class AccountEdiFormat(models.Model):
|
||||
# Invoice lines.
|
||||
for i, line in enumerate(invoice.invoice_line_ids.filtered(lambda l: not l.display_type)):
|
||||
price_unit_with_discount = line.price_unit * (1 - (line.discount / 100.0))
|
||||
taxes_res = line.tax_ids.compute_all(
|
||||
taxes_res = line.tax_ids.with_context(force_sign=line.move_id._get_tax_force_sign()).compute_all(
|
||||
price_unit_with_discount,
|
||||
currency=line.currency_id,
|
||||
quantity=line.quantity,
|
||||
|
||||
@@ -30,7 +30,7 @@ class AccountMoveLine(models.Model):
|
||||
invoice.l10n_latam_document_type_id and invoice.l10n_latam_document_type_id._filter_taxes_included(
|
||||
line.tax_ids)
|
||||
if not included_taxes:
|
||||
price_unit = line.tax_ids.with_context(round=False).compute_all(
|
||||
price_unit = line.tax_ids.with_context(round=False, force_sign=invoice._get_tax_force_sign()).compute_all(
|
||||
line.price_unit, invoice.currency_id, 1.0, line.product_id, invoice.partner_id)
|
||||
l10n_latam_price_unit = price_unit['total_excluded']
|
||||
l10n_latam_price_subtotal = line.price_subtotal
|
||||
@@ -38,11 +38,11 @@ class AccountMoveLine(models.Model):
|
||||
l10n_latam_price_net = l10n_latam_price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||
else:
|
||||
not_included_taxes = line.tax_ids - included_taxes
|
||||
l10n_latam_price_unit = included_taxes.compute_all(
|
||||
l10n_latam_price_unit = included_taxes.with_context(force_sign=invoice._get_tax_force_sign()).compute_all(
|
||||
line.price_unit, invoice.currency_id, 1.0, line.product_id, invoice.partner_id)['total_included']
|
||||
l10n_latam_price_net = l10n_latam_price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
|
||||
l10n_latam_price_subtotal = included_taxes.compute_all(
|
||||
l10n_latam_price_subtotal = included_taxes.with_context(force_sign=invoice._get_tax_force_sign()).compute_all(
|
||||
price, invoice.currency_id, line.quantity, line.product_id,
|
||||
invoice.partner_id)['total_included']
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ class AccountMove(models.Model):
|
||||
# Since compute_all still rounds the total, we use an ugly workaround:
|
||||
# multiply then divide the price unit.
|
||||
price_unit *= line.quantity
|
||||
price_unit = line.tax_ids.with_context(round=False).compute_all(
|
||||
price_unit = line.tax_ids.with_context(round=False, force_sign=move._get_tax_force_sign()).compute_all(
|
||||
price_unit, currency=move.currency_id, quantity=1.0, is_refund=move.move_type == 'in_refund')['total_excluded']
|
||||
price_unit /= line.quantity
|
||||
|
||||
|
||||
Reference in New Issue
Block a user