Merge remote-tracking branch 'frappe/v4.x.x' into develop

Conflicts:
	.travis.yml
	erpnext/__version__.py
	erpnext/controllers/queries.py
	erpnext/hooks.py
	erpnext/selling/sales_common.js
	erpnext/stock/doctype/bin/bin.py
	erpnext/stock/doctype/stock_entry/stock_entry.js
	erpnext/stock/doctype/stock_entry/stock_entry.py
	erpnext/stock/stock_ledger.py
	setup.py
diff --git a/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.json b/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.json
index e3a658e..42e37fd 100644
--- a/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.json
+++ b/erpnext/accounts/report/purchase_order_items_to_be_billed/purchase_order_items_to_be_billed.json
@@ -6,12 +6,12 @@
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "modified": "2014-06-03 07:18:17.244501", 
+ "modified": "2015-03-26 11:00:48.720037", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Order Items To Be Billed", 
  "owner": "Administrator", 
- "query": "select \n    `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n    `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t`tabPurchase Order Item`.billed_amt as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - ifnull(`tabPurchase Order Item`.billed_amt, 0)) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Order Item`.billed_amt, 0) < ifnull(`tabPurchase Order Item`.base_amount, 0)\norder by `tabPurchase Order`.transaction_date asc", 
+ "query": "select \n    `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n    `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t(`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1))) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1)) < ifnull(`tabPurchase Order Item`.base_amount, 0)\norder by `tabPurchase Order`.transaction_date asc", 
  "ref_doctype": "Purchase Invoice", 
  "report_name": "Purchase Order Items To Be Billed", 
  "report_type": "Query Report"
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 6e73778..ea1c4fe 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -5,6 +5,7 @@
 import frappe
 from frappe.desk.reportview import get_match_cond
 from frappe.model.db_query import DatabaseQuery
+from frappe.utils import nowdate
 
 def get_filters_cond(doctype, filters, conditions):
 	if filters:
@@ -154,8 +155,6 @@
 	return tax_accounts
 
 def item_query(doctype, txt, searchfield, start, page_len, filters):
-	from frappe.utils import nowdate
-
 	conditions = []
 
 	return frappe.db.sql("""select tabItem.name,
@@ -230,38 +229,45 @@
 			}, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) })
 
 def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
-	from erpnext.controllers.queries import get_match_cond
+	if not filters.get("posting_date"):
+		filters["posting_date"] = nowdate()
 
-	if filters.has_key('warehouse'):
-		return frappe.db.sql("""select batch_no, round(sum(actual_qty),2), stock_uom, expiry_date from `tabStock Ledger Entry` sle
-			    INNER JOIN `tabBatch`
-				on sle.batch_no = `tabBatch`.batch_id 
-				where item_code = '%(item_code)s'
-					and warehouse = '%(warehouse)s'
-					and batch_no like '%(txt)s'
-					and exists(select * from `tabBatch`
-							where name = sle.batch_no
-								and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
-								and docstatus != 2)
-					%(mcond)s
-				group by batch_no having sum(actual_qty) > 0
-				order by expiry_date,batch_no desc
-				limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'],
-					'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'],
-					'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
-					'start': start, 'page_len': page_len})
+	batch_nos = None
+	args = {
+		'item_code': filters.get("item_code"),
+		'warehouse': filters.get("warehouse"),
+		'posting_date': filters.get('posting_date'),
+		'txt': "%{0}%".format(txt),
+		"start": start,
+		"page_len": page_len
+	}
+
+	if args.get('warehouse'):
+		batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, batch.expiry_date
+				from `tabStock Ledger Entry` sle
+				    INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
+				where
+					sle.item_code = %(item_code)s
+					and sle.warehouse = %(warehouse)s
+					and sle.batch_no like %(txt)s
+					and batch.docstatus < 2
+					and (ifnull(batch.expiry_date, '')='' or batch.expiry_date >= %(posting_date)s)
+					{match_conditions}
+				group by batch_no having sum(sle.actual_qty) > 0
+				order by batch.expiry_date, sle.batch_no desc
+				limit %(start)s, %(page_len)s""".format(match_conditions=get_match_cond(doctype)), args)
+
+	if batch_nos:
+		return batch_nos
 	else:
-		return frappe.db.sql("""select name from tabBatch
-				where docstatus != 2
-					and item = '%(item_code)s'
-					and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
-					and name like '%(txt)s'
-					%(mcond)s
-				order by name desc
-				limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'],
-				'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
-				'mcond':get_match_cond(doctype),'start': start,
-				'page_len': page_len})
+		return frappe.db.sql("""select name, expiry_date from `tabBatch`
+			where item = %(item_code)s
+			and name like %(txt)s
+			and docstatus < 2
+			and (ifnull(batch.expiry_date, '')='' or batch.expiry_date >= %(posting_date)s)
+			{match_conditions}
+			order by expiry_date, name desc
+			limit %(start)s, %(page_len)s""".format(match_conditions=get_match_cond(doctype)), args)
 
 def get_account_list(doctype, txt, searchfield, start, page_len, filters):
 	filter_list = []
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 67a7cee..c640b8b 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -197,9 +197,10 @@
 		sl_dict.update(args)
 		return sl_dict
 
-	def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False):
+	def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False, 
+			via_landed_cost_voucher=False):
 		from erpnext.stock.stock_ledger import make_sl_entries
-		make_sl_entries(sl_entries, is_amended, allow_negative_stock)
+		make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
 
 	def make_gl_entries_on_cancel(self):
 		if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index f74ee7c..94fedcc 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -282,7 +282,8 @@
 	batch_no: function(doc, cdt, cdn) {
 		var me = this;
 		var item = frappe.get_doc(cdt, cdn);
-		if(item.item_code) {		
+
+		if(item.warehouse && item.item_code && item.batch_no) {
 		    return this.frm.call({
 		        method: "erpnext.stock.get_item_details.get_batch_qty",
 		        child: item,
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 4ee9328..2b1ac94 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -23,7 +23,7 @@
 			if (not getattr(self, f, None)) or (not self.get(f)):
 				self.set(f, 0.0)
 
-	def update_stock(self, args, allow_negative_stock=False):
+	def update_stock(self, args, allow_negative_stock=False, via_landed_cost_voucher=False):
 		self.update_qty(args)
 
 		if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation":
@@ -39,7 +39,7 @@
 				"posting_date": args.get("posting_date"),
 				"posting_time": args.get("posting_time"),
 				"voucher_no": args.get("voucher_no")
-			}, allow_negative_stock=allow_negative_stock)
+			}, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
 
 	def update_qty(self, args):
 		# update the stock values (for current quantities)
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 b37576a..733821d 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -6,6 +6,7 @@
 from frappe import _
 from frappe.utils import flt
 from frappe.model.document import Document
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
 
 class LandedCostVoucher(Document):
 	def get_items_from_purchase_receipts(self):
@@ -93,12 +94,24 @@
 			# as those fields are allowed to edit after submit
 			pr.save()
 
+			# update latest valuation rate in serial no
+			self.update_rate_in_serial_no(pr)
+
 			# update stock & gl entries for cancelled state of PR
 			pr.docstatus = 2
-			pr.update_stock_ledger(allow_negative_stock=True)
+			pr.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
 			pr.make_gl_entries_on_cancel()
 
+
 			# update stock & gl entries for submit state of PR
 			pr.docstatus = 1
-			pr.update_stock_ledger()
+			pr.update_stock_ledger(via_landed_cost_voucher=True)
 			pr.make_gl_entries()
+
+	def update_rate_in_serial_no(self, purchase_receipt):
+		for item in purchase_receipt.get("items"):
+			if item.serial_no:
+				serial_nos = get_serial_nos(item.serial_no)
+				if serial_nos:
+					frappe.db.sql("update `tabSerial No` set purchase_rate=%s where name in ({0})"
+						.format(", ".join(["%s"]*len(serial_nos))), tuple([item.valuation_rate] + serial_nos))
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 791e15e..d978116 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -183,6 +183,7 @@
 def update_item(obj, target, source_parent):
 	target.conversion_factor = 1
 	target.qty = flt(obj.qty) - flt(obj.ordered_qty)
+	target.stock_qty = target.qty
 
 @frappe.whitelist()
 def make_purchase_order(source_name, target_doc=None):
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 5c54d68..e785041 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -126,7 +126,7 @@
 				 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):
+	def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
 		sl_entries = []
 		stock_items = self.get_stock_items()
 
@@ -151,7 +151,8 @@
 					}))
 
 		self.bk_flush_supp_wh(sl_entries)
-		self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
+		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 = {}
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index b630f64..c7c7aaa 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -132,7 +132,7 @@
 		var me = this;
 		if(!this.frm.doc.fg_completed_qty || !this.frm.doc.bom_no)
 			frappe.throw(__("BOM and Manufacturing Quantity are required"));
-		
+
 		if(this.frm.doc.production_order || this.frm.doc.bom_no) {
 			// if production order / bom is mentioned, get items
 			return this.frm.call({
@@ -393,18 +393,21 @@
 
 // Overloaded query for link batch_no
 cur_frm.fields_dict['items'].grid.get_field('batch_no').get_query = function(doc, cdt, cdn) {
-	var d = locals[cdt][cdn];
-	if(d.item_code) {
-		return{
-			query: "erpnext.stock.doctype.stock_entry.stock_entry.get_batch_no",
-			filters:{
-				'item_code'		: d.item_code,
-				's_warehouse'	: d.s_warehouse,
-				'posting_date'	: doc.posting_date
-			}
-		}
+	var item = locals[cdt][cdn];
+	if(!item.item_code) {
+		frappe.throw(__("Please enter Item Code to get batch no"));
 	} else {
-		msgprint(__("Please enter Item Code to get batch no"));
+		var filters = {
+			'item_code': item.item_code,
+			'posting_date': me.frm.doc.posting_date,
+		}
+
+		if(item.s_warehouse) filters["warehouse"] = item.s_warehouse
+
+		return {
+			query : "erpnext.controllers.queries.get_batch_no",
+			filters: filters
+		}
 	}
 }
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index e936582..bd2d945 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -289,8 +289,8 @@
 					incoming_rate = flt(self.get_incoming_rate(args), self.precision("incoming_rate", d))
 					if incoming_rate > 0:
 						d.incoming_rate = incoming_rate
-				
-				d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
+
+				d.amount = flt(flt(d.transfer_qty) * flt(d.incoming_rate), d.precision("amount"))
 				if not d.t_warehouse:
 					raw_material_cost += flt(d.amount)
 
@@ -386,7 +386,7 @@
 	def validate_return_reference_doc(self):
 		"""validate item with reference doc"""
 		ref = get_return_doc_and_details(self)
-		
+
 		if ref.doc:
 			# validate docstatus
 			if ref.doc.docstatus != 1:
@@ -400,7 +400,7 @@
 			# posting date check
 			ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00")
 			this_posting_datetime = "%s %s" % (self.posting_date, self.posting_time)
-			
+
 			if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime):
 				from frappe.utils.dateutils import datetime_in_user_format
 				frappe.throw(_("Posting timestamp must be after {0}")
@@ -784,51 +784,6 @@
 
 	return result[start:start+page_len]
 
-def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
-	if not filters.get("posting_date"):
-		filters["posting_date"] = nowdate()
-
-	batch_nos = None
-	args = {
-		'item_code': filters.get("item_code"),
-		's_warehouse': filters.get('s_warehouse'),
-		'posting_date': filters.get('posting_date'),
-		'txt': "%%%s%%" % txt,
-		'mcond':get_match_cond(doctype),
-		"start": start,
-		"page_len": page_len
-	}
-
-	if filters.get("s_warehouse"):
-		batch_nos = frappe.db.sql("""select batch_no
-			from `tabStock Ledger Entry` sle
-			where item_code = '%(item_code)s'
-				and warehouse = '%(s_warehouse)s'
-				and batch_no like '%(txt)s'
-				and exists(select * from `tabBatch`
-					where name = sle.batch_no
-					and (ifnull(expiry_date, '2099-12-31') >= %(posting_date)s
-						or expiry_date = '')
-					and docstatus != 2)
-			%(mcond)s
-			group by batch_no having sum(actual_qty) > 0
-			order by batch_no desc
-			limit %(start)s, %(page_len)s """
-			% args)
-
-	if batch_nos:
-		return batch_nos
-	else:
-		return frappe.db.sql("""select name from `tabBatch`
-			where item = '%(item_code)s'
-			and docstatus < 2
-			and (ifnull(expiry_date, '2099-12-31') >= %(posting_date)s
-				or expiry_date = '' or expiry_date = "0000-00-00")
-			%(mcond)s
-			order by name desc
-			limit %(start)s, %(page_len)s
-		""" % args)
-
 def get_stock_items_for_return(ref_doc, parentfields):
 	"""return item codes filtered from doc, which are stock items"""
 	if isinstance(parentfields, basestring):
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 812c5df..1b3dc06 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -27,8 +27,9 @@
 		self.check_stock_frozen_date()
 		self.actual_amt_check()
 
-		from erpnext.stock.doctype.serial_no.serial_no import process_serial_no
-		process_serial_no(self)
+		if not self.get("via_landed_cost_voucher"):
+			from erpnext.stock.doctype.serial_no.serial_no import process_serial_no
+			process_serial_no(self)
 
 	#check for item quantity available in stock
 	def actual_amt_check(self):
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 8b2da79..e24f67a 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -305,13 +305,13 @@
 		}))
 
 def get_actual_batch_qty(batch_no,warehouse,item_code):
-        actual_batch_qty = 0
-        if batch_no:
-            actual_batch_qty = flt(frappe.db.sql("""select sum(actual_qty)
-				from `tabStock Ledger Entry`
-				where warehouse=%s and item_code=%s and batch_no=%s""",
-				(warehouse, item_code, batch_no))[0][0])
-        return actual_batch_qty
+	actual_batch_qty = 0
+	if batch_no:
+		actual_batch_qty = flt(frappe.db.sql("""select sum(actual_qty)
+			from `tabStock Ledger Entry`
+			where warehouse=%s and item_code=%s and batch_no=%s""",
+			(warehouse, item_code, batch_no))[0][0])
+	return actual_batch_qty
 
 @frappe.whitelist()
 def get_conversion_factor(item_code, uom):
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index a554f22..5bb2f0c 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -14,7 +14,7 @@
 _exceptions = frappe.local('stockledger_exceptions')
 # _exceptions = []
 
-def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False):
+def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False, via_landed_cost_voucher=False):
 	if sl_entries:
 		from erpnext.stock.utils import update_bin
 
@@ -28,14 +28,14 @@
 				sle['actual_qty'] = -flt(sle['actual_qty'])
 
 			if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
-				sle_id = make_entry(sle, allow_negative_stock)
+				sle_id = make_entry(sle, allow_negative_stock, via_landed_cost_voucher)
 
 			args = sle.copy()
 			args.update({
 				"sle_id": sle_id,
 				"is_amended": is_amended
 			})
-			update_bin(args, allow_negative_stock)
+			update_bin(args, allow_negative_stock, via_landed_cost_voucher)
 
 		if cancel:
 			delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
@@ -46,11 +46,12 @@
 		where voucher_no=%s and voucher_type=%s""",
 		(now(), frappe.session.user, voucher_type, voucher_no))
 
-def make_entry(args, allow_negative_stock=False):
+def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False):
 	args.update({"doctype": "Stock Ledger Entry"})
 	sle = frappe.get_doc(args)
 	sle.flags.ignore_permissions = 1
 	sle.allow_negative_stock=allow_negative_stock
+	sle.via_landed_cost_voucher = via_landed_cost_voucher
 	sle.insert()
 	sle.submit()
 	return sle.name
@@ -73,13 +74,14 @@
 				"posting_time": "12:00"
 			}
 	"""
-	def __init__(self, args, allow_zero_rate=False, allow_negative_stock=None, verbose=1):
+	def __init__(self, args, allow_zero_rate=False, allow_negative_stock=None, via_landed_cost_voucher=False, verbose=1):
 		from frappe.model.meta import get_field_precision
 
 		self.exceptions = []
 		self.verbose = verbose
 		self.allow_zero_rate = allow_zero_rate
 		self.allow_negative_stock = allow_negative_stock
+		self.via_landed_cost_voucher = via_landed_cost_voucher
 		if not self.allow_negative_stock:
 			self.allow_negative_stock = cint(frappe.db.get_single_value("Stock Settings",
 				"allow_negative_stock"))
@@ -141,7 +143,7 @@
 		bin_doc.save(ignore_permissions=True)
 
 	def process_sle(self, sle):
-		if sle.serial_no or not cint(self.allow_negative_stock):
+		if (sle.serial_no and not self.via_landed_cost_voucher) or not cint(self.allow_negative_stock):
 			# validate negative stock for serialized items, fifo valuation
 			# or when negative stock is not allowed for moving average
 			if not self.validate_negative_stock(sle):
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index c34ba40..1a9e828 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -79,11 +79,11 @@
 	bin_obj.flags.ignore_permissions = True
 	return bin_obj
 
-def update_bin(args, allow_negative_stock=False):
+def update_bin(args, allow_negative_stock=False, via_landed_cost_voucher=False):
 	is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
 	if is_stock_item == 'Yes':
 		bin = get_bin(args.get("item_code"), args.get("warehouse"))
-		bin.update_stock(args, allow_negative_stock)
+		bin.update_stock(args, allow_negative_stock, via_landed_cost_voucher)
 		return bin
 	else:
 		frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code")))