Added Make Receipt (Update Stock) and IsCash option on Purchase Invoice
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 32ad6d2..7ac5400 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -4,6 +4,7 @@
 frappe.provide("erpnext.accounts");
 {% include 'buying/doctype/purchase_common/purchase_common.js' %};
 
+
 erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
 	onload: function() {
 		this._super();
@@ -14,6 +15,8 @@
 				this.frm.set_df_property("credit_to", "print_hide", 0);
 			}
 		}
+		
+		cur_frm.cscript.hide_fields(this.frm.doc);
 	},
 
 	refresh: function(doc) {
@@ -28,9 +31,16 @@
 					this.frm.add_custom_button(__('Payment'), this.make_bank_entry, __("Make"));
 					cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
 				}
-				if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
-					cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note, __("Make"));
+				
+				if (!doc.make_receipt) {
+					if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
+						cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note, __("Make"));
+					}
 				}
+				else {
+					cur_frm.add_custom_button(__('Return'), this.make_debit_note, __("Make"));
+				}
+
 			}
 
 			if(doc.docstatus===0) {
@@ -62,6 +72,52 @@
 				}, __("Get items from"));
 			}
 		}
+		if(doc.docstatus==1 && doc.make_receipt==1) {
+				this.show_stock_ledger();
+			}
+
+	},
+
+	received_qty: function(doc, cdt, cdn) {
+		var item = frappe.get_doc(cdt, cdn);
+		frappe.model.round_floats_in(item, ["qty", "received_qty"]);
+
+		item.qty = (item.qty < item.received_qty) ? item.qty : item.received_qty;
+		this.qty(doc, cdt, cdn);
+	},
+
+	qty: function(doc, cdt, cdn) {
+		var item = frappe.get_doc(cdt, cdn);
+		frappe.model.round_floats_in(item, ["qty", "received_qty"]);
+
+		if(!(item.received_qty || item.rejected_qty) && item.qty) {
+			item.received_qty = item.qty;
+		}
+
+		if(item.qty > item.received_qty) {
+			msgprint(__("Error: {0} > {1}", [__(frappe.meta.get_label(item.doctype, "qty", item.name)),
+						__(frappe.meta.get_label(item.doctype, "received_qty", item.name))]))
+			item.qty = item.rejected_qty = 0.0;
+		} else {
+			item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item));
+		}
+
+		this._super(doc, cdt, cdn);
+	},
+
+	rejected_qty: function(doc, cdt, cdn) {
+		var item = frappe.get_doc(cdt, cdn);
+		frappe.model.round_floats_in(item, ["received_qty", "rejected_qty"]);
+
+		if(item.rejected_qty > item.received_qty) {
+			msgprint(__("Error: {0} > {1}", [__(frappe.meta.get_label(item.doctype, "rejected_qty", item.name)),
+						__(frappe.meta.get_label(item.doctype, "received_qty", item.name))]));
+			item.qty = item.rejected_qty = 0.0;
+		} else {
+			item.qty = flt(item.received_qty - item.rejected_qty, precision("qty", item));
+		}
+
+		this.qty(doc, cdt, cdn);
 	},
 
 	supplier: function() {
@@ -100,12 +156,30 @@
 		}
 	},
 
+	is_cash: function() {
+		cur_frm.cscript.hide_fields(this.frm.doc);
+		if(cint(this.frm.doc.is_cash)) {
+			if(!this.frm.doc.company) {
+				this.frm.set_value("is_cash", 0);
+				msgprint(__("Please specify Company to proceed"));
+			}
+		}
+		this.calculate_outstanding_amount();
+		this.frm.refresh_fields();
+	},
+
 	write_off_amount: function() {
 		this.set_in_company_currency(this.frm.doc, ["write_off_amount"]);
 		this.calculate_outstanding_amount();
 		this.frm.refresh_fields();
 	},
 
+	paid_amount: function() {
+		this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
+		this.write_off_outstanding_amount();
+		this.frm.refresh_fields();
+	},
+
 	allocated_amount: function() {
 		this.calculate_total_advance();
 		this.frm.refresh_fields();
@@ -137,6 +211,63 @@
 
 cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
 
+// Hide Fields
+// ------------
+cur_frm.cscript.hide_fields = function(doc) {
+	par_flds = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date'];
+
+	if(cint(doc.is_cash) == 1) {
+		hide_field(par_flds);
+	} else {
+		for (i in par_flds) {
+			var docfield = frappe.meta.docfield_map[doc.doctype][par_flds[i]];
+			if(!docfield.hidden) unhide_field(par_flds[i]);
+		}
+	
+	}
+
+	item_flds_stock = ['sc_wh', 'received_qty', 'rejected_qty'];
+
+	//item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse', 'expense_account', 'warehouse']
+	cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_stock,
+		(cint(doc.make_receipt)==1 ? true : false));	
+
+	cur_frm.refresh_fields();
+}
+
+cur_frm.cscript.make_receipt = function(doc, dt, dn) {
+	cur_frm.cscript.hide_fields(doc, dt, dn);
+}
+
+cur_frm.cscript.mode_of_payment = function(doc) {
+	if(doc.is_cash) {
+		return cur_frm.call({
+			method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
+			args: {
+				"mode_of_payment": doc.mode_of_payment,
+				"company": doc.company
+			 },
+			 callback: function(r, rt) {
+				if(r.message) {
+					cur_frm.set_value("cash_bank_account", r.message["account"]);
+				}
+
+			 }
+		});
+	 }
+}
+
+cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
+	return {
+		filters: [
+			["Account", "account_type", "in", ["Cash", "Bank"]],
+			["Account", "root_type", "=", "Asset"],
+			["Account", "is_group", "=",0],
+			["Account", "company", "=", doc.company]
+		]
+	}
+}
+
 cur_frm.cscript.make_bank_entry = function() {
 	return frappe.call({
 		method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index bba4a4a..df47ba7 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -807,6 +807,31 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "default": "0", 
+   "fieldname": "make_receipt", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Make Receipt (Update Stock)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "items", 
    "fieldtype": "Table", 
    "hidden": 0, 
@@ -1667,6 +1692,156 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
+   "collapsible_depends_on": "paid_amount", 
+   "depends_on": "eval:doc.is_cash===1", 
+   "fieldname": "sc_br_payments", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Payments", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "mode_of_payment", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Mode of Payment", 
+   "length": 0, 
+   "no_copy": 0, 
+   "oldfieldname": "mode_of_payment", 
+   "oldfieldtype": "Select", 
+   "options": "Mode of Payment", 
+   "permlevel": 0, 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "cash_bank_account", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Cash/Bank Account", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Account", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "col_br_payments", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "paid_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Paid Amount", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "base_paid_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Paid Amount (Company Currency)", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Company:company:default_currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 1, 
    "collapsible_depends_on": "write_off_amount", 
    "depends_on": "grand_total", 
    "fieldname": "write_off", 
@@ -2700,18 +2875,19 @@
  "permissions": [
   {
    "amend": 1, 
-   "apply_user_permissions": 0, 
+   "apply_user_permissions": 1, 
    "cancel": 1, 
    "create": 1, 
    "delete": 0, 
-   "email": 1, 
-   "export": 0, 
+   "email": 0, 
+   "export": 1, 
    "if_owner": 0, 
    "import": 0, 
    "permlevel": 0, 
    "print": 1, 
    "read": 1, 
-   "report": 1, 
+   "report": 0, 
+   "restrict": 0, 
    "role": "Accounts User", 
    "set_user_permissions": 0, 
    "share": 1, 
@@ -2720,18 +2896,19 @@
   }, 
   {
    "amend": 0, 
-   "apply_user_permissions": 0, 
+   "apply_user_permissions": 1, 
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
-   "email": 1, 
+   "email": 0, 
    "export": 0, 
    "if_owner": 0, 
    "import": 0, 
    "permlevel": 0, 
-   "print": 1, 
+   "print": 0, 
    "read": 1, 
-   "report": 1, 
+   "report": 0, 
+   "restrict": 0, 
    "role": "Purchase User", 
    "set_user_permissions": 0, 
    "share": 0, 
@@ -2743,15 +2920,16 @@
    "apply_user_permissions": 0, 
    "cancel": 1, 
    "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
+   "delete": 0, 
+   "email": 0, 
+   "export": 1, 
    "if_owner": 0, 
    "import": 0, 
    "permlevel": 0, 
    "print": 1, 
    "read": 1, 
    "report": 1, 
+   "restrict": 0, 
    "role": "Accounts Manager", 
    "set_user_permissions": 0, 
    "share": 1, 
@@ -2760,7 +2938,7 @@
   }, 
   {
    "amend": 0, 
-   "apply_user_permissions": 0, 
+   "apply_user_permissions": 1, 
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
@@ -2772,6 +2950,7 @@
    "print": 1, 
    "read": 1, 
    "report": 1, 
+   "restrict": 0, 
    "role": "Auditor", 
    "set_user_permissions": 0, 
    "share": 0, 
@@ -2792,11 +2971,11 @@
    "print": 0, 
    "read": 1, 
    "report": 0, 
-   "role": "Accounts Manager", 
+   "role": "All", 
    "set_user_permissions": 0, 
    "share": 0, 
    "submit": 0, 
-   "write": 1
+   "write": 0
   }
  ], 
  "read_only": 0, 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 427e040..ba80bcf 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 cint, formatdate, flt, getdate
+from frappe.utils import cstr, cint, formatdate, flt, getdate
 from frappe import msgprint, _, throw
 from erpnext.setup.utils import get_company_currency
 import frappe.defaults
@@ -13,6 +13,7 @@
 from erpnext.accounts.utils import get_account_currency, get_fiscal_year
 from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
 
+
 form_grid_templates = {
 	"items": "templates/form_grid/item_grid.html"
 }
@@ -45,6 +46,23 @@
 			self.validate_supplier_invoice()
 			self.validate_advance_jv("Purchase Order")
 
+		# validate cash purchase
+		if (self.is_cash == 1):
+			self.validate_cash()
+
+		# validate stock items
+		if (self.make_receipt == 1):
+			self.validate_purchase_return()
+			self.validate_rejected_warehouse()
+			self.validate_accepted_rejected_qty()
+
+		# sub-contracting
+		# self.validate_for_subcontracting()
+		# self.create_raw_materials_supplied("supplied_items")
+		# self.set_landed_cost_voucher_amount()
+		# self.update_valuation_rate("items")
+
+		self.check_active_purchase_items()
 		self.check_conversion_rate()
 		self.validate_credit_to_acc()
 		self.clear_unallocated_advances("Purchase Invoice Advance", "advances")
@@ -58,6 +76,45 @@
 		self.validate_fixed_asset_account()
 		self.create_remarks()
 
+	def validate_cash(self):
+		if not self.cash_bank_account and flt(self.paid_amount):
+			frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
+
+		if flt(self.paid_amount) + flt(self.write_off_amount) \
+				- flt(self.base_grand_total) > 1/(10**(self.precision("base_grand_total") + 1)):
+			frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
+
+	def validate_purchase_return(self):
+		for d in self.get("items"):
+			if self.is_return and flt(d.rejected_qty) != 0:
+				frappe.throw(_("Row #{0}: Rejected Qty can not be entered in Purchase Return").format(d.idx))
+
+			# validate rate with ref PR
+
+	def validate_rejected_warehouse(self):
+		for d in self.get("items"):
+			if flt(d.rejected_qty) and not d.rejected_warehouse:
+				d.rejected_warehouse = self.rejected_warehouse
+				if not d.rejected_warehouse:
+					frappe.throw(_("Row #{0}: Rejected Warehouse is mandatory against rejected Item {1}").format(d.idx, d.item_code))
+
+	# validate accepted and rejected qty
+	def validate_accepted_rejected_qty(self):
+		for d in self.get("items"):
+			if not flt(d.received_qty) and flt(d.qty):
+				d.received_qty = flt(d.qty) - flt(d.rejected_qty)
+
+			elif not flt(d.qty) and flt(d.rejected_qty):
+				d.qty = flt(d.received_qty) - flt(d.rejected_qty)
+
+			elif not flt(d.rejected_qty):
+				d.rejected_qty = flt(d.received_qty) -  flt(d.qty)
+
+			# Check Received Qty = Accepted Qty + Rejected Qty
+			if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)):
+				frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
+
+
 	def create_remarks(self):
 		if not self.remarks:
 			if self.bill_no and self.bill_date:
@@ -228,6 +285,75 @@
 			from erpnext.accounts.utils import reconcile_against_document
 			reconcile_against_document(lst)
 
+	def update_status_updater_args(self):
+		if cint(self.make_receipt):
+			self.status_updater.extend([{
+				'source_dt': 'Purchase Invoice Item',
+				'target_dt': 'Purchase Order Item',
+				'join_field': 'po_detail',
+				'target_field': 'received_qty',
+				'target_parent_dt': 'Purchase Order',
+				'target_parent_field': 'per_received',
+				'target_ref_field': 'qty',
+				'source_field': 'qty',
+				'percent_join_field':'purchase_order',
+				# 'percent_join_field': 'prevdoc_docname',
+				'overflow_type': 'receipt',
+				'extra_cond': """ and exists(select name from `tabPurchase Invoice`
+					where name=`tabPurchase Invoice Item`.parent and make_receipt = 1)"""
+			},
+			{
+				'source_dt': 'Purchase Invoice Item',
+				'target_dt': 'Purchase Order Item',
+				'join_field': 'po_detail',
+				'target_field': 'returned_qty',
+				'target_parent_dt': 'Purchase Order',
+				# 'target_parent_field': 'per_received',
+				# 'target_ref_field': 'qty',
+				'source_field': '-1 * qty',
+				# 'percent_join_field': 'prevdoc_docname',
+				# 'overflow_type': 'receipt',
+				'extra_cond': """ and exists (select name from `tabPurchase Invoice` where name=`tabPurchase Invoice Item`.parent and is_return=1)"""
+			}
+		])
+
+	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()
@@ -235,8 +361,18 @@
 		frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
 			self.company, self.base_grand_total)
 
+                # make purchase receipt
+		if (self.make_receipt == 1):
+			# from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_stock_ledger
+			self.update_stock_ledger()
+			self.make_gl_entries()
+			from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
+			update_serial_nos_after_submit(self, "items")
+			self.update_status_updater_args()
+			self.update_prevdoc_status()
+
 		# this sequence because outstanding may get -negative
-		self.make_gl_entries()
+		self.make_gl_entries1()
 		if not self.is_return:
 			self.update_against_document_in_jv()
 			self.update_prevdoc_status()
@@ -281,6 +417,33 @@
 
 		gl_entries = []
 
+		# Make Cash GL Entries
+		if cint(self.is_cash) and self.cash_bank_account and self.paid_amount:
+			bank_account_currency = get_account_currency(self.cash_bank_account)
+			# CASH, make payment entries
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": self.credit_to,
+					"party_type": "Supplier",
+					"party": self.supplier,
+					"against": self.cash_bank_account,
+					"debit": self.base_paid_amount,
+					"debit_in_account_currency": self.base_paid_amount \
+						if self.party_account_currency==self.company_currency else self.paid_amount,
+					"against_voucher": self.return_against if cint(self.is_return) else self.name,
+					"against_voucher_type": self.doctype,
+				}, self.party_account_currency)
+			)
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": self.cash_bank_account,
+					"against": self.supplier,
+					"credit": self.base_paid_amount,
+					"credit_in_account_currency": self.base_paid_amount \
+						if bank_account_currency==self.company_currency else self.paid_amount
+				}, bank_account_currency)
+			)
+
 		# parent's gl entry
 		if self.grand_total:
 			# Didnot use base_grand_total to book rounding loss gle
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 784c747..cc9e1d3 100755
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -215,6 +215,30 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "received_qty", 
+   "fieldtype": "Float", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Received Qty", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "2", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
    "fieldname": "qty", 
@@ -243,6 +267,30 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "rejected_qty", 
+   "fieldtype": "Float", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Rejected Qty", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "2", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "col_break2", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -767,6 +815,178 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "sc_wh", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Warehouse", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "default": "", 
+   "fieldname": "warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Accepted Warehouse", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "rejected_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Rejected Warehouse", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "batch_no", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Batch No", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Batch", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "col_br_wh", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "serial_no", 
+   "fieldtype": "Text", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Serial No", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "rejected_serial_no", 
+   "fieldtype": "Text", 
+   "hidden": 1, 
+   "ignore_user_permissions": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Rejected Serial No", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
    "fieldname": "accounting", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index ac8a5df..9187706 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -152,6 +152,7 @@
 			target_doc.prevdoc_docname = source_doc.prevdoc_docname
 			target_doc.prevdoc_detail_docname = source_doc.prevdoc_detail_docname
 		elif doctype == "Purchase Invoice":
+			target_doc.received_qty = -1* source_doc.qty
 			target_doc.purchase_order = source_doc.purchase_order
 			target_doc.purchase_receipt = source_doc.purchase_receipt
 			target_doc.po_detail = source_doc.po_detail
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index a832ab7..bd1f258 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -169,7 +169,7 @@
 		else:
 			is_expense_account = frappe.db.get_value("Account",
 				item.get("expense_account"), "report_type")=="Profit and Loss"
-			if self.doctype not in ("Purchase Receipt", "Stock Reconciliation", "Stock Entry") and not is_expense_account:
+			if self.doctype not in ("Purchase Receipt", "Purchase Invoice", "Stock Reconciliation", "Stock Entry") and not is_expense_account:
 				frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account")
 					.format(item.get("expense_account")))
 			if is_expense_account and not item.get("cost_center"):
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index a2ee1b7..b93857d 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -516,10 +516,10 @@
 			);
 		}
 		
-		if(this.frm.doc.doctype == "Sales Invoice") {
+		if(this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") {
 			frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]);
 			
-			if(this.frm.doc.is_pos) {
+			if(this.frm.doc.is_pos || this.frm.doc.is_cash) {
 				if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) {
 					this.frm.doc.paid_amount = flt(total_amount_to_pay);
 				}