[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:
Nasreddin (bon)
2020-12-02 15:51:55 +00:00
parent 66b404341e
commit eb0b664349
5 changed files with 24 additions and 9 deletions
+15 -3
View File
@@ -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:
+4 -1
View File
@@ -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