mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-20 21:49:18 +00:00
Merge pull request #36237 from frappe/mergify/bp/version-14-hotfix/pr-36206
test: overallocation validation in payment entry (backport #36206)
This commit is contained in:
@@ -1061,6 +1061,101 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
}
|
}
|
||||||
self.assertDictEqual(ref_details, expected_response)
|
self.assertDictEqual(ref_details, expected_response)
|
||||||
|
|
||||||
|
@change_settings(
|
||||||
|
"Accounts Settings",
|
||||||
|
{
|
||||||
|
"unlink_payment_on_cancellation_of_invoice": 1,
|
||||||
|
"delete_linked_ledger_entries": 1,
|
||||||
|
"allow_multi_currency_invoices_against_single_party_account": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def test_overallocation_validation_on_payment_terms(self):
|
||||||
|
"""
|
||||||
|
Validate Allocation on Payment Entry based on Payment Schedule. Upon overallocation, validation error must be thrown.
|
||||||
|
|
||||||
|
"""
|
||||||
|
customer = create_customer()
|
||||||
|
create_payment_terms_template()
|
||||||
|
|
||||||
|
# Validate allocation on base/company currency
|
||||||
|
si1 = create_sales_invoice(do_not_save=1, qty=1, rate=200)
|
||||||
|
si1.payment_terms_template = "Test Receivable Template"
|
||||||
|
si1.save().submit()
|
||||||
|
|
||||||
|
si1.reload()
|
||||||
|
pe = get_payment_entry(si1.doctype, si1.name).save()
|
||||||
|
# Allocated amount should be according to the payment schedule
|
||||||
|
for idx, schedule in enumerate(si1.payment_schedule):
|
||||||
|
with self.subTest(idx=idx):
|
||||||
|
self.assertEqual(flt(schedule.payment_amount), flt(pe.references[idx].allocated_amount))
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
# Overallocation validation should trigger
|
||||||
|
pe.paid_amount = 400
|
||||||
|
pe.references[0].allocated_amount = 200
|
||||||
|
pe.references[1].allocated_amount = 200
|
||||||
|
self.assertRaises(frappe.ValidationError, pe.save)
|
||||||
|
pe.delete()
|
||||||
|
si1.cancel()
|
||||||
|
si1.delete()
|
||||||
|
|
||||||
|
# Validate allocation on foreign currency
|
||||||
|
si2 = create_sales_invoice(
|
||||||
|
customer="_Test Customer USD",
|
||||||
|
debit_to="_Test Receivable USD - _TC",
|
||||||
|
currency="USD",
|
||||||
|
conversion_rate=80,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
si2.payment_terms_template = "Test Receivable Template"
|
||||||
|
si2.save().submit()
|
||||||
|
|
||||||
|
si2.reload()
|
||||||
|
pe = get_payment_entry(si2.doctype, si2.name).save()
|
||||||
|
# Allocated amount should be according to the payment schedule
|
||||||
|
for idx, schedule in enumerate(si2.payment_schedule):
|
||||||
|
with self.subTest(idx=idx):
|
||||||
|
self.assertEqual(flt(schedule.payment_amount), flt(pe.references[idx].allocated_amount))
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
# Overallocation validation should trigger
|
||||||
|
pe.paid_amount = 200
|
||||||
|
pe.references[0].allocated_amount = 100
|
||||||
|
pe.references[1].allocated_amount = 100
|
||||||
|
self.assertRaises(frappe.ValidationError, pe.save)
|
||||||
|
pe.delete()
|
||||||
|
si2.cancel()
|
||||||
|
si2.delete()
|
||||||
|
|
||||||
|
# Validate allocation in base/company currency on a foreign currency document
|
||||||
|
# when invoice is made is foreign currency, but posted to base/company currency debtors account
|
||||||
|
si3 = create_sales_invoice(
|
||||||
|
customer=customer,
|
||||||
|
currency="USD",
|
||||||
|
conversion_rate=80,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
si3.payment_terms_template = "Test Receivable Template"
|
||||||
|
si3.save().submit()
|
||||||
|
|
||||||
|
si3.reload()
|
||||||
|
pe = get_payment_entry(si3.doctype, si3.name).save()
|
||||||
|
# Allocated amount should be equal to payment term outstanding
|
||||||
|
self.assertEqual(len(pe.references), 2)
|
||||||
|
for idx, ref in enumerate(pe.references):
|
||||||
|
with self.subTest(idx=idx):
|
||||||
|
self.assertEqual(ref.payment_term_outstanding, ref.allocated_amount)
|
||||||
|
pe.save()
|
||||||
|
|
||||||
|
# Overallocation validation should trigger
|
||||||
|
pe.paid_amount = 16000
|
||||||
|
pe.references[0].allocated_amount = 8000
|
||||||
|
pe.references[1].allocated_amount = 8000
|
||||||
|
self.assertRaises(frappe.ValidationError, pe.save)
|
||||||
|
pe.delete()
|
||||||
|
si3.cancel()
|
||||||
|
si3.delete()
|
||||||
|
|
||||||
|
|
||||||
def create_payment_entry(**args):
|
def create_payment_entry(**args):
|
||||||
payment_entry = frappe.new_doc("Payment Entry")
|
payment_entry = frappe.new_doc("Payment Entry")
|
||||||
@@ -1150,3 +1245,17 @@ def create_payment_terms_template_with_discount(
|
|||||||
def create_payment_term(name):
|
def create_payment_term(name):
|
||||||
if not frappe.db.exists("Payment Term", name):
|
if not frappe.db.exists("Payment Term", name):
|
||||||
frappe.get_doc({"doctype": "Payment Term", "payment_term_name": name}).insert()
|
frappe.get_doc({"doctype": "Payment Term", "payment_term_name": name}).insert()
|
||||||
|
|
||||||
|
|
||||||
|
def create_customer(name="_Test Customer 2 USD", currency="USD"):
|
||||||
|
customer = None
|
||||||
|
if frappe.db.exists("Customer", name):
|
||||||
|
customer = name
|
||||||
|
else:
|
||||||
|
customer = frappe.new_doc("Customer")
|
||||||
|
customer.customer_name = name
|
||||||
|
customer.default_currency = currency
|
||||||
|
customer.type = "Individual"
|
||||||
|
customer.save()
|
||||||
|
customer = customer.name
|
||||||
|
return customer
|
||||||
|
|||||||
Reference in New Issue
Block a user