fix: dunning calculation of grand total when rate of interest is 0% (#26286)
This commit is contained in:
parent
4b4ac7c051
commit
7e05bea6a9
@ -25,7 +25,7 @@ class Dunning(AccountsController):
|
|||||||
|
|
||||||
def validate_amount(self):
|
def validate_amount(self):
|
||||||
amounts = calculate_interest_and_amount(
|
amounts = calculate_interest_and_amount(
|
||||||
self.posting_date, self.outstanding_amount, self.rate_of_interest, self.dunning_fee, self.overdue_days)
|
self.outstanding_amount, self.rate_of_interest, self.dunning_fee, self.overdue_days)
|
||||||
if self.interest_amount != amounts.get('interest_amount'):
|
if self.interest_amount != amounts.get('interest_amount'):
|
||||||
self.interest_amount = flt(amounts.get('interest_amount'), self.precision('interest_amount'))
|
self.interest_amount = flt(amounts.get('interest_amount'), self.precision('interest_amount'))
|
||||||
if self.dunning_amount != amounts.get('dunning_amount'):
|
if self.dunning_amount != amounts.get('dunning_amount'):
|
||||||
@ -91,13 +91,13 @@ def resolve_dunning(doc, state):
|
|||||||
for dunning in dunnings:
|
for dunning in dunnings:
|
||||||
frappe.db.set_value("Dunning", dunning.name, "status", 'Resolved')
|
frappe.db.set_value("Dunning", dunning.name, "status", 'Resolved')
|
||||||
|
|
||||||
def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
|
def calculate_interest_and_amount(outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
|
||||||
interest_amount = 0
|
interest_amount = 0
|
||||||
grand_total = 0
|
grand_total = flt(outstanding_amount) + flt(dunning_fee)
|
||||||
if rate_of_interest:
|
if rate_of_interest:
|
||||||
interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100
|
interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100
|
||||||
interest_amount = (interest_per_year * cint(overdue_days)) / 365
|
interest_amount = (interest_per_year * cint(overdue_days)) / 365
|
||||||
grand_total = flt(outstanding_amount) + flt(interest_amount) + flt(dunning_fee)
|
grand_total += flt(interest_amount)
|
||||||
dunning_amount = flt(interest_amount) + flt(dunning_fee)
|
dunning_amount = flt(interest_amount) + flt(dunning_fee)
|
||||||
return {
|
return {
|
||||||
'interest_amount': interest_amount,
|
'interest_amount': interest_amount,
|
||||||
|
@ -16,6 +16,7 @@ class TestDunning(unittest.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(self):
|
def setUpClass(self):
|
||||||
create_dunning_type()
|
create_dunning_type()
|
||||||
|
create_dunning_type_with_zero_interest_rate()
|
||||||
unlink_payment_on_cancel_of_invoice()
|
unlink_payment_on_cancel_of_invoice()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -25,11 +26,19 @@ class TestDunning(unittest.TestCase):
|
|||||||
def test_dunning(self):
|
def test_dunning(self):
|
||||||
dunning = create_dunning()
|
dunning = create_dunning()
|
||||||
amounts = calculate_interest_and_amount(
|
amounts = calculate_interest_and_amount(
|
||||||
dunning.posting_date, dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days)
|
dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days)
|
||||||
self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
|
self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
|
||||||
self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
|
self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
|
||||||
self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
|
self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
|
||||||
|
|
||||||
|
def test_dunning_with_zero_interest_rate(self):
|
||||||
|
dunning = create_dunning_with_zero_interest_rate()
|
||||||
|
amounts = calculate_interest_and_amount(
|
||||||
|
dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days)
|
||||||
|
self.assertEqual(round(amounts.get('interest_amount'), 2), 0)
|
||||||
|
self.assertEqual(round(amounts.get('dunning_amount'), 2), 20)
|
||||||
|
self.assertEqual(round(amounts.get('grand_total'), 2), 120)
|
||||||
|
|
||||||
def test_gl_entries(self):
|
def test_gl_entries(self):
|
||||||
dunning = create_dunning()
|
dunning = create_dunning()
|
||||||
dunning.submit()
|
dunning.submit()
|
||||||
@ -83,6 +92,27 @@ def create_dunning():
|
|||||||
dunning.save()
|
dunning.save()
|
||||||
return dunning
|
return dunning
|
||||||
|
|
||||||
|
def create_dunning_with_zero_interest_rate():
|
||||||
|
posting_date = add_days(today(), -20)
|
||||||
|
due_date = add_days(today(), -15)
|
||||||
|
sales_invoice = create_sales_invoice_against_cost_center(
|
||||||
|
posting_date=posting_date, due_date=due_date, status='Overdue')
|
||||||
|
dunning_type = frappe.get_doc("Dunning Type", 'First Notice with 0% Rate of Interest')
|
||||||
|
dunning = frappe.new_doc("Dunning")
|
||||||
|
dunning.sales_invoice = sales_invoice.name
|
||||||
|
dunning.customer_name = sales_invoice.customer_name
|
||||||
|
dunning.outstanding_amount = sales_invoice.outstanding_amount
|
||||||
|
dunning.debit_to = sales_invoice.debit_to
|
||||||
|
dunning.currency = sales_invoice.currency
|
||||||
|
dunning.company = sales_invoice.company
|
||||||
|
dunning.posting_date = nowdate()
|
||||||
|
dunning.due_date = sales_invoice.due_date
|
||||||
|
dunning.dunning_type = 'First Notice with 0% Rate of Interest'
|
||||||
|
dunning.rate_of_interest = dunning_type.rate_of_interest
|
||||||
|
dunning.dunning_fee = dunning_type.dunning_fee
|
||||||
|
dunning.save()
|
||||||
|
return dunning
|
||||||
|
|
||||||
def create_dunning_type():
|
def create_dunning_type():
|
||||||
dunning_type = frappe.new_doc("Dunning Type")
|
dunning_type = frappe.new_doc("Dunning Type")
|
||||||
dunning_type.dunning_type = 'First Notice'
|
dunning_type.dunning_type = 'First Notice'
|
||||||
@ -98,3 +128,19 @@ def create_dunning_type():
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
dunning_type.save()
|
dunning_type.save()
|
||||||
|
|
||||||
|
def create_dunning_type_with_zero_interest_rate():
|
||||||
|
dunning_type = frappe.new_doc("Dunning Type")
|
||||||
|
dunning_type.dunning_type = 'First Notice with 0% Rate of Interest'
|
||||||
|
dunning_type.start_day = 10
|
||||||
|
dunning_type.end_day = 20
|
||||||
|
dunning_type.dunning_fee = 20
|
||||||
|
dunning_type.rate_of_interest = 0
|
||||||
|
dunning_type.append(
|
||||||
|
"dunning_letter_text", {
|
||||||
|
'language': 'en',
|
||||||
|
'body_text': 'We have still not received payment for our invoice ',
|
||||||
|
'closing_text': 'We kindly request that you pay the outstanding amount immediately, and late fees.'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
dunning_type.save()
|
Loading…
Reference in New Issue
Block a user