fix: Sales Return cancellation if linked with Payment Entry (#26551)
This commit is contained in:
parent
84c4161c00
commit
1cba77cfbd
@ -22,7 +22,7 @@ from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accoun
|
|||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
|
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
|
||||||
unlink_inter_company_doc
|
unlink_inter_company_doc, check_if_return_invoice_linked_with_payment_entry
|
||||||
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
|
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
|
||||||
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
||||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import get_item_account_wise_additional_cost
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import get_item_account_wise_additional_cost
|
||||||
@ -1014,6 +1014,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
}, item=self))
|
}, item=self))
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
check_if_return_invoice_linked_with_payment_entry(self)
|
||||||
|
|
||||||
super(PurchaseInvoice, self).on_cancel()
|
super(PurchaseInvoice, self).on_cancel()
|
||||||
|
|
||||||
self.check_on_hold_or_closed_status()
|
self.check_on_hold_or_closed_status()
|
||||||
|
@ -290,6 +290,8 @@ class SalesInvoice(SellingController):
|
|||||||
self.update_time_sheet(None)
|
self.update_time_sheet(None)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
check_if_return_invoice_linked_with_payment_entry(self)
|
||||||
|
|
||||||
super(SalesInvoice, self).on_cancel()
|
super(SalesInvoice, self).on_cancel()
|
||||||
|
|
||||||
self.check_sales_order_on_hold_or_close("sales_order")
|
self.check_sales_order_on_hold_or_close("sales_order")
|
||||||
@ -922,7 +924,7 @@ class SalesInvoice(SellingController):
|
|||||||
asset = frappe.get_doc("Asset", item.asset)
|
asset = frappe.get_doc("Asset", item.asset)
|
||||||
else:
|
else:
|
||||||
frappe.throw(_(
|
frappe.throw(_(
|
||||||
"Row #{0}: You must select an Asset for Item {1}.").format(item.idx, item.item_name),
|
"Row #{0}: You must select an Asset for Item {1}.").format(item.idx, item.item_name),
|
||||||
title=_("Missing Asset")
|
title=_("Missing Asset")
|
||||||
)
|
)
|
||||||
if (len(asset.finance_books) > 1 and not item.finance_book
|
if (len(asset.finance_books) > 1 and not item.finance_book
|
||||||
@ -944,7 +946,7 @@ class SalesInvoice(SellingController):
|
|||||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
gl_entries.append(self.get_gl_dict(gle, item=item))
|
||||||
|
|
||||||
self.set_asset_status(asset)
|
self.set_asset_status(asset)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Do not book income for transfer within same company
|
# Do not book income for transfer within same company
|
||||||
if not self.is_internal_transfer():
|
if not self.is_internal_transfer():
|
||||||
@ -973,7 +975,7 @@ class SalesInvoice(SellingController):
|
|||||||
def set_asset_status(self, asset):
|
def set_asset_status(self, asset):
|
||||||
if self.is_return:
|
if self.is_return:
|
||||||
asset.set_status()
|
asset.set_status()
|
||||||
else:
|
else:
|
||||||
asset.set_status("Sold" if self.docstatus==1 else None)
|
asset.set_status("Sold" if self.docstatus==1 else None)
|
||||||
|
|
||||||
def make_loyalty_point_redemption_gle(self, gl_entries):
|
def make_loyalty_point_redemption_gle(self, gl_entries):
|
||||||
@ -1941,3 +1943,41 @@ def create_dunning(source_name, target_doc=None):
|
|||||||
}
|
}
|
||||||
}, target_doc, set_missing_values)
|
}, target_doc, set_missing_values)
|
||||||
return doclist
|
return doclist
|
||||||
|
|
||||||
|
def check_if_return_invoice_linked_with_payment_entry(self):
|
||||||
|
# If a Return invoice is linked with payment entry along with other invoices,
|
||||||
|
# the cancellation of the Return causes allocated amount to be greater than paid
|
||||||
|
|
||||||
|
if not frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
|
||||||
|
return
|
||||||
|
|
||||||
|
payment_entries = []
|
||||||
|
if self.is_return and self.return_against:
|
||||||
|
invoice = self.return_against
|
||||||
|
else:
|
||||||
|
invoice = self.name
|
||||||
|
|
||||||
|
payment_entries = frappe.db.sql_list("""
|
||||||
|
SELECT
|
||||||
|
t1.name
|
||||||
|
FROM
|
||||||
|
`tabPayment Entry` t1, `tabPayment Entry Reference` t2
|
||||||
|
WHERE
|
||||||
|
t1.name = t2.parent
|
||||||
|
and t1.docstatus = 1
|
||||||
|
and t2.reference_name = %s
|
||||||
|
and t2.allocated_amount < 0
|
||||||
|
""", invoice)
|
||||||
|
|
||||||
|
links_to_pe = []
|
||||||
|
if payment_entries:
|
||||||
|
for payment in payment_entries:
|
||||||
|
payment_entry = frappe.get_doc("Payment Entry", payment)
|
||||||
|
if len(payment_entry.references) > 1:
|
||||||
|
links_to_pe.append(payment_entry.name)
|
||||||
|
if links_to_pe:
|
||||||
|
payment_entries_link = [get_link_to_form('Payment Entry', name, label=name) for name in links_to_pe]
|
||||||
|
message = _("Please cancel and amend the Payment Entry")
|
||||||
|
message += " " + ", ".join(payment_entries_link) + " "
|
||||||
|
message += _("to unallocate the amount of this Return Invoice before cancelling it.")
|
||||||
|
frappe.throw(message)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user