validation to check for possible duplicate payment terms
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
index 363484d..7939d8d 100644
--- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
@@ -14,6 +14,7 @@
def validate(self):
self.validate_invoice_portion()
self.validate_credit_days()
+ self.check_duplicate_terms()
def validate_invoice_portion(self):
total_portion = 0
@@ -28,3 +29,14 @@
if term.credit_days < 0:
frappe.msgprint(_('Credit Days cannot be a negative number'), raise_exception=1, indicator='red')
+ def check_duplicate_terms(self):
+ terms = []
+ for term in self.terms:
+ term_info = (term.credit_days, term.due_date_based_on)
+ if term_info in terms:
+ frappe.msgprint(
+ _('The Payment Term at row {0} is possibly a duplicate.').format(term.idx),
+ raise_exception=1, indicator='red'
+ )
+ else:
+ terms.append(term_info)
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 bf9b75a..6daaf1e 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
@@ -46,4 +46,27 @@
}]
})
- self.assertRaises(frappe.ValidationError, template.insert)
\ No newline at end of file
+ self.assertRaises(frappe.ValidationError, template.insert)
+
+ def test_duplicate_terms(self):
+ template = frappe.get_doc({
+ 'doctype': 'Payment Terms Template',
+ 'template_name': '_Test Payment Terms Template For Test',
+ 'terms': [
+ {
+ 'doctype': 'Payment Terms Template Detail',
+ 'invoice_portion': 50.00,
+ 'credit_days_based_on': 'Day(s) after invoice date',
+ 'credit_days': 30
+ },
+ {
+ 'doctype': 'Payment Terms Template Detail',
+ 'invoice_portion': 50.00,
+ 'credit_days_based_on': 'Day(s) after invoice date',
+ 'credit_days': 30
+ }
+
+ ]
+ })
+
+ self.assertRaises(frappe.ValidationError, template.insert)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index cd5b751..3907029 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -645,6 +645,13 @@
self.assertTrue(pi.get('payment_schedule'))
+ def test_duplicate_due_date_in_terms(self):
+ pi = make_purchase_invoice(do_not_save=1)
+ pi.append('payment_schedule', dict(due_date='2017-01-01', invoice_portion=50.00, payment_amount=50))
+ pi.append('payment_schedule', dict(due_date='2017-01-01', invoice_portion=50.00, payment_amount=50))
+
+ self.assertRaises(frappe.ValidationError, pi.insert)
+
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 5e26f52..4d0fa90 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1361,6 +1361,13 @@
si.insert()
self.assertTrue(si.get('payment_schedule'))
+ def test_duplicate_due_date_in_terms(self):
+ si = create_sales_invoice(do_not_save=1)
+ si.append('payment_schedule', dict(due_date='2017-01-01', invoice_portion=50.00, payment_amount=50))
+ si.append('payment_schedule', dict(due_date='2017-01-01', invoice_portion=50.00, payment_amount=50))
+
+ self.assertRaises(frappe.ValidationError, si.insert)
+
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 16b22ce..488d221 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -648,12 +648,15 @@
self.validate_payment_schedule_amount()
def validate_payment_schedule_dates(self):
+ dates = []
if self.due_date and getdate(self.due_date) < getdate(self.posting_date):
frappe.throw(_("Due Date cannot be before posting date"))
for d in self.get("payment_schedule"):
if getdate(d.due_date) < getdate(self.posting_date):
frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx))
+ elif d.due_date in dates:
+ frappe.throw(_("Row {0}: Duplicate due date found").format(d.idx))
def validate_payment_schedule_amount(self):
total = 0