[FIX] account: wrong quick encoding calculation with cash discount
Before: when using the quick encoding feature on an invoice or bill with payment term containing an early payment discount and the epd computation is set to "Always (upon invoice)", the calculation was done incorrectly.
Example: if you invoice a 100€ product with a 21% tax with a 2% cash discount, the total of the invoice will be 120.58 (the 21% is calculated on 98€ (100€*2%) which is 20.28€).
In our case, if you tried to calculate suggestions from a quick encoding value of 120.58, the calculation would calculate the untaxed amount from the 120.58 based on the 21% tax without applying the 2% discount.
After: when calculating the suggestions check if an early discount is set on the payment term and the epd computation is set to "mixed" ("Always (upon invoice)") and if so, apply the discount to the tax before calculating the untaxed amount from the total.
task-3339223
closes odoo/odoo#125505
X-original-commit: 162443f1ad913a0388bea60f04ff140e75fdb0ed
Signed-off-by: Laurent Smet <las@odoo.com>
This commit is contained in:
@@ -2651,8 +2651,27 @@ class AccountMove(models.Model):
|
||||
self.journal_id.company_id.account_purchase_tax_id
|
||||
)
|
||||
taxes = self.fiscal_position_id.map_tax(taxes)
|
||||
price_untaxed = taxes.with_context(force_price_include=True).compute_all(
|
||||
self.quick_edit_total_amount - self.tax_totals['amount_total'])['total_excluded']
|
||||
|
||||
# When a payment term has an early payment discount with the epd computation set to 'mixed', recomputing
|
||||
# the untaxed amount should take in consideration the discount percentage otherwise we'd get a wrong value.
|
||||
# We check that we have only one percentage tax as computing from multiple taxes with different types can get complicated.
|
||||
# In one example: let's say: base = 100, discount = 2%, tax = 21%
|
||||
# the total will be calculated as: total = base + (base * (1 - discount)) * tax
|
||||
# If we manipulate the equation to get the base from the total, we'll have base = total / ((1 - discount) * tax + 1)
|
||||
term = self.invoice_payment_term_id
|
||||
discount_percentage = term.discount_percentage if term.early_discount else 0
|
||||
remaining_amount = self.quick_edit_total_amount - self.tax_totals['amount_total']
|
||||
|
||||
if (
|
||||
discount_percentage
|
||||
and term.early_pay_discount_computation == 'mixed'
|
||||
and len(taxes) == 1
|
||||
and taxes.amount_type == 'percent'
|
||||
):
|
||||
price_untaxed = self.currency_id.round(
|
||||
remaining_amount / (((1.0 - discount_percentage / 100.0) * (taxes.amount / 100.0)) + 1.0))
|
||||
else:
|
||||
price_untaxed = taxes.with_context(force_price_include=True).compute_all(remaining_amount)['total_excluded']
|
||||
return {'account_id': account_id, 'tax_ids': taxes.ids, 'price_unit': price_untaxed}
|
||||
|
||||
@api.onchange('quick_edit_mode', 'journal_id', 'company_id')
|
||||
|
||||
@@ -3344,6 +3344,55 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
self.assertEqual(invoice.amount_tax, 17.36)
|
||||
self.assertEqual(len(invoice.invoice_line_ids), 2)
|
||||
|
||||
def test_quick_edit_total_amount_with_mixed_epd(self):
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='out_invoice'))
|
||||
move_form.invoice_date = fields.Date.from_string('2022-01-01')
|
||||
|
||||
# Quick edit total amount activated
|
||||
self.env.company.quick_edit_mode = "out_and_in_invoices"
|
||||
# 21% sale tax
|
||||
self.env.company.account_sale_tax_id = self.env['account.tax'].create({
|
||||
'name': '21%',
|
||||
'amount': 21,
|
||||
'type_tax_use': 'sale',
|
||||
})
|
||||
# Create a payment term with early payment discount of 2% and computation set to mixed (Always (upon invoice))
|
||||
epd_payment_term = self.env['account.payment.term'].create({
|
||||
'name': "2/7 Term",
|
||||
'discount_days': 7,
|
||||
'discount_percentage': 2,
|
||||
'early_discount': True,
|
||||
'early_pay_discount_computation': 'mixed',
|
||||
})
|
||||
# Set the payment term to the one we just created
|
||||
move_form.invoice_payment_term_id = epd_payment_term
|
||||
|
||||
invoice = move_form.save()
|
||||
|
||||
# Invoice of one item of price 100, discount 2% and tax 21%:
|
||||
# 21% tax = 100 * (1 - 0.2) * 0.21 = 20.58
|
||||
# total_amount = 100 + 20.58 = 120.58
|
||||
|
||||
# Make sure the quick edit added one line with the correct values
|
||||
with Form(invoice) as move_form:
|
||||
move_form.quick_edit_total_amount = 120.58
|
||||
self.assertRecordValues(invoice, [{'amount_total': 120.58, 'amount_untaxed': 100, 'amount_tax': 20.58}])
|
||||
self.assertEqual(len(invoice.invoice_line_ids), 1)
|
||||
|
||||
# Modify one invoice line
|
||||
with Form(invoice) as move_form:
|
||||
with move_form.invoice_line_ids.edit(0) as line_form:
|
||||
line_form.price_unit = 70
|
||||
self.assertRecordValues(invoice, [{'amount_total': 84.41, 'amount_untaxed': 70, 'amount_tax': 14.41}])
|
||||
self.assertEqual(len(invoice.invoice_line_ids), 1)
|
||||
|
||||
# Suggest the new amount such that the total is equal to the quick amount
|
||||
with Form(invoice) as move_form:
|
||||
with move_form.invoice_line_ids.new() as line_form:
|
||||
self.assertEqual(line_form.price_unit, 30)
|
||||
self.assertRecordValues(invoice, [{'amount_total': 120.58, 'amount_untaxed': 100, 'amount_tax': 20.58}])
|
||||
self.assertEqual(len(invoice.invoice_line_ids), 2)
|
||||
|
||||
def test_out_invoice_depreciated_account(self):
|
||||
move = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
|
||||
Reference in New Issue
Block a user