Incoming rate fixes (#11986)

diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 75704b0..0cd5a07 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -185,7 +185,10 @@
 							'batch_no': cstr(p.batch_no).strip(),
 							'serial_no': cstr(p.serial_no).strip(),
 							'name': d.name,
-							'target_warehouse': p.target_warehouse
+							'target_warehouse': p.target_warehouse,
+							'company': self.company,
+							'voucher_type': self.doctype,
+							'allow_zero_valuation': d.allow_zero_valuation_rate
 						}))
 			else:
 				il.append(frappe._dict({
@@ -198,7 +201,10 @@
 					'batch_no': cstr(d.get("batch_no")).strip(),
 					'serial_no': cstr(d.get("serial_no")).strip(),
 					'name': d.name,
-					'target_warehouse': d.target_warehouse
+					'target_warehouse': d.target_warehouse,
+					'company': self.company,
+					'voucher_type': self.doctype,
+					'allow_zero_valuation': d.allow_zero_valuation_rate
 				}))
 		return il
 
@@ -293,7 +299,11 @@
 								"posting_date": self.posting_date,
 								"posting_time": self.posting_time,
 								"qty": -1*flt(d.qty),
-								"serial_no": d.serial_no
+								"serial_no": d.serial_no,
+								"company": d.company,
+								"voucher_type": d.voucher_type,
+								"voucher_no": d.name,
+								"allow_zero_valuation": d.allow_zero_valuation
 							})
 							target_warehouse_sle.update({
 								"incoming_rate": get_incoming_rate(args)
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index a97a24f..428e366 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -426,7 +426,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "depends_on": "eval:(doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no)", 
+   "depends_on": "is_stock_item", 
    "fieldname": "valuation_rate", 
    "fieldtype": "Currency", 
    "hidden": 0, 
@@ -3453,7 +3453,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 1, 
- "modified": "2017-12-08 07:20:25.932499", 
+ "modified": "2017-12-13 07:20:25.932499", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item", 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 40fc44d..79afb21 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -127,7 +127,7 @@
 		}
 	},
 
-	set_serial_no: function(frm, cdt, cdn) {
+	set_serial_no: function(frm, cdt, cdn, callback) {
 		var d = frappe.model.get_doc(cdt, cdn);
 		if(!d.item_code && !d.s_warehouse && !d.qty) return;
 		var	args = {
@@ -142,6 +142,10 @@
 				if (!r.exe){
 					frappe.model.set_value(cdt, cdn, "serial_no", r.message);
 				}
+
+				if (callback) {
+					callback();
+				}
 			}
 		});
 	},
@@ -170,7 +174,7 @@
 		frm.fields_dict["items"].grid.set_column_disp(["cost_center", "expense_account"], enabled);
 	},
 
-	set_basic_rate: function(frm, cdt, cdn, callback) {
+	set_basic_rate: function(frm, cdt, cdn) {
 		const item = locals[cdt][cdn];
 		item.transfer_qty = flt(item.qty) * flt(item.conversion_factor);
 
@@ -179,9 +183,12 @@
 			'posting_date'		: frm.doc.posting_date,
 			'posting_time'		: frm.doc.posting_time,
 			'warehouse'			: cstr(item.s_warehouse) || cstr(item.t_warehouse),
-			'serial_no	'		: item.serial_no,
+			'serial_no'			: item.serial_no,
 			'company'			: frm.doc.company,
-			'qty'				: item.s_warehouse ? -1*flt(item.transfer_qty) : flt(item.transfer_qty)
+			'qty'				: item.s_warehouse ? -1*flt(item.transfer_qty) : flt(item.transfer_qty),
+			'voucher_type'		: frm.doc.doctype,
+			'voucher_no'		: item.name,
+			'allow_zero_valuation': 1,
 		};
 
 		frappe.call({
@@ -190,17 +197,13 @@
 				args: args
 			},
 			callback: function(r) {
-				frappe.model.set_value(cdt, cdn, 'basic_rate', r.message);
+				frappe.model.set_value(cdt, cdn, 'basic_rate', (r.message || 0.0));
 				frm.events.calculate_basic_amount(frm, item);
-
-				if (callback) {
-					callback();
-				}
 			}
 		})
 	},
 
-	get_warehouse_details: function(frm, cdt, cdn, callback) {
+	get_warehouse_details: function(frm, cdt, cdn) {
 		var child = locals[cdt][cdn];
 		if(!child.bom_no) {
 			frappe.call({
@@ -213,7 +216,11 @@
 						'serial_no': child.serial_no,
 						'qty': child.s_warehouse ? -1* child.transfer_qty : child.transfer_qty,
 						'posting_date': frm.doc.posting_date,
-						'posting_time': frm.doc.posting_time
+						'posting_time': frm.doc.posting_time,
+						'company': frm.doc.company,
+						'voucher_type': frm.doc.doctype,
+						'voucher_no': child.name,
+						'allow_zero_valuation': 1
 					}
 				},
 				callback: function(r) {
@@ -221,10 +228,6 @@
 						$.extend(child, r.message);
 						frm.events.calculate_basic_amount(frm, child);
 					}
-
-					if (callback) {
-						callback();
-					}
 				}
 			});
 		}
@@ -276,8 +279,8 @@
 
 frappe.ui.form.on('Stock Entry Detail', {
 	qty: function(frm, cdt, cdn) {
-		frm.events.set_basic_rate(frm, cdt, cdn, () => {
-			frm.events.set_serial_no(frm, cdt, cdn);
+		frm.events.set_serial_no(frm, cdt, cdn, () => {
+			frm.events.set_basic_rate(frm, cdt, cdn);
 		});
 	},
 
@@ -286,8 +289,8 @@
 	},
 
 	s_warehouse: function(frm, cdt, cdn) {
-		frm.events.get_warehouse_details(frm, cdt, cdn, () => {
-			frm.events.set_serial_no(frm, cdt, cdn);
+		frm.events.set_serial_no(frm, cdt, cdn, () => {
+			frm.events.get_warehouse_details(frm, cdt, cdn);
 		});
 	},
 
@@ -342,11 +345,14 @@
 				'warehouse'			: cstr(d.s_warehouse) || cstr(d.t_warehouse),
 				'transfer_qty'		: d.transfer_qty,
 				'serial_no'		: d.serial_no,
-				'bom_no'			: d.bom_no,
+				'bom_no'		: d.bom_no,
 				'expense_account'	: d.expense_account,
 				'cost_center'		: d.cost_center,
-				'company'			: frm.doc.company,
-				'qty'				: d.qty
+				'company'		: frm.doc.company,
+				'qty'			: d.qty,
+				'voucher_type'		: frm.doc.doctype,
+				'voucher_no'		: d.name,
+				'allow_zero_valuation': 1,
 			};
 			return frappe.call({
 				doc: frm.doc,
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 4e87011..8eb2bd2 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -2,12 +2,12 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 import frappe.defaults
 from frappe import _
 from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate, format_time
 from erpnext.stock.utils import get_incoming_rate
-from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
+from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate
 from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
 from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
@@ -55,6 +55,7 @@
 		else:
 			set_batch_nos(self, 's_warehouse')
 
+		self.set_incoming_rate()
 		self.set_actual_qty()
 		self.calculate_rate_and_amount(update_finished_item_rate=False)
 
@@ -213,6 +214,18 @@
 				frappe.throw(_("Stock Entries already created for Production Order ")
 					+ self.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError)
 
+	def set_incoming_rate(self):
+		for d in self.items:
+			if d.s_warehouse:
+				args = self.get_args_for_incoming_rate(d)
+				d.basic_rate = get_incoming_rate(args)
+			elif d.allow_zero_valuation_rate and not d.s_warehouse:
+				d.basic_rate = 0.0
+			elif d.t_warehouse and not d.basic_rate:
+				d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse,
+					self.doctype, d.name, d.allow_zero_valuation_rate,
+					currency=erpnext.get_company_currency(self.company))
+
 	def set_actual_qty(self):
 		allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
 
@@ -268,14 +281,7 @@
 
 		for d in self.get('items'):
 			if d.t_warehouse: fg_basic_rate = flt(d.basic_rate)
-			args = frappe._dict({
-				"item_code": d.item_code,
-				"warehouse": d.s_warehouse or d.t_warehouse,
-				"posting_date": self.posting_date,
-				"posting_time": self.posting_time,
-				"qty": d.s_warehouse and -1*flt(d.transfer_qty) or flt(d.transfer_qty),
-				"serial_no": d.serial_no,
-			})
+			args = self.get_args_for_incoming_rate(d)
 
 			# get basic rate
 			if not d.bom_no:
@@ -304,6 +310,20 @@
 		if (fg_basic_rate == 0.0 and number_of_fg_items == 1) or update_finished_item_rate:
 			self.set_basic_rate_for_finished_goods(raw_material_cost, scrap_material_cost)
 
+	def get_args_for_incoming_rate(self, item):
+		return frappe._dict({
+			"item_code": item.item_code,
+			"warehouse": item.s_warehouse or item.t_warehouse,
+			"posting_date": self.posting_date,
+			"posting_time": self.posting_time,
+			"qty": item.s_warehouse and -1*flt(item.transfer_qty) or flt(item.transfer_qty),
+			"serial_no": item.serial_no,
+			"voucher_type": self.doctype,
+			"voucher_no": item.name,
+			"company": self.company,
+			"allow_zero_valuation": item.allow_zero_valuation_rate,
+		})
+
 	def set_basic_rate_for_finished_goods(self, raw_material_cost, scrap_material_cost):
 		if self.purpose in ["Manufacture", "Repack"]:
 			for d in self.get("items"):
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 6f09144..ae71f35 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -2,7 +2,7 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 from frappe import _
 import json
 from frappe.utils import flt, cstr, nowdate, nowtime
@@ -125,8 +125,7 @@
 @frappe.whitelist()
 def get_incoming_rate(args):
 	"""Get Incoming Rate based on valuation method"""
-	from erpnext.stock.stock_ledger import get_previous_sle
-
+	from erpnext.stock.stock_ledger import get_previous_sle, get_valuation_rate
 	if isinstance(args, basestring):
 		args = json.loads(args)
 
@@ -137,15 +136,19 @@
 		valuation_method = get_valuation_method(args.get("item_code"))
 		previous_sle = get_previous_sle(args)
 		if valuation_method == 'FIFO':
-			if not previous_sle:
-				return 0.0
-			previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]') or '[]')
-			in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0
-			if not in_rate and not previous_stock_queue:
-				in_rate = previous_sle.get('valuation_rate') or 0
+			if previous_sle:
+				previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]') or '[]')
+				in_rate = get_fifo_rate(previous_stock_queue, args.get("qty") or 0) if previous_stock_queue else 0
 		elif valuation_method == 'Moving Average':
 			in_rate = previous_sle.get('valuation_rate') or 0
 
+	if not in_rate:
+		voucher_no = args.get('voucher_no') or args.get('name')
+
+		in_rate = get_valuation_rate(args.get('item_code'), args.get('warehouse'),
+			args.get('voucher_type'), voucher_no, args.get('allow_zero_valuation'),
+			currency=erpnext.get_company_currency(args.get('company')))
+
 	return in_rate
 
 def get_avg_purchase_rate(serial_nos):