Merge pull request #18182 from rohitwaghchaure/provision_to_make_debit_credit_note_against_return_entry

feat: provision to make debit / credit note against the stock returned entry
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 1b03896..70e98d9 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -337,7 +337,8 @@
 		if not self.is_return:
 			self.update_against_document_in_jv()
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
-			self.update_billing_status_in_pr()
+
+		self.update_billing_status_in_pr()
 
 		# Updating stock ledger should always be called after updating prevdoc status,
 		# because updating ordered qty in bin depends upon updated ordered qty in PO
@@ -773,7 +774,8 @@
 
 		if not self.is_return:
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
-			self.update_billing_status_in_pr()
+
+		self.update_billing_status_in_pr()
 
 		# Updating stock ledger should always be called after updating prevdoc status,
 		# because updating ordered qty in bin depends upon updated ordered qty in PO
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index f70870b..b193ac2 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -294,7 +294,7 @@
 			frappe.db.sql("""update `tab%(target_parent_dt)s`
 				set %(target_parent_field)s = round(
 					ifnull((select
-						ifnull(sum(if(%(target_ref_field)s > %(target_field)s, abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
+						ifnull(sum(if(abs(%(target_ref_field)s) > abs(%(target_field)s), abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
 						/ sum(abs(%(target_ref_field)s)) * 100
 					from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 6)
 					%(update_modified)s
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 6bcdc2b..569a03a 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -77,8 +77,34 @@
 
 
 	},
+
 	print_without_amount: function(frm) {
 		erpnext.stock.delivery_note.set_print_hide(frm.doc);
+	},
+
+	refresh: function(frm) {
+		if (frm.doc.docstatus === 1 && frm.doc.is_return === 1 && frm.doc.per_billed !== 100) {
+			frm.add_custom_button(__('Credit Note'), function() {
+				frappe.confirm(__("Are you sure you want to make credit note?"),
+					function() {
+						frm.trigger("make_credit_note");
+					}
+				);
+			}, __('Create'));
+
+			frm.page.set_inner_btn_group_as_primary(__('Create'));
+		}
+	},
+
+	make_credit_note: function(frm) {
+		frm.call({
+			method: "make_return_invoice",
+			doc: frm.doc,
+			freeze: true,
+			callback: function() {
+				frm.reload_doc();
+			}
+		});
 	}
 });
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 1e522b8..ec7df2d 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -333,7 +333,10 @@
 			return_invoice.is_return = True
 			return_invoice.save()
 			return_invoice.submit()
-			frappe.msgprint(_("Credit Note {0} has been created automatically").format(return_invoice.name))
+
+			credit_note_link = frappe.utils.get_link_to_form('Sales Invoice', return_invoice.name)
+
+			frappe.msgprint(_("Credit Note {0} has been created automatically").format(credit_note_link))
 		except:
 			frappe.throw(_("Could not create Credit Note automatically, please uncheck 'Issue Credit Note' and submit again"))
 
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index e82aa2c..a2d3e75 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -38,6 +38,29 @@
 		if(frm.doc.company) {
 			frm.trigger("toggle_display_account_head");
 		}
+
+		if (frm.doc.docstatus === 1 && frm.doc.is_return === 1 && frm.doc.per_billed !== 100) {
+			frm.add_custom_button(__('Debit Note'), function() {
+				frappe.confirm(__("Are you sure you want to make debit note?"),
+					function() {
+						frm.trigger("make_debit_note");
+					}
+				);
+			}, __('Create'));
+
+			frm.page.set_inner_btn_group_as_primary(__('Create'));
+		}
+	},
+
+	make_debit_note: function(frm) {
+		frm.call({
+			method: "make_return_invoice",
+			doc: frm.doc,
+			freeze: true,
+			callback: function() {
+				frm.reload_doc();
+			}
+		});
 	},
 
 	company: function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 67cd7f8..df28bec 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -387,6 +387,16 @@
 
 		self.load_from_db()
 
+	def make_return_invoice(self):
+		return_invoice = make_purchase_invoice(self.name)
+		return_invoice.is_return = True
+		return_invoice.save()
+		return_invoice.submit()
+
+		debit_note_link = frappe.utils.get_link_to_form('Purchase Invoice', return_invoice.name)
+
+		frappe.msgprint(_("Debit Note {0} has been created automatically").format(debit_note_link))
+
 def update_billed_amount_based_on_po(po_detail, update_modified=True):
 	# Billed against Sales Order directly
 	billed_against_po = frappe.db.sql("""select sum(amount) from `tabPurchase Invoice Item`