Merge pull request #6947 from saurabh6790/delink_jv_from_advance

[fix] delink jv from advance table
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 145ed81..2802835 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -64,11 +64,20 @@
 		from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
 		from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
 		unlink_ref_doc_from_payment_entries(self.doctype, self.name)
-		unlink_ref_doc_from_salary_slip(self.name)		
+		unlink_ref_doc_from_salary_slip(self.name)
 		self.make_gl_entries(1)
 		self.update_advance_paid()
 		self.update_expense_claim()
-		
+		self.unlink_advance_entry_reference()
+
+	def unlink_advance_entry_reference(self):
+		for d in self.get("accounts"):
+			if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
+				doc = frappe.get_doc(d.reference_type, d.reference_name)
+				doc.delink_advance_entries(self.name)
+				d.reference_type = ''
+				d.reference_name = ''
+				d.db_update()
 
 	def validate_party(self):
 		for d in self.get("accounts"):
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index b4b8444..e82d55e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -437,6 +437,38 @@
 
 		self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
 			"warehouse"), pi.get("items")[0].rejected_warehouse)
+	
+	def test_outstanding_amount_after_advance_jv_cancelation(self):
+		from erpnext.accounts.doctype.journal_entry.test_journal_entry \
+			import test_records as jv_test_records
+
+		jv = frappe.copy_doc(jv_test_records[1])
+		jv.insert()
+		jv.submit()
+
+		pi = frappe.copy_doc(test_records[0])
+		pi.append("advances", {
+			"reference_type": "Journal Entry",
+			"reference_name": jv.name,
+			"reference_row": jv.get("accounts")[0].name,
+			"advance_amount": 400,
+			"allocated_amount": 300,
+			"remarks": jv.remark
+		})
+		pi.insert()
+		pi.submit()
+		pi.load_from_db()
+		
+		#check outstanding after advance allocation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance, pi.precision("outstanding_amount")))
+		
+		#added to avoid Document has been modified exception
+		jv = frappe.get_doc("Journal Entry", jv.name)
+		jv.cancel()
+		
+		pi.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance, pi.precision("outstanding_amount")))
 
 def unlink_payment_on_cancel_of_invoice(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 0011dfe..12b90ed 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -980,6 +980,39 @@
 		pe.submit()
 
 		self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
+	
+	def test_outstanding_amount_after_advance_jv_cancelation(self):
+		from erpnext.accounts.doctype.journal_entry.test_journal_entry \
+			import test_records as jv_test_records
+
+		jv = frappe.copy_doc(jv_test_records[0])
+		jv.insert()
+		jv.submit()
+
+		si = frappe.copy_doc(test_records[0])
+		si.append("advances", {
+			"doctype": "Sales Invoice Advance",
+			"reference_type": "Journal Entry",
+			"reference_name": jv.name,
+			"reference_row": jv.get("accounts")[0].name,
+			"advance_amount": 400,
+			"allocated_amount": 300,
+			"remarks": jv.remark
+		})
+		si.insert()
+		si.submit()
+		si.load_from_db()
+
+		#check outstanding after advance allocation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
+		
+		#added to avoid Document has been modified exception
+		jv = frappe.get_doc("Journal Entry", jv.name)
+		jv.cancel()
+		
+		si.load_from_db()
+		#check outstanding after advance cancellation
+		self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
 
 def create_sales_invoice(**args):
 	si = frappe.new_doc("Sales Invoice")
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 3cc79ef..f85edfd 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -125,6 +125,20 @@
 			ret = None
 		
 		return ret
+	
+	def delink_advance_entries(self, jv):
+		total_allocated_amount = 0
+		for adv in self.advances:
+			consider_for_total_advance = True
+			if adv.reference_name == jv:
+				frappe.db.sql("""delete from `tab{0} Advance`
+					where name = %s""".format(self.doctype), adv.name)
+				consider_for_total_advance = False
+
+			if consider_for_total_advance:
+				total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount"))
+
+		frappe.db.set_value(self.doctype, self.name, "total_advance", total_allocated_amount, update_modified=False)
 
 def delete_events(ref_type, ref_name):
 	frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`