Merge branch 'saurabh6790-pi_update_stock' into develop
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 32ad6d2..5af3e82 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();
@@ -18,50 +19,58 @@
 
 	refresh: function(doc) {
 		this._super();
+		
+		hide_fields(this.frm.doc);
 
 		// Show / Hide button
 		this.show_general_ledger();
+		
+		if(doc.update_stock==1 && doc.docstatus==1) {
+			this.show_stock_ledger();
+		}
 
-		if(!doc.is_return) {
-			if(doc.docstatus==1) {
-				if(doc.outstanding_amount > 0) {
-					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.is_return && doc.docstatus==1) {
+			if(doc.outstanding_amount > 0) {
+				this.frm.add_custom_button(__('Payment'), this.make_bank_entry, __("Make"));
+				cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
 			}
-
-			if(doc.docstatus===0) {
-				cur_frm.add_custom_button(__('Purchase Order'), function() {
-					frappe.model.map_current_doc({
-						method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
-						source_doctype: "Purchase Order",
-						get_query_filters: {
-							supplier: cur_frm.doc.supplier || undefined,
-							docstatus: 1,
-							status: ["!=", "Closed"],
-							per_billed: ["<", 99.99],
-							company: cur_frm.doc.company
-						}
-					})
-				}, __("Get items from"));
-
-				cur_frm.add_custom_button(__('Purchase Receipt'), function() {
-					frappe.model.map_current_doc({
-						method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
-						source_doctype: "Purchase Receipt",
-						get_query_filters: {
-							supplier: cur_frm.doc.supplier || undefined,
-							docstatus: 1,
-							status: ["!=", "Closed"],
-							company: cur_frm.doc.company
-						}
-					})
-				}, __("Get items from"));
+			
+			if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
+				cur_frm.add_custom_button(doc.update_stock ? __('Purchase Return') : __('Debit Note'), 
+					this.make_debit_note, __("Make"));
 			}
 		}
+		
+		if(doc.docstatus===0) {
+			cur_frm.add_custom_button(__('Purchase Order'), function() {
+				frappe.model.map_current_doc({
+					method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
+					source_doctype: "Purchase Order",
+					get_query_filters: {
+						supplier: cur_frm.doc.supplier || undefined,
+						docstatus: 1,
+						status: ["!=", "Closed"],
+						per_billed: ["<", 99.99],
+						company: cur_frm.doc.company
+					}
+				})
+			}, __("Get items from"));
+
+			cur_frm.add_custom_button(__('Purchase Receipt'), function() {
+				frappe.model.map_current_doc({
+					method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
+					source_doctype: "Purchase Receipt",
+					get_query_filters: {
+						supplier: cur_frm.doc.supplier || undefined,
+						docstatus: 1,
+						status: ["!=", "Closed"],
+						company: cur_frm.doc.company
+					}
+				})
+			}, __("Get items from"));
+		}
+		
+		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
 	},
 
 	supplier: function() {
@@ -100,19 +109,33 @@
 		}
 	},
 
+	is_paid: function() {
+		hide_fields(this.frm.doc);
+		if(cint(this.frm.doc.is_paid)) {
+			if(!this.frm.doc.company) {
+				cur_frm.set_value("is_paid", 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();
 	},
 
-	allocated_amount: function() {
-		this.calculate_total_advance();
+	paid_amount: function() {
+		this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
+		this.write_off_outstanding_amount();
 		this.frm.refresh_fields();
 	},
 
-	tc_name: function() {
-		this.get_terms();
+	allocated_amount: function() {
+		this.calculate_total_advance();
+		this.frm.refresh_fields();
 	},
 
 	items_add: function(doc, cdt, cdn) {
@@ -137,6 +160,44 @@
 
 cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
 
+// Hide Fields
+// ------------
+function hide_fields(doc) {
+	parent_fields = ['due_date', 'is_opening', 'advances_section', 'from_date', 'to_date'];
+
+	if(cint(doc.is_paid) == 1) {
+		hide_field(parent_fields);
+	} else {
+		for (i in parent_fields) {
+			var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
+			if(!docfield.hidden) unhide_field(parent_fields[i]);
+		}
+	
+	}
+
+	item_fields_stock = ['warehouse_section', 'received_qty', 'rejected_qty'];
+
+	cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
+		(cint(doc.update_stock)==1 ? true : false));	
+
+	cur_frm.refresh_fields();
+}
+
+cur_frm.cscript.update_stock = function(doc, dt, dn) {
+	hide_fields(doc, dt, dn);
+}
+
+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",
@@ -267,3 +328,29 @@
 	else
 		cur_frm.pformat.print_heading = __("Purchase Invoice");
 }
+
+frappe.ui.form.on("Purchase Invoice", {
+	onload: function(frm) {
+		$.each(["warehouse", "rejected_warehouse"], function(i, field) {
+			frm.set_query(field, "items", function() {
+				return {
+					filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+				}
+			})
+		})
+
+		frm.set_query("supplier_warehouse", function() {
+			return {
+				filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+			}
+		})
+	},
+	
+	is_subcontracted: function(frm) {
+		if (frm.doc.is_subcontracted === "Yes") {
+			erpnext.buying.get_default_bom(frm);
+		}
+		frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
+	}
+})
+	
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index bba4a4a..90a0053 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -120,6 +120,31 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "is_paid", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Is Paid", 
+   "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": "column_break1", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -262,8 +287,6 @@
    "label": "Company", 
    "length": 0, 
    "no_copy": 0, 
-   "oldfieldname": "company", 
-   "oldfieldtype": "Link", 
    "options": "Company", 
    "permlevel": 0, 
    "print_hide": 1, 
@@ -279,6 +302,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "default": "0", 
    "fieldname": "is_return", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -807,6 +831,32 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "default": "0", 
+   "fieldname": "update_stock", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "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 +1717,162 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
+   "collapsible_depends_on": "paid_amount", 
+   "depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)", 
+   "fieldname": "payments_section", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Mode of Payment", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Mode of Payment", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "depends_on": "is_paid", 
+   "fieldname": "paid_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Paid Amount", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "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, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Paid Amount (Company Currency)", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Company:company:default_currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "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", 
@@ -1975,15 +2181,15 @@
   {
    "allow_on_submit": 0, 
    "bold": 0, 
-   "collapsible": 1, 
-   "fieldname": "printing_settings", 
+   "collapsible": 0, 
+   "fieldname": "raw_materials_supplied", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Printing Settings", 
+   "label": "Raw Materials Supplied", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -2001,21 +2207,102 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "language", 
-   "fieldtype": "Data", 
+   "default": "No", 
+   "fieldname": "is_subcontracted", 
+   "fieldtype": "Select", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Print Language", 
+   "label": "Raw Materials Supplied", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "No\nYes", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 1, 
    "print_hide_if_no_value": 0, 
-   "read_only": 1, 
+   "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": "supplier_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Supplier Warehouse", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "print_width": "50px", 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0, 
+   "width": "50px"
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "supplied_items", 
+   "fieldtype": "Table", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Supplied Items", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Purchase Receipt Item Supplied", 
+   "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, 
+   "fieldname": "printing_settings", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Printing Settings", 
+   "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, 
@@ -2263,28 +2550,28 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "mode_of_payment", 
-   "fieldtype": "Link", 
+   "fieldname": "posting_time", 
+   "fieldtype": "Time", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Mode of Payment", 
+   "label": "Posting Time", 
    "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "mode_of_payment", 
-   "oldfieldtype": "Select", 
-   "options": "Mode of Payment", 
+   "no_copy": 1, 
    "permlevel": 0, 
-   "print_hide": 0, 
+   "precision": "", 
+   "print_hide": 1, 
    "print_hide_if_no_value": 0, 
+   "print_width": "100px", 
    "read_only": 0, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "unique": 0
+   "unique": 0, 
+   "width": "100px"
   }, 
   {
    "allow_on_submit": 0, 
@@ -2315,6 +2602,33 @@
   {
    "allow_on_submit": 0, 
    "bold": 0, 
+   "collapsible": 0, 
+   "description": "Warehouse where you are maintaining stock of rejected items", 
+   "fieldname": "rejected_warehouse", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Rejected Warehouse", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Warehouse", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "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": "is_recurring", 
    "depends_on": "eval:doc.docstatus<2", 
@@ -2369,35 +2683,8 @@
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "is_recurring", 
-   "description": "", 
-   "fieldname": "recurring_id", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Reference Document", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Purchase Invoice", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name", 
-   "description": "", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "Select the period when the invoice will be generated automatically", 
    "fieldname": "recurring_type", 
    "fieldtype": "Select", 
    "hidden": 0, 
@@ -2405,7 +2692,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Frequency", 
+   "label": "Recurring Type", 
    "length": 0, 
    "no_copy": 1, 
    "options": "Monthly\nQuarterly\nHalf-yearly\nYearly", 
@@ -2423,16 +2710,16 @@
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name", 
-   "description": "", 
-   "fieldname": "repeat_on_day_of_month", 
-   "fieldtype": "Int", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "Start date of current invoice's period", 
+   "fieldname": "from_date", 
+   "fieldtype": "Date", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Repeat on Day of Month", 
+   "label": "From Date", 
    "length": 0, 
    "no_copy": 1, 
    "permlevel": 0, 
@@ -2449,16 +2736,16 @@
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name", 
-   "description": "", 
-   "fieldname": "end_date", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "End date of current invoice's period", 
+   "fieldname": "to_date", 
    "fieldtype": "Date", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Recurring Ends On", 
+   "label": "To Date", 
    "length": 0, 
    "no_copy": 1, 
    "permlevel": 0, 
@@ -2528,19 +2815,18 @@
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name", 
-   "description": "", 
-   "fieldname": "notification_email_address", 
-   "fieldtype": "Code", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "The day of the month on which auto invoice will be generated e.g. 05, 28 etc", 
+   "fieldname": "repeat_on_day_of_month", 
+   "fieldtype": "Int", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Notification Email Address", 
+   "label": "Repeat on Day of Month", 
    "length": 0, 
    "no_copy": 1, 
-   "options": "Email", 
    "permlevel": 0, 
    "print_hide": 1, 
    "print_hide_if_no_value": 0, 
@@ -2552,24 +2838,23 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 0, 
+   "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name", 
-   "fieldname": "recurring_print_format", 
-   "fieldtype": "Link", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "The date on which recurring invoice will be stop", 
+   "fieldname": "end_date", 
+   "fieldtype": "Date", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Recurring Print Format", 
+   "label": "End Date", 
    "length": 0, 
-   "no_copy": 0, 
-   "options": "Print Format", 
+   "no_copy": 1, 
    "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
+   "print_hide": 1, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "report_hide": 0, 
@@ -2603,25 +2888,51 @@
    "width": "50%"
   }, 
   {
-   "allow_on_submit": 1, 
+   "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "is_recurring", 
-   "description": "", 
-   "fieldname": "from_date", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "The date on which next invoice will be generated. It is generated on submit.", 
+   "fieldname": "next_date", 
    "fieldtype": "Date", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "From Date", 
+   "label": "Next Date", 
    "length": 0, 
    "no_copy": 1, 
    "permlevel": 0, 
    "print_hide": 1, 
    "print_hide_if_no_value": 0, 
-   "read_only": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "The unique id for tracking all recurring invoices. It is generated on submit.", 
+   "fieldname": "recurring_id", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Recurring Id", 
+   "length": 0, 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
@@ -2632,16 +2943,16 @@
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "is_recurring", 
-   "description": "", 
-   "fieldname": "to_date", 
-   "fieldtype": "Date", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "description": "Enter email id separated by commas, invoice will be mailed automatically on particular date", 
+   "fieldname": "notification_email_address", 
+   "fieldtype": "Small Text", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "To Date", 
+   "label": "Notification Email Address", 
    "length": 0, 
    "no_copy": 1, 
    "permlevel": 0, 
@@ -2658,20 +2969,21 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "depends_on": "is_recurring", 
-   "description": "", 
-   "fieldname": "next_date", 
-   "fieldtype": "Date", 
+   "depends_on": "eval:doc.is_recurring==1", 
+   "fieldname": "recurring_print_format", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Next Date", 
+   "label": "Recurring Print Format", 
    "length": 0, 
-   "no_copy": 1, 
+   "no_copy": 0, 
+   "options": "Print Format", 
    "permlevel": 0, 
-   "print_hide": 1, 
+   "precision": "", 
+   "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "report_hide": 0, 
@@ -2692,7 +3004,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2016-04-06 05:39:45.475873", 
+ "modified": "2016-04-11 14:37:27.243253", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice", 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 427e040..43d14ed 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.utils import cint, formatdate, flt, getdate
-from frappe import msgprint, _, throw
+from frappe import _, throw
 from erpnext.setup.utils import get_company_currency
 import frappe.defaults
 
@@ -12,6 +12,9 @@
 from erpnext.accounts.party import get_party_account, get_due_date
 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
+from erpnext.controllers.stock_controller import get_warehouse_account
+from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
+from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
 
 form_grid_templates = {
 	"items": "templates/form_grid/item_grid.html"
@@ -45,19 +48,31 @@
 			self.validate_supplier_invoice()
 			self.validate_advance_jv("Purchase Order")
 
+		# validate cash purchase
+		if (self.is_paid == 1):
+			self.validate_cash()
+
 		self.check_conversion_rate()
 		self.validate_credit_to_acc()
 		self.clear_unallocated_advances("Purchase Invoice Advance", "advances")
 		self.check_for_closed_status()
 		self.validate_with_previous_doc()
 		self.validate_uom_is_integer("uom", "qty")
+		self.set_expense_account()
 		self.set_against_expense_account()
 		self.validate_write_off_account()
-		self.update_valuation_rate("items")
 		self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
 		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 create_remarks(self):
 		if not self.remarks:
 			if self.bill_no and self.bill_date:
@@ -135,52 +150,55 @@
 				["Purchase Order", "purchase_order", "po_detail"],
 				["Purchase Receipt", "purchase_receipt", "pr_detail"]
 			])
-
-	def set_against_expense_account(self):
+			
+	def set_expense_account(self):
 		auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
 
 		if auto_accounting_for_stock:
 			stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
-
-		against_accounts = []
-		stock_items = self.get_stock_items()
+			stock_items = self.get_stock_items()
+			
+		if self.update_stock:
+			warehouse_account = get_warehouse_account()
+		
 		for item in self.get("items"):
 			# in case of auto inventory accounting,
 			# expense account is always "Stock Received But Not Billed" for a stock item 
 			# except epening entry, drop-ship entry and fixed asset items
 
-			if auto_accounting_for_stock and item.item_code in stock_items and self.is_opening == 'No' \
-				and (not item.po_detail 
-					or not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier")
-					or not frappe.db.get_value("Item", item.item_code, "is_fixed_asset")):
+			if auto_accounting_for_stock and self.is_opening == 'No' \
+				and item.item_code in stock_items and ((not item.po_detail 
+				or not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier"))
+				or not frappe.db.get_value("Item", item.item_code, "is_fixed_asset")):
 
-				item.expense_account = stock_not_billed_account
-				item.cost_center = None
-
-				if stock_not_billed_account not in against_accounts:
-					against_accounts.append(stock_not_billed_account)
-
+				if self.update_stock:
+					item.expense_account = warehouse_account[item.warehouse]["name"]
+				else:
+					item.expense_account = stock_not_billed_account
+					
 			elif not item.expense_account:
 				throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name))
 
-			elif item.expense_account not in against_accounts:
-				# if no auto_accounting_for_stock or not a stock item
+	def set_against_expense_account(self):
+		against_accounts = []
+		for item in self.get("items"):
+			if item.expense_account not in against_accounts:
 				against_accounts.append(item.expense_account)
 
 		self.against_expense_account = ",".join(against_accounts)
 
 	def po_required(self):
 		if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
-			 for d in self.get('items'):
-				 if not d.purchase_order:
-					 throw(_("Purchse Order number required for Item {0}").format(d.item_code))
+			for d in self.get('items'):
+				if not d.purchase_order:
+					throw(_("Purchse Order number required for Item {0}").format(d.item_code))
 
 	def pr_required(self):
 		stock_items = self.get_stock_items()
 		if frappe.db.get_value("Buying Settings", None, "pr_required") == 'Yes':
-			 for d in self.get('items'):
-				 if not d.purchase_receipt and d.item_code in stock_items:
-					 throw(_("Purchase Receipt number required for Item {0}").format(d.item_code))
+			for d in self.get('items'):
+				if not d.purchase_receipt and d.item_code in stock_items:
+					throw(_("Purchase Receipt number required for Item {0}").format(d.item_code))
 
 	def validate_write_off_account(self):
 		if self.write_off_amount and not self.write_off_account:
@@ -228,21 +246,71 @@
 			from erpnext.accounts.utils import reconcile_against_document
 			reconcile_against_document(lst)
 
+	def update_status_updater_args(self):
+		if cint(self.update_stock):
+			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 update_stock = 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 update_stock=1 and is_return=1)"""
+			}
+		])
+	
+	def validate_purchase_receipt_if_update_stock(self):
+		if self.update_stock:
+			for item in self.get("items"):
+				if item.purchase_receipt:
+					frappe.throw(_("Stock cannot be updated against Purchase Receipt {0}")
+						.format(item.purchase_receipt))
+
 	def on_submit(self):
 		self.check_prev_docstatus()
+		self.update_status_updater_args()
+		
 		self.validate_asset()
 
 		frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
 			self.company, self.base_grand_total)
-
-		# this sequence because outstanding may get -negative
-		self.make_gl_entries()
+			
 		if not self.is_return:
 			self.update_against_document_in_jv()
 			self.update_prevdoc_status()
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
 			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
+		if self.update_stock == 1:
+			self.update_stock_ledger()
+			from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
+			update_serial_nos_after_submit(self, "items")
+			
+		# this sequence because outstanding may get -negative
+		self.make_gl_entries()
+
 		self.update_project()
 		
 	def validate_asset(self):
@@ -271,22 +339,51 @@
 						
 					if self.docstatus==1 and not asset.supplier:
 						frappe.db.set_value("Asset", asset.name, "supplier", self.supplier)
-					
-	def make_gl_entries(self):
-		auto_accounting_for_stock = \
+
+	def make_gl_entries(self, repost_future_gle=False):
+		self.auto_accounting_for_stock = \
 			cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
 
-		stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed")
-		expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
-
+		self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed")
+		self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
+		self.negative_expense_to_be_booked = 0.0
 		gl_entries = []
+		
+		
+		self.make_supplier_gl_entry(gl_entries)
+		self.make_item_gl_entries(gl_entries)
+		self.make_tax_gl_entries(gl_entries)
+		
+		gl_entries = merge_similar_entries(gl_entries)
+		
+		self.make_payment_gl_entries(gl_entries)
 
-		# parent's gl entry
+		self.make_write_off_gl_entry(gl_entries)
+		
+		if gl_entries:
+			update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
+			
+			make_gl_entries(gl_entries,  cancel=(self.docstatus == 2),
+				update_outstanding=update_outstanding, merge_entries=False)
+			
+			if update_outstanding == "No":
+				update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
+					self.doctype, self.return_against if cint(self.is_return) else self.name)
+
+			if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
+				from erpnext.controllers.stock_controller import update_gl_entries_after
+				items, warehouses = self.get_items_and_warehouses()
+				update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+					
+		elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
+			delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+		
+
+	def make_supplier_gl_entry(self, gl_entries):
 		if self.grand_total:
 			# Didnot use base_grand_total to book rounding loss gle
 			grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate,
 				self.precision("grand_total"))
-
 			gl_entries.append(
 				self.get_gl_dict({
 					"account": self.credit_to,
@@ -301,6 +398,88 @@
 				}, self.party_account_currency)
 			)
 
+	def make_item_gl_entries(self, gl_entries):
+		# item gl entries
+		stock_items = self.get_stock_items()
+		expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
+		warehouse_account = get_warehouse_account()
+		
+		for item in self.get("items"):
+			if flt(item.base_net_amount):
+				account_currency = get_account_currency(item.expense_account)
+				
+				if self.update_stock and self.auto_accounting_for_stock:
+					val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
+
+					# warehouse account
+					warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision) 
+						* flt(item.qty)	* flt(item.conversion_factor), item.precision("base_net_amount"))
+						
+					gl_entries.append(
+						self.get_gl_dict({
+							"account": item.expense_account,
+							"against": self.supplier,
+							"debit": warehouse_debit_amount,
+							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+							"cost_center": item.cost_center
+						}, account_currency)
+					)
+					
+					# Amount added through landed-cost-voucher
+					if flt(item.landed_cost_voucher_amount):
+						gl_entries.append(self.get_gl_dict({
+							"account": expenses_included_in_valuation,
+							"against": item.expense_account,
+							"cost_center": item.cost_center,
+							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+							"credit": flt(item.landed_cost_voucher_amount)
+						}))
+
+					# sub-contracting warehouse
+					if flt(item.rm_supp_cost):
+						supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["name"]
+						gl_entries.append(self.get_gl_dict({
+							"account": supplier_warehouse_account,
+							"against": item.expense_account,
+							"cost_center": item.cost_center,
+							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+							"credit": flt(item.rm_supp_cost)
+						}, warehouse_account[self.supplier_warehouse]["account_currency"]))
+				else:
+					gl_entries.append(
+						self.get_gl_dict({
+							"account": item.expense_account,
+							"against": self.supplier,
+							"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
+							"debit_in_account_currency": (flt(item.base_net_amount, 
+								item.precision("base_net_amount")) if account_currency==self.company_currency 
+								else flt(item.net_amount, item.precision("net_amount"))),
+							"cost_center": item.cost_center
+						}, account_currency)
+					)
+				
+			if self.auto_accounting_for_stock and self.is_opening == "No" and \
+				item.item_code in stock_items and item.item_tax_amount:
+					# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
+					if item.purchase_receipt:
+						negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
+							where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""",
+							(item.purchase_receipt, self.expenses_included_in_valuation))
+
+						if not negative_expense_booked_in_pr:
+							gl_entries.append(
+								self.get_gl_dict({
+									"account": self.stock_received_but_not_billed,
+									"against": self.supplier,
+									"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
+									"remarks": self.remarks or "Accounting Entry for Stock"
+								})
+							)
+
+							self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
+								item.precision("item_tax_amount"))
+
+	def make_tax_gl_entries(self, gl_entries):
 		# tax table gl entries
 		valuation_tax = {}
 		for tax in self.get("taxes"):
@@ -320,69 +499,31 @@
 						"cost_center": tax.cost_center
 					}, account_currency)
 				)
-
 			# accumulate valuation tax
 			if self.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount):
-				if auto_accounting_for_stock and not tax.cost_center:
+				if self.auto_accounting_for_stock and not tax.cost_center:
 					frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category)))
 				valuation_tax.setdefault(tax.cost_center, 0)
 				valuation_tax[tax.cost_center] += \
 					(tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount)
-
-		# item gl entries
-		negative_expense_to_be_booked = 0.0
-		stock_items = self.get_stock_items()
-		for item in self.get("items"):
-			if flt(item.base_net_amount):
-				account_currency = get_account_currency(item.expense_account)
-				gl_entries.append(
-					self.get_gl_dict({
-						"account": item.expense_account,
-						"against": self.supplier,
-						"debit": item.base_net_amount,
-						"debit_in_account_currency": item.base_net_amount \
-							if account_currency==self.company_currency else item.net_amount,
-						"cost_center": item.cost_center
-					}, account_currency)
-				)
-
-			if auto_accounting_for_stock and self.is_opening == "No" and \
-				item.item_code in stock_items and item.item_tax_amount:
-					# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
-					if item.purchase_receipt:
-						negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
-							where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""",
-							(item.purchase_receipt, expenses_included_in_valuation))
-
-						if not negative_expense_booked_in_pr:
-							gl_entries.append(
-								self.get_gl_dict({
-									"account": stock_received_but_not_billed,
-									"against": self.supplier,
-									"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
-									"remarks": self.remarks or "Accounting Entry for Stock"
-								})
-							)
-
-							negative_expense_to_be_booked += flt(item.item_tax_amount, self.precision("item_tax_amount", item))
-
-		if self.is_opening == "No" and negative_expense_to_be_booked and valuation_tax:
+		
+		if self.is_opening == "No" and self.negative_expense_to_be_booked and valuation_tax:
 			# credit valuation tax amount in "Expenses Included In Valuation"
 			# this will balance out valuation amount included in cost of goods sold
 
 			total_valuation_amount = sum(valuation_tax.values())
-			amount_including_divisional_loss = negative_expense_to_be_booked
+			amount_including_divisional_loss = self.negative_expense_to_be_booked
 			i = 1
 			for cost_center, amount in valuation_tax.items():
 				if i == len(valuation_tax):
 					applicable_amount = amount_including_divisional_loss
 				else:
-					applicable_amount = negative_expense_to_be_booked * (amount / total_valuation_amount)
+					applicable_amount = self.negative_expense_to_be_booked * (amount / total_valuation_amount)
 					amount_including_divisional_loss -= applicable_amount
 
 				gl_entries.append(
 					self.get_gl_dict({
-						"account": expenses_included_in_valuation,
+						"account": self.expenses_included_in_valuation,
 						"cost_center": cost_center,
 						"against": self.supplier,
 						"credit": applicable_amount,
@@ -392,6 +533,36 @@
 
 				i += 1
 
+	def make_payment_gl_entries(self, gl_entries):
+		# Make Cash GL Entries
+		if cint(self.is_paid) 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)
+			)
+
+	def make_write_off_gl_entry(self, gl_entries):
 		# writeoff account includes petty difference in the invoice amount
 		# and the amount that is paid
 		if self.write_off_account and flt(self.write_off_amount):
@@ -421,13 +592,11 @@
 				})
 			)
 
-		if gl_entries:
-			from erpnext.accounts.general_ledger import make_gl_entries
-			make_gl_entries(gl_entries, cancel=(self.docstatus == 2))
-
 	def on_cancel(self):
 		self.check_for_closed_status()
-
+		
+		self.update_status_updater_args()
+		
 		if not self.is_return:
 			from erpnext.accounts.utils import remove_against_link_from_jv
 			remove_against_link_from_jv(self.doctype, self.name)
@@ -436,6 +605,11 @@
 			self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
 			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
+		if self.update_stock == 1:
+			self.update_stock_ledger()
+			
 		self.make_gl_entries_on_cancel()
 		self.update_project()
 		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 b0ac627..9afcd21 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -6,11 +6,12 @@
 import unittest
 import frappe
 import frappe.model
-from frappe.utils import cint
+from frappe.utils import cint, flt
 import frappe.defaults
 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"]
@@ -119,20 +120,20 @@
 		set_perpetual_inventory(0)
 
 	def test_purchase_invoice_calculation(self):
-		wrapper = frappe.copy_doc(test_records[0])
-		wrapper.insert()
-		wrapper.load_from_db()
+		pi = frappe.copy_doc(test_records[0])
+		pi.insert()
+		pi.load_from_db()
 
 		expected_values = [
 			["_Test Item Home Desktop 100", 90, 59],
 			["_Test Item Home Desktop 200", 135, 177]
 		]
-		for i, item in enumerate(wrapper.get("items")):
+		for i, item in enumerate(pi.get("items")):
 			self.assertEqual(item.item_code, expected_values[i][0])
 			self.assertEqual(item.item_tax_amount, expected_values[i][1])
 			self.assertEqual(item.valuation_rate, expected_values[i][2])
 
-		self.assertEqual(wrapper.base_net_total, 1250)
+		self.assertEqual(pi.base_net_total, 1250)
 
 		# tax amounts
 		expected_values = [
@@ -146,7 +147,7 @@
 			["_Test Account Discount - _TC", 168.03, 1512.30],
 		]
 
-		for i, tax in enumerate(wrapper.get("taxes")):
+		for i, tax in enumerate(pi.get("taxes")):
 			self.assertEqual(tax.account_head, expected_values[i][0])
 			self.assertEqual(tax.tax_amount, expected_values[i][1])
 			self.assertEqual(tax.total, expected_values[i][2])
@@ -314,6 +315,88 @@
 			where voucher_type='Sales Invoice' and voucher_no=%s""", pi.name)
 
 		self.assertFalse(gle)
+	
+	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())
+		
+		gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
+			debit_in_account_currency, credit_in_account_currency
+			from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
+			order by account asc""", pi.name, as_dict=1)
+
+		self.assertTrue(gl_entries)
+		
+		expected_gl_entries = dict((d[0], d) for d in [
+			[pi.credit_to, 0.0, 250.0],
+			[pi.items[0].warehouse, 250.0, 0.0]
+		])
+		
+		for i, gle in enumerate(gl_entries):
+			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_purchase_invoice_for_is_paid_and_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(), cash_bank_account="Cash - _TC", is_paid=1)
+
+		gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit, 
+				sum(credit) as credit, debit_in_account_currency, credit_in_account_currency 
+			from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s 
+			group by account, voucher_no order by account asc;""", pi.name, as_dict=1)
+
+		self.assertTrue(gl_entries)
+		
+		expected_gl_entries = dict((d[0], d) for d in [
+			[pi.credit_to, 250.0, 250.0],
+			[pi.items[0].warehouse, 250.0, 0.0],
+			["Cash - _TC", 0.0, 250.0]
+		])
+				
+		for i, gle in enumerate(gl_entries):
+			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)
+		
+		pi1.cancel()
+		self.assertEquals(actual_qty_1, get_qty_after_transaction())
+		
+		pi.cancel()
+		self.assertEquals(actual_qty_0, get_qty_after_transaction())
+		
+	def test_subcontracting_via_purchase_invoice(self):
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+		
+		make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100)
+		make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", 
+			qty=100, basic_rate=100)
+		
+		pi = make_purchase_invoice(item_code="_Test FG Item", qty=10, rate=500, 
+			update_stock=1, is_subcontracted="Yes")
+		
+		self.assertEquals(len(pi.get("supplied_items")), 2)
+		
+		rm_supp_cost = sum([d.amount for d in pi.get("supplied_items")])
+		self.assertEquals(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
 
 def make_purchase_invoice(**args):
 	pi = frappe.new_doc("Purchase Invoice")
@@ -322,12 +405,22 @@
 		pi.posting_date = args.posting_date
 	if args.posting_time:
 		pi.posting_time = args.posting_time
+	if args.update_stock:
+		pi.update_stock = 1
+	if args.is_paid:
+		pi.is_paid = 1
+		
+	if args.cash_bank_account:
+		pi.cash_bank_account=args.cash_bank_account
+		
 	pi.company = args.company or "_Test Company"
 	pi.supplier = args.supplier or "_Test Supplier"
 	pi.currency = args.currency or "INR"
 	pi.conversion_rate = args.conversion_rate or 1
 	pi.is_return = args.is_return
 	pi.return_against = args.return_against
+	pi.is_subcontracted = args.is_subcontracted
+	pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
 
 	pi.append("items", {
 		"item_code": args.item or args.item_code or "_Test Item",
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json
index 4218828..7feca23 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_records.json
+++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json
@@ -22,7 +22,8 @@
     "parentfield": "items",
     "qty": 10,
     "rate": 50,
-    "uom": "_Test UOM"
+    "uom": "_Test UOM",
+	"warehouse": "_Test Warehouse - _TC"
    },
    {
     "amount": 750,
@@ -37,7 +38,8 @@
     "parentfield": "items",
     "qty": 5,
     "rate": 150,
-    "uom": "_Test UOM"
+    "uom": "_Test UOM",
+	"warehouse": "_Test Warehouse - _TC"
    }
   ],
   "grand_total": 0,
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..f9f7660 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,31 @@
   }, 
   {
    "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "received_qty", 
+   "fieldtype": "Float", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 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 +268,31 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "rejected_qty", 
+   "fieldtype": "Float", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 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 +817,185 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "warehouse_section", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
+   "ignore_xss_filter": 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, 
@@ -1057,6 +1286,32 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
+   "fieldname": "bom", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "BOM", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "BOM", 
+   "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_break6", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -1206,7 +1461,7 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 0, 
+   "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
    "fieldname": "valuation_rate", 
@@ -1254,6 +1509,31 @@
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
+  }, 
+  {
+   "allow_on_submit": 1, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "landed_cost_voucher_amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Landed Cost Voucher Amount", 
+   "length": 0, 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
   }
  ], 
  "hide_heading": 0, 
@@ -1265,7 +1545,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2016-03-28 05:05:27.752823", 
+ "modified": "2016-04-07 16:38:30.502386", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice Item", 
@@ -1274,5 +1554,6 @@
  "read_only": 0, 
  "read_only_onload": 0, 
  "sort_field": "modified", 
- "sort_order": "DESC"
+ "sort_order": "DESC", 
+ "track_seen": 0
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index f6f746a..18049cc 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -278,20 +278,20 @@
 // Hide Fields
 // ------------
 cur_frm.cscript.hide_fields = function(doc) {
-	par_flds = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances_received',
+	parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances_received',
 		'advances', 'sales_partner', 'commission_rate', 'total_commission', 'advances', 'from_date', 'to_date'];
 
 	if(cint(doc.is_pos) == 1) {
-		hide_field(par_flds);
+		hide_field(parent_fields);
 	} 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]);
+		for (i in parent_fields) {
+			var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
+			if(!docfield.hidden) unhide_field(parent_fields[i]);
 		}
 	}
 
-	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,
+	item_fields_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse', 'expense_account', 'warehouse']
+	cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
 		(cint(doc.update_stock)==1 ? true : false));
 
 	// India related fields
@@ -303,25 +303,6 @@
 	cur_frm.refresh_fields();
 }
 
-
-cur_frm.cscript.mode_of_payment = function(doc) {
-	if(doc.is_pos) {
-		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.cscript.update_stock = function(doc, dt, dn) {
 	cur_frm.cscript.hide_fields(doc, dt, dn);
 }
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index bc1d73d..53747bf 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -81,14 +81,10 @@
 		self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
 		self.update_packing_list()
 
-	def on_submit(self):
-		if cint(self.update_stock) == 1:
-			self.update_stock_ledger()
-		else:
-			# Check for Approving Authority
-			if not self.recurring_id:
-				frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
-				 	self.company, self.base_grand_total, self)
+	def on_submit(self):			
+		if not self.recurring_id:
+			frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
+			 	self.company, self.base_grand_total, self)
 
 		self.check_prev_docstatus()
 
@@ -99,7 +95,12 @@
 		self.update_status_updater_args()
 		self.update_prevdoc_status()
 		self.update_billing_status_in_dn()
-
+		
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating reserved qty in bin depends upon updated delivered qty in SO
+		if self.update_stock == 1:
+			self.update_stock_ledger()
+		
 		# this sequence because outstanding may get -ve
 		self.make_gl_entries()
 
@@ -117,9 +118,6 @@
 		self.update_time_log_batch(None)
 
 	def on_cancel(self):
-		if cint(self.update_stock) == 1:
-			self.update_stock_ledger()
-
 		self.check_close_sales_order("sales_order")
 
 		from erpnext.accounts.utils import remove_against_link_from_jv
@@ -137,6 +135,11 @@
 			self.update_billing_status_for_zero_amount_refdoc("Sales Order")
 
 		self.validate_c_form_on_cancel()
+		
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating reserved qty in bin depends upon updated delivered qty in SO
+		if self.update_stock == 1:
+			self.update_stock_ledger()
 
 		self.make_gl_entries_on_cancel()
 
@@ -461,21 +464,6 @@
 				
 				d.income_account = disposal_account
 
-	def on_update(self):
-		if cint(self.is_pos) == 1:
-			if flt(self.paid_amount) == 0:
-				if self.cash_bank_account:
-					frappe.db.set(self, 'paid_amount',
-						flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
-				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"))
-		else:
-			frappe.db.set(self,'paid_amount',0)
-
-		frappe.db.set(self, 'base_paid_amount',
-			flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
 
 	def check_prev_docstatus(self):
 		for d in self.get('items'):
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 2063edf..a8a090f 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -25,7 +25,6 @@
 def process_gl_map(gl_map, merge_entries=True):
 	if merge_entries:
 		gl_map = merge_similar_entries(gl_map)
-
 	for entry in gl_map:
 		# toggle debit, credit if negative entry
 		if flt(entry.debit) < 0:
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 2f1959b..79eaeeb 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -42,7 +42,7 @@
 
 		this.frm.set_query("item_code", "items", function() {
 			if(me.frm.doc.is_subcontracted == "Yes") {
-				 return{
+				return{
 					query: "erpnext.controllers.queries.item_query",
 					filters:{ 'is_sub_contracted_item': 1 }
 				}
@@ -114,8 +114,49 @@
 	},
 
 	qty: function(doc, cdt, cdn) {
+		if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && doc.update_stock)) {
+			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);
 		this.conversion_factor(doc, cdt, cdn);
+		
+	},
+	
+	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);
+	},
+	
+	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);
 	},
 
 	conversion_factor: function(doc, cdt, cdn) {
@@ -194,6 +235,10 @@
 
 		erpnext.utils.get_address_display(this.frm, "shipping_address",
 			"shipping_address_display", is_your_company_address=true)
+	},
+	
+	tc_name: function() {
+		this.get_terms();
 	}
 });
 
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 94dd070..c24bcdc 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -45,6 +45,32 @@
 
 		po.load_from_db()
 		self.assertEquals(po.get("items")[0].received_qty, 4)
+		
+	def test_ordered_qty_against_pi_with_update_stock(self):
+		existing_ordered_qty = get_ordered_qty()
+
+		po = create_purchase_order()
+		
+		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10)
+
+		frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
+
+		pi = make_purchase_invoice(po.name)
+		pi.update_stock = 1
+		pi.items[0].qty = 12
+		pi.insert()
+		pi.submit()
+		
+		self.assertEqual(get_ordered_qty(), existing_ordered_qty)
+
+		po.load_from_db()
+		self.assertEquals(po.get("items")[0].received_qty, 12)
+
+		pi.cancel()
+		self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10)
+
+		po.load_from_db()
+		self.assertEquals(po.get("items")[0].received_qty, 0)
 
 	def test_make_purchase_invoice(self):
 		po = create_purchase_order(do_not_submit=True)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 50d4d8a..594a576 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -54,6 +54,26 @@
 			if not self.get("__islocal"):
 				validate_recurring_document(self)
 				convert_to_recurring(self, self.get("posting_date") or self.get("transaction_date"))
+		
+		self.validate_paid_amount()
+	
+	def validate_paid_amount(self):
+		if hasattr(self, "is_pos") or hasattr(self, "is_paid"):
+			is_paid = self.get("is_pos") or self.get("is_paid")
+			if cint(is_paid) == 1:
+				if flt(self.paid_amount) == 0:
+					if self.cash_bank_account:
+						self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount), 
+							self.precision("paid_amount"))
+					else:
+						# show message that the amount is not paid
+						self.paid_amount = 0
+						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)
+
+			frappe.db.set(self, 'base_paid_amount',
+				flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
 
 	def on_update_after_submit(self):
 		if self.meta.get_field("is_recurring"):
@@ -126,14 +146,6 @@
 		"""set missing item values"""
 		from erpnext.stock.get_item_details import get_item_details
 
-		if self.doctype == "Purchase Invoice":
-			auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
-
-			if auto_accounting_for_stock:
-				stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
-
-			stock_items = self.get_stock_items()
-
 		if hasattr(self, "items"):
 			parent_dict = {}
 			for fieldname in self.meta.get_valid_columns():
@@ -180,14 +192,8 @@
 							item.rate = flt(item.price_list_rate *
 								(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
 
-					if self.doctype == "Purchase Invoice":
-						if auto_accounting_for_stock and item.item_code in stock_items \
-							and self.is_opening == 'No' \
-							and (not item.po_detail or not frappe.db.get_value("Purchase Order Item",
-								item.po_detail, "delivered_by_supplier")):
-
-								item.expense_account = stock_not_billed_account
-								item.cost_center = None
+			if self.doctype == "Purchase Invoice":
+				self.set_expense_account()
 
 	def set_taxes(self):
 		if not self.meta.get_field("taxes"):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 6a1b205..74a3d69 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
@@ -32,10 +32,29 @@
 		self.set_qty_as_per_stock_uom()
 		self.validate_stock_or_nonstock_items()
 		self.validate_warehouse()
+		
+		if self.doctype=="Purchase Invoice":
+			self.validate_purchase_receipt_if_update_stock()
+		
+		if self.doctype=="Purchase Receipt" or (self.doctype=="Purchase Invoice" and self.update_stock):
+			self.validate_purchase_return()
+			self.validate_rejected_warehouse()
+			self.validate_accepted_rejected_qty()
+			
+			pc_obj = frappe.get_doc('Purchase Common')
+			pc_obj.validate_for_items(self)
+			
+			#sub-contracting
+			self.validate_for_subcontracting()
+			self.create_raw_materials_supplied("supplied_items")
+			self.set_landed_cost_voucher_amount()
+		
+		if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
+			self.update_valuation_rate("items")
 
 	def set_missing_values(self, for_validate=False):
 		super(BuyingController, self).set_missing_values(for_validate)
-
+		
 		self.set_supplier_from_item_default()
 		self.set_price_list_currency("Buying")
 
@@ -60,6 +79,13 @@
 			if tax_for_valuation:
 				frappe.throw(_("Tax Category can not be 'Valuation' or 'Valuation and Total' as all items are non-stock items"))
 
+	def set_landed_cost_voucher_amount(self):
+		for d in self.get("items"):
+			lc_voucher_amount = frappe.db.sql("""select sum(applicable_charges)
+				from `tabLanded Cost Item`
+				where docstatus = 1 and purchase_receipt_item = %s""", d.name)
+			d.landed_cost_voucher_amount = lc_voucher_amount[0][0] if lc_voucher_amount else 0.0
+			
 	def set_total_in_words(self):
 		from frappe.utils import money_in_words
 		company_currency = get_company_currency(self.company)
@@ -94,7 +120,6 @@
 			if item.item_code and item.qty and item.item_code in stock_items:
 				item_proportion = flt(item.base_net_amount) / stock_items_amount if stock_items_amount \
 					else flt(item.qty) / stock_items_qty
-
 				if i == (last_stock_item_idx - 1):
 					item.item_tax_amount = flt(valuation_amount_adjustment,
 						self.precision("item_tax_amount", item))
@@ -108,10 +133,10 @@
 					item.conversion_factor = get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0
 
 				qty_in_stock_uom = flt(item.qty * item.conversion_factor)
-				rm_supp_cost = flt(item.rm_supp_cost) if self.doctype=="Purchase Receipt" else 0.0
+				rm_supp_cost = flt(item.rm_supp_cost) if self.doctype in ["Purchase Receipt", "Purchase Invoice"] else 0.0
 
 				landed_cost_voucher_amount = flt(item.landed_cost_voucher_amount) \
-					if self.doctype == "Purchase Receipt" else 0.0
+					if self.doctype in ["Purchase Receipt", "Purchase Invoice"] else 0.0
 
 				item.valuation_rate = ((item.base_net_amount + item.item_tax_amount + rm_supp_cost
 					 + landed_cost_voucher_amount) / qty_in_stock_uom)
@@ -123,7 +148,7 @@
 			frappe.throw(_("Please enter 'Is Subcontracted' as Yes or No"))
 
 		if self.is_subcontracted == "Yes":
-			if self.doctype == "Purchase Receipt" and not self.supplier_warehouse:
+			if self.doctype in ["Purchase Receipt", "Purchase Invoice"] and not self.supplier_warehouse:
 				frappe.throw(_("Supplier Warehouse mandatory for sub-contracted Purchase Receipt"))
 
 			for item in self.get("items"):
@@ -139,7 +164,7 @@
 		if self.is_subcontracted=="Yes":
 			parent_items = []
 			for item in self.get("items"):
-				if self.doctype == "Purchase Receipt":
+				if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
 					item.rm_supp_cost = 0.0
 				if item.item_code in self.sub_contracted_items:
 					self.update_raw_materials_supplied(item, raw_material_table)
@@ -149,7 +174,7 @@
 
 			self.cleanup_raw_materials_supplied(parent_items, raw_material_table)
 
-		elif self.doctype == "Purchase Receipt":
+		elif self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
 			for item in self.get("items"):
 				item.rm_supp_cost = 0.0
 
@@ -179,7 +204,7 @@
 
 			rm.conversion_factor = item.conversion_factor
 
-			if self.doctype == "Purchase Receipt":
+			if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
 				rm.consumed_qty = required_qty
 				rm.description = bom_item.description
 				if item.batch_no and not rm.batch_no:
@@ -205,7 +230,7 @@
 			rm.amount = required_qty * flt(rm.rate)
 			raw_materials_cost += flt(rm.amount)
 
-		if self.doctype == "Purchase Receipt":
+		if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
 			item.rm_supp_cost = raw_materials_cost
 
 	def cleanup_raw_materials_supplied(self, parent_items, raw_material_table):
@@ -261,3 +286,106 @@
 				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 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:
+				if self.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 update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
+		self.update_ordered_qty()
+		
+		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 update_ordered_qty(self):
+		po_map = {}
+		for d in self.get("items"):
+			if self.doctype=="Purchase Receipt" \
+				and d.prevdoc_doctype=="Purchase Order" and d.prevdoc_detail_docname:
+					po_map.setdefault(d.prevdoc_docname, []).append(d.prevdoc_detail_docname)
+			
+			elif self.doctype=="Purchase Invoice" and d.purchase_order and d.po_detail:
+				po_map.setdefault(d.purchase_order, []).append(d.po_detail)
+
+		for po, po_item_rows in po_map.items():
+			if po and po_item_rows:
+				po_obj = frappe.get_doc("Purchase Order", po)
+
+				if po_obj.status in ["Closed", "Cancelled"]:
+					frappe.throw(_("{0} {1} is cancelled or closed").format(_("Purchase Order"), po),
+						frappe.InvalidStatusError)
+
+				po_obj.update_ordered_qty(po_item_rows)
+	
+	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/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/selling_controller.py b/erpnext/controllers/selling_controller.py
index 3c9efa1..b9b94f5 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -7,6 +7,7 @@
 from erpnext.setup.utils import get_company_currency
 from frappe import _, throw
 from erpnext.stock.get_item_details import get_bin_details
+from erpnext.stock.utils import get_incoming_rate
 
 from erpnext.controllers.stock_controller import StockController
 
@@ -228,6 +229,79 @@
 				status = frappe.db.get_value("Sales Order", d.get(ref_fieldname), "status")
 				if status == "Closed":
 					frappe.throw(_("Sales Order {0} is {1}").format(d.get(ref_fieldname), status))
+					
+	def update_reserved_qty(self):
+		so_map = {}
+		for d in self.get("items"):
+			if d.so_detail:
+				if self.doctype == "Delivery Note" and d.against_sales_order:
+					so_map.setdefault(d.against_sales_order, []).append(d.so_detail)
+				elif self.doctype == "Sales Invoice" and d.sales_order and self.update_stock:
+					so_map.setdefault(d.sales_order, []).append(d.so_detail)
+
+		for so, so_item_rows in so_map.items():
+			if so and so_item_rows:
+				sales_order = frappe.get_doc("Sales Order", so)
+
+				if sales_order.status in ["Closed", "Cancelled"]:
+					frappe.throw(_("{0} {1} is cancelled or closed").format(_("Sales Order"), so),
+						frappe.InvalidStatusError)
+
+				sales_order.update_reserved_qty(so_item_rows)
+
+	def update_stock_ledger(self):
+		self.update_reserved_qty()
+
+		sl_entries = []
+		for d in self.get_item_list():
+			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and flt(d.qty):
+				return_rate = 0
+				if cint(self.is_return) and self.return_against and self.docstatus==1:
+					return_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
+
+				# On cancellation or if return entry submission, make stock ledger entry for
+				# target warehouse first, to update serial no values properly
+
+				if d.warehouse and ((not cint(self.is_return) and self.docstatus==1)
+					or (cint(self.is_return) and self.docstatus==2)):
+						sl_entries.append(self.get_sl_entries(d, {
+							"actual_qty": -1*flt(d.qty),
+							"incoming_rate": return_rate
+						}))
+
+				if d.target_warehouse:
+					target_warehouse_sle = self.get_sl_entries(d, {
+						"actual_qty": flt(d.qty),
+						"warehouse": d.target_warehouse
+					})
+
+					if self.docstatus == 1:
+						if not cint(self.is_return):
+							args = frappe._dict({
+								"item_code": d.item_code,
+								"warehouse": d.warehouse,
+								"posting_date": self.posting_date,
+								"posting_time": self.posting_time,
+								"qty": -1*flt(d.qty),
+								"serial_no": d.serial_no
+							})
+							target_warehouse_sle.update({
+								"incoming_rate": get_incoming_rate(args)
+							})
+						else:
+							target_warehouse_sle.update({
+								"outgoing_rate": return_rate
+							})
+					sl_entries.append(target_warehouse_sle)
+
+				if d.warehouse and ((not cint(self.is_return) and self.docstatus==2)
+					or (cint(self.is_return) and self.docstatus==1)):
+						sl_entries.append(self.get_sl_entries(d, {
+							"actual_qty": -1*flt(d.qty),
+							"incoming_rate": return_rate
+						}))
+
+		self.make_sl_entries(sl_entries)
 
 def check_active_sales_items(obj):
 	for d in obj.get("items"):
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index a832ab7..845a4d0 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -8,8 +8,6 @@
 import frappe.defaults
 from erpnext.accounts.utils import get_fiscal_year
 from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
-from erpnext.stock.utils import get_incoming_rate
-
 from erpnext.controllers.accounts_controller import AccountsController
 
 class StockController(AccountsController):
@@ -169,7 +167,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"):
@@ -230,79 +228,6 @@
 			incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
 
 		return incoming_rate
-
-	def update_reserved_qty(self):
-		so_map = {}
-		for d in self.get("items"):
-			if d.so_detail:
-				if self.doctype == "Delivery Note" and d.against_sales_order:
-					so_map.setdefault(d.against_sales_order, []).append(d.so_detail)
-				elif self.doctype == "Sales Invoice" and d.sales_order and self.update_stock:
-					so_map.setdefault(d.sales_order, []).append(d.so_detail)
-
-		for so, so_item_rows in so_map.items():
-			if so and so_item_rows:
-				sales_order = frappe.get_doc("Sales Order", so)
-
-				if sales_order.status in ["Closed", "Cancelled"]:
-					frappe.throw(_("{0} {1} is cancelled or closed").format(_("Sales Order"), so),
-						frappe.InvalidStatusError)
-
-				sales_order.update_reserved_qty(so_item_rows)
-
-	def update_stock_ledger(self):
-		self.update_reserved_qty()
-
-		sl_entries = []
-		for d in self.get_item_list():
-			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and flt(d.qty):
-				return_rate = 0
-				if cint(self.is_return) and self.return_against and self.docstatus==1:
-					return_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
-
-				# On cancellation or if return entry submission, make stock ledger entry for
-				# target warehouse first, to update serial no values properly
-
-				if d.warehouse and ((not cint(self.is_return) and self.docstatus==1)
-					or (cint(self.is_return) and self.docstatus==2)):
-						sl_entries.append(self.get_sl_entries(d, {
-							"actual_qty": -1*flt(d.qty),
-							"incoming_rate": return_rate
-						}))
-
-				if d.target_warehouse:
-					target_warehouse_sle = self.get_sl_entries(d, {
-						"actual_qty": flt(d.qty),
-						"warehouse": d.target_warehouse
-					})
-
-					if self.docstatus == 1:
-						if not cint(self.is_return):
-							args = frappe._dict({
-								"item_code": d.item_code,
-								"warehouse": d.warehouse,
-								"posting_date": self.posting_date,
-								"posting_time": self.posting_time,
-								"qty": -1*flt(d.qty),
-								"serial_no": d.serial_no
-							})
-							target_warehouse_sle.update({
-								"incoming_rate": get_incoming_rate(args)
-							})
-						else:
-							target_warehouse_sle.update({
-								"outgoing_rate": return_rate
-							})
-					sl_entries.append(target_warehouse_sle)
-
-				if d.warehouse and ((not cint(self.is_return) and self.docstatus==2)
-					or (cint(self.is_return) and self.docstatus==1)):
-						sl_entries.append(self.get_sl_entries(d, {
-							"actual_qty": -1*flt(d.qty),
-							"incoming_rate": return_rate
-						}))
-
-		self.make_sl_entries(sl_entries)
 		
 	def validate_warehouse(self):
 		from erpnext.stock.utils import validate_warehouse_company
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 469e327..ccc4629 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -196,7 +196,7 @@
 erpnext.patches.v5_7.item_template_attributes
 execute:frappe.delete_doc_if_exists("DocType", "Manage Variants")
 execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item")
-erpnext.patches.v4_2.repost_reserved_qty #2015-08-20
+erpnext.patches.v4_2.repost_reserved_qty #2016-04-15
 erpnext.patches.v5_4.update_purchase_cost_against_project
 erpnext.patches.v5_8.update_order_reference_in_return_entries
 erpnext.patches.v5_8.add_credit_note_print_heading
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index a2ee1b7..b4e712a 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_paid) {
 				if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) {
 					this.frm.doc.paid_amount = flt(total_amount_to_pay);
 				}
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 7ac8941..5fa2d7e 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -126,6 +126,34 @@
 
 		dn.cancel()
 		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
+		
+	def test_reserved_qty_for_over_delivery_via_sales_invoice(self):
+		# set over-delivery tolerance
+		frappe.db.set_value('Item', "_Test Item", 'tolerance', 50)
+
+		existing_reserved_qty = get_reserved_qty()
+
+		so = make_sales_order()
+		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
+
+		si = make_sales_invoice(so.name)
+		si.update_stock = 1
+		si.get("items")[0].qty = 12
+		si.insert()
+		si.submit()
+		
+		self.assertEqual(get_reserved_qty(), existing_reserved_qty)
+		
+		so.load_from_db()
+		self.assertEqual(so.get("items")[0].delivered_qty, 12)
+		self.assertEqual(so.per_delivered, 100)
+
+		si.cancel()
+		self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
+		
+		so.load_from_db()
+		self.assertEqual(so.get("items")[0].delivered_qty, 0)
+		self.assertEqual(so.per_delivered, 0)
 
 	def test_reserved_qty_for_partial_delivery_with_packing_list(self):
 		existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 63abaa5..6712ee8 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -191,6 +191,8 @@
 		if not self.is_return:
 			self.check_credit_limit()
 
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating reserved qty in bin depends upon updated delivered qty in SO
 		self.update_stock_ledger()
 		self.make_gl_entries()
 
@@ -201,6 +203,8 @@
 		self.update_prevdoc_status()
 		self.update_billing_status()
 
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating reserved qty in bin depends upon updated delivered qty in SO
 		self.update_stock_ledger()
 
 		self.cancel_packing_slips()
diff --git a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json
index 9c1a74f..fafcc84 100644
--- a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json
+++ b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json
@@ -6,6 +6,7 @@
  "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
+ "document_type": "Document", 
  "fields": [
   {
    "allow_on_submit": 0, 
@@ -15,6 +16,7 @@
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Item Code", 
@@ -23,6 +25,7 @@
    "options": "Item", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 1, 
@@ -39,6 +42,7 @@
    "fieldtype": "Text Editor", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Description", 
@@ -48,6 +52,7 @@
    "oldfieldtype": "Data", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "print_width": "300px", 
    "read_only": 1, 
    "report_hide": 0, 
@@ -61,18 +66,47 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "purchase_receipt", 
-   "fieldtype": "Link", 
+   "fieldname": "receipt_document_type", 
+   "fieldtype": "Select", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "label": "Purchase Receipt", 
+   "label": "Receipt Document Type", 
    "length": 0, 
    "no_copy": 1, 
-   "options": "Purchase Receipt", 
+   "options": "Purchase Invoice\nPurchase Receipt", 
    "permlevel": 0, 
+   "precision": "", 
    "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "receipt_document", 
+   "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Receipt Document", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "receipt_document_type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -88,12 +122,14 @@
    "fieldtype": "Column Break", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -109,6 +145,7 @@
    "fieldtype": "Float", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Qty", 
@@ -116,6 +153,7 @@
    "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -131,6 +169,7 @@
    "fieldtype": "Currency", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "label": "Rate", 
@@ -139,6 +178,7 @@
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -154,6 +194,7 @@
    "fieldtype": "Currency", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Amount", 
@@ -164,6 +205,7 @@
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 1, 
@@ -179,6 +221,7 @@
    "fieldtype": "Currency", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Applicable Charges", 
@@ -187,6 +230,7 @@
    "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -202,6 +246,7 @@
    "fieldtype": "Data", 
    "hidden": 1, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "label": "Purchase Receipt Item", 
@@ -209,6 +254,7 @@
    "no_copy": 1, 
    "permlevel": 0, 
    "print_hide": 1, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -226,12 +272,13 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2015-11-16 06:29:49.057949", 
+ "modified": "2016-04-07 16:18:00.859492", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Landed Cost Item", 
  "owner": "wasim@webnotestech.com", 
  "permissions": [], 
  "read_only": 0, 
- "read_only_onload": 0
+ "read_only_onload": 0, 
+ "track_seen": 0
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json
index 165982f..db3b89e 100644
--- a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json
+++ b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json
@@ -6,25 +6,54 @@
  "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
+ "document_type": "Document", 
  "fields": [
   {
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "fieldname": "purchase_receipt", 
-   "fieldtype": "Link", 
+   "fieldname": "receipt_document_type", 
+   "fieldtype": "Select", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Receipt Document Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "\nPurchase Invoice\nPurchase Receipt", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "fieldname": "receipt_document", 
+   "fieldtype": "Dynamic Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
-   "label": "Purchase Receipt", 
+   "label": "Receipt Document", 
    "length": 0, 
    "no_copy": 0, 
    "oldfieldname": "purchase_receipt_no", 
    "oldfieldtype": "Link", 
-   "options": "Purchase Receipt", 
+   "options": "receipt_document_type", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "print_width": "220px", 
    "read_only": 0, 
    "report_hide": 0, 
@@ -42,6 +71,7 @@
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Supplier", 
@@ -50,6 +80,7 @@
    "options": "Supplier", 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -65,12 +96,14 @@
    "fieldtype": "Column Break", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -87,6 +120,7 @@
    "fieldtype": "Date", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Posting Date", 
@@ -94,6 +128,7 @@
    "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -109,6 +144,7 @@
    "fieldtype": "Currency", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Grand Total", 
@@ -116,6 +152,7 @@
    "no_copy": 0, 
    "permlevel": 0, 
    "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
    "read_only": 1, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -133,12 +170,13 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2015-11-16 06:29:49.106523", 
+ "modified": "2016-04-07 15:14:56.955036", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Landed Cost Purchase Receipt", 
  "owner": "wasim@webnotestech.com", 
  "permissions": [], 
  "read_only": 0, 
- "read_only_onload": 0
+ "read_only_onload": 0, 
+ "track_seen": 0
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
index 0bb8f90..5a86c89 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
@@ -8,20 +8,28 @@
 erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
 	setup: function() {
 		var me = this;
-		this.frm.fields_dict.purchase_receipts.grid.get_field('purchase_receipt').get_query =
-			function() {
+		this.frm.fields_dict.purchase_receipts.grid.get_field('receipt_document').get_query =
+			function(doc, cdt ,cdn) {
+				var d = locals[cdt][cdn]
+				
+				var filters = [
+					[d.receipt_document_type, 'docstatus', '=', '1'],
+					[d.receipt_document_type, 'company', '=', me.frm.doc.company],
+				]
+				
+				if(d.receipt_document_type == "Purchase Invoice") {
+					filters.push(["Purchase Invoice", "update_stock", "=", "1"])
+				}
+								
 				if(!me.frm.doc.company) msgprint(__("Please enter company first"));
 				return {
-					filters:[
-						['Purchase Receipt', 'docstatus', '=', '1'],
-						['Purchase Receipt', 'company', '=', me.frm.doc.company],
-					]
+					filters:filters
 				}
 		};
 
-		this.frm.add_fetch("purchase_receipt", "supplier", "supplier");
-		this.frm.add_fetch("purchase_receipt", "posting_date", "posting_date");
-		this.frm.add_fetch("purchase_receipt", "base_grand_total", "grand_total");
+		this.frm.add_fetch("receipt_document", "supplier", "supplier");
+		this.frm.add_fetch("receipt_document", "posting_date", "posting_date");
+		this.frm.add_fetch("receipt_document", "base_grand_total", "grand_total");
 
 	},
 
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 3418c9e..ac59e06 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -14,9 +14,9 @@
 		for pr in self.get("purchase_receipts"):
 			pr_items = frappe.db.sql("""select pr_item.item_code, pr_item.description,
 				pr_item.qty, pr_item.base_rate, pr_item.base_amount, pr_item.name
-				from `tabPurchase Receipt Item` pr_item where parent = %s
-				and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 1)""",
-				pr.purchase_receipt, as_dict=True)
+				from `tab{doctype} Item` pr_item where parent = %s
+				and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 1)
+				""".format(doctype=pr.receipt_document_type), pr.receipt_document, as_dict=True)
 
 			for d in pr_items:
 				item = self.append("items")
@@ -25,13 +25,13 @@
 				item.qty = d.qty
 				item.rate = d.base_rate
 				item.amount = d.base_amount
-				item.purchase_receipt = pr.purchase_receipt
+				item.receipt_document_type = pr.receipt_document_type
+				item.receipt_document = pr.receipt_document
 				item.purchase_receipt_item = d.name
 
 		if self.get("taxes"):
 			self.set_applicable_charges_for_item()
 
-
 	def validate(self):
 		self.check_mandatory()
 		self.validate_purchase_receipts()
@@ -43,25 +43,26 @@
 
 	def check_mandatory(self):
 		if not self.get("purchase_receipts"):
-			frappe.throw(_("Please enter Purchase Receipts"))
+			frappe.throw(_("Please enter Receipt Document"))
 
 		if not self.get("taxes"):
 			frappe.throw(_("Please enter Taxes and Charges"))
 
 	def validate_purchase_receipts(self):
-		purchase_receipts = []
+		receipt_documents = []
+		
 		for d in self.get("purchase_receipts"):
-			if frappe.db.get_value("Purchase Receipt", d.purchase_receipt, "docstatus") != 1:
-				frappe.throw(_("Purchase Receipt must be submitted"))
+			if frappe.db.get_value(d.receipt_document_type, d.receipt_document, "docstatus") != 1:
+				frappe.throw(_("Receipt document must be submitted"))
 			else:
-				purchase_receipts.append(d.purchase_receipt)
+				receipt_documents.append(d.receipt_document)
 
 		for item in self.get("items"):
-			if not item.purchase_receipt:
+			if not item.receipt_document:
 				frappe.throw(_("Item must be added using 'Get Items from Purchase Receipts' button"))
-			elif item.purchase_receipt not in purchase_receipts:
-				frappe.throw(_("Item Row {0}: Purchase Receipt {1} does not exist in above 'Purchase Receipts' table")
-					.format(item.idx, item.purchase_receipt))
+			elif item.receipt_document not in receipt_documents:
+				frappe.throw(_("Item Row {idx}: {doctype} {docname} does not exist in above '{doctype}' table")
+					.format(idx=item.idx, doctype=item.receipt_document_type, docname=item.receipt_document))
 
 	def set_total_taxes_and_charges(self):
 		self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("taxes")])
@@ -83,36 +84,35 @@
 		self.update_landed_cost()
 
 	def update_landed_cost(self):
-		purchase_receipts = list(set([d.purchase_receipt for d in self.get("items")]))
-		for purchase_receipt in purchase_receipts:
-			pr = frappe.get_doc("Purchase Receipt", purchase_receipt)
+		for d in self.get("items"):
+			doc = frappe.get_doc(d.receipt_document_type, d.receipt_document)
 
 			# set landed cost voucher amount in pr item
-			pr.set_landed_cost_voucher_amount()
+			doc.set_landed_cost_voucher_amount()
 
 			# set valuation amount in pr item
-			pr.update_valuation_rate("items")
+			doc.update_valuation_rate("items")
 
 			# save will update landed_cost_voucher_amount and voucher_amount in PR,
 			# as those fields are allowed to edit after submit
-			pr.save()
+			doc.save()
 
 			# update latest valuation rate in serial no
-			self.update_rate_in_serial_no(pr)
+			self.update_rate_in_serial_no(doc)
 
 			# update stock & gl entries for cancelled state of PR
-			pr.docstatus = 2
-			pr.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
-			pr.make_gl_entries_on_cancel()
+			doc.docstatus = 2
+			doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
+			doc.make_gl_entries_on_cancel()
 
 
 			# update stock & gl entries for submit state of PR
-			pr.docstatus = 1
-			pr.update_stock_ledger(via_landed_cost_voucher=True)
-			pr.make_gl_entries()
+			doc.docstatus = 1
+			doc.update_stock_ledger(via_landed_cost_voucher=True)
+			doc.make_gl_entries()
 
-	def update_rate_in_serial_no(self, purchase_receipt):
-		for item in purchase_receipt.get("items"):
+	def update_rate_in_serial_no(self, receipt_document):
+		for item in receipt_document.get("items"):
 			if item.serial_no:
 				serial_nos = get_serial_nos(item.serial_no)
 				if serial_nos:
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 7f190d2..c58607f 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -7,7 +7,7 @@
 import frappe
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
 	import set_perpetual_inventory, get_gl_entries, test_records as pr_test_records
-
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
 
 class TestLandedCostVoucher(unittest.TestCase):
 	def test_landed_cost_voucher(self):
@@ -21,10 +21,9 @@
 				"item_code": "_Test Item",
 				"warehouse": "_Test Warehouse - _TC"
 			},
-			fieldname=["qty_after_transaction", "stock_value"],
-			as_dict=1)
+			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
-		self.submit_landed_cost_voucher(pr)
+		self.submit_landed_cost_voucher("Purchase Receipt", pr.name)
 
 		pr_lc_value = frappe.db.get_value("Purchase Receipt Item", {"parent": pr.name}, "landed_cost_voucher_amount")
 		self.assertEquals(pr_lc_value, 25.0)
@@ -35,8 +34,7 @@
 				"item_code": "_Test Item",
 				"warehouse": "_Test Warehouse - _TC"
 			},
-			fieldname=["qty_after_transaction", "stock_value"],
-			as_dict=1)
+			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
 		self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction)
 
@@ -62,7 +60,56 @@
 			self.assertEquals(expected_values[gle.account][1], gle.credit)
 
 		set_perpetual_inventory(0)
+		
+	def test_landed_cost_voucher_against_purchase_invoice(self):
+		set_perpetual_inventory(1)
+		
+		pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
+			posting_time=frappe.utils.nowtime())
 
+		last_sle = frappe.db.get_value("Stock Ledger Entry", {
+				"voucher_type": pi.doctype,
+				"voucher_no": pi.name,
+				"item_code": "_Test Item",
+				"warehouse": "_Test Warehouse - _TC"
+			},
+			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
+
+		self.submit_landed_cost_voucher("Purchase Invoice", pi.name)
+		
+		pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name}, 
+			"landed_cost_voucher_amount")
+			
+		self.assertEquals(pi_lc_value, 50.0)
+
+		last_sle_after_landed_cost = frappe.db.get_value("Stock Ledger Entry", {
+				"voucher_type": pi.doctype,
+				"voucher_no": pi.name,
+				"item_code": "_Test Item",
+				"warehouse": "_Test Warehouse - _TC"
+			},
+			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
+
+		self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction)
+
+		self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 50.0)
+
+		gl_entries = get_gl_entries("Purchase Invoice", pi.name)
+
+		self.assertTrue(gl_entries)
+
+		expected_values = {
+			pi.get("items")[0].warehouse: [300.0, 0.0],
+			"Creditors - _TC": [0.0, 250.0],
+			"Expenses Included In Valuation - _TC": [0.0, 50.0]
+		}
+
+		for gle in gl_entries:
+			self.assertEquals(expected_values[gle.account][0], gle.debit)
+			self.assertEquals(expected_values[gle.account][1], gle.credit)
+
+		set_perpetual_inventory(0)
+		
 	def test_landed_cost_voucher_for_serialized_item(self):
 		set_perpetual_inventory(1)
 		frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')")
@@ -74,7 +121,7 @@
 
 		serial_no_rate = frappe.db.get_value("Serial No", "SN001", "purchase_rate")
 
-		self.submit_landed_cost_voucher(pr)
+		self.submit_landed_cost_voucher("Purchase Receipt", pr.name)
 
 		serial_no = frappe.db.get_value("Serial No", "SN001",
 			["warehouse", "purchase_rate"], as_dict=1)
@@ -84,19 +131,23 @@
 
 		set_perpetual_inventory(0)
 
-	def submit_landed_cost_voucher(self, pr):
+	def submit_landed_cost_voucher(self, receipt_document_type, receipt_document):
+		ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
+		
 		lcv = frappe.new_doc("Landed Cost Voucher")
 		lcv.company = "_Test Company"
 		lcv.set("purchase_receipts", [{
-			"purchase_receipt": pr.name,
-			"supplier": pr.supplier,
-			"posting_date": pr.posting_date,
-			"grand_total": pr.base_grand_total
+			"receipt_document_type": receipt_document_type,
+			"receipt_document": receipt_document,
+			"supplier": ref_doc.supplier,
+			"posting_date": ref_doc.posting_date,
+			"grand_total": ref_doc.base_grand_total
 		}])
+		
 		lcv.set("taxes", [{
 			"description": "Insurance Charges",
 			"account": "_Test Account Insurance Charges - _TC",
-			"amount": 50.0
+			"amount": 50
 		}])
 
 		lcv.insert()
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 2a7629e..9b9581b 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -21,10 +21,23 @@
 				"batch_no": doc.batch_no
 			}
 		}
+
+		$.each(["warehouse", "rejected_warehouse"], function(i, field) {
+			frm.set_query(field, "items", function() {
+				return {
+					filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+				}
+			})
+		})
+		
+		frm.set_query("supplier_warehouse", function() {
+			return {
+				filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+			}
+		})
 	}
 });
 
-
 erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({
 	refresh: function() {
 		this._super();
@@ -76,48 +89,6 @@
 		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
 	},
 
-	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);
-	},
-
 	make_purchase_invoice: function() {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
@@ -132,10 +103,6 @@
 		})
 	},
 
-	tc_name: function() {
-		this.get_terms();
-	},
-
 	close_purchase_receipt: function() {
 		cur_frm.cscript.update_status("Closed");
 	},
@@ -242,8 +209,6 @@
 		cur_frm.email_doc(frappe.boot.notification_settings.purchase_receipt_message);
 }
 
-
-
 frappe.provide("erpnext.buying");
 
 frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 8ee6de9..1babf2e 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 
-from frappe.utils import cstr, flt, cint
+from frappe.utils import flt, cint
 
 from frappe import _
 import frappe.defaults
@@ -52,62 +52,13 @@
 		self.set_status()
 		self.po_required()
 		self.validate_with_previous_doc()
-		self.validate_purchase_return()
-		self.validate_rejected_warehouse()
-		self.validate_accepted_rejected_qty()
 		self.validate_inspection()
 		self.validate_uom_is_integer("uom", ["qty", "received_qty"])
 		self.validate_uom_is_integer("stock_uom", "stock_qty")
 
 		pc_obj = frappe.get_doc('Purchase Common')
-		pc_obj.validate_for_items(self)
 		self.check_for_closed_status(pc_obj)
 
-		# sub-contracting
-		self.validate_for_subcontracting()
-		self.create_raw_materials_supplied("supplied_items")
-		self.set_landed_cost_voucher_amount()
-		self.update_valuation_rate("items")
-
-
-	def set_landed_cost_voucher_amount(self):
-		for d in self.get("items"):
-			lc_voucher_amount = frappe.db.sql("""select sum(applicable_charges)
-				from `tabLanded Cost Item`
-				where docstatus = 1 and purchase_receipt_item = %s""", d.name)
-			d.landed_cost_voucher_amount = lc_voucher_amount[0][0] if lc_voucher_amount else 0.0
-
-	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 validate_with_previous_doc(self):
 		super(PurchaseReceipt, self).validate_with_previous_doc({
 			"Purchase Order": {
@@ -130,59 +81,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"):
-			if d.prevdoc_doctype and d.prevdoc_doctype == "Purchase Order" and d.prevdoc_detail_docname:
-				po_map.setdefault(d.prevdoc_docname, []).append(d.prevdoc_detail_docname)
-
-		for po, po_item_rows in po_map.items():
-			if po and po_item_rows:
-				po_obj = frappe.get_doc("Purchase Order", po)
-
-				if po_obj.status in ["Closed", "Cancelled"]:
-					frappe.throw(_("{0} {1} is cancelled or closed").format(_("Purchase Order"), po),
-						frappe.InvalidStatusError)
-
-				po_obj.update_ordered_qty(po_item_rows)
-
 	def get_already_received_qty(self, po, po_detail):
 		qty = frappe.db.sql("""select sum(qty) from `tabPurchase Receipt Item`
 			where prevdoc_detail_docname = %s and docstatus = 1
@@ -195,16 +93,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:
@@ -225,19 +113,20 @@
 		purchase_controller = frappe.get_doc("Purchase Common")
 
 		# Check for Approving Authority
-		frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.base_grand_total)
+		frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, 
+			self.company, self.base_grand_total)
 
 		# Set status as Submitted
 		frappe.db.set(self, 'status', 'Submitted')
 
 		self.update_prevdoc_status()
-		self.update_ordered_qty()
-
 		self.update_billing_status()
 
 		if not self.is_return:
 			purchase_controller.update_last_purchase_rate(self, 1)
 
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating ordered qty in bin depends upon updated ordered qty in PO
 		self.update_stock_ledger()
 
 		from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
@@ -267,17 +156,15 @@
 
 		frappe.db.set(self,'status','Cancelled')
 
-		self.update_stock_ledger()
-
-		self.update_prevdoc_status()
-		# Must be called after updating received qty in PO
-		self.update_ordered_qty()
-
+		self.update_prevdoc_status()		
 		self.update_billing_status()
 
 		if not self.is_return:
 			pc_obj.update_last_purchase_rate(self, 0)
-
+		
+		# Updating stock ledger should always be called after updating prevdoc status, 
+		# because updating ordered qty in bin depends upon updated ordered qty in PO
+		self.update_stock_ledger()
 		self.make_gl_entries_on_cancel()
 
 	def get_current_stock(self):
@@ -352,13 +239,11 @@
 						}, warehouse_account[self.supplier_warehouse]["account_currency"]))
 
 					# divisional loss adjustment
-					sle_valuation_amount = flt(flt(d.valuation_rate, val_rate_db_precision) * flt(d.qty) * flt(d.conversion_factor),
-							self.precision("base_net_amount", d))
-
-					distributed_amount = flt(flt(d.base_net_amount, self.precision("base_net_amount", d))) + \
+					distributed_amount = flt(flt(d.base_net_amount, d.precision("base_net_amount"))) + \
 						flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount)
 
-					divisional_loss = flt(distributed_amount - sle_valuation_amount, self.precision("base_net_amount", d))
+					divisional_loss = flt(distributed_amount - stock_value_diff, 
+						d.precision("base_net_amount"))
 					if divisional_loss:
 						gl_entries.append(self.get_gl_dict({
 							"account": stock_rbnb,