[fixes] test-case to validate quantity after update stock and purchase return and code-cleaning
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 123f4ea..03d0180 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -16,7 +16,7 @@
 			}
 		}
 		
-		cur_frm.cscript.hide_fields(this.frm.doc);
+		hide_fields(this.frm.doc);
 	},
 
 	refresh: function(doc) {
@@ -108,7 +108,7 @@
 	},
 
 	is_paid: function() {
-		cur_frm.cscript.hide_fields(this.frm.doc);
+		hide_fields(this.frm.doc);
 		if(cint(this.frm.doc.is_paid)) {
 			if(!this.frm.doc.company) {
 				cur_frm.set_value("is_paid", 0)
@@ -164,7 +164,7 @@
 
 // Hide Fields
 // ------------
-cur_frm.cscript.hide_fields = function(doc) {
+function hide_fields(doc) {
 	parent_fields = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date'];
 
 	if(cint(doc.is_paid) == 1) {
@@ -186,7 +186,7 @@
 }
 
 cur_frm.cscript.update_stock = function(doc, dt, dn) {
-	cur_frm.cscript.hide_fields(doc, dt, dn);
+	hide_fields(doc, dt, dn);
 }
 
 cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 728088b..14f157e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -3,7 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cstr, cint, formatdate, flt, getdate
+from frappe.utils import cint, formatdate, flt, getdate
 from frappe import msgprint, _, throw
 from erpnext.setup.utils import get_company_currency
 import frappe.defaults
@@ -53,6 +53,9 @@
 
 		# validate stock items
 		if (self.update_stock == 1):
+			pc_obj = frappe.get_doc('Purchase Common')
+			pc_obj.validate_for_items(self)
+			
 			self.validate_purchase_return()
 			self.validate_rejected_warehouse()
 			self.validate_accepted_rejected_qty()
@@ -318,43 +321,6 @@
 			}
 		])
 
-	def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
-		sl_entries = []
-		stock_items = self.get_stock_items()
-
-		for d in self.get('items'):
-			if d.item_code in stock_items and d.warehouse:
-				pr_qty = flt(d.qty) * flt(d.conversion_factor)
-
-				if pr_qty:
-					val_rate_db_precision = 6 if cint(self.precision("valuation_rate", d)) <= 6 else 9
-					rate = flt(d.valuation_rate, val_rate_db_precision)
-					sle = self.get_sl_entries(d, {
-						"actual_qty": flt(pr_qty),
-						"serial_no": cstr(d.serial_no).strip()
-					})
-					if self.is_return:
-						sle.update({
-							"outgoing_rate": rate
-						})
-					else:
-						sle.update({
-							"incoming_rate": rate
-						})
-					sl_entries.append(sle)
-
-				if flt(d.rejected_qty) > 0:
-					sl_entries.append(self.get_sl_entries(d, {
-						"warehouse": d.rejected_warehouse,
-						"actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor),
-						"serial_no": cstr(d.rejected_serial_no).strip(),
-						"incoming_rate": 0.0
-					}))
-
-		# self.bk_flush_supp_wh(sl_entries)
-		self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock,
-			via_landed_cost_voucher=via_landed_cost_voucher)
-		
 	def on_submit(self):
 		self.check_prev_docstatus()
 		self.validate_asset()
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 5405373..f58fd44 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -11,6 +11,7 @@
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
 	test_records as pr_test_records
 from erpnext.exceptions import InvalidCurrency
+from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
 
 test_dependencies = ["Item", "Cost Center"]
 test_ignore = ["Serial No"]
@@ -317,6 +318,7 @@
 	
 	def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self):
 		set_perpetual_inventory()
+		
 		pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), 
 			posting_time=frappe.utils.nowtime())
 		
@@ -359,6 +361,22 @@
 			self.assertEquals(expected_gl_entries[gle.account][0], gle.account)
 			self.assertEquals(expected_gl_entries[gle.account][1], gle.debit)
 			self.assertEquals(expected_gl_entries[gle.account][2], gle.credit)
+	
+	def test_update_stock_and_purchase_return(self):
+		actual_qty_0 = get_qty_after_transaction()
+		
+		pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), 
+			posting_time=frappe.utils.nowtime())
+		
+		actual_qty_1 = get_qty_after_transaction()
+		self.assertEquals(actual_qty_0 + 5, actual_qty_1)
+
+		# return entry
+		pi1 = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2, rate=50, update_stock=1)
+
+		actual_qty_2 = get_qty_after_transaction()
+
+		self.assertEquals(actual_qty_1 - 2, actual_qty_2)
 
 def make_purchase_invoice(**args):
 	pi = frappe.new_doc("Purchase Invoice")
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index cc64a26..cf93e5b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -68,7 +68,7 @@
 					else:
 						# show message that the amount is not paid
 						frappe.db.set(self,'paid_amount',0)
-						frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
+						frappe.throw(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
 			else:
 				frappe.db.set(self,'paid_amount',0)
 
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 6a1b205..abd1764 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _, msgprint
-from frappe.utils import flt
+from frappe.utils import flt,cint, cstr
 
 from erpnext.setup.utils import get_company_currency
 from erpnext.accounts.party import get_party_details
@@ -261,3 +261,52 @@
 				if not d.conversion_factor:
 					frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
 				d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
+	
+	def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
+		sl_entries = []
+		stock_items = self.get_stock_items()
+
+		for d in self.get('items'):
+			if d.item_code in stock_items and d.warehouse:
+				pr_qty = flt(d.qty) * flt(d.conversion_factor)
+
+				if pr_qty:
+					val_rate_db_precision = 6 if cint(self.precision("valuation_rate", d)) <= 6 else 9
+					rate = flt(d.valuation_rate, val_rate_db_precision)
+					sle = self.get_sl_entries(d, {
+						"actual_qty": flt(pr_qty),
+						"serial_no": cstr(d.serial_no).strip()
+					})
+					if self.is_return:
+						sle.update({
+							"outgoing_rate": rate
+						})
+					else:
+						sle.update({
+							"incoming_rate": rate
+						})
+					sl_entries.append(sle)
+
+				if flt(d.rejected_qty) > 0:
+					sl_entries.append(self.get_sl_entries(d, {
+						"warehouse": d.rejected_warehouse,
+						"actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor),
+						"serial_no": cstr(d.rejected_serial_no).strip(),
+						"incoming_rate": 0.0
+					}))
+
+		self.make_sl_entries_for_supplier_warehouse(sl_entries)
+		self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock,
+			via_landed_cost_voucher=via_landed_cost_voucher)
+	
+	def make_sl_entries_for_supplier_warehouse(self, sl_entries):
+		if hasattr(self, 'supplied_items'):
+			for d in self.get('supplied_items'):
+				# negative quantity is passed, as raw material qty has to be decreased
+				# when PR is submitted and it has to be increased when PR is cancelled
+				sl_entries.append(self.get_sl_entries(d, {
+					"item_code": d.rm_item_code,
+					"warehouse": self.supplier_warehouse,
+					"actual_qty": -1*flt(d.consumed_qty),
+				}))
+	
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 8ee6de9..d16dd39 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -130,43 +130,6 @@
 				 if not d.prevdoc_docname:
 					 frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
 
-	def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
-		sl_entries = []
-		stock_items = self.get_stock_items()
-
-		for d in self.get('items'):
-			if d.item_code in stock_items and d.warehouse:
-				pr_qty = flt(d.qty) * flt(d.conversion_factor)
-
-				if pr_qty:
-					val_rate_db_precision = 6 if cint(self.precision("valuation_rate", d)) <= 6 else 9
-					rate = flt(d.valuation_rate, val_rate_db_precision)
-					sle = self.get_sl_entries(d, {
-						"actual_qty": flt(pr_qty),
-						"serial_no": cstr(d.serial_no).strip()
-					})
-					if self.is_return:
-						sle.update({
-							"outgoing_rate": rate
-						})
-					else:
-						sle.update({
-							"incoming_rate": rate
-						})
-					sl_entries.append(sle)
-
-				if flt(d.rejected_qty) > 0:
-					sl_entries.append(self.get_sl_entries(d, {
-						"warehouse": d.rejected_warehouse,
-						"actual_qty": flt(d.rejected_qty) * flt(d.conversion_factor),
-						"serial_no": cstr(d.rejected_serial_no).strip(),
-						"incoming_rate": 0.0
-					}))
-
-		self.bk_flush_supp_wh(sl_entries)
-		self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock,
-			via_landed_cost_voucher=via_landed_cost_voucher)
-
 	def update_ordered_qty(self):
 		po_map = {}
 		for d in self.get("items"):
@@ -195,16 +158,6 @@
 			["qty", "warehouse"])
 		return po_qty, po_warehouse
 
-	def bk_flush_supp_wh(self, sl_entries):
-		for d in self.get('supplied_items'):
-			# negative quantity is passed as raw material qty has to be decreased
-			# when PR is submitted and it has to be increased when PR is cancelled
-			sl_entries.append(self.get_sl_entries(d, {
-				"item_code": d.rm_item_code,
-				"warehouse": self.supplier_warehouse,
-				"actual_qty": -1*flt(d.consumed_qty),
-			}))
-
 	def validate_inspection(self):
 		for d in self.get('items'):		 #Enter inspection date for all items that require inspection
 			if frappe.db.get_value("Item", d.item_code, "inspection_required") and not d.qa_no: