Skip to content

Commit

Permalink
Override a function to improve error msg (#205)
Browse files Browse the repository at this point in the history
* Allocated ammount validation override for msg improvement

* comment add

* add a comment on function

* Refactor: Rename 'uniq_vouchers' to 'unique_vouchers' in payment_entry.py

---------

Co-authored-by: viralpatel15 <[email protected]>
  • Loading branch information
viralkansodiya and viralpatel15 authored Feb 6, 2024
1 parent 927c61c commit ddfde87
Showing 1 changed file with 153 additions and 2 deletions.
155 changes: 153 additions & 2 deletions check_run/overrides/payment_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
# For license information, please see license.txt

import frappe
from frappe.utils import get_link_to_form, comma_and
from erpnext.accounts.doctype.payment_entry.payment_entry import PaymentEntry
from frappe.utils import get_link_to_form, comma_and, flt
from erpnext.accounts.general_ledger import make_gl_entries, process_gl_map
from frappe.utils.data import getdate
from erpnext.accounts.doctype.payment_entry.payment_entry import (
PaymentEntry,
get_outstanding_reference_documents,
)
from frappe import _
import json


Expand Down Expand Up @@ -53,6 +57,153 @@ def get_valid_reference_doctypes(self):
elif self.party_type == "Employee":
return ("Journal Entry", "Expense Claim") # Expense Claim

"""
Because Check Run processes multiple payment entries in a background queue, errors generally do not include
enough data to identify the problem since there were written and remain appropriate for the context of an individual
Payment Entry. This code is copied from:
https://github.com/frappe/erpnext/blob/version-14/erpnext/accounts/doctype/payment_entry/payment_entry.py#L164
https://github.com/frappe/erpnext/blob/version-14/erpnext/accounts/doctype/payment_entry/payment_entry.py#L194
"""

def validate_allocated_amount(self):
if self.payment_type == "Internal Transfer":
return

if self.party_type in ("Customer", "Supplier"):
self.validate_allocated_amount_with_latest_data()
else:
fail_message = _(
"{0} Row {1} / {2}: Allocated Amount of {3} cannot be greater than outstanding amount of {4}."
)
for d in self.get("references"):
if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(d.outstanding_amount):
frappe.throw(
fail_message.format(
self.party_name,
d.idx,
get_link_to_form(d.reference_doctype, d.reference_name),
d.allocated_amount,
d.outstanding_amount,
)
)

# Check for negative outstanding invoices as well
if flt(d.allocated_amount) < 0 and flt(d.allocated_amount) < flt(d.outstanding_amount):
frappe.throw(
fail_message.format(
self.party_name,
d.idx,
get_link_to_form(d.reference_doctype, d.reference_name),
d.allocated_amount,
d.outstanding_amount,
)
)

def validate_allocated_amount_with_latest_data(self):
if self.references:
unique_vouchers = {(x.reference_doctype, x.reference_name) for x in self.references}
vouchers = [frappe._dict({"voucher_type": x[0], "voucher_no": x[1]}) for x in unique_vouchers]
latest_references = get_outstanding_reference_documents(
{
"posting_date": self.posting_date,
"company": self.company,
"party_type": self.party_type,
"payment_type": self.payment_type,
"party": self.party,
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
"get_outstanding_invoices": True,
"get_orders_to_be_billed": True,
"vouchers": vouchers,
}
)

# Group latest_references by (voucher_type, voucher_no)
latest_lookup = {}
for d in latest_references:
d = frappe._dict(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):
latest = latest_lookup.get((d.reference_doctype, d.reference_name)) or frappe._dict()

# If term based allocation is enabled, throw
if (
d.payment_term is None or d.payment_term == ""
) and self.term_based_allocation_enabled_for_reference(
d.reference_doctype, d.reference_name
):
frappe.throw(
_(
"{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))
)

# 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"))
and d.payment_term == ""
):
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 = _(
"<b>Row #{1}</b> {0} / {2}: Allocated Amount of {3} cannot be greater than outstanding amount of {4}."
)

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(
self.party_name,
d.idx,
get_link_to_form(d.reference_doctype, d.reference_name),
d.allocated_amount,
d.outstanding_amount,
)
)

# 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(
self.party_name,
d.idx,
get_link_to_form(d.reference_doctype, d.reference_name),
d.allocated_amount,
d.outstanding_amount,
)
)


@frappe.whitelist()
def update_check_number(doc: PaymentEntry, method: str | None = None) -> None:
Expand Down

0 comments on commit ddfde87

Please sign in to comment.