diff --git a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py index 9fc91b6f2de..92d9126fe5f 100644 --- a/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py @@ -2,7 +2,9 @@ # See license.txt import frappe +from frappe.utils import add_days, getdate +from erpnext.controllers.accounts_controller import get_payment_term_details from erpnext.tests.utils import ERPNextTestSuite @@ -55,6 +57,52 @@ class TestPaymentTermsTemplate(ERPNextTestSuite): self.assertRaises(frappe.ValidationError, template.insert) + def test_no_discount_date_without_discount(self): + posting_date = "2026-05-29" + term = frappe._dict( + { + "payment_term": "_Test No Discount Term", + "invoice_portion": 100.0, + "due_date_based_on": "Day(s) after invoice date", + "credit_days": 0, + "credit_months": 0, + "discount_type": "Percentage", + "discount": 0, + "discount_validity_based_on": "Day(s) after invoice date", + "discount_validity": 0, + } + ) + + details = get_payment_term_details( + term, posting_date=posting_date, grand_total=100, base_grand_total=100 + ) + + self.assertEqual(getdate(details.due_date), getdate(posting_date)) + self.assertIsNone(details.discount_date) + + def test_discount_date_generated_with_discount(self): + posting_date = "2026-05-29" + term = frappe._dict( + { + "payment_term": "_Test Discount Term", + "invoice_portion": 100.0, + "due_date_based_on": "Day(s) after invoice date", + "credit_days": 30, + "credit_months": 0, + "discount_type": "Percentage", + "discount": 5, + "discount_validity_based_on": "Day(s) after invoice date", + "discount_validity": 10, + } + ) + + details = get_payment_term_details( + term, posting_date=posting_date, grand_total=100, base_grand_total=100 + ) + + self.assertEqual(getdate(details.due_date), getdate(add_days(posting_date, 30))) + self.assertEqual(getdate(details.discount_date), getdate(add_days(posting_date, 10))) + def test_duplicate_terms(self): template = frappe.get_doc( { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 177118a0fd2..547c81f3ad7 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2687,7 +2687,7 @@ class AccountsController(TransactionBase): payment_schedule["credit_days"] = cint(schedule.credit_days) payment_schedule["credit_months"] = cint(schedule.credit_months) - if schedule.discount_validity_based_on: + if schedule.discount_validity_based_on and flt(schedule.discount): payment_schedule["discount_date"] = get_discount_date(schedule, posting_date) payment_schedule["discount_validity_based_on"] = schedule.discount_validity_based_on payment_schedule["discount_validity"] = cint(schedule.discount_validity) @@ -2729,6 +2729,8 @@ class AccountsController(TransactionBase): return for d in self.get("payment_schedule"): + if not flt(d.discount): + d.discount_date = None d.validate_from_to_dates("discount_date", "due_date") if self.doctype in ["Sales Order", "Quotation"] and getdate(d.due_date) < getdate( self.transaction_date @@ -3618,12 +3620,11 @@ def get_payment_term_details( term_details.outstanding = term_details.payment_amount term_details.base_outstanding = term_details.base_payment_amount - if bill_date: - term_details.due_date = get_due_date(term, bill_date) - term_details.discount_date = get_discount_date(term, bill_date) - elif posting_date: - term_details.due_date = get_due_date(term, posting_date) - term_details.discount_date = get_discount_date(term, posting_date) + has_discount = flt(term.get("discount")) + date = bill_date or posting_date + if date: + term_details.due_date = get_due_date(term, date) + term_details.discount_date = get_discount_date(term, date) if has_discount else None if posting_date and getdate(term_details.due_date) < getdate(posting_date): term_details.due_date = posting_date