perf: pull latest details only for referenced vouchers
This commit is contained in:
parent
e023e33a15
commit
deb0d71294
@ -230,84 +230,88 @@ class PaymentEntry(AccountsController):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_allocated_amount_with_latest_data(self):
|
def validate_allocated_amount_with_latest_data(self):
|
||||||
latest_references = get_outstanding_reference_documents(
|
if self.references:
|
||||||
{
|
uniq_vouchers = set([(x.reference_doctype, x.reference_name) for x in self.references])
|
||||||
"posting_date": self.posting_date,
|
vouchers = [frappe._dict({"voucher_type": x[0], "voucher_no": x[1]}) for x in uniq_vouchers]
|
||||||
"company": self.company,
|
latest_references = get_outstanding_reference_documents(
|
||||||
"party_type": self.party_type,
|
{
|
||||||
"payment_type": self.payment_type,
|
"posting_date": self.posting_date,
|
||||||
"party": self.party,
|
"company": self.company,
|
||||||
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
|
"party_type": self.party_type,
|
||||||
"get_outstanding_invoices": True,
|
"payment_type": self.payment_type,
|
||||||
"get_orders_to_be_billed": True,
|
"party": self.party,
|
||||||
},
|
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
|
||||||
validate=True,
|
"get_outstanding_invoices": True,
|
||||||
)
|
"get_orders_to_be_billed": True,
|
||||||
|
"vouchers": vouchers,
|
||||||
|
},
|
||||||
|
validate=True,
|
||||||
|
)
|
||||||
|
|
||||||
# Group latest_references by (voucher_type, voucher_no)
|
# Group latest_references by (voucher_type, voucher_no)
|
||||||
latest_lookup = {}
|
latest_lookup = {}
|
||||||
for d in latest_references:
|
for d in latest_references:
|
||||||
d = frappe._dict(d)
|
d = frappe._dict(d)
|
||||||
latest_lookup.setdefault((d.voucher_type, d.voucher_no), frappe._dict())[d.payment_term] = d
|
latest_lookup.setdefault((d.voucher_type, d.voucher_no), frappe._dict())[d.payment_term] = d
|
||||||
|
|
||||||
for idx, d in enumerate(self.get("references"), start=1):
|
for idx, d in enumerate(self.get("references"), start=1):
|
||||||
latest = latest_lookup.get((d.reference_doctype, d.reference_name)) or frappe._dict()
|
latest = latest_lookup.get((d.reference_doctype, d.reference_name)) or frappe._dict()
|
||||||
|
|
||||||
# If term based allocation is enabled, throw
|
# If term based allocation is enabled, throw
|
||||||
if (
|
if (
|
||||||
d.payment_term is None or d.payment_term == ""
|
d.payment_term is None or d.payment_term == ""
|
||||||
) and self.term_based_allocation_enabled_for_reference(
|
) and self.term_based_allocation_enabled_for_reference(
|
||||||
d.reference_doctype, d.reference_name
|
d.reference_doctype, d.reference_name
|
||||||
):
|
):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"{0} has Payment Term based allocation enabled. Select a Payment Term for Row #{1} in Payment References section"
|
"{0} has Payment Term based allocation enabled. Select a Payment Term for Row #{1} in Payment References section"
|
||||||
).format(frappe.bold(d.reference_name), frappe.bold(idx))
|
).format(frappe.bold(d.reference_name), frappe.bold(idx))
|
||||||
)
|
|
||||||
|
|
||||||
# if no payment template is used by invoice and has a custom term(no `payment_term`), then invoice outstanding will be in 'None' key
|
|
||||||
latest = latest.get(d.payment_term) or latest.get(None)
|
|
||||||
|
|
||||||
# The reference has already been fully paid
|
|
||||||
if not latest:
|
|
||||||
frappe.throw(
|
|
||||||
_("{0} {1} has already been fully paid.").format(_(d.reference_doctype), d.reference_name)
|
|
||||||
)
|
|
||||||
# The reference has already been partly paid
|
|
||||||
elif latest.outstanding_amount < latest.invoice_amount and flt(
|
|
||||||
d.outstanding_amount, d.precision("outstanding_amount")
|
|
||||||
) != flt(latest.outstanding_amount, d.precision("outstanding_amount")):
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
|
|
||||||
).format(_(d.reference_doctype), d.reference_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
|
|
||||||
|
|
||||||
if (
|
|
||||||
d.payment_term
|
|
||||||
and (
|
|
||||||
(flt(d.allocated_amount)) > 0
|
|
||||||
and latest.payment_term_outstanding
|
|
||||||
and (flt(d.allocated_amount) > flt(latest.payment_term_outstanding))
|
|
||||||
)
|
|
||||||
and self.term_based_allocation_enabled_for_reference(d.reference_doctype, d.reference_name)
|
|
||||||
):
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"Row #{0}: Allocated amount:{1} is greater than outstanding amount:{2} for Payment Term {3}"
|
|
||||||
).format(
|
|
||||||
d.idx, d.allocated_amount, latest.payment_term_outstanding, d.payment_term
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(latest.outstanding_amount):
|
# if no payment template is used by invoice and has a custom term(no `payment_term`), then invoice outstanding will be in 'None' key
|
||||||
frappe.throw(fail_message.format(d.idx))
|
latest = latest.get(d.payment_term) or latest.get(None)
|
||||||
|
|
||||||
# Check for negative outstanding invoices as well
|
# The reference has already been fully paid
|
||||||
if flt(d.allocated_amount) < 0 and flt(d.allocated_amount) < flt(latest.outstanding_amount):
|
if not latest:
|
||||||
frappe.throw(fail_message.format(d.idx))
|
frappe.throw(
|
||||||
|
_("{0} {1} has already been fully paid.").format(_(d.reference_doctype), d.reference_name)
|
||||||
|
)
|
||||||
|
# The reference has already been partly paid
|
||||||
|
elif latest.outstanding_amount < latest.invoice_amount and flt(
|
||||||
|
d.outstanding_amount, d.precision("outstanding_amount")
|
||||||
|
) != flt(latest.outstanding_amount, d.precision("outstanding_amount")):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
|
||||||
|
).format(_(d.reference_doctype), d.reference_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
|
||||||
|
|
||||||
|
if (
|
||||||
|
d.payment_term
|
||||||
|
and (
|
||||||
|
(flt(d.allocated_amount)) > 0
|
||||||
|
and latest.payment_term_outstanding
|
||||||
|
and (flt(d.allocated_amount) > flt(latest.payment_term_outstanding))
|
||||||
|
)
|
||||||
|
and self.term_based_allocation_enabled_for_reference(d.reference_doctype, d.reference_name)
|
||||||
|
):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Row #{0}: Allocated amount:{1} is greater than outstanding amount:{2} for Payment Term {3}"
|
||||||
|
).format(
|
||||||
|
d.idx, d.allocated_amount, latest.payment_term_outstanding, d.payment_term
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(latest.outstanding_amount):
|
||||||
|
frappe.throw(fail_message.format(d.idx))
|
||||||
|
|
||||||
|
# Check for negative outstanding invoices as well
|
||||||
|
if flt(d.allocated_amount) < 0 and flt(d.allocated_amount) < flt(latest.outstanding_amount):
|
||||||
|
frappe.throw(fail_message.format(d.idx))
|
||||||
|
|
||||||
def delink_advance_entry_references(self):
|
def delink_advance_entry_references(self):
|
||||||
for reference in self.references:
|
for reference in self.references:
|
||||||
@ -1587,6 +1591,7 @@ def get_outstanding_reference_documents(args, validate=False):
|
|||||||
min_outstanding=args.get("outstanding_amt_greater_than"),
|
min_outstanding=args.get("outstanding_amt_greater_than"),
|
||||||
max_outstanding=args.get("outstanding_amt_less_than"),
|
max_outstanding=args.get("outstanding_amt_less_than"),
|
||||||
accounting_dimensions=accounting_dimensions_filter,
|
accounting_dimensions=accounting_dimensions_filter,
|
||||||
|
vouchers=args.get("vouchers") or None,
|
||||||
)
|
)
|
||||||
|
|
||||||
outstanding_invoices = split_invoices_based_on_payment_terms(
|
outstanding_invoices = split_invoices_based_on_payment_terms(
|
||||||
|
|||||||
@ -908,6 +908,7 @@ def get_outstanding_invoices(
|
|||||||
min_outstanding=None,
|
min_outstanding=None,
|
||||||
max_outstanding=None,
|
max_outstanding=None,
|
||||||
accounting_dimensions=None,
|
accounting_dimensions=None,
|
||||||
|
vouchers=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
ple = qb.DocType("Payment Ledger Entry")
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
@ -933,6 +934,7 @@ def get_outstanding_invoices(
|
|||||||
|
|
||||||
ple_query = QueryPaymentLedger()
|
ple_query = QueryPaymentLedger()
|
||||||
invoice_list = ple_query.get_voucher_outstandings(
|
invoice_list = ple_query.get_voucher_outstandings(
|
||||||
|
vouchers=vouchers,
|
||||||
common_filter=common_filter,
|
common_filter=common_filter,
|
||||||
posting_date=posting_date,
|
posting_date=posting_date,
|
||||||
min_outstanding=min_outstanding,
|
min_outstanding=min_outstanding,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user