fix: handle dunning status change on all changes to outstanding amount

This commit is contained in:
Sagar Vora
2025-08-18 12:21:32 +05:30
committed by Karm Soni
parent fe2d0ea43b
commit d959ca1694
3 changed files with 13 additions and 39 deletions

View File

@@ -164,43 +164,17 @@ class Dunning(AccountsController):
] ]
def resolve_dunnings(doc, method=None): def update_linked_dunnings(doc, previous_outstanding_amount):
""" if (
Resolve / unresolve Dunning based on whether all payments have been made. doc.doctype != "Sales Invoice"
Called when a Payment Entry / Credit Note is submitted / cancelled. or doc.is_return
""" or previous_outstanding_amount == doc.outstanding_amount
):
match doc.doctype:
case "Payment Entry":
return resolve_dunnings_from_payment_entry(doc)
case "Sales Invoice":
return resolve_dunnings_from_credit_note(doc)
def resolve_dunnings_from_payment_entry(doc):
is_submitted = doc.docstatus == 1
for reference in doc.references:
if reference.reference_doctype != "Sales Invoice" or not reference.allocated_amount:
continue
_update_linked_dunnings(reference.reference_name, to_resolve=is_submitted)
def resolve_dunnings_from_credit_note(doc):
"""
Check if dunning should be resolved when a credit note is issued against a Sales Invoice.
Only process if update_outstanding_for_self is False (credit note is being applied against the original invoice).
"""
if not doc.is_return or doc.update_outstanding_for_self or not doc.return_against:
return return
_update_linked_dunnings(doc.return_against, to_resolve=doc.docstatus == 1) to_resolve = doc.outstanding_amount < previous_outstanding_amount
def _update_linked_dunnings(sales_invoice: str, to_resolve: bool = True):
state = "Unresolved" if to_resolve else "Resolved" state = "Unresolved" if to_resolve else "Resolved"
dunnings = get_linked_dunnings_as_per_state(sales_invoice, state) dunnings = get_linked_dunnings_as_per_state(doc.name, state)
if not dunnings: if not dunnings:
return return
@@ -245,7 +219,7 @@ def _update_linked_dunnings(sales_invoice: str, to_resolve: bool = True):
if has_outstanding: if has_outstanding:
break break
new_status = "Resolved" if (not has_outstanding and to_resolve) else "Unresolved" new_status = "Resolved" if not has_outstanding else "Unresolved"
if dunning.status != new_status: if dunning.status != new_status:
dunning.status = new_status dunning.status = new_status

View File

@@ -1940,6 +1940,8 @@ def create_payment_ledger_entry(
def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, party): def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, party):
from erpnext.accounts.doctype.dunning.dunning import update_linked_dunnings
if not voucher_type or not voucher_no: if not voucher_type or not voucher_no:
return return
@@ -1969,6 +1971,7 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa
outstanding = voucher_outstanding[0] outstanding = voucher_outstanding[0]
ref_doc = frappe.get_lazy_doc(voucher_type, voucher_no) ref_doc = frappe.get_lazy_doc(voucher_type, voucher_no)
previous_outstanding_amount = ref_doc.outstanding_amount
outstanding_amount = flt( outstanding_amount = flt(
outstanding["outstanding_in_account_currency"], ref_doc.precision("outstanding_amount") outstanding["outstanding_in_account_currency"], ref_doc.precision("outstanding_amount")
) )
@@ -1982,6 +1985,7 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa
outstanding_amount, outstanding_amount,
) )
update_linked_dunnings(ref_doc, previous_outstanding_amount)
ref_doc.set_status(update=True) ref_doc.set_status(update=True)
ref_doc.notify_update() ref_doc.notify_update()

View File

@@ -359,11 +359,9 @@ doc_events = {
"on_submit": [ "on_submit": [
"erpnext.regional.create_transaction_log", "erpnext.regional.create_transaction_log",
"erpnext.regional.italy.utils.sales_invoice_on_submit", "erpnext.regional.italy.utils.sales_invoice_on_submit",
"erpnext.accounts.doctype.dunning.dunning.resolve_dunnings",
], ],
"on_cancel": [ "on_cancel": [
"erpnext.regional.italy.utils.sales_invoice_on_cancel", "erpnext.regional.italy.utils.sales_invoice_on_cancel",
"erpnext.accounts.doctype.dunning.dunning.resolve_dunnings",
], ],
"on_trash": "erpnext.regional.check_deletion_permission", "on_trash": "erpnext.regional.check_deletion_permission",
}, },
@@ -376,9 +374,7 @@ doc_events = {
"Payment Entry": { "Payment Entry": {
"on_submit": [ "on_submit": [
"erpnext.regional.create_transaction_log", "erpnext.regional.create_transaction_log",
"erpnext.accounts.doctype.dunning.dunning.resolve_dunnings",
], ],
"on_cancel": ["erpnext.accounts.doctype.dunning.dunning.resolve_dunnings"],
"on_trash": "erpnext.regional.check_deletion_permission", "on_trash": "erpnext.regional.check_deletion_permission",
}, },
"Address": { "Address": {