fix(Payment Entry): split orders as per the schedules in the refrence table

(cherry picked from commit a9e52833fe)
This commit is contained in:
Jatin3128
2026-02-02 12:46:49 +05:30
committed by Mergify
parent f9bbf7bee4
commit 2693ffe680
2 changed files with 101 additions and 15 deletions

View File

@@ -2376,9 +2376,7 @@ def get_outstanding_reference_documents(args, validate=False):
vouchers=args.get("vouchers") or None,
)
outstanding_invoices = split_invoices_based_on_payment_terms(
outstanding_invoices, args.get("company")
)
outstanding_invoices = split_refdocs_based_on_payment_terms(outstanding_invoices, args.get("company"))
for d in outstanding_invoices:
d["exchange_rate"] = 1
@@ -2416,6 +2414,8 @@ def get_outstanding_reference_documents(args, validate=False):
filters=args,
)
orders_to_be_billed = split_refdocs_based_on_payment_terms(orders_to_be_billed, args.get("company"))
data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
if not data:
@@ -2438,13 +2438,13 @@ def get_outstanding_reference_documents(args, validate=False):
return data
def split_invoices_based_on_payment_terms(outstanding_invoices, company) -> list:
def split_refdocs_based_on_payment_terms(refdocs, company) -> list:
"""Split a list of invoices based on their payment terms."""
exc_rates = get_currency_data(outstanding_invoices, company)
exc_rates = get_currency_data(refdocs, company)
outstanding_invoices_after_split = []
for entry in outstanding_invoices:
if entry.voucher_type in ["Sales Invoice", "Purchase Invoice"]:
outstanding_refdoc_after_split = []
for entry in refdocs:
if entry.voucher_type in ["Sales Invoice", "Purchase Invoice", "Sales Order", "Purchase Order"]:
if payment_term_template := frappe.db.get_value(
entry.voucher_type, entry.voucher_no, "payment_terms_template"
):
@@ -2459,25 +2459,25 @@ def split_invoices_based_on_payment_terms(outstanding_invoices, company) -> list
),
alert=True,
)
outstanding_invoices_after_split += split_rows
outstanding_refdoc_after_split += split_rows
continue
# If not an invoice or no payment terms template, add as it is
outstanding_invoices_after_split.append(entry)
outstanding_refdoc_after_split.append(entry)
return outstanding_invoices_after_split
return outstanding_refdoc_after_split
def get_currency_data(outstanding_invoices: list, company: str | None = None) -> dict:
def get_currency_data(outstanding_refdocs: list, company: str | None = None) -> dict:
"""Get currency and conversion data for a list of invoices."""
exc_rates = frappe._dict()
company_currency = frappe.db.get_value("Company", company, "default_currency") if company else None
for doctype in ["Sales Invoice", "Purchase Invoice"]:
invoices = [x.voucher_no for x in outstanding_invoices if x.voucher_type == doctype]
for doctype in ["Sales Invoice", "Purchase Invoice", "Sales Order", "Purchase Order"]:
refdoc = [x.voucher_no for x in outstanding_refdocs if x.voucher_type == doctype]
for x in frappe.db.get_all(
doctype,
filters={"name": ["in", invoices]},
filters={"name": ["in", refdoc]},
fields=["name", "currency", "conversion_rate", "party_account_currency"],
):
exc_rates[x.name] = frappe._dict(

View File

@@ -2019,6 +2019,92 @@ class TestPaymentEntry(ERPNextTestSuite):
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, pe.doctype, pe.name)
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, "Journal Entry", jv[0])
def test_outstanding_orders_split_by_payment_terms(self):
create_payment_terms_template()
so = make_sales_order(do_not_save=1, qty=1, rate=200)
so.payment_terms_template = "Test Receivable Template"
so.save().submit()
args = {
"posting_date": nowdate(),
"company": so.company,
"party_type": "Customer",
"payment_type": "Receive",
"party": so.customer,
"party_account": "Debtors - _TC",
"get_orders_to_be_billed": True,
}
references = get_outstanding_reference_documents(args)
self.assertEqual(len(references), 2)
self.assertEqual(references[0].voucher_no, so.name)
self.assertEqual(references[1].voucher_no, so.name)
self.assertEqual(references[0].payment_term, "Basic Amount Receivable")
self.assertEqual(references[1].payment_term, "Tax Receivable")
def test_outstanding_orders_no_split_when_allocate_disabled(self):
create_payment_terms_template()
template = frappe.get_doc("Payment Terms Template", "Test Receivable Template")
template.allocate_payment_based_on_payment_terms = 0
template.save()
so = make_sales_order(do_not_save=1, qty=1, rate=200)
so.payment_terms_template = "Test Receivable Template"
so.save().submit()
args = {
"posting_date": nowdate(),
"company": so.company,
"party_type": "Customer",
"payment_type": "Receive",
"party": so.customer,
"party_account": "Debtors - _TC",
"get_orders_to_be_billed": True,
}
references = get_outstanding_reference_documents(args)
self.assertEqual(len(references), 1)
self.assertIsNone(references[0].payment_term)
template.allocate_payment_based_on_payment_terms = 1
template.save()
def test_outstanding_multicurrency_sales_order_split(self):
create_payment_terms_template()
so = make_sales_order(
customer="_Test Customer USD",
currency="USD",
qty=1,
rate=100,
do_not_submit=True,
)
so.payment_terms_template = "Test Receivable Template"
so.conversion_rate = 50
so.save().submit()
args = {
"posting_date": nowdate(),
"company": so.company,
"party_type": "Customer",
"payment_type": "Receive",
"party": so.customer,
"party_account": "Debtors - _TC",
"get_orders_to_be_billed": True,
}
references = get_outstanding_reference_documents(args)
# Should split without throwing currency errors
self.assertEqual(len(references), 2)
for ref in references:
self.assertEqual(ref.voucher_no, so.name)
self.assertIsNotNone(ref.payment_term)
def create_payment_entry(**args):
payment_entry = frappe.new_doc("Payment Entry")