Merge pull request #2296 from nabinhait/stock_reco

Stock balance report and valuation fixes
diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py
index 7a4345e..04e45d4 100644
--- a/erpnext/config/stock.py
+++ b/erpnext/config/stock.py
@@ -142,10 +142,10 @@
 					"doctype": "Item",
 				},
 				{
-					"type": "page",
-					"name": "stock-balance",
-					"label": _("Stock Balance"),
-					"icon": "icon-table",
+					"type": "report",
+					"is_query_report": True,
+					"name": "Stock Balance",
+					"doctype": "Warehouse"
 				},
 				{
 					"type": "report",
@@ -170,13 +170,7 @@
 					"name": "stock-analytics",
 					"label": _("Stock Analytics"),
 					"icon": "icon-bar-chart"
-				},
-				{
-					"type": "report",
-					"is_query_report": True,
-					"name": "Warehouse-Wise Stock Balance",
-					"doctype": "Warehouse"
-				},
+				}
 			]
 		},
 		{
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 3d25c21..66d5792 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -269,7 +269,7 @@
 			# get raw materials rate
 			if self.doctype == "Purchase Receipt":
 				from erpnext.stock.utils import get_incoming_rate
-				rm.rate = get_incoming_rate({
+				item_rate = get_incoming_rate({
 					"item_code": bom_item.item_code,
 					"warehouse": self.supplier_warehouse,
 					"posting_date": self.posting_date,
@@ -277,6 +277,7 @@
 					"qty": -1 * required_qty,
 					"serial_no": rm.serial_no
 				})
+				rm.rate = item_rate or bom_item.rate
 			else:
 				rm.rate = bom_item.rate
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 20eb40c..ad553d8 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -305,9 +305,15 @@
 	last_valuation_rate = frappe.db.sql("""select valuation_rate
 		from `tabStock Ledger Entry`
 		where item_code = %s and warehouse = %s
-		and ifnull(qty_after_transaction, 0) > 0
+		and ifnull(valuation_rate, 0) > 0
 		order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse))
 
+	if not last_valuation_rate:
+		last_valuation_rate = frappe.db.sql("""select valuation_rate
+			from `tabStock Ledger Entry`
+			where item_code = %s and ifnull(valuation_rate, 0) > 0
+			order by posting_date desc, posting_time desc, name desc limit 1""", item_code)
+
 	valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
 
 	if not valuation_rate:
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 29049f7..bd2d436 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -81,4 +81,5 @@
 erpnext.patches.v4_2.set_company_country
 erpnext.patches.v4_2.update_sales_order_invoice_field_name
 erpnext.patches.v4_2.cost_of_production_cycle
-erpnext.patches.v4_2.seprate_manufacture_and_repack
\ No newline at end of file
+erpnext.patches.v4_2.seprate_manufacture_and_repack
+execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 51c85ce..67f621a 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -95,7 +95,7 @@
 		pr.insert()
 
 		self.assertEquals(len(pr.get("pr_raw_material_details")), 2)
-		self.assertEquals(pr.get("purchase_receipt_details")[0].rm_supp_cost, 70000.0)
+		self.assertEquals(pr.get("purchase_receipt_details")[0].rm_supp_cost, 20750.0)
 
 
 	def test_serial_no_supplier(self):
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 038606c..e010bd1 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -9,14 +9,64 @@
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
 from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError
 
+def get_sle(**args):
+	condition, values = "", []
+	for key, value in args.iteritems():
+		condition += " and " if condition else " where "
+		condition += "`{0}`=%s".format(key)
+		values.append(value)
+
+	return frappe.db.sql("""select * from `tabStock Ledger Entry` %s
+		order by timestamp(posting_date, posting_time) desc, name desc limit 1"""% condition,
+		values, as_dict=1)
+
+def make_zero(item_code, warehouse):
+	sle = get_sle(item_code = item_code, warehouse = warehouse)
+	qty = sle[0].qty_after_transaction if sle else 0
+	if qty < 0:
+		make_stock_entry(item_code, None, warehouse, abs(qty), incoming_rate=10)
+	elif qty > 0:
+		make_stock_entry(item_code, warehouse, None, qty, incoming_rate=10)
+
 class TestStockEntry(unittest.TestCase):
-	
 	def tearDown(self):
 		frappe.set_user("Administrator")
 		set_perpetual_inventory(0)
 		if hasattr(self, "old_default_company"):
 			frappe.db.set_default("company", self.old_default_company)
 
+	def test_fifo(self):
+		frappe.db.set_default("allow_negative_stock", 1)
+		item_code = "_Test Item 2"
+		warehouse = "_Test Warehouse - _TC"
+		make_zero(item_code, warehouse)
+
+		make_stock_entry(item_code, None, warehouse, 1, incoming_rate=10)
+		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
+
+		self.assertEqual([[1, 10]], eval(sle.stock_queue))
+
+		# negative qty
+		make_zero(item_code, warehouse)
+		make_stock_entry(item_code, warehouse, None, 1, incoming_rate=10)
+		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
+
+		self.assertEqual([[-1, 10]], eval(sle.stock_queue))
+
+		# further negative
+		make_stock_entry(item_code, warehouse, None, 1)
+		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
+
+		self.assertEqual([[-2, 10]], eval(sle.stock_queue))
+
+		# move stock to positive
+		make_stock_entry(item_code, None, warehouse, 3, incoming_rate=10)
+		sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
+
+		self.assertEqual([[1, 10]], eval(sle.stock_queue))
+
+		frappe.db.set_default("allow_negative_stock", 0)
+
 	def test_auto_material_request(self):
 		frappe.db.sql("""delete from `tabMaterial Request Item`""")
 		frappe.db.sql("""delete from `tabMaterial Request`""")
@@ -821,19 +871,19 @@
 		se = frappe.copy_doc(test_records[0]).insert()
 		self.assertRaises (StockFreezeError, se.submit)
 		frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0)
-		
+
 	def test_production_order(self):
-		bom_no = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", 
+		bom_no = frappe.db.get_value("BOM", {"item": "_Test FG Item 2",
 			"is_default": 1, "docstatus": 1})
-		
+
 		production_order = frappe.new_doc("Production Order")
 		production_order.update({
 			"company": "_Test Company",
-			"fg_warehouse": "_Test Warehouse 1 - _TC", 
-			"production_item": "_Test FG Item 2", 
+			"fg_warehouse": "_Test Warehouse 1 - _TC",
+			"production_item": "_Test FG Item 2",
 			"bom_no": bom_no,
 			"qty": 1.0,
-			"stock_uom": "Nos", 
+			"stock_uom": "Nos",
 			"wip_warehouse": "_Test Warehouse - _TC"
 		})
 		production_order.insert()
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 183e3e5..91775d9 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -28,7 +28,7 @@
 			[20, "", "2012-12-26", "12:05", 16000, 15, 18000],
 			[10, 2000, "2012-12-26", "12:10", 20000, 5, 6000],
 			[1, 1000, "2012-12-01", "00:00", 1000, 11, 13200],
-			[0, "", "2012-12-26", "12:10", 0, -5, 0]
+			[0, "", "2012-12-26", "12:10", 0, -5, -6000]
 		]
 
 		for d in input_data:
@@ -63,16 +63,16 @@
 		input_data = [
 			[50, 1000, "2012-12-26", "12:00", 50000, 45, 48000],
 			[5, 1000, "2012-12-26", "12:00", 5000, 0, 0],
-			[15, 1000, "2012-12-26", "12:00", 15000, 10, 12000],
+			[15, 1000, "2012-12-26", "12:00", 15000, 10, 11500],
 			[25, 900, "2012-12-26", "12:00", 22500, 20, 22500],
 			[20, 500, "2012-12-26", "12:00", 10000, 15, 18000],
 			[50, 1000, "2013-01-01", "12:00", 50000, 65, 68000],
 			[5, 1000, "2013-01-01", "12:00", 5000, 20, 23000],
-			["", 1000, "2012-12-26", "12:05", 15000, 10, 12000],
+			["", 1000, "2012-12-26", "12:05", 15000, 10, 11500],
 			[20, "", "2012-12-26", "12:05", 18000, 15, 18000],
-			[10, 2000, "2012-12-26", "12:10", 20000, 5, 6000],
-			[1, 1000, "2012-12-01", "00:00", 1000, 11, 13200],
-			[0, "", "2012-12-26", "12:10", 0, -5, 0]
+			[10, 2000, "2012-12-26", "12:10", 20000, 5, 7600],
+			[1, 1000, "2012-12-01", "00:00", 1000, 11, 12512.73],
+			[0, "", "2012-12-26", "12:10", 0, -5, -5142.86]
 
 		]
 
diff --git a/erpnext/stock/page/stock_balance/README.md b/erpnext/stock/page/stock_balance/README.md
deleted file mode 100644
index 6522aeb..0000000
--- a/erpnext/stock/page/stock_balance/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Stock balances on a particular day, per warehouse.
\ No newline at end of file
diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js
deleted file mode 100644
index ecd1108..0000000
--- a/erpnext/stock/page/stock_balance/stock_balance.js
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
-
-frappe.require("assets/erpnext/js/stock_analytics.js");
-
-frappe.pages['stock-balance'].onload = function(wrapper) {
-	frappe.ui.make_app_page({
-		parent: wrapper,
-		title: __('Stock Balance'),
-		single_column: true
-	});
-
-	new erpnext.StockBalance(wrapper);
-
-	wrapper.appframe.add_module_icon("Stock");
-}
-
-erpnext.StockBalance = erpnext.StockAnalytics.extend({
-	init: function(wrapper) {
-		this._super(wrapper, {
-			title: __("Stock Balance"),
-			doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand",
-				"Stock Entry", "Project", "Serial No"],
-		});
-	},
-	setup_columns: function() {
-		this.columns = [
-			{id: "name", name: __("Item"), field: "name", width: 300,
-				formatter: this.tree_formatter},
-			{id: "item_name", name: __("Item Name"), field: "item_name", width: 100},
-			{id: "description", name: __("Description"), field: "description", width: 200,
-				formatter: this.text_formatter},
-			{id: "brand", name: __("Brand"), field: "brand", width: 100},
-			{id: "stock_uom", name: __("UOM"), field: "stock_uom", width: 100},
-			{id: "opening_qty", name: __("Opening Qty"), field: "opening_qty", width: 100,
-				formatter: this.currency_formatter},
-			{id: "inflow_qty", name: __("In Qty"), field: "inflow_qty", width: 100,
-				formatter: this.currency_formatter},
-			{id: "outflow_qty", name: __("Out Qty"), field: "outflow_qty", width: 100,
-				formatter: this.currency_formatter},
-			{id: "closing_qty", name: __("Closing Qty"), field: "closing_qty", width: 100,
-				formatter: this.currency_formatter},
-
-			{id: "opening_value", name: __("Opening Value"), field: "opening_value", width: 100,
-				formatter: this.currency_formatter},
-			{id: "inflow_value", name: __("In Value"), field: "inflow_value", width: 100,
-				formatter: this.currency_formatter},
-			{id: "outflow_value", name: __("Out Value"), field: "outflow_value", width: 100,
-				formatter: this.currency_formatter},
-			{id: "closing_value", name: __("Closing Value"), field: "closing_value", width: 100,
-				formatter: this.currency_formatter},
-			{id: "valuation_rate", name: __("Valuation Rate"), field: "valuation_rate", width: 100,
-				formatter: this.currency_formatter},
-		];
-	},
-
-	filters: [
-		{fieldtype:"Select", label: __("Brand"), link:"Brand", fieldname: "brand",
-			default_value: __("Select Brand..."), filter: function(val, item, opts) {
-				return val == opts.default_value || item.brand == val || item._show;
-			}, link_formatter: {filter_input: "brand"}},
-		{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse", fieldname: "warehouse",
-			default_value: __("Select Warehouse..."), filter: function(val, item, opts, me) {
-				return me.apply_zero_filter(val, item, opts, me);
-			}},
-		{fieldtype:"Select", label: __("Project"), link:"Project", fieldname: "project",
-			default_value: __("Select Project..."), filter: function(val, item, opts, me) {
-				return me.apply_zero_filter(val, item, opts, me);
-			}, link_formatter: {filter_input: "project"}},
-		{fieldtype:"Date", label: __("From Date"), fieldname: "from_date"},
-		{fieldtype:"Label", label: __("To")},
-		{fieldtype:"Date", label: __("To Date"), fieldname: "to_date"},
-		{fieldtype:"Button", label: __("Refresh"), icon:"icon-refresh icon-white"},
-		{fieldtype:"Button", label: __("Reset Filters"), icon: "icon-filter"}
-	],
-
-	setup_plot_check: function() {
-		return;
-	},
-
-	prepare_data: function() {
-		this.stock_entry_map = this.make_name_map(frappe.report_dump.data["Stock Entry"], "name");
-		this._super();
-	},
-
-	prepare_balances: function() {
-		var me = this;
-		var from_date = dateutil.str_to_obj(this.from_date);
-		var to_date = dateutil.str_to_obj(this.to_date);
-		var data = frappe.report_dump.data["Stock Ledger Entry"];
-
-		this.item_warehouse = {};
-		this.serialized_buying_rates = this.get_serialized_buying_rates();
-
-		for(var i=0, j=data.length; i<j; i++) {
-			var sl = data[i];
-			var sl_posting_date = dateutil.str_to_obj(sl.posting_date);
-
-			if((me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) &&
-				(me.is_default("project") ? true : me.project == sl.project)) {
-				var item = me.item_by_name[sl.item_code];
-				var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
-				var valuation_method = item.valuation_method ?
-					item.valuation_method : sys_defaults.valuation_method;
-				var is_fifo = valuation_method == "FIFO";
-
-				if(sl.voucher_type=="Stock Reconciliation") {
-					var qty_diff = sl.qty_after_transaction - (item.temp_closing_qty || 0.0);
-					var value_diff = (sl.valuation_rate * sl.qty_after_transaction) - (item.temp_closing_value || 0.0);
-					wh.fifo_stack.push([sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]);
-					wh.balance_qty = sl.qty_after_transaction;
-					wh.balance_value = sl.valuation_rate * sl.qty_after_transaction;
-				} else {
-					var qty_diff = sl.qty;
-					var value_diff = me.get_value_diff(wh, sl, is_fifo);
-				}
-				item.temp_closing_qty += qty_diff;
-				item.temp_closing_value += value_diff;
-
-				if(sl_posting_date < from_date) {
-					item.opening_qty += qty_diff;
-					item.opening_value += value_diff;
-				} else if(sl_posting_date <= to_date) {
-					var ignore_inflow_outflow = this.is_default("warehouse")
-						&& sl.voucher_type=="Stock Entry"
-						&& this.stock_entry_map[sl.voucher_no].purpose=="Material Transfer";
-
-					if(!ignore_inflow_outflow) {
-						if(qty_diff < 0) {
-							item.outflow_qty += Math.abs(qty_diff);
-						} else {
-							item.inflow_qty += qty_diff;
-						}
-						if(value_diff < 0) {
-							item.outflow_value += Math.abs(value_diff);
-						} else {
-							item.inflow_value += value_diff;
-						}
-
-						item.closing_qty += qty_diff;
-						item.closing_value += value_diff;
-					}
-
-				} else {
-					break;
-				}
-			}
-		}
-
-		// opening + diff = closing
-		// adding opening, since diff already added to closing
-		$.each(me.item_by_name, function(key, item) {
-			item.closing_qty += item.opening_qty;
-			item.closing_value += item.opening_value;
-
-			// valuation rate
-			if(!item.is_group && flt(item.closing_qty) > 0)
-				item.valuation_rate = flt(item.closing_value) / flt(item.closing_qty);
-			else item.valuation_rate = 0.0
-		});
-	},
-
-	update_groups: function() {
-		var me = this;
-
-		$.each(this.data, function(i, item) {
-			// update groups
-			if(!item.is_group && me.apply_filter(item, "brand")) {
-				var parent = me.parent_map[item.name];
-				while(parent) {
-					parent_group = me.item_by_name[parent];
-					$.each(me.columns, function(c, col) {
-						if (col.formatter == me.currency_formatter && col.field != "valuation_rate") {
-							parent_group[col.field] = flt(parent_group[col.field]) + flt(item[col.field]);
-						}
-					});
-
-					// show parent if filtered by brand
-					if(item.brand == me.brand)
-						parent_group._show = true;
-
-					parent = me.parent_map[parent];
-				}
-			}
-		});
-	},
-
-	get_plot_data: function() {
-		return;
-	}
-});
diff --git a/erpnext/stock/page/stock_balance/stock_balance.json b/erpnext/stock/page/stock_balance/stock_balance.json
deleted file mode 100644
index 6f25be4..0000000
--- a/erpnext/stock/page/stock_balance/stock_balance.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "creation": "2012-12-27 18:57:47.000000", 
- "docstatus": 0, 
- "doctype": "Page", 
- "icon": "icon-table", 
- "idx": 1, 
- "modified": "2013-07-11 14:44:15.000000", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "stock-balance", 
- "owner": "Administrator", 
- "page_name": "stock-balance", 
- "roles": [
-  {
-   "role": "Material Manager"
-  }, 
-  {
-   "role": "Analytics"
-  }
- ], 
- "standard": "Yes", 
- "title": "Stock Balance"
-}
\ No newline at end of file
diff --git a/erpnext/stock/page/stock_balance/__init__.py b/erpnext/stock/report/stock_balance/__init__.py
similarity index 100%
rename from erpnext/stock/page/stock_balance/__init__.py
rename to erpnext/stock/report/stock_balance/__init__.py
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/erpnext/stock/report/stock_balance/stock_balance.js
similarity index 74%
rename from erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
rename to erpnext/stock/report/stock_balance/stock_balance.js
index 2543fa4..c0aed51 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
+++ b/erpnext/stock/report/stock_balance/stock_balance.js
@@ -1,7 +1,7 @@
-// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-// License: GNU General Public License v3. See license.txt
+// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
+// For license information, please see license.txt
 
-frappe.query_reports["Warehouse-Wise Stock Balance"] = {
+frappe.query_reports["Stock Balance"] = {
 	"filters": [
 		{
 			"fieldname":"from_date",
@@ -18,4 +18,4 @@
 			"default": frappe.datetime.get_today()
 		}
 	]
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/report/stock_balance/stock_balance.json b/erpnext/stock/report/stock_balance/stock_balance.json
new file mode 100644
index 0000000..ab331dc
--- /dev/null
+++ b/erpnext/stock/report/stock_balance/stock_balance.json
@@ -0,0 +1,17 @@
+{
+ "add_total_row": 0, 
+ "apply_user_permissions": 1, 
+ "creation": "2014-10-10 17:58:11.577901", 
+ "disabled": 0, 
+ "docstatus": 0, 
+ "doctype": "Report", 
+ "is_standard": "Yes", 
+ "modified": "2014-10-10 17:58:11.577901", 
+ "modified_by": "Administrator", 
+ "module": "Stock", 
+ "name": "Stock Balance", 
+ "owner": "Administrator", 
+ "ref_doctype": "Stock Ledger Entry", 
+ "report_name": "Stock Balance", 
+ "report_type": "Script Report"
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
similarity index 79%
rename from erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
rename to erpnext/stock/report/stock_balance/stock_balance.py
index dc552cb..95de739 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -59,9 +59,9 @@
 def get_stock_ledger_entries(filters):
 	conditions = get_conditions(filters)
 	return frappe.db.sql("""select item_code, warehouse, posting_date,
-		actual_qty, valuation_rate, stock_uom, company
+		actual_qty, valuation_rate, stock_uom, company, voucher_type, qty_after_transaction
 		from `tabStock Ledger Entry`
-		where docstatus < 2 %s order by item_code, warehouse""" %
+		where docstatus < 2 %s order by posting_date, posting_time, name""" %
 		conditions, as_dict=1)
 
 def get_item_warehouse_map(filters):
@@ -80,21 +80,27 @@
 		qty_dict = iwb_map[d.company][d.item_code][d.warehouse]
 		qty_dict.uom = d.stock_uom
 
+		if d.voucher_type == "Stock Reconciliation":
+			qty_diff = flt(d.qty_after_transaction) - qty_dict.bal_qty
+			value_diff = flt(d.stock_value) - qty_dict.bal_val
+		else:
+			qty_diff = flt(d.actual_qty)
+			value_diff = flt(d.actual_qty) * flt(d.valuation_rate)
+
 		if d.posting_date < filters["from_date"]:
-			qty_dict.opening_qty += flt(d.actual_qty)
-			qty_dict.opening_val += flt(d.actual_qty) * flt(d.valuation_rate)
+			qty_dict.opening_qty += qty_diff
+			qty_dict.opening_val += value_diff
 		elif d.posting_date >= filters["from_date"] and d.posting_date <= filters["to_date"]:
 			qty_dict.val_rate = d.valuation_rate
-
-			if flt(d.actual_qty) > 0:
-				qty_dict.in_qty += flt(d.actual_qty)
-				qty_dict.in_val += flt(d.actual_qty) * flt(d.valuation_rate)
+			if qty_diff > 0:
+				qty_dict.in_qty += qty_diff
+				qty_dict.in_val += value_diff
 			else:
-				qty_dict.out_qty += abs(flt(d.actual_qty))
-				qty_dict.out_val += flt(abs(flt(d.actual_qty) * flt(d.valuation_rate)))
+				qty_dict.out_qty += abs(qty_diff)
+				qty_dict.out_val += abs(value_diff)
 
-		qty_dict.bal_qty += flt(d.actual_qty)
-		qty_dict.bal_val += flt(d.actual_qty) * flt(d.valuation_rate)
+		qty_dict.bal_qty += qty_diff
+		qty_dict.bal_val += value_diff
 
 	return iwb_map
 
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py b/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/stock/report/warehouse_wise_stock_balance/__init__.py
+++ /dev/null
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json
deleted file mode 100644
index f911956..0000000
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "apply_user_permissions": 1, 
- "creation": "2013-06-05 11:00:31", 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 1, 
- "is_standard": "Yes", 
- "modified": "2014-06-03 07:18:17.384923", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Warehouse-Wise Stock Balance", 
- "owner": "Administrator", 
- "ref_doctype": "Stock Ledger Entry", 
- "report_name": "Warehouse-Wise Stock Balance", 
- "report_type": "Script Report"
-}
\ No newline at end of file
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index e8a84c2..a2614d7 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -6,6 +6,7 @@
 from frappe import _
 from frappe.utils import cint, flt, cstr, now
 from erpnext.stock.utils import get_valuation_method
+from erpnext.controllers.stock_controller import get_valuation_rate
 import json
 
 # future reposting
@@ -110,14 +111,14 @@
 				else:
 					valuation_rate = get_fifo_values(qty_after_transaction, sle, stock_queue)
 
+
 				qty_after_transaction += flt(sle.actual_qty)
 
 		# get stock value
 		if sle.serial_no:
 			stock_value = qty_after_transaction * valuation_rate
 		elif valuation_method == "Moving Average":
-			stock_value = (qty_after_transaction > 0) and \
-				(qty_after_transaction * valuation_rate) or 0
+			stock_value = qty_after_transaction * valuation_rate
 		else:
 			stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
 
@@ -255,65 +256,72 @@
 	incoming_rate = flt(sle.incoming_rate)
 	actual_qty = flt(sle.actual_qty)
 
-	if not incoming_rate:
-		# In case of delivery/stock issue in_rate = 0 or wrong incoming rate
-		incoming_rate = valuation_rate
+	if flt(sle.actual_qty) > 0:
+		if qty_after_transaction < 0 and not valuation_rate:
+			# if negative stock, take current valuation rate as incoming rate
+			valuation_rate = incoming_rate
 
-	elif qty_after_transaction < 0:
-		# if negative stock, take current valuation rate as incoming rate
-		valuation_rate = incoming_rate
+		new_stock_qty = abs(qty_after_transaction) + actual_qty
+		new_stock_value = (abs(qty_after_transaction) * valuation_rate) + (actual_qty * incoming_rate)
 
-	new_stock_qty = qty_after_transaction + actual_qty
-	new_stock_value = qty_after_transaction * valuation_rate + actual_qty * incoming_rate
+		if new_stock_qty:
+			valuation_rate = new_stock_value / flt(new_stock_qty)
+	elif not valuation_rate:
+		valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse)
 
-	if new_stock_qty > 0 and new_stock_value > 0:
-		valuation_rate = new_stock_value / flt(new_stock_qty)
-	elif new_stock_qty <= 0:
-		valuation_rate = 0.0
-
-	# NOTE: val_rate is same as previous entry if new stock value is negative
-
-	return valuation_rate
+	return abs(valuation_rate)
 
 def get_fifo_values(qty_after_transaction, sle, stock_queue):
 	incoming_rate = flt(sle.incoming_rate)
 	actual_qty = flt(sle.actual_qty)
-	if not stock_queue:
-		stock_queue.append([0, 0])
+
+	intialize_stock_queue(stock_queue, sle.item_code, sle.warehouse)
 
 	if actual_qty > 0:
 		if stock_queue[-1][0] > 0:
 			stock_queue.append([actual_qty, incoming_rate])
 		else:
 			qty = stock_queue[-1][0] + actual_qty
-			stock_queue[-1] = [qty, qty > 0 and incoming_rate or 0]
+			if qty == 0:
+				stock_queue.pop(-1)
+			else:
+				stock_queue[-1] = [qty, incoming_rate]
 	else:
-		incoming_cost = 0
 		qty_to_pop = abs(actual_qty)
 		while qty_to_pop:
-			if not stock_queue:
-				stock_queue.append([0, 0])
+			intialize_stock_queue(stock_queue, sle.item_code, sle.warehouse)
 
 			batch = stock_queue[0]
 
-			if 0 < batch[0] <= qty_to_pop:
-				# if batch qty > 0
-				# not enough or exactly same qty in current batch, clear batch
-				incoming_cost += flt(batch[0]) * flt(batch[1])
-				qty_to_pop -= batch[0]
+			# print qty_to_pop, batch
+
+			if qty_to_pop >= batch[0]:
+				# consume current batch
+				qty_to_pop = qty_to_pop - batch[0]
 				stock_queue.pop(0)
+				if not stock_queue and qty_to_pop:
+					# stock finished, qty still remains to be withdrawn
+					# negative stock, keep in as a negative batch
+					stock_queue.append([-qty_to_pop, batch[1]])
+					break
+
 			else:
-				# all from current batch
-				incoming_cost += flt(qty_to_pop) * flt(batch[1])
-				batch[0] -= qty_to_pop
+				# qty found in current batch
+				# consume it and exit
+				batch[0] = batch[0] - qty_to_pop
 				qty_to_pop = 0
 
 	stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
 	stock_qty = sum((flt(batch[0]) for batch in stock_queue))
 
-	valuation_rate = stock_qty and (stock_value / flt(stock_qty)) or 0
+	valuation_rate = (stock_value / flt(stock_qty)) if stock_qty else 0
 
-	return valuation_rate
+	return abs(valuation_rate)
+
+def intialize_stock_queue(stock_queue, item_code, warehouse):
+	if not stock_queue:
+		estimated_val_rate = get_valuation_rate(item_code, warehouse)
+		stock_queue.append([0, estimated_val_rate])
 
 def _raise_exceptions(args, verbose=1):
 	deficiency = min(e["diff"] for e in _exceptions)
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 7264f36..b444e84 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -5,7 +5,6 @@
 from frappe import _
 import json
 from frappe.utils import flt, cstr, nowdate, add_days, cint
-from frappe.defaults import get_global_default
 from frappe.utils.email_lib import sendmail
 from erpnext.accounts.utils import get_fiscal_year, FiscalYearError
 
@@ -94,7 +93,7 @@
 	"""get valuation method from item or default"""
 	val_method = frappe.db.get_value('Item', item_code, 'valuation_method')
 	if not val_method:
-		val_method = get_global_default('valuation_method') or "FIFO"
+		val_method = frappe.db.get_value("Stock Settings", None, "valuation_method") or "FIFO"
 	return val_method
 
 def get_fifo_rate(previous_stock_queue, qty):
diff --git a/erpnext/utilities/repost_stock.py b/erpnext/utilities/repost_stock.py
index 51b472e..7d9423d 100644
--- a/erpnext/utilities/repost_stock.py
+++ b/erpnext/utilities/repost_stock.py
@@ -211,12 +211,14 @@
 
 def repost_all_stock_vouchers():
 	vouchers = frappe.db.sql("""select distinct voucher_type, voucher_no
-		from `tabStock Ledger Entry` order by posting_date, posting_time, name""")
+		from `tabStock Ledger Entry`
+		order by posting_date, posting_time, name""")
 
 	rejected = []
-	# vouchers = [["Purchase Receipt", "GRN00062"]]
+	i = 0
 	for voucher_type, voucher_no in vouchers:
-		print voucher_type, voucher_no
+		i+=1
+		print i, "/", len(vouchers)
 		try:
 			for dt in ["Stock Ledger Entry", "GL Entry"]:
 				frappe.db.sql("""delete from `tab%s` where voucher_type=%s and voucher_no=%s"""%
@@ -225,8 +227,8 @@
 			doc = frappe.get_doc(voucher_type, voucher_no)
 			if voucher_type=="Stock Entry" and doc.purpose in ["Manufacture", "Repack"]:
 				doc.get_stock_and_rate(force=1)
-			# elif voucher_type=="Purchase Receipt":
-			# 	doc.create_raw_materials_supplied("pr_raw_material_details")
+			elif voucher_type=="Purchase Receipt" and doc.is_subcontracted == "Yes":
+				doc.validate()
 
 			doc.update_stock_ledger()
 			doc.make_gl_entries(repost_future_gle=False, allow_negative_stock=True)