Merge pull request #4157 from nabinhait/bin

[fix][patch] Delete duplicate bins
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 85bf3cb..efa4906 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -215,4 +215,5 @@
 erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
 erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
 erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
-erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
\ No newline at end of file
+erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
+erpnext.patches.v6_4.fix_duplicate_bins
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/fix_duplicate_bins.py b/erpnext/patches/v6_4/fix_duplicate_bins.py
new file mode 100644
index 0000000..77d0527
--- /dev/null
+++ b/erpnext/patches/v6_4/fix_duplicate_bins.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.stock.stock_balance import repost_stock
+
+def execute():
+	bins = frappe.db.sql("""select item_code, warehouse, count(*) from `tabBin` 
+		group by item_code, warehouse having count(*) > 1""", as_dict=True)
+		
+	for d in bins:
+		try:
+			frappe.db.sql("delete from tabBin where item_code=%s and warehouse=%s", (d.item_code, d.warehouse))
+		
+			repost_stock(d.item_code, d.warehouse, allow_zero_rate=True, only_actual=False, only_bin=True)
+			
+			frappe.db.commit()
+		except:
+			frappe.db.rollback()
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index f55c12c..d1f7827 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -727,7 +727,7 @@
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
-   "description": "This will override Difference Account in Item", 
+   "description": "", 
    "fieldname": "difference_account", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -1291,7 +1291,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2015-09-11 12:20:21.220215", 
+ "modified": "2015-10-12 18:27:59.381894", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Stock Entry", 
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 3cb18ee..cba2464 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -9,7 +9,7 @@
 from erpnext.stock.stock_ledger import update_entries_after
 from erpnext.accounts.utils import get_fiscal_year
 
-def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False):
+def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False):
 	"""
 	Repost everything!
 	"""
@@ -24,7 +24,7 @@
 		union
 		select item_code, warehouse from `tabStock Ledger Entry`) a"""):
 			try:
-				repost_stock(d[0], d[1], allow_zero_rate, only_actual)
+				repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin)
 				frappe.db.commit()
 			except:
 				frappe.db.rollback()
@@ -33,22 +33,37 @@
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
 	frappe.db.auto_commit_on_many_writes = 0
 
-def repost_stock(item_code, warehouse, allow_zero_rate=False, only_actual=False):
-	repost_actual_qty(item_code, warehouse, allow_zero_rate)
+def repost_stock(item_code, warehouse, allow_zero_rate=False, only_actual=False, only_bin=False):
+	if not only_bin:
+		repost_actual_qty(item_code, warehouse, allow_zero_rate, only_bin)
 
 	if item_code and warehouse and not only_actual:
-		update_bin_qty(item_code, warehouse, {
+		qty_dict = {
 			"reserved_qty": get_reserved_qty(item_code, warehouse),
 			"indented_qty": get_indented_qty(item_code, warehouse),
 			"ordered_qty": get_ordered_qty(item_code, warehouse),
 			"planned_qty": get_planned_qty(item_code, warehouse)
-		})
+		}
+		if only_bin:
+			qty_dict.update({
+				"actual_qty": get_balance_qty_from_sle(item_code, warehouse)
+			})
+			
+		update_bin_qty(item_code, warehouse, qty_dict)
 
 def repost_actual_qty(item_code, warehouse, allow_zero_rate=False):
 	try:
 		update_entries_after({ "item_code": item_code, "warehouse": warehouse }, allow_zero_rate)
 	except:
 		pass
+		
+def get_balance_qty_from_sle(item_code, warehouse):
+	balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
+		where item_code=%s and warehouse=%s and is_cancelled='No'
+		order by posting_date desc, posting_time desc, name desc
+		limit 1""", (item_code, warehouse))
+		
+	return flt(balance_qty[0][0]) if balance_qty else 0.0
 
 def get_reserved_qty(item_code, warehouse):
 	reserved_qty = frappe.db.sql("""